From 44d9c8a95c2b6fe53efd56cb57485fa31c21970d Mon Sep 17 00:00:00 2001 From: derconno Date: Sun, 11 Aug 2024 15:10:09 +0200 Subject: [PATCH] Adding sqlite3 support (#6) * Added support for sqlite3 * Updating compose files & README.md with the new mechanism to db driver selection * changing the sqlite driver to a pure go implementation * switching sqlite driver to one without a wasm dependency and making the in-memory db warning more verbose --- README.md | 16 ++++++++------- docker-compose.dev.yaml | 1 + docker-compose.yaml | 1 + go.mod | 16 ++++++++++++++- go.sum | 45 +++++++++++++++++++++++++++++++++++++++++ main.go | 32 ++++++++++++++++++++++++----- 6 files changed, 98 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 193da1a..53e65b4 100644 --- a/README.md +++ b/README.md @@ -19,13 +19,15 @@ interact with the system: This backend depends on several other services, that should be configured alongside with this application. Not all are strictly required, but some functions might not work if a service is configured improperly. -### Postgres -go-drink uses Postgresql as a database backend and fully depends on it. If a database backend is not configured, or if -it is unreachable during the application startup, go-drink terminates instantly. - -| Environment Variable | Example Value | Notes | -|----------------------|-----------------------------------------------------------------|---------------------------------------------------------------| -| GODRINK_DB | `postgresql://godrink:changeme@db:5432/godrink?sslmode=disable` | A connection string describing of the database can be reached | +### Database +go-drink can either be used with Postgresql as a database backend, or sqlite. If no database backend is configured, an +in-memory sqlite database is used. However, if a backend is configured, but it is unreachable during the application +startup, go-drink terminates instantly. + +| Environment Variable | Example Value | Notes | +|----------------------|-----------------------------------------------------------------|--------------------------------------------------------------------| +| GODRINK_DBDRIVER | `postgres` | The database backend to use. May either be `postgres` or `sqlite`. | +| GODRINK_DB | `postgresql://godrink:changeme@db:5432/godrink?sslmode=disable` | A connection string describing of the database can be reached | ### SMTP / Mailing An SMTP server can be configured, so that the application can send out emails to users, for example if a password reset diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml index a898cb6..92dbe33 100644 --- a/docker-compose.dev.yaml +++ b/docker-compose.dev.yaml @@ -15,6 +15,7 @@ services: dockerfile: Dockerfile restart: on-failure environment: + GODRINK_DBDRIVER: "postgres" GODRINK_DB: "postgresql://godrink:changeme@db:5432/godrink?sslmode=disable" GODRINK_SMTPHOST: "yourmailhost.example:465" GODRINK_SMTPUSER: "godrink@yourmailhost.example" diff --git a/docker-compose.yaml b/docker-compose.yaml index 9e60b81..f4f3f37 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -12,6 +12,7 @@ services: image: ghcr.io/port39/go-drink:latest restart: on-failure environment: + GODRINK_DBDRIVER: "postgres" GODRINK_DB: "postgresql://godrink:changeme@db:5432/godrink?sslmode=disable" GODRINK_SMTPHOST: "yourmailhost.example:465" GODRINK_SMTPUSER: "godrink@yourmailhost.example" diff --git a/go.mod b/go.mod index 2b03482..d31ac13 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,20 @@ require ( github.com/lib/pq v1.10.9 github.com/wneessen/go-mail v0.4.2 golang.org/x/crypto v0.25.0 + modernc.org/sqlite v1.32.0 ) -require golang.org/x/sys v0.22.0 // indirect +require ( + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/ncruces/go-strftime v0.1.9 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + golang.org/x/sys v0.22.0 // indirect + modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect + modernc.org/libc v1.55.3 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.8.0 // indirect + modernc.org/strutil v1.2.0 // indirect + modernc.org/token v1.1.0 // indirect +) diff --git a/go.sum b/go.sum index 53aee6e..0e19a45 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,55 @@ +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= +github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/wneessen/go-mail v0.4.2 h1:wISuU9LOGqrA7pxy7OipRtwoExXTzuGKmAjb8gYwc00= github.com/wneessen/go-mail v0.4.2/go.mod h1:zxOlafWCP/r6FEhAaRgH4IC1vg2YXxO0Nar9u0IScZ8= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= +golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= +modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= +modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= +modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y= +modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s= +modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= +modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= +modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= +modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= +modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= +modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= +modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= +modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= +modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s= +modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA= +modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= +modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= diff --git a/main.go b/main.go index 3a86770..e16cdbd 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,7 @@ import ( "github.com/Port39/go-drink/users" _ "github.com/lib/pq" "log" + _ "modernc.org/sqlite" "net/http" "os" "strconv" @@ -20,7 +21,11 @@ import ( const ContextKeySessionToken = "SESSION_TOKEN" +// The SQLITE_DRIVER value comes from modernc.org/sqlite/sqlite.driverName +const SQLITE_DRIVER = "sqlite" + type Config struct { + DbDriver string DbConnectionString string Port int SessionLifetime int @@ -49,10 +54,26 @@ func mkconf() Config { } } - dbstring, exists := os.LookupEnv("GODRINK_DB") - if !exists { - log.Fatal("No database given, exiting!") + dbdriver, driverExists := os.LookupEnv("GODRINK_DBDRIVER") + dbUrl, dbUrlExists := os.LookupEnv("GODRINK_DB") + if !driverExists { + log.Println("No database driver given, using embedded sqlite.") + log.Println("##############################################################") + log.Println("# Caution: NO DATA WILL PERSIST ACROSS APPLICATION RESTARTS! #") + log.Println("##############################################################") + dbdriver = SQLITE_DRIVER + dbUrl = "file::memory:?cache=shared" + } else { + dbdriver = strings.ToLower(dbdriver) + if !dbUrlExists { + if dbdriver == SQLITE_DRIVER { + dbUrl = "file::memory:?cache=shared" + } else { + log.Fatalf("The database driver (%s) requires specifying a connection string!", dbdriver) + } + } } + lifetime := 300 lifetimeString, exists := os.LookupEnv("GODRINK_SESSIONLIFETIME") if exists { @@ -94,7 +115,8 @@ func mkconf() Config { cors, addCorsHeader := os.LookupEnv("GODRINK_CORS") return Config{ - DbConnectionString: dbstring, + DbDriver: dbdriver, + DbConnectionString: dbUrl, Port: port, SessionLifetime: lifetime, MailHost: mailHost, @@ -109,7 +131,7 @@ func mkconf() Config { func initialize() { config = mkconf() - db, err := sql.Open("postgres", config.DbConnectionString) + db, err := sql.Open(config.DbDriver, config.DbConnectionString) if err != nil { log.Fatal("Error connecting to database: ", err) }