Repository navigation
Conversation
… worker (STA-9122) Before: opening the Automations page read Hermes's state.db with node:sqlite on the main thread: once per Hermes job for the run-count badge, and once per run when a page of runs was shown, each run opening the database again. After: the two raw SQLite reads are pure readers in foreign-sqlite-readers/readers/hermes-session-runs.ts, run only on the worker. Mapping rows into runs, merging with output files, and the run-count cache stay on the main thread. - A page of runs is one hermesSessionRuns request carrying every session id, so state.db opens once per page instead of once per run. - Failure behaviour per call site is unchanged: the run-ref read resolves to [] (count and list fall back to output files), and a run the batch could not read hydrates from its output file or ref, as a null per-run read did. The existsSync guard stays on the main thread, so no thread starts without state.db. - Each kind has its own lane with the default 30 s idle teardown. Not changed: src/relay/ keeps its own Hermes reader (hermes-session-run-database.ts) and shares none of these functions. orcad does not bundle hermes-cron-output. Tests: readers against a real state.db (job filter with an escaped LIKE, newest first, message order, missing runs left out, missing/corrupt throw), dispatch routing, client (one request per page, failure values, dedupe per id set), and the page reader (one batched call, no call without state.db or for counts, output-file fallback on worker failure).
Contributor
There was a problem hiding this comment.
ℹ️ Minor suggestions only — one weak test assertion.
Reviewed changes
- Hermes's
state.dbreads moved onto the shared worker:hermes-cron-output.tsnow callsreadHermesSessionRunRefRows/readHermesSessionRunsthroughforeign-sqlite-reader-spawn.tsinstead of opening the DB synchronously; the raw SQL lives inreaders/hermes-session-runs.ts, with parsers/failure values inhermes-session-runs-result.tsand two new request kinds wired through the protocol, dispatch, and client. - One
state.dbopen per page:readHermesCronOutputRunsPagecollects the page's session ids and reads them in a single batched request, hydrating from aMap; a missing or failed run still falls back to its output file or ref, preserving the prior per-run failure behaviour. - Tests: reader SQL/throws, dispatch routing, client batching + failure + in-flight sharing, and page-level failure fallbacks.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
| const { readHermesCronOutputRunsPage } = await loadReader() | ||
| const withRefs = await readHermesCronOutputRunsPage('job-1', { page: 1, pageSize: 25 }) | ||
| expect(withRefs.runs.length).toBeGreaterThan(0) | ||
| expect(withRefs.runs.every((run) => run !== null)).toBe(true) |
Contributor
There was a problem hiding this comment.
This assertion can never fail: hydrateHermesRunRef always falls back to ref, so no entry is ever null, and the length > 0 above only proves the array is non-empty. Pin the concrete run the failure path should still produce, otherwise this half of the test cannot catch a regression in the fallback.
Suggested change
| expect(withRefs.runs.every((run) => run !== null)).toBe(true) | |
| expect(withRefs.runs).toMatchObject([{ id: 'job-1:2026-05-15_09-02-00.md' }]) |
Contributor
Author
|
Closing: low value now that the scope is narrowed. It only affects Hermes users when they open the Automations page. See #24649. |
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

ELI5
When you open Orca's Automations page, Orca reads Hermes's database to list when each scheduled job ran. That read ran on the thread that draws Orca's window, once per run. This PR moves it to a background thread and reads a whole page of runs in one go.
What Changed
hermes-cron-output.tsopened Hermes'sstate.dbsynchronously on the main thread, andhydrateHermesRunRefopened it once per run throughPromise.all.foreign-sqlite-readers/readers/hermes-session-runs.ts.[], and a run the batch can't read falls back to its output file or ref.Why
Same approach as #24603: reuse the shared worker and never fall back to the main thread. The
src/relay/Hermes reader runs on remote hosts and shares none of these functions, so it's untouched.Linked Issue
Related to #24360. Stacked on #24649.
Visual Proof
N/A. No UI change; the Automations page shows the same data.
Testing
pnpm tcpasses.oxlintandcheck:code-quality:changedpass.pnpm build:orcadpass.Review
Agent skill upstream boundary
Notes
A page currently uses two short-lived reader threads, one per read kind. Sharing one Hermes thread would need the reader class to handle more than one result type, which wasn't worth it here.
Checklist
N/Awith reason for visual proof