Repository navigation
Conversation
Preserve PUT upload and reconciliation behavior while incorporating GET diagnostics, fixture response delays, request logs, and Readium-weighted remote resume. Share the weighted model between downloads and uploads to keep percentages consistent. Resolve documentation conflicts with Unix command examples. Validation: 474 repository tests, 20 fixture server tests, 83 final focused tests, targeted lint, and main/reader Webpack builds passed.
Log the resume heuristic before suppressing matching local and remote positions. Include compared progression values, position equality, timestamp freshness, and local movement alongside the locators and dialog decision.
|
Extend the existing OPDS progression GET support with authenticated PUT uploads. Local reading-position changes are synchronized remotely after initial retrieval and any resume dialog have been resolved. |
Restore the GET branch's locator comparison, timestamp-based resume policy, and diagnostics. Remove matching-position prompt suppression and its regression test while retaining PUT retrieval gating, dialog reconciliation, and weighted upload mapping.
Keep one pending update, debounce timer, and retry/authentication state per publication. Send only from the locked reader, replace pending state on ownership handoff, and ignore stale upload outcomes. Remove forced-shutdown coordination and close-time upload draining. Cancel pending updates when the owning reader closes, retain lightweight per-reader GET/dialog state, and cover ownership handoff and remote-resume suppression with regression tests.
Replace the synchronization coordinator with minimal Redux reader state and a five-second trailing saga debounce. Read the latest locator at expiry, recheck reader ownership and GET/dialog readiness, and suppress remote-applied navigation. Remove upload queues, retry state, authentication forwarding and replay, and timestamp rebasing. Log PUT failures without replay and cancel debounce work on close. Preserve the GET resume policy and add reducer/saga regression coverage.
flowchart TB
subgraph GET["GET — Retrieve remote progression"]
G1["Open reader<br/>Block uploads"] --> G2["Retrieve and validate remote progression"]
G2 --> G3["Compare remote and local positions<br/>Offer resume when appropriate"]
G3 --> G4["Resolve resume decision<br/>Keep local position or navigate to remote position"]
G4 --> G5["Allow uploads<br/>Skip uploading accepted remote navigation"]
end
subgraph PUT["PUT — Upload local progression"]
P1["Local reading progression changes"] --> P2["Verify reader ownership<br/>Restart 5-second debounce"]
P2 --> P3["Check GET/resume is complete<br/>Reader still owns lock<br/>Publication is eligible"]
P3 --> P4["Read latest progression<br/>Add current timestamp and device identity"]
P4 --> P5["Send authenticated PUT"]
P5 --> P6["Validate response<br/>Log failures without scheduled retry"]
P7["Reader closes"] --> P8["Cancel pending debounce<br/>No final upload"]
end
G5 -. Upload permission .-> P3
style GET fill:#eef5ff,stroke:#3973ac
style PUT fill:#eef8ef,stroke:#42854a
|
|
The PUT feature uploads the latest reading progression after movement, once the initial GET/resume decision is complete.
Algorithm flowchartflowchart TD
L["Locator update received"] --> M{"Current reader<br/>and publication match?"}
M -- No --> STOP["Stop processing this update"]
M -- Yes --> N["Convert locator to progression<br/>between 0 and 1"]
N --> O{"Conversion succeeded?"}
O -- No --> STOP
O -- Yes --> P["Compare with previous progression<br/>and accepted remote progression to skip<br/>Store new progression"]
P --> Q{"Matches accepted remote<br/>progression to skip?"}
Q -- Yes --> R["Clear progression to skip<br/>Cancel pending debounce"]
R --> STOP
Q -- No --> S{"Previous progression exists,<br/>progression changed,<br/>and reader owns the lock?"}
S -- No --> STOP
S -- Yes --> T["Cancel pending debounce<br/>Start a new 5-second trailing debounce"]
T --> U{"Locator change<br/>before expiry?"}
U -- Yes --> L
U -- No --> V{"Reader still owns lock,<br/>ready = true,<br/>and no resume dialog pending?"}
V -- No --> SKIP["Skip upload"]
V -- Yes --> W{"EPUB with an OPDS<br/>progression URL?"}
W -- No --> SKIP
W -- Yes --> X["Read latest locator from Redux<br/>Convert to progression"]
X --> Y{"Valid progression?"}
Y -- No --> SKIP
Y -- Yes --> Z["Retrieve device ID and name"]
Z --> AA{"Still locked, ready,<br/>and no resume dialog pending?"}
AA -- No --> SKIP
AA -- Yes --> AB["Build JSON payload"]
AB --> AC["Authenticated PUT"]
AC --> AD{"200 or 201 with<br/>valid response document?"}
AD -- Yes --> AE["Upload complete"]
AD -- No --> AF["Log failure<br/>No scheduled retry"]
AE -. Later movement .-> L
AF -. Later movement may retry .-> L
SKIP -. Later movement .-> L
CLOSE["Reader closes"] --> CANCEL["Cancel pending debounce<br/>No final upload"]
|
|
The main risks are:
The most visible consequence is lost synchronization when the reader closes quickly, a request fails, or movement occurs before reconciliation finishes. |
Tests:Start the server: node projects/opds-progression/server.mjsAdd Inspect request counters and uploaded JSON at: curl http://127.0.0.1:4873/__test/stateBasic upload and debounce
GET and resume reconciliationcurl --request PUT http://127.0.0.1:4873/__test/state \
--header 'Content-Type: application/json' \
--data '{"progression":0.75,"modified":"2040-01-02T03:04:05.000Z"}'
Retrieval failurecurl --request PUT http://127.0.0.1:4873/__test/state \
--header 'Content-Type: application/json' \
--data '{"delayMs":8000}'
PUT errors and recovery
Reader ownership and closing
Progression mapping
|
# Conflicts: # src/common/models/opdsProgression.ts # src/renderer/reader/opdsProgression.ts
# Conflicts: # src/main/network/http.ts # test/main/network/httpPutWithAuth.test.ts
|
The PUT implementation now uses a five-second trailing debounce per publication. Locator events from any reader window showing that publication reset the same timer; the latest event supplies the progression uploaded by PUT. Different publications debounce independently. PUT no longer depends on reader locks or main-process session snapshots. It also does not wait for GET or the resume dialog to complete. A received position can still upload if its reader closes during the debounce. |
flowchart TD
A[Main receives setLocator] --> B{Renderer sender and valid window?}
B -- No --> X[Ignore event]
B -- Yes --> C{Window belongs to sender's publication?}
C -- No --> X
C -- Yes --> D{EPUB with an OPDS progression endpoint?}
D -- No --> X
D -- Yes --> E[Convert locator to publication progression]
E --> F{Valid progression?}
F -- No --> X
F -- Yes --> G[Cancel pending debounce for this publication]
G --> H[Start a new five-second timer with this progression]
H --> I{Another valid event before expiry?}
I -- Yes --> G
I -- No --> J[Look up the current progression endpoint]
J --> K{Endpoint still exists?}
K -- No --> L[Clear pending task]
K -- Yes --> M[Read device identity and locale]
M --> N[PUT progression with current timestamp]
N --> O{Successful?}
O -- No --> P[Log failure]
O -- Yes --> L
P --> L
The algorithm is:
All readers of one publication share the timer. Different publications have independent timers. There is no upload lock, GET/resume gate, session-snapshot dependency, or automatic retry. Closing a reader does not cancel an already scheduled upload. |
GET’s existing resume policy remains unchanged. HTTP credential handling stays in the networking layer.