KomicK
Komic

Sync behaviour (on a Komga compatible server)

Hello, I've been working on my own server ComicRevolution (originally compatible with ComicRack devices, but I have added compatibility with Komga) Right now I can browse, read, sync progress with Komga clients. But I noticed a lot of queries when syncing from Komic. **First Sync on a large library stops partway ("Sync couldn't be completed") with a Komga-compatible server** **Setup:** Komic 71 (iOS). The server is a self-hosted Komga-compatible API (not Komga itself), with one library of ~50k books. The account has ~40k books with read progress. **What Sync sends** (captured on the server): ``` POST /api/v1/books/list?page=N&sort=readProgress.readDate,desc {"condition":{"allOf":[{"readStatus":{"operator":"is","value":"IN_PROGRESS"}}]}} <- page 0 only {"condition":{"allOf":[{"readStatus":{"operator":"is","value":"READ"}}]}} <- pages 0, 1, 2, ... ``` At the default page size of 20, `READ` currently has `totalElements: 39816` and `totalPages: 1991`. **What happens:** Komic pages through `READ` one page at a time and usually stops long before the last page, at a different page each time. Every response is HTTP 200 and takes ~0.18 s (p95 ~0.2 s): | Run | Last page requested | Duration | How it ended | |---|---|---|---| | 1 | 707 | ~139 s | 200, then no further request | | 2 | 542 | ~105 s | 200, then no further request; app shows "Sync couldn't be completed" | | 3 | 312 | ~57 s | request cancelled by the client within a second | | 4 (app in the foreground the whole time) | 533 | ~107 s | 200, then no further request | | 5 | 1111 | ~4 min | request cancelled by the client (the phone screen turned off) | | 6 | 269 | ~50 s | 200, then no further request | | 7 | **1990 (`last: true`)** | ~7 min | **completed: "Everything up to date"** | Each run that stopped early ended after a normal full page (`content` 20, `last: false`). Earlier, when the server took ~1 s per page, runs stopped even sooner (pages 5–105). **What changed on the server before run 7:** before that run, `READ` could include a few books whose `readProgress.completed` was `false` (the server counted a book on its second-to-last page as read). From run 7 onwards, every book in `READ` has `completed: true`. Run 7 is the first run that went through to the end. That may be a coincidence: in earlier runs, Komic went straight past pages containing such books. **After the first complete run:** once run 7 had finished, later syncs (8 in ~30 s) each sent only page 0 of `IN_PROGRESS` and page 0 of `READ` and finished in ~0.3 s with "Everything up to date". It looks like Komic keeps a checkpoint from the last successful sync and stops once `readDate` is older than it. If so, the long walks above were all first syncs, because no sync had ever finished. That means the problem mainly hits the first sync on a large library, and any later sync that follows a failed one. **Also observed:** Komic requests every `READ` page about twice: 4,372 responses for 1,991 pages in run 7. The two copies of each request differ only in JSON key order (`{"operator":"is","value":"READ"}` and `{"value":"READ","operator":"is"}`), so it looks like two fetchers running in parallel. **Expected:** A first sync walks to `last: true`, or it resumes where it stopped instead of starting again from page 0, and it doesn't report a failure part of the way through. **Questions:** 1. Is there a time limit or page limit on Sync? A first sync over ~2,000 pages needs ~7 minutes at ~0.2 s per page, and most of ours stopped after 1–4 minutes. 2. Does Komic check the books it receives, for example a book in `READ` whose `readProgress.completed` is `false`, and stop or retry when they don't match? 3. Is the page-0-only behaviour after a successful sync a `readDate` checkpoint, as it looks? For the first sync, could Komic use a larger `size`, or keep the pages it already fetched so that a retry resumes instead of starting again from page 0? 4. Is fetching every page twice intended? 5. Is there a way to export Komic's sync log to see why it stops? I can share more captures (request/response timings, sample response bodies) if useful.
PendingPending