Flow
What happens to each open run at startup
1Scheduled or replay run that never started
Marked as interrupted.
2Scheduled run with only partial pages
Marked as interrupted. The bookmark never moved.
3Scheduled run with at least one complete page and no failed pages
Marked as succeeded.
4Replay run
Always marked as interrupted.
5Manual run
Left open so it can pick up where it stopped.
Purchase orders got one rule in the archive's resume check, and everything else got a looser one. Purchase orders had to reach the end to count as done, while any other source was done after one good page.
That was fine while purchase orders were the only source I read in pages. Then I moved the customer list onto pages too.
Reading a source in pages
My archive copies the stores' sales data into my own database and keeps each raw response so I can check it later. The customer list used to come back in one big response, and a big enough list would hit the size cap and get dropped. So customers moved to paged reads, and the paging loop became a setting any source can use. The first run copies everything, one page at a time. Later runs only ask for recent changes.
The loop has clear rules: a page with rows is marked partial. Only an empty page, the source saying it has nothing left, is marked complete, and only that page moves the bookmark the next run starts from. A repeated page, or too many pages, ends the run as a failure.
The code around the loop didn't follow those rules.
One good page
If the worker restarts in the middle of a manual run, it checks which sources are already done for each store and skips them. For anything but purchase orders, one good page was enough to count as done. So a customer copy that got a few pages in before a restart would be skipped, and I don't think anything would have flagged it. A later run might have started it over, since the bookmark never moved, but I wasn't counting on that.
The final empty page's status was also left blank, and an old test hid that by treating "missing" as "complete". Now the last page always says complete, and every source gets the same check.
A pair now counts as settled whenever its status isn't partial.
A failed page still counts as done here, so a restart won't retry it. I'm not sure I like that.
A timer standing in for evidence
Scheduled runs had a different cleanup. On startup, the worker failed any run that had been going longer than a set time. That could fail a run that had finished, and it ignored scheduled runs that were queued and never started.
The timer is gone. On startup, every scheduled or replay run that's still open gets closed. A scheduled run is marked succeeded only if it has at least one complete page and no failed pages, and everything else, replays included, is marked as interrupted. Manual runs are left alone so they can pick up where they stopped. This seems to assume only one worker is running.
Reading while it's being written
The console pages through the archive with a cursor, and a request can also name two times: the moment you're viewing and how much the archive knew by then. The console never sent the second one before. If those times change between requests, page two can come from a different moment than page one. Now the console keeps both times from the first page, shows them, and sends them back every time you load more.
Taking turns
The scheduler used to check sources in a fixed order and stop at a cap, so the sources at the top could hog every turn. Now it rotates through all of them, the cap went up, and the rotation resets whenever the worker restarts.
One more: the current-stock source only lists items that are in stock, so an empty list there can be right. It no longer counts against archive health.