So for this weeks main project, I had decided to latch onto another’s project and help out. My target was Richard’s mappyr mobile app, built in React Native; it’s kind of like a geolocation reddit where posting and viewing comments are done when actually at a location. My job, I offered, was to build the backend.
Backend First Draft
This first draft, aptly named mappyr-backend was a very simple implementation of what he needed to proceed: a database of comments which can be upvoted. The things I need to implement are many, but mainly:
- authentication (even anonymous)
- a relational table for upvotes/downvotes
- a user table
The backend itself, however simple, took about a day to cook up: it’s a Go powered database wrapper and api route handler. This kind of thing gets done pretty fast with Go, and it took me a similar amount of time to simply deploy it. That is the tricky part:
Step One: Translation to Postgres
Because I don’t pay for a virtual machine somewhere on the internet, I decided to take a swing at using Heroku to deploy the developer backend, so that Richard could play around with the api as soon as possible (we figured the authentication etc could wait). Effectively this meant I had to translate the database portion of the code to Postgresql (from my wonderfully simple sqlite3). After getting the postgresql server and user running on my machine, there were not too many small syntax changes I had to muddle through first:
- Instead of an
AUTOINCREMENT INTEGER, postgres can simply take a
- I had to swap a
DATETIMEtype for the
- Rather than a
?for insert/select values, I used
$i, which has a useful number variable.
- The Go sql driver doesn’t provide a function for returning the
lastInsertId, and so I had to add
returning idto the
INSERTstatement, and then
Scanit into a id variable.
Onto Heroku’s Postgres
Oh, but that’s not all. After having translated the statements, the Go sql
Open() function takes modified parameters for it’s database infos (such as the user, password, and db name – which also will change once the postgres database is set up on Heroku. For the second parameter of
sql.Open(), the aforementioned “infos”, Heroku needs
url := os.Getenv("DATABASE_URL"), and this needs to be parsed by the driver (so it should be unhidden),
connection, _ := pq.ParseURL(url) along with the parameter:
Step Two: Prepare for Heroku
Aside from the typical
heroku-toolbelt and account needed for this deploy type thing, a Go application (lacking otherwise a standard package manager) needs a few special tweaks. As the instructions dictate, it needs dependencies tracked by a package called Godep. This is so easy to use, one command will save the dependencies to the
Vendor/ directory along with a handy JSON file of versions and package names. Next I needed to add the standard
Procfile for running the server, looking like this:
web: mappyr-backend -port=$PORT
So I added a
flag to my program for setting the port, or otherwise the server needs to
ListenAndServe on dynamically created port. This can be retrieved again with the
os.Getenv("PORT") function and concatenated with a colon.
Step Three: These steps are not linear
The trail and error for this took me a not-unexpected long time. In fact, the back and forth of combinations I attempted make me a bit hestitant to say I could repeat it outright, but in any case there is one tip which helped me a long:
heroku logs --tail
Otherwise this whole shambled process is done blind.