You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(api): add Turso/libSQL backend for heartbeat repositories (NdoleStudio#886)
* docs: add design spec for Turso/libSQL heartbeat backend
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(api): add Turso/libSQL backend for heartbeat repositories
Add alternative HeartbeatRepository and HeartbeatMonitorRepository
implementations using libSQL (Turso) via database/sql.
Switchable via HEARTBEAT_DB_BACKEND=turso env var.
Requires TURSO_DATABASE_URL and TURSO_AUTH_TOKEN when enabled.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(api): add context timeout to DeleteAllForUser in libSQL repos
Also update design spec to reference correct package
(libsql-client-go, not go-libsql).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs: add design spec for hedging repository pattern
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(api): add hedging repositories for heartbeat dual-write
Add composite repositories that write to GORM (primary) and Turso
(secondary) with fail-open semantics. Secondary failures are logged
and counted via OTel metric. Activated via HEARTBEAT_DB_BACKEND=hedging.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* test(api): add hedging heartbeat integration test with Turso
Add sqld (libSQL server) to test docker-compose. Integration test
stores a heartbeat via the hedging repository and reads it back from
both PostgreSQL (primary) and Turso/libSQL (secondary) to verify
dual-write. Gated by TEST_DATABASE_URL and TEST_TURSO_DATABASE_URL
environment variables.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* ci: run hedging integration test in GitHub Actions
Wait for sqld health before running tests. Set TEST_DATABASE_URL and
TEST_TURSO_DATABASE_URL env vars pointing to docker compose services.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* test: add black-box heartbeat integration test with hedging
Store a heartbeat via POST /v1/heartbeats and read it back via the
Index endpoint. The API is configured with HEARTBEAT_DB_BACKEND=hedging
so it dual-writes to both PostgreSQL and Turso/sqld. The test only
interacts with the HTTP API, no implementation details exposed.
- Add sqld dependency to API service in docker-compose
- Add HEARTBEAT_DB_BACKEND, TURSO_DATABASE_URL to .env.test
- Remove repo-level integration test in favor of black-box test
- Keep sqld health wait in CI workflow
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(tests): remove curl-based healthcheck from sqld container
The ghcr.io/tursodatabase/libsql-server:latest image is based on
debian:bullseye-slim and does not include curl. The health check was
always failing, causing the container to be reported as unhealthy and
blocking the api service from starting.
Instead, use service_started condition since sqld starts nearly
instantly and the workflow already has an explicit health polling step
that checks sqld readiness from the host before running tests.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* refactor(api): combine Turso URL and auth token into single DSN env var
Replace TURSO_DATABASE_URL and TURSO_AUTH_TOKEN with a single
TURSO_DATABASE_DSN that contains the full connection string including
the authToken query parameter. This simplifies configuration and
aligns with standard DSN conventions.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(tests): retry heartbeat store to wait for async phone-API-key association
The phone API key gets its phone numbers associated asynchronously via
the PhoneUpdated event. In the emulator queue mode used by CI, this
event is processed in a background goroutine. The heartbeat test was
calling the store endpoint immediately, before the async event had
associated the phone number with the API key, resulting in a 401.
Add a retry loop (up to 15s) consistent with other integration tests
that use polling patterns (waitForFCMPush, waitForWebhookEvents).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(api): handle rows.Err() and uuid.Parse errors in libsql repositories
- Add rows.Err() check after iteration loop in Index to catch
network errors or timeouts that silently end iteration
- Propagate uuid.Parse errors in scanHeartbeat and scanHeartbeatRow
instead of discarding them with _
- Propagate uuid.Parse errors in scanHeartbeatMonitorRow for both
monitor ID and phone ID fields
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* refactor(api): make scan functions methods on libsql repository structs
Convert package-level functions scanHeartbeat, scanHeartbeatRow, and
scanHeartbeatMonitorRow into methods on their respective repository
structs for consistency with the repository pattern.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Remove uneeded log
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
0 commit comments