Repository navigation
refactor(engine): one replay loop for every native host - #83
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
ℹ️ No critical issues. Two rough edges inline: the round limit no longer matches the loader's, and the Postgres host still reports a lost connection as a database refusal.
Reviewed changes
I reviewed the new core replay module, the three oracle hosts ported onto it, and the rebuilt artifacts.
engine/core/src/replay.rs:AnswererandAsyncAnswererseparate a host failure (outerErr) from a database refusal (innerErr).runandrun_asynccallDb::unbundleand thenDb::roundon the engine's stack, asapi::calldoes.AnswerCacheports the loader's cache, with the same 60 s and 5 s TTLs and failures never kept.- Oracle hosts: Postgres, SQLite and MySQL now each implement one of the traits. The JSON request and response loops,
engine()andengine_call()are gone, and every statement gets a freshAnswerCache. - Artifacts: all three
engine.wasmfiles were rebuilt, since core's fingerprint changed.
I checked that extension::unbundle is idempotent (it uses or_insert), so keeping the unbundled answers in answers from one round to the next is safe.
claude-opus-5-5 | 𝕏
caecb2e to
d95f950
Compare
A host that links the engine natively wrote its own loop around each round and its own answers. replay::run and run_async run the loop over an Answerer, on the engine's stack, with an answer cache like the loader's. The oracle's three hosts now answer through it.
A describe that never reached the Postgres server now ends the replay as the host's failure, as the MySQL host's does, rather than reading as a refusal.
There was a problem hiding this comment.
✅ No new issues found. Both points from the previous review are fixed.
Reviewed changes
Since the previous Pullfrog review, the branch was rebased onto 3a14b0a and gained d95f950, which I reviewed here.
- Round limit:
replay::ROUNDSis now 16, the same bound as the replay loop insrc/engine-core.ts. Its doc comment names that file, so the oracle no longer passes statements the loader would give up on. - Postgres host failures:
pg_errornow returnsOption<DbError>and givesNonefor an error that never reached the server.PgAnswers::describeturns thatNoneinto the outerErr, so a lost connection ends the replay. The MySQL host already did this. Server refusals still carry the same message, code and position as before. - Artifacts: all three
engine.wasmfiles were rebuilt, andtests/fingerprint.test.tspasses for each of them atd95f950.
claude-opus-5-5 | 𝕏
d95f950 to
f3a37e0
Compare

A host that links the engine natively has to drive its replay itself: call a round, answer every describe and catalog query it names, call again until the analysis comes back. The oracle did that three times, once per database, each with its own loop over the JSON entry point. This puts the loop in the core crate.
What changes
engine/core/src/replay.rsAnswerer(a client that blocks) andAsyncAnswerer(one whose answers are futures) each answer a describe and a catalog query. A database's refusal, such as an unknown column, is the innerErr, an answer the engine reads as it does today. The host's own failure, such as a lost connection, is the outer one, and ends the replay.runandrun_asyncrun each round on the engine's stack, asapi::callruns one, and give up after 64 rounds.AnswerCacheis the loader's cache in Rust. Needs are named by what they ask, so a later statement reuses an answer: a whole-database answer for 60 s, any other for 5 s, and a failure never.tokio-postgres), SQLite (rusqlite) and MySQL (mysql_async) hosts areAnswerers now. They build the same JSON as before and decode it into each database's typed describe. The JSON helpers they used are gone.engine.wasmartifacts are rebuilt, since their fingerprints hash core's sources. The wasm entry points don't use the new module.Verified
--strict-coverage: 116 cases, 0 failed, so every analysis through the new loop matches itsexpected.txt.cargo build --workspace --all-targetswith no warnings, the engine's tests, the artifacts' fingerprints, and the loader's typecheck and tests (226, none skipped).