diff --git a/Dockerfile b/Dockerfile index d837742..a4336dc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,10 +2,12 @@ FROM thevlang/vlang:alpine AS build WORKDIR /tmp/app COPY . . -RUN v -prod . +RUN v -prod -o highscore-server . FROM alpine:latest +RUN apk --no-cache add sqlite-dev + WORKDIR /app COPY --from=build /tmp/app/highscore-server . COPY --from=build /tmp/app/config.example.toml ./config.toml diff --git a/src/config.v b/src/config.v index d2be073..01cd7cd 100644 --- a/src/config.v +++ b/src/config.v @@ -15,6 +15,10 @@ struct Config { db_path string } +fn (config Config) copy() Config { + return config +} + fn load_config() Config { config := toml.parse_file(path) or { panic(err) } diff --git a/src/database.v b/src/database.v index 79fad4d..2704a93 100644 --- a/src/database.v +++ b/src/database.v @@ -8,7 +8,7 @@ pub mut: time i64 } -fn (mut app App) create_tables() bool { +fn (mut app App) create_tables() int { return app.db.exec_none( "CREATE TABLE IF NOT EXISTS ScoreRes ( id INTEGER PRIMARY KEY, @@ -16,7 +16,7 @@ fn (mut app App) create_tables() bool { score INTEGER NOT NULL, time SQLITE_INT64_TYPE NOT NULL )" - ) == 0 + ) } fn (mut app App) insert_score(score ScoreRes) { diff --git a/src/main.v b/src/main.v index 8d8bb17..fed1520 100644 --- a/src/main.v +++ b/src/main.v @@ -2,36 +2,64 @@ module main import vweb import sqlite +import time +import os struct App { vweb.Context pub mut: db sqlite.DB - config Config + config shared Config is_admin bool } fn main() { mut app := &App{} + mut app_config := Config{} - app.config = load_config() + lock app.config { + app.config = load_config() + app_config = app.config.copy() + } - app.db = sqlite.connect(app.config.db_path) or { - println('Database Error!') + if !os.exists(app_config.db_path) { + println("Creating database file at " + app_config.db_path) + mut file := os.create(app_config.db_path) or { panic(err) } + file.close() + } + + app.db = sqlite.connect(app_config.db_path) or { + println('Database error!') panic(err) } - app.create_tables() + sql_code := app.create_tables() + + if sqlite.is_error(sql_code) { + println('Could not create tables!') + panic('Error code ' + sql_code.str()) + } mut host := '::' - - if app.config.host != "" { - host = app.config.host + if app_config.host != "" { + host = app_config.host } + // Handle graceful shutdown for Docker + os.signal_opt(os.Signal.int, app.shutdown) or { panic(err) } + os.signal_opt(os.Signal.term, app.shutdown) or { panic(err) } + vweb.run_at(app, vweb.RunParams{ host: host - port: app.config.port + port: app_config.port family: .ip6 }) or { panic(err) } } + +fn (mut app App) shutdown(sig os.Signal) { + app.db.close() or { panic(err) } + println("Shut down database gracefully") + println("Exiting...") + time.sleep(1e+9) // Sleep one second + exit(0) +} diff --git a/src/web.v b/src/web.v index a38f0ab..8760f92 100644 --- a/src/web.v +++ b/src/web.v @@ -4,7 +4,7 @@ import vweb import json import time -struct Status { +struct ResultStatus { status int message string } @@ -16,8 +16,10 @@ struct ErrorStatus { } pub fn (mut app App) index() vweb.Result { - if app.config.redirect { - app.redirect(app.config.redirect_url) + rlock app.config { + if app.config.redirect { + app.redirect(app.config.redirect_url) + } } return app.text("Hello :)") @@ -69,7 +71,7 @@ pub fn (mut app App) score_submit() vweb.Result { app.insert_score(ScoreRes{player:body.player, score:body.score, time:time.now().unix_time()}) return app.json( - Status { + ResultStatus { 200, "Success" } @@ -77,10 +79,14 @@ pub fn (mut app App) score_submit() vweb.Result { } fn (mut app App) auth() bool { - app.config = load_config() - auth_header := app.get_header('Authorization') token := auth_header.after('Bearer ') - return token == app.config.token + mut config_token := "" + + rlock app.config { + config_token = app.config.token + } + + return config_token.len != 0 && token == config_token }