Skip to content

Commit a600fc9

Browse files
mo4islonaclaude
andauthored
fix(portal): persist discovered factory children to the sync store (#2)
The portal historical sync discovered factory children with its wide scan but wrote them only to the in-memory childAddresses map — never to the sync store. Core marks requiredFactoryIntervals cached after every interval and, on startup, loads children ONLY from the store (no re-derivation from logs). So a single uninterrupted run worked, but any restart/crash-resume of a factory app loaded an empty child set against already-cached factory intervals — discovery never re-ran and every factory-child event was silently skipped. Fix: queue newly discovered children and flush them via syncStore.insertChildAddresses inside syncBlockRangeData — the same transaction core commits with insertIntervals, so "factory interval cached ⇒ its children are in the store" is atomic. The flush is scoped to children whose creation block falls within the current interval, leaving the rest queued for their owning interval. Grabbing the whole cross-interval queue would commit one interval's children in another interval's transaction and, under core's concurrent per-interval transactions, could lose a child if that transaction rolled back after a lower interval had committed as cached (restart re-discovery is floored at the lowest uncached factory interval and would never rescan it). This mirrors stock sync-historical's per-interval child set. A failed flush restores the queue and fails the interval loud (core rolls back). Tests: persistence in the same syncBlockRangeData call; interval-scoped flush (fails against a whole-queue flush, verified); loud failure + re-flush; post-flush insertLogs failure rejects loud; restart seeded only from the store; live re-discovery de-dup. Also: delete the orphaned packages/portal-sync/src/historical.ts prototype (unimported duplicate of the live engine); fix the identical noAssignInExpressions in portal-realtime.ts; add repo code-style rules (CLAUDE.md + biome useSingleVarDeclarator). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 70f48cc commit a600fc9

6 files changed

Lines changed: 684 additions & 233 deletions

File tree

CLAUDE.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# portal-ponder — contributor & agent rules
2+
3+
Fork of Ponder's historical sync that backfills from SQD Portal. The Portal layer lives in
4+
`portal/`; `scripts/sync-upstream.sh` grafts it onto a pinned ponder checkout to build/test.
5+
6+
## Code style
7+
8+
These are enforced expectations for all TypeScript in this repo. Some are checked by Biome
9+
(`biome check .`); the rest are conventions Biome can't express — follow them anyway.
10+
11+
1. **Braces on control-flow bodies.** An `if`/`for`/`while` whose body is a real statement
12+
uses `{ }` — never a braceless multi-line body.
13+
- **Exception:** a single-statement guard on one line stays braceless:
14+
`if (!x) continue;` / `if (!x) break;` / `if (!x) return;`.
15+
16+
2. **One variable per declaration.** Never `const a = 1, b = 2;` — one `const`/`let` each.
17+
*(Biome flags this — `style/useSingleVarDeclarator`, currently `warn` while pre-existing
18+
violations get cleaned up; bump to `error` once the repo is swept.)*
19+
20+
3. **Let guards and returns breathe.** Blank line *after* a guard clause
21+
(`if (...) continue;` / `break;`) when code follows, and a blank line *before* a `return`.
22+
23+
4. **No assignment used as an expression.** No `(m ??= new Map()).set(...)` or
24+
`while ((n = idx()) >= 0)` — expand into explicit statements.
25+
*(Biome-enforced: `suspicious/noAssignInExpressions`.)*
26+
27+
Match the surrounding code otherwise. `npm run lint` runs `biome check .`; `npm run lint:fix`
28+
applies the safe fixes.
29+
30+
## Tests
31+
32+
The Portal unit tests run inside the grafted ponder tree, not from this repo root:
33+
`scripts/sync-upstream.sh <ponder-version> --test` (config: `portal/vite.portal.config.ts`,
34+
files `portal/*.test.ts`). Keep every `portal/*.test.ts` green before pushing.

biome.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
"linter": {
1717
"enabled": true,
1818
"rules": {
19-
"preset": "recommended"
19+
"recommended": true,
20+
"style": {
21+
"useSingleVarDeclarator": "warn"
22+
}
2023
}
2124
},
2225
"javascript": {

packages/portal-sync/src/historical.ts

Lines changed: 0 additions & 216 deletions
This file was deleted.

portal/portal-realtime.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,14 @@ export async function* streamHotBlocks(
161161
const { done, value } = await reader.read();
162162
if (done) break;
163163
buf += dec.decode(value, { stream: true });
164-
let nl: number;
165-
while ((nl = buf.indexOf("\n")) >= 0) {
164+
for (;;) {
165+
const nl = buf.indexOf("\n");
166+
if (nl < 0) break;
167+
166168
const line = buf.slice(0, nl);
167169
buf = buf.slice(nl + 1);
168170
if (!line) continue;
171+
169172
const batch = JSON.parse(line);
170173
if (batch?.header?.number != null) {
171174
cursor = batch.header.number + 1; // resume past this block on reconnect

0 commit comments

Comments
 (0)