Skip to content

Add sync worker, HTTP API and sync server tests - #2

Merged
evgTSV merged 6 commits into
mainfrom
sync-service
Oct 24, 2026
Merged

evgTSV merged 6 commits into
mainfrom
sync-service

Conversation

@evgTSV

@evgTSV evgTSV commented Oct 24, 2026

Copy link
Copy Markdown
Owner

Summary

  • Sync service: logs in, syncs the collection and logs the final SyncStatus. rslib errors are classified into SyncFailed (invalid credentials, aborted, network, server rejected, full sync required, backend/native failures). Follows server redirects.
  • Sync worker: commands are applied to the local collection right away and answered through the message's reply; one sync runs when the debounce window (Ankit:SyncDebounceTime) closes. Handlers only see the result of their command.
  • HTTP API
    • POST /decks { "name" }
    • POST /notes { "deckId", "noteTypeId", "fields", "tags"? }
    • POST /sync/full { "direction": "upload" | "download" }: resolves FullSyncRequired, which the first sync of a non-empty collection always hits
  • Validation and errors: DataAnnotations on the DTOs. Missing, null and invalid fields return 422 with per-field errors in camelCase. Failed commands return 422, failed full syncs return 502, and other errors go through a JSON error middleware.
  • Config: appsettings.json with the Ankit and SyncServer sections. Credentials are left empty, so set them with SyncServer__Username / SyncServer__Password.

Tests

Ankit.Server.Tests runs the sync service against a real Anki sync server started with Testcontainers.

  • Image: built from Anki's example Dockerfile at the Anki tag in paket.dependencies. Cargo is limited to 4 jobs because a build with the default parallelism ran out of memory.
  • Build time: the first build takes about 7 minutes; after that Docker's cache makes it quick.
  • Skipping: the tests are skipped when Docker with Linux containers isn't available. On CI that means they run on Ubuntu and are skipped on Windows and macOS.

Results:

  • 5/5 tests passed locally.
  • I also ran the app manually against the containerized server: validation errors, deck creation, the background sync reporting FullSyncRequired FullSync, then /sync/full upload and download.
  • The deck and note endpoints don't have automated tests yet.

Notes

  • On a fresh deployment, background syncs fail with FullSyncRequired until someone calls /sync/full once.
  • The 422 for null fields depends on matching FSharp.SystemTextJson's error message text, so re-check it after upgrading that package.

🤖 Generated with Claude Code

evgTSV and others added 6 commits October 24, 2026 20:10
Commands are applied to the local collection right away and answered
through the message's reply, then pushed to the sync server once the
debounce window closes. Sync failures are classified and logged by
AnkiSyncService along with the final sync status.

Request bodies are bound with FSharp.SystemTextJson and validated with
DataAnnotations; missing, null and invalid fields come back as 422 with
per-field errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Defaults for the Ankit and SyncServer sections, listening on port 5000
to match compose.yaml. Sync credentials are left empty and are meant to
come from environment variables or user-secrets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
POST /sync/full with "upload" or "download" resolves FullSyncRequired,
which the first sync of a non-empty collection always runs into. The
full sync goes through the worker like the other commands, media is
synced right after it, and failures come back as 502.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The server is built with Testcontainers from Anki's example Dockerfile
at the Anki tag the rslib bindings use, with cargo limited to 4 jobs so
the build doesn't run out of memory. The tests skip without Docker
running Linux containers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Verify-Format runs Fantomas, a local tool, but the verify job never ran
"dotnet tool restore", so the check failed before Fantomas started.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@evgTSV
evgTSV merged commit fc7145f into main Oct 24, 2026
4 checks passed
@evgTSV
evgTSV deleted the sync-service branch October 24, 2026 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant