From 79d26c3104b582a0cf1ea77469cf26d470d64516 Mon Sep 17 00:00:00 2001 From: "Levy A." Date: Tue, 27 May 2025 16:05:43 -0300 Subject: [PATCH 1/6] chore: update header --- lib/include/libsql.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/include/libsql.h b/lib/include/libsql.h index 7fdfb4b..505c4b2 100644 --- a/lib/include/libsql.h +++ b/lib/include/libsql.h @@ -40,6 +40,7 @@ typedef struct { const char *encryption_key; int sync_interval; char with_webpki; + char offline; } libsql_config; typedef const libsql_connection *libsql_connection_t; @@ -61,6 +62,8 @@ typedef struct { extern "C" { #endif // __cplusplus +int libsql_enable_internal_tracing(void); + int libsql_sync(libsql_database_t db, const char **out_err_msg); int libsql_sync2(libsql_database_t db, replicated *out_replicated, const char **out_err_msg); From 0beaff95858ae1f25b20863f19bce322d219c1a2 Mon Sep 17 00:00:00 2001 From: "Levy A." Date: Tue, 27 May 2025 17:08:38 -0300 Subject: [PATCH 2/6] feat: use libsql_open_sync_with_config with explicit offline param --- libsql.go | 59 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/libsql.go b/libsql.go index 6ffcd97..f841348 100644 --- a/libsql.go +++ b/libsql.go @@ -54,7 +54,7 @@ type Option interface { type option func(*config) error type Replicated struct { - FrameNo int + FrameNo int FramesSynced int } @@ -135,7 +135,37 @@ func NewEmbeddedReplicaConnector(dbPath string, primaryUrl string, opts ...Optio if config.syncInterval != nil { syncInterval = *config.syncInterval } - return openEmbeddedReplicaConnector(dbPath, primaryUrl, authToken, readYourWrites, encryptionKey, syncInterval) + return openSyncConnector(dbPath, primaryUrl, authToken, readYourWrites, encryptionKey, syncInterval, false) +} + +func NewSyncedDatabaseConnector(dbPath string, primaryUrl string, opts ...Option) (*Connector, error) { + var config config + errs := make([]error, 0, len(opts)) + for _, opt := range opts { + if err := opt.apply(&config); err != nil { + errs = append(errs, err) + } + } + if len(errs) > 0 { + return nil, errors.Join(errs...) + } + authToken := "" + if config.authToken != nil { + authToken = *config.authToken + } + readYourWrites := true + if config.readYourWrites != nil { + readYourWrites = *config.readYourWrites + } + encryptionKey := "" + if config.encryptionKey != nil { + encryptionKey = *config.encryptionKey + } + syncInterval := time.Duration(0) + if config.syncInterval != nil { + syncInterval = *config.syncInterval + } + return openSyncConnector(dbPath, primaryUrl, authToken, readYourWrites, encryptionKey, syncInterval, true) } type driver struct{} @@ -173,7 +203,7 @@ func (d driver) OpenConnector(dbAddress string) (sqldriver.Connector, error) { func libsqlSync(nativeDbPtr C.libsql_database_t) (Replicated, error) { var errMsg *C.char - var rep C.replicated; + var rep C.replicated statusCode := C.libsql_sync2(nativeDbPtr, &rep, &errMsg) if statusCode != 0 { return Replicated{0, 0}, libsqlError("failed to sync database ", statusCode, errMsg) @@ -198,10 +228,10 @@ func openRemoteConnector(primaryUrl, authToken string) (*Connector, error) { return &Connector{nativeDbPtr: nativeDbPtr}, nil } -func openEmbeddedReplicaConnector(dbPath, primaryUrl, authToken string, readYourWrites bool, encryptionKey string, syncInterval time.Duration) (*Connector, error) { +func openSyncConnector(dbPath, primaryUrl, authToken string, readYourWrites bool, encryptionKey string, syncInterval time.Duration, offline bool) (*Connector, error) { var closeCh chan struct{} var closeAckCh chan struct{} - nativeDbPtr, err := libsqlOpenWithSync(dbPath, primaryUrl, authToken, readYourWrites, encryptionKey) + nativeDbPtr, err := libsqlOpenWithSync(dbPath, primaryUrl, authToken, readYourWrites, encryptionKey, offline) if err != nil { return nil, err } @@ -309,7 +339,7 @@ func libsqlOpenRemote(url, authToken string) (C.libsql_database_t, error) { return db, nil } -func libsqlOpenWithSync(dbPath, primaryUrl, authToken string, readYourWrites bool, encryptionKey string) (C.libsql_database_t, error) { +func libsqlOpenWithSync(dbPath, primaryUrl, authToken string, readYourWrites bool, encryptionKey string, offline bool) (C.libsql_database_t, error) { dbPathNativeString := C.CString(dbPath) defer C.free(unsafe.Pointer(dbPathNativeString)) primaryUrlNativeString := C.CString(primaryUrl) @@ -321,15 +351,30 @@ func libsqlOpenWithSync(dbPath, primaryUrl, authToken string, readYourWrites boo if readYourWrites { readYourWritesNative = 1 } + + var offlineNative C.char = 0 + if offline { + offlineNative = 1 + } + var encrytionKeyNativeString *C.char if encryptionKey != "" { encrytionKeyNativeString = C.CString(encryptionKey) defer C.free(unsafe.Pointer(encrytionKeyNativeString)) } + config := C.libsql_config{ + db_path: dbPathNativeString, + auth_token: authTokenNativeString, + primary_url: primaryUrlNativeString, + read_your_writes: readYourWritesNative, + encryption_key: encrytionKeyNativeString, + offline: offlineNative, + } + var db C.libsql_database_t var errMsg *C.char - statusCode := C.libsql_open_sync(dbPathNativeString, primaryUrlNativeString, authTokenNativeString, readYourWritesNative, encrytionKeyNativeString, &db, &errMsg) + statusCode := C.libsql_open_sync_with_config(config, &db, &errMsg) if statusCode != 0 { return nil, libsqlError(fmt.Sprintf("failed to open database %s %s", dbPath, primaryUrl), statusCode, errMsg) } From e6c75996384c8947fa74a1eed8d0ef3e740b8e55 Mon Sep 17 00:00:00 2001 From: "Levy A." Date: Tue, 27 May 2025 18:36:27 -0300 Subject: [PATCH 3/6] feat: add test workflow --- .github/workflows/test.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..ba67a31 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,25 @@ +name: Test + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + test: + strategy: + matrix: + go-version: [ '1.20' ] + os: [ubuntu-latest, macos-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: ${{ matrix.go-version }} + - name: Build + run: go build -v ./... + - name: Test + run: go test -v ./... From e1893c9eb82c33af03803cc32538c824ce28dbd5 Mon Sep 17 00:00:00 2001 From: "Levy A." Date: Tue, 27 May 2025 18:55:27 -0300 Subject: [PATCH 4/6] feat: add sqld to the CI environment --- .github/workflows/test.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ba67a31..4170895 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,6 +12,7 @@ jobs: matrix: go-version: [ '1.20' ] os: [ubuntu-latest, macos-latest] + libsql-server-release: [libsql-server-v0.24.32] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 @@ -19,7 +20,27 @@ jobs: uses: actions/setup-go@v3 with: go-version: ${{ matrix.go-version }} + + - name: Install sqld + run: | + curl --proto '=https' --tlsv1.2 -LsSf https://github.com/tursodatabase/libsql/releases/download/${{ matrix.libsql-server-release }}/libsql-server-installer.sh | sh + echo "$HOME/.sqld/bin" >> $GITHUB_PATH + sqld --version + + - name: Start sqld server + run: | + sqld & + while ! curl -s http://localhost:8080/health > /dev/null; do + echo "Waiting for sqld..." + sleep 1 + done + echo "sqld is ready!" + - name: Build run: go build -v ./... + - name: Test + env: + LIBSQL_PRIMARY_URL: "http://localhost:8080" + LIBSQL_AUTH_TOKEN: "" run: go test -v ./... From 148b4cbbf9643e042338bf43e3277ec36ceb8868 Mon Sep 17 00:00:00 2001 From: "Levy A." Date: Wed, 28 May 2025 06:27:10 -0300 Subject: [PATCH 5/6] chore(ci): bump go version --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4170895..ba197a8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ jobs: test: strategy: matrix: - go-version: [ '1.20' ] + go-version: [ '1.24' ] os: [ubuntu-latest, macos-latest] libsql-server-release: [libsql-server-v0.24.32] runs-on: ${{ matrix.os }} From 550f5eafee58718b8bfb59bd0e28c2e45df19856 Mon Sep 17 00:00:00 2001 From: "Levy A." Date: Wed, 28 May 2025 06:31:19 -0300 Subject: [PATCH 6/6] feat(ci): add libsql-server version as workflow_dispatch input --- .github/workflows/test.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ba197a8..236f146 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,6 +5,12 @@ on: branches: [ main ] pull_request: branches: [ main ] + workflow_dispatch: + inputs: + libsql-server-release: + description: 'LibSQL Server Release' + required: true + default: 'libsql-server-v0.24.32' jobs: test: @@ -12,10 +18,10 @@ jobs: matrix: go-version: [ '1.24' ] os: [ubuntu-latest, macos-latest] - libsql-server-release: [libsql-server-v0.24.32] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 + - name: Set up Go uses: actions/setup-go@v3 with: @@ -23,7 +29,7 @@ jobs: - name: Install sqld run: | - curl --proto '=https' --tlsv1.2 -LsSf https://github.com/tursodatabase/libsql/releases/download/${{ matrix.libsql-server-release }}/libsql-server-installer.sh | sh + curl --proto '=https' --tlsv1.2 -LsSf https://github.com/tursodatabase/libsql/releases/download/${{ github.event.inputs.libsql-server-release || 'libsql-server-v0.24.32' }}/libsql-server-installer.sh | sh echo "$HOME/.sqld/bin" >> $GITHUB_PATH sqld --version