Dany the spacecowboy
Posted on May 5, 2021
You can check the original post in my blog
First of all, let's talk about encore.dev which is a magical Go backend framework with almost 0 boilerplate,tracing out of the box, serverless deploys immediately, support for postgreSQL, auth and much more! I first heard about this framework in the TLDR Newsletter and I tried it for a little bit and I'm falling in love with it even though I barely know how to code in Go!
To start a new project you need to download and install encore, the good thing is that is available in brew for mac so we can just do the following command in our terminal:
$ brew install encoredev/tap/encore
//then run
$ encore app create
When doing the
encore app create
it will ask you to login in our encore app to create a new project, after doing that it will ask you for the name of the app and a starter template, for this project I chose the Hello World template just to have a base to start with, after finishing with the prompt questions you'll have something like this
Now if we go into that folder with
cd bingo
and then do
encore run
we should be able to go to
and see the "API Explorer" which is a nice interface that lists all our API endpoints so we can trigger the request from there with a custom body, params and all that
![encore api explorer](https://i.imgur.com/bSQuZfR.png)
There's also a nice thing about this app that encore creates for us, we also have available an auto generated API docs which specify a little description about the API endpoint, the params types and response schema of each defined endpoint
## Creating our bingo database and migration
In this post I won't be generating all the authentication part of the app, since it's a small project, I will be creating the following routes with it's functionality:
- User creation route (with a number list)
- Randomizer route (to get a random number and compare to the number list of a specified user)
### Doing the migration
So let's start with how the migration of the user is going to look, to create the right file, we need to add a new folder called
```bingo```
on the root of the project, then create a
```migration```
folder with a file on it called
```1_create_user_table.up.sql```
,
__Notes:__
- the number of the file means the order that the migrations are going to be executed
- after the first underscore (_) comes the name of the migration
- we have to add the extension
```.up.sql```
to all migrations
```sql
CREATE TABLE client (
email TEXT PRIMARY KEY,
list INTEGER []
);
Defining the logic of the route
after doing this, whenever we do encore run the next time it will run our migration, but before that let's create a
file inside the bingo folder to create our routes inside of it.
first we need to include the package name which should match the folder name (our bingo service) then after that we should define our imports and include encore sqldb handler inside of it
```go
package bingo
import (
"context"
"encore.dev/storage/sqldb"
)
now we need to declare some structs for our response and request for the route to be used inside the function to cover our needs, we need a struct for the request params and a struct for the response we're sending, that should look like the following
type UserParams struct {
Email string
}
type RegisterResponse struct {
Email string
List []int
}
then it comes the fun part, creating the function that in charge of creating the list, the user, store it in the database and returnn it, NOTE: keep in mind that we need to add the comment
//encore:api public
before the function so encore can detect it as an API route, the following code looks something like this:
//encore:api public
func RegisterUser(ctx context.Context, params *UserParams) (*RegisterResponse, error) {
var list = generateList(0, 100)
var user RegisterResponse
err := sqldb.QueryRow(ctx, `
INSERT INTO "client" (email, list)
VALUES ($1, $2)
RETURNING *;
`, params.Email, list).Scan(&user.Email, &user.List)
if err != nil {
return nil, err
}
return &user, nil
}
func generateList(min, max int) []int {
a := make([]int, max-min+1)
for i := range a {
a[i] = min + i
}
return a
}
Verifying the database
Now after doing that we can do
encore run
go to localhost:4060 and try hitting the registerUser Endpoint with the request to call the API
quick note: To check the database data, you can do
encore db conn-uri ${service name}
in this case service name is bingo so it should be
encore db conn-uri bingo
, then you can take this URL and use it in postico or some other postgreSQL UI app to see the table and the rows, also you can use the PSQL command in mac (you need to install it first with brew)
Selecting a number and updating the array
Now the next task is to get the list array from a user, then select a random number from the list, remove that number from that list, updating it in the database and return the selected number! so let's get started, we will do this code in the same bingo.go file:
//encore:api public
func DrawFromList(ctx context.Context, params *UserParams) (*DrawResponse, error) {
var list []int // empty list to be asssigned after the SQL query
err := sqldb.QueryRow(ctx, `
SELECT list from "client"
WHERE email = ($1)`, params.Email).Scan(&list)
if err != nil {
return nil, err
}
var response DrawResponse
// generate a random number everytime you hit the request
rand.Seed(time.Now().UnixNano())
var randomIndex = rand.Intn(len(list) - list[0] + 1 + list[0])
// assign the random number to the response selected struct
response.Selected = list[randomIndex]
//remove the item from the array by the index
list = RemoveIndex(list, randomIndex)
// update the list of the user with the new one without the selected item
sqldb.QueryRow(ctx, `
UPDATE "client"
SET list = ($1)
WHERE email = ($2)`, list, params.Email)
response.Removed = true
return &response, nil
}
//Function to remove an item from an array by the index
func RemoveIndex(s []int, index int) []int {
return append(s[:index], s[index+1:]...)
}
After this we can commit what we did, and then run
git push encore
to build the project and deploy it inside encore.dev platform (which uses a free tier of aws under the hood) and if we go to encore.dev and select the project you should see a build completed
Also, to check the database in production, we can use
encore db shell bingo --env=prod
and from here we will be able to see our database with psql from the terminal
So TLDR:
In this tuto we created a encore.dev backend app from scratch which uses two routes to create a user based on an email and assigns a list of a 100 numbers to it, and another route to draw a random number and remove it from that user array list
you can test this API on this url https://bingo-c7m2.encoreapi.com/prod/bingo.RegisterUser with this CURL to register:
curl --location --request POST 'https://bingo-c7m2.encoreapi.com/prod/bingo.RegisterUser' \
--header 'Content-Type: application/json' \
--data-raw '{
"Email": "your-mail@gg.com"
}'
and this CURL to draw a number
curl --location --request POST 'https://bingo-c7m2.encoreapi.com/prod/bingo.DrawFromList' \
--header 'Content-Type: application/json' \
--data-raw '{
"Email": "your-mail@gg.com"
}'
Sources
- https://encore.dev
- https://www.postgresqltutorial.com/postgresql-array/
- https://www.digitalocean.com/community/tutorials/defining-structs-in-go-es
- Encore.dev slack group
- https://www.golangprograms.com/how-to-delete-an-element-from-a-slice-in-golang.html
- https://www.postgresqltutorial.com/postgresql-update/
Posted on May 5, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.