From f2ef0f500203482b213f66acddd6fb3d48811e40 Mon Sep 17 00:00:00 2001 From: Will Andrews Date: Wed, 1 Apr 2026 19:49:36 +0100 Subject: [PATCH] Implement turso as a database Signed-off-by: Will Andrews --- cmd/cocoon/main.go | 6 ++++++ go.mod | 4 ++++ go.sum | 10 ++++++++-- identity/identity.go | 6 +++--- server/server.go | 20 ++++++++++++++++++-- 5 files changed, 39 insertions(+), 7 deletions(-) diff --git a/cmd/cocoon/main.go b/cmd/cocoon/main.go index e10606f..3adb24e 100644 --- a/cmd/cocoon/main.go +++ b/cmd/cocoon/main.go @@ -54,6 +54,11 @@ func main() { Usage: "PostgreSQL connection string (required if db-type is postgres)", EnvVars: []string{"COCOON_DATABASE_URL", "DATABASE_URL"}, }, + &cli.StringFlag{ + Name: "turso-token", + Usage: "Token for a cloud Turso instance", + EnvVars: []string{"COCOON_TURSO_TOKEN", "TURSO_TOKEN"}, + }, &cli.StringFlag{ Name: "did", EnvVars: []string{"COCOON_DID"}, @@ -218,6 +223,7 @@ var runServe = &cli.Command{ DbName: cmd.String("db-name"), DbType: cmd.String("db-type"), DatabaseURL: cmd.String("database-url"), + TursoToken: cmd.String("turso-token"), Did: cmd.String("did"), Hostname: cmd.String("hostname"), RotationKeyPath: cmd.String("rotation-key-path"), diff --git a/go.mod b/go.mod index 931708d..2075396 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( github.com/multiformats/go-multihash v0.2.3 github.com/prometheus/client_golang v1.23.2 github.com/samber/slog-echo v1.16.1 + github.com/tursodatabase/libsql-client-go v0.0.0-20251219100830-236aa1ff8acc github.com/urfave/cli/v2 v2.27.6 github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b @@ -41,8 +42,10 @@ require ( require ( github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/RussellLuo/slidingwindow v0.0.0-20200528002341-535bb99d338b // indirect + github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/coder/websocket v1.8.12 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/earthboundkid/versioninfo/v2 v2.24.1 // indirect @@ -124,6 +127,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect + golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect golang.org/x/net v0.43.0 // indirect golang.org/x/sync v0.16.0 // indirect golang.org/x/sys v0.35.0 // indirect diff --git a/go.sum b/go.sum index e169b45..92e0743 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,8 @@ github.com/RussellLuo/slidingwindow v0.0.0-20200528002341-535bb99d338b h1:5/++qT github.com/RussellLuo/slidingwindow v0.0.0-20200528002341-535bb99d338b/go.mod h1:4+EPqMRApwwE/6yo6CxiHoSnBzjRr3jsqer7frxP8y4= github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 h1:iW0a5ljuFxkLGPNem5Ui+KBjFJzKg4Fv2fnxe4dvzpM= github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5/go.mod h1:Y2QMoi1vgtOIfc+6DhrMOGkLoGzqSV2rKp4Sm+opsyA= +github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE= github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -26,6 +28,8 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3 github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo= +github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -330,6 +334,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/tursodatabase/libsql-client-go v0.0.0-20251219100830-236aa1ff8acc h1:lzi/5fg2EfinRlh3v//YyIhnc4tY7BTqazQGwb1ar+0= +github.com/tursodatabase/libsql-client-go v0.0.0-20251219100830-236aa1ff8acc/go.mod h1:08inkKyguB6CGGssc/JzhmQWwBgFQBgjlYFjxjRh7nU= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g= github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= @@ -386,8 +392,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= diff --git a/identity/identity.go b/identity/identity.go index 3f422f8..2902412 100644 --- a/identity/identity.go +++ b/identity/identity.go @@ -82,11 +82,11 @@ func ResolveHandle(ctx context.Context, cli *http.Client, handle string) (string return maybeDidFromTxt, nil } - if maybeDidFromWeb, err := ResolveHandleFromWellKnown(ctx, cli, handle); err == nil { + maybeDidFromWeb, err := ResolveHandleFromWellKnown(ctx, cli, handle) + if err == nil { return maybeDidFromWeb, nil } - - return "", fmt.Errorf("handle could not be resolved") + return "", fmt.Errorf("resolve well known: %w", err) } func DidToDocUrl(did string) (string, error) { diff --git a/server/server.go b/server/server.go index f92b15b..53fd011 100644 --- a/server/server.go +++ b/server/server.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "crypto/ecdsa" + "database/sql" "embed" "errors" "fmt" @@ -44,6 +45,7 @@ import ( "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" slogecho "github.com/samber/slog-echo" + _ "github.com/tursodatabase/libsql-client-go/libsql" "gorm.io/driver/postgres" "gorm.io/driver/sqlite" "gorm.io/gorm" @@ -97,6 +99,7 @@ type Args struct { DbName string DbType string DatabaseURL string + TursoToken string Version string Did string Hostname string @@ -349,6 +352,19 @@ func New(args *Args) (*Server, error) { return nil, fmt.Errorf("failed to connect to postgres: %w", err) } logger.Info("connected to PostgreSQL database") + case "turso": + primaryUrl := args.DatabaseURL + authToken := args.TursoToken + + db, err := sql.Open("libsql", fmt.Sprintf("%s?authToken=%s", primaryUrl, authToken)) + gdb, err = gorm.Open(sqlite.New(sqlite.Config{ + Conn: db, + }), &gorm.Config{}) + if err != nil { + return nil, fmt.Errorf("failed to connect to postgres: %w", err) + } + logger.Info("connected to PostgreSQL database") + default: gdb, err = gorm.Open(sqlite.Open(args.DbName), &gorm.Config{}) if err != nil { @@ -658,8 +674,8 @@ func (s *Server) requestCrawl(ctx context.Context) error { func (s *Server) doBackup() { logger := s.logger.With("name", "doBackup") - if s.dbType == "postgres" { - logger.Info("skipping S3 backup - PostgreSQL backups should be handled externally (pg_dump, managed database backups, etc.)") + if s.dbType == "postgres" || s.dbType == "turso" { + logger.Info("skipping S3 backup - PostgreSQL or Turso backups should be handled externally (pg_dump, managed database backups, etc.)") return } -- 2.51.2