Add asynchronous historical import jobs - #721
Conversation
roborev: Combined Review (
|
041d043 to
19a8bec
Compare
roborev: Combined Review (
|
19a8bec to
ad67f07
Compare
roborev: Combined Review (
|
ad67f07 to
e83dba5
Compare
roborev: Combined Review (
|
|
This seems a bit excessive, most of the machinery needed for this was already present. |
Historical imports already run through the sync system, but the API kept a second in-memory job queue and progress model. That duplicated lifecycle and counter logic, lost status on restart, and made one API route much larger than the behavior required. Store the operation status with its sync runs and let the existing operation gate control concurrency. Imports now use the same durable state and shutdown rules as other sync work, with no separate queue or retention policy. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
The import progress test crossed the repository's limit for direct testify package calls. The regular lint command did not catch that rule, but the separate CI checker rejected the branch after all Go tests passed. Use local assertion objects in that test so the checker and the test suite enforce the same repository convention without changing test behavior. Generated with Codex Co-authored-by: Codex <noreply@openai.com>
This comment has been minimized.
This comment has been minimized.
Starting a second sync for one source used to fail the first run and let the replacement proceed while the original worker could still be writing. Reject the second start instead. A stopped worker now leaves a failed, resumable checkpoint, and the next attempt resumes that checkpoint in a new run. Historical import creation now reports an active sync as a conflict. It also waits for its first durable operation row without the ordinary request deadline, and cancellation records the operation as failed rather than done. Addresses the three findings reported in the same-head roborev-ci comment: kenn-io#721 (comment) Generated with Codex Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
A durable running row cannot prove that its worker is still alive. Rejecting new work from that row alone can leave a source blocked forever after a hard process exit. Hold one operating-system or database-session lock for each active source. Live workers cannot overlap, while process exit releases ownership without a lease timeout. The next worker records the abandoned run as failed and keeps its checkpoint available for resumption. Addresses the stale-worker finding reported at: kenn-io#721 (comment) Generated with Codex Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
|
reviewing |
A running database row cannot prove that its worker still owns the source. Checking that row before the process lock prevented restart after a crash, and releasing the lock between Gmail recovery phases allowed another worker into the same source. Keep one source owner for the complete sync invocation. Status reads use that same ownership check to fail abandoned runs and operations, while a live owner continues to reject every competing sync. Addresses the three findings reported at: kenn-io#721 (comment) Generated with Codex Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
A bounded Gmail import cannot establish the incremental baseline for mail it did not enumerate. Preserve the prior source cursor for partial runs, and bind resumable checkpoints to the exact request that created them. IMAP also has provider state to save after message enumeration. Keep the same source owner through that final write so no second worker can start from stale folder metadata. Addresses the three findings reported at: kenn-io#721 (comment) Generated with Codex Co-authored-by: Codex <noreply@openai.com>
roborev: Combined Review (
|
|
@mariusvniekerk please don't make more fixes here because there is a need to reconcile #721 vs #722 |
|
rebasing |
What changed
POST /api/v1/importsfor bounded Gmail and IMAP historical imports.GET /api/v1/imports/{job_id}for durable running, done, and failed status with progress and final counters.The create request returns after the sync has written its durable operation row. That short wait is exempt from the ordinary HTTP request deadline. Cancellation records the operation as failed.
One source lock stays held for the complete sync invocation. This includes Gmail history recovery and the final IMAP mailbox-state write. It releases when the invocation completes, fails, or its process exits. Status reads use the same lock to distinguish a live worker from abandoned database rows. When no worker owns the lock, msgvault marks the abandoned run and operation as failed and preserves compatible checkpoints for the next sync.
Why
Historical imports were only available through the command line. The daemon now exposes the same bounded
sync-fullpath while keeping status in the existing sync tables. Command-line, scheduled, and API syncs share one concurrency rule without a separate job system.Closes #378
Usage
Create an import:
Read its status: