This repository contains sources of server part of Wroclive iOS app.
(Psst… the app itself is also open-sourced!)
We use Google Cloud for hosting.
We extensively use their free tier, to keep our hosting costs low. The only thing that we actually pay for is storage for App Engine instances, but this is about 0.20 zł (~$0.05) per month (only the instances in US are free and we chose Frankfurt because of GDPR and latency).
Anyway, this is how it works:
And this is the push notification pipeline:
- Handles all traffic to wroclive.app and wroclive.app/api
- Runs code from AppEngine directory
- Every 1h it fetches MPK data (for example available lines and stop locations) from
Firestore - Every 5 seconds it fetches new vehicle locations from wroclaw.pl/open-data
- If you want to deploy it yourself (
make deploy), then remember to putGCP-Credentials.jsonforapp-engine-firestoreservice account in AppEngine directory - Since AppEngine instances should not have state (they may be restarted by Google at whim) every 30s we store last heading/angle update location for every vehicle in the database. If something goes wrong we will use those locations to calculate new headings. This is also nice because now we can update the app without worrying about losing the state.
- Stores persistent data:
- lines - filled by
ComputeEngine-Updater - stops - filled by
ComputeEngine-Updater - notifications - filled by
ComputeEngine-Notifications - push notification tokens - filled by
AppEngine - send push notifications - filled by
ComputeEngine-Notifications
- lines - filled by
- Single instance named
backend - Startup script:
/home/USERNAME/on-vm-startup.sh - Runs code from following directories:
- ComputeEngine
- Manage
ComputeEngineinstance (installations, updates etc.) - Update flow:
make packageto create.zippackage with all of theComputeEnginemodulesmake uploadto send package toGCPmake connectto log intoGCP- (on VM)
./install-package.sh exitmake restartto restart VM (if needed)
- Manage
- ComputeEngine-Updater
- Simple app that downloads GTFS file from wroclaw.pl/open-data and upload it to
Firestore - Uses sqlite.org for intermediate processing
- Before installing remember to put
GCP-Credentials.jsonforcompute-engine-firestoreservice account in ComputeEngine-Updater directory
- Simple app that downloads GTFS file from wroclaw.pl/open-data and upload it to
- ComputeEngine-PubSub
Pub/Subsubscriber- After receiving
backend-update-gtfs-datamessage runsComputeEngine-Updater - Starts when the
Compute Engineinstance starts - Before installing remember to put
GCP-Credentials.jsonforpubsubservice account in ComputeEngine-PubSub directory
- ComputeEngine-Notifications
- Gets latest tweets from @AlertMPK and sends them as push notifications
- Stores notifications in
Firestore - Starts when the
Compute Engineinstance starts - Before installing remember to put following in ComputeEngine-Notifications directory:
GCP-Credentials.jsonforcompute-engine-firestoreservice accountTwitter-Credentials.json- seeTwitter-Credentials-example.jsonfor detailsAPN-Key.p8- key for Apple Push Notification serviceAPN-Credentials.json- seeAPN-Credentials-example.jsonfor details
- ComputeEngine
- Runs code from CloudFunctions directory
backendStartfunction- Looks for
backendinstance onCompute Engineand starts it - Scheduled by
Cloud Scheduler
- Looks for
backendStopfunction- Looks for
backendinstance onCompute Engineand stops it - scheduled by
Cloud Scheduler
- Looks for
Pub/Sub - following topics need to be created:
backend-stopbackend-startbackend-update-gtfs-data
- Every day at 1am (
0 3 * * *): publishbackend-stopmessage onPub/Sub - Every day at 5am (
15 3 * * *): publishbackend-startmessage onPub/Sub - Every day at 3am (
30 3 * * *): publishbackend-update-gtfs-datamessage onPub/Sub
IAM & Admin - following service accounts are used:
-
App Engine default service account- automatically created by
App Engine - no configuration needed
- automatically created by
-
app-engine-firestore- account used byApp Engineto read/write data inFirestore- Role: Viewer, Editor
- Key should be exported and placed in AppEngine
-
compute-engine-firestore- account used inComputeEngine-UpdaterandComputeEngine-Notificationsto read/write data inFirestore- Role: Owner
- Key should be exported and placed in ComputeEngine-Updater and ComputeEngine-Notifications
-
pubsub- account used for creating subscriptions inComputeEngine-PubSub- Roles: Editor, Pub/Sub Publisher, Pub/Sub Subscriber
- Key should be exported and placed in ComputeEngine-PubSub
- SSL certificate expiring soon
- Alert: 7 days prior
- Uptime check on
wroclive.app/api(this will also keep ourApp Engineinstance alive)- Protocol: HTTPS
- Hostname: wroclive.app
- Path: api
- Check frequency: 10 minutes
- Regions: Europe
-
We use winstonjs/winston with
@google-cloud/logging-winstonbackend -
Add following filers:
- App Engine life cycle
- Query:
resource.type="gae_app" AND (textPayload=~"(Starting app|Quitting on terminated signal)$" OR protoPayload.methodName="google.appengine.v1.Versions.CreateVersion")
- Query:
- Api by user agent
- Query:
protoPayload.userAgent =~ "Wroclive.*"
- Query:
- App Engine life cycle
-
- Parse logs from Cloud Logging and output them in human-readable form
Error reporting - standard reporting by mail
-
- preset to
Unix siegetool + baseline - used to check burst performance - tiny module written in Python to check sustained performance
- preset to
-
postman.json - configuration file to import into postman app (it contains our endpoints + some basic tests)
Wroclive is licensed under the Mozilla Public License 2.0 license. See LICENSE for more information.