Part 3: Developing stock-checker app

jonjam

Jonathan Harrison

Posted on December 26, 2020

Part 3: Developing stock-checker app

This post is part of a series detailing my journey with golang from learning the language to entering the DigitalOcean App Platform Hackathon.

The app I built can be found on GitHub.

Part 3 details:

  • golang packages used to build stock-checker
  • docker setup for both development and production
  • Integrating with Twilio SMS API

Overview

stock-checker is a golang app that spawns a task every hour to check whether any of the following UK retailers have an Xbox Series X console in stock:

This is done using a web automation library that navigates each site in a headless chromium browser.

If the app determines stock is available, a text message is sent using Twilio to the configured mobile number.

golang packages

A number of different packages were used to build this app which are detailed in this section.

These packages were discovered on Awesome Go.

Web Automation - go-rod/rod

rod is a high-level driver for the DevTools Protocol.

This package is used to navigate the various retailer's sites to find the Xbox Series X console listing. Once found, it checks whether the console is in or out of stock.

Notable features include:

Configuration - spf13/viper

Viper is a configuration package that supports reading configuration files in various formats, as well as from environment variables.

This is being used to control:

  • The scheduler interval
  • Debug settings for rod
  • Enables/disables sending notifications and the secrets used to communicate with Twilio.

I used an envfile to define the app's configuration. Originally, I tried using a YAML file but due to a couple of issues, I had to swap the file format.

To help others, here are the issues I ran into when using YAML:

  • GitHub Issue: If you want to override a YAML subobject property with an environment variable, you have to name the variable using the following format: PREFIX_SECURE.KEY. DigitalOcean App Platform environment variables do not support . in the name.
  • GitHub Issue: If you want to override a YAML subobject property with an environment variable and unmarshal that object to a struct, this isn't currently possible. This is because viper.UnmarshalKey doesn't take account of environment variables.

Scheduler - go-co-op/gocron

goCron is a scheduling package that lets you run functions periodically at a pre-determined interval.

This is being used to run a task once an hour that checks the various retailers and if applicable, sends a notification.

docker support

To simplify running the app on DigitalOcean, I added docker support which this section covers.

Dockerfile

This amazing JetBrains blog post series greatly inspired the Dockerfile created for this project.

Using multi-stage builds it provides both a development image with debugging support and a production image.

# Builder
FROM golang:1.15.6-buster AS builder
COPY . /src
WORKDIR /src
RUN go get github.com/go-delve/delve/cmd/dlv
RUN go build -gcflags="all=-N -l" -o app-dev
RUN go build -o app

# Base runner
FROM debian:10.7 AS base-runner
RUN apt-get update && apt-get install -y \
    ca-certificates \
    chromium \
    && rm -rf /var/lib/apt/lists/*

# Dev runner
FROM base-runner AS dev-runner
WORKDIR /server
COPY config.env /server
COPY --from=builder /src/app-dev /server/app
COPY --from=builder /go/bin/dlv /server
EXPOSE 40000
CMD ["/server/dlv", "--listen=:40000", "--headless=true", "--api-version=2", "--accept-multiclient", "exec", "/server/app"]

# Prod runner
FROM base-runner AS prod-runner
WORKDIR /server
COPY config.env /server
COPY --from=builder /src/app /server
CMD ["./app"]
Enter fullscreen mode Exit fullscreen mode

docker-compose

To assist with development, this docker-compose file starts a development container with debugging enabled and enables a few rod debug options via environment variables.

version: "3.9"

services:
  app:
    build:
      context: ./..
      target: dev-runner 
    security_opt:
      - seccomp:unconfined
    cap_add:
      - SYS_PTRACE
    container_name: stock-checker-$USER

    ports:
      - "40000:40000" # DEBUG

    environment:
      - SC_ROD_TRACE=true
      - SC_ROD_PAGEPOOLSIZE=1
Enter fullscreen mode Exit fullscreen mode

Remote debugging using VS Code

To remote debug the app within docker, we need to create a launch configuration by following this guide.

The resulting config looks like this:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch and debug in Docker",
            "type": "go",
            "request": "attach",
            "mode": "remote",
            "cwd": "${workspaceFolder}",
            "port": 40000,
            "host": "127.0.0.1",
            // This corresponds to the directory the app is built in
            "remotePath": "/src"
        },
    ]
}
Enter fullscreen mode Exit fullscreen mode

Integrating with Twilio

Twilio is being used to send a SMS when the app detects a Xbox Series X console is in stock.

Originally, I was going to use saintpete/twilio-go which I discovered here. However I ran into issues with this package due to incompatible package versions.

In the end, I went with a simpler approach and ended up following this blog post to integrate with their SMS API directly.

Next

That's it for this post.

In the final part, I will detail my DigitalOcean App Platform Hackathon submission as well as deploying to DigitalOcean.

💖 💪 🙅 🚩
jonjam
Jonathan Harrison

Posted on December 26, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Part 1: Background and learning golang
dohackathon Part 1: Background and learning golang

December 26, 2020

Part 2: Development environment
dohackathon Part 2: Development environment

December 26, 2020

Part 3: Developing stock-checker app
dohackathon Part 3: Developing stock-checker app

December 26, 2020