You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite. Learn more
This PR adds a comprehensive memory soak testing harness for SQLite-backed Rivet Actors, including:
A new sqliteMemoryPressure test actor (sqlite-memory-pressure.ts)
A standalone harness script (sqlite-memory-soak.ts) that spawns a local engine + kitchen-sink server and drives actors through configurable workloads
A metrics report renderer (proc-metrics-report.ts) that produces HTML charts from collected data
An agent note documenting current known issues from runs so far
The tooling is sophisticated and clearly the result of real investigation work. The notes doc is especially useful as it captures concrete run results and open questions.
Issues and Suggestions
sqlite-memory-pressure.ts
Large commented-out code blocks
Several logical paths are commented out and left in the file:
And the entire delete/VACUUM path in runCycle and releaseStorage. If these are intentionally disabled for the current soak focus (as noted in the agent doc), either remove them or add a brief // intentionally disabled: see .agent/notes/sqlite-memory-soak-issues.md so readers understand the state.
onSleep crash risk on failed startup (Issue 4 from agent notes)
onSleep: (c)=>{c.state.sleepCount+=1;// crashes if state was never initialized
The notes already flag this as Issue 4. Given the investigation found Cannot read properties of undefined (reading 'sleepCount') in real runs, add a defensive guard:
This works around a camelCase/snake_case uncertainty in the SqliteNativeMetrics type at runtime. If the type is known at compile time, use the correct field name directly. If the type can come from either runtime, add a comment explaining why both are needed.
queryOne uses rest-spread args on a typed interface
args is typed unknown[] but the actual c.db.execute signature may not match. Consider using the concrete c.db type directly to get compile-time safety rather than the structural duck-type here.
sqlite-memory-soak.ts
Indentation inconsistency in parseArgs
Around the validation block at the end of parseArgs, the indentation switches between 2-space indent inside the for...of and 4-space (\t-equivalent) for the surrounding array elements:
These appear to be stray mixed-indent lines that escaped the formatter. Worth cleaning up.
runWithSpikeConcurrency — actor exhaustion is a thrown error, not a run failure
if(nextActor>=args.actors){thrownewError(`ran out of actors before spike duration completed`);}
This throws afterPromise.allSettled(workers) already drained, meaning the run succeeded but the spike window outlasted the actor pool. Throwing here prevents the normal summary from printing. Consider logging a warning instead and returning normally (or emit a run_actor_pool_exhausted event).
spawnActor uses var-style hoisting pattern with let worker; worker = ...
This is valid TypeScript but worker is referenced inside the finally closure before the outer let is assigned in some engine analyses. Consider using const worker = ...; workers.add(worker); with the .finally moved after .add to make the self-reference explicit.
failed flag is checked but errors array is not always populated
.catch((err)=>{failed=true;errors.push(err);})
The loop exits on failed, but errors[0] is re-thrown only after Promise.allSettled. If Promise.allSettled is called with an empty workers set (edge case where all actors exhaust immediately), errors.length > 0 check is fine — but if failed is set but errors is empty for any code path, the error is silently dropped. The current code looks correct, but the errors array should be the sole source of truth; failed adds redundancy without benefit — consider removing failed and checking errors.length > 0 in the loop condition.
waitForHttpOk polls with 100ms sleep — fragile for slow cold starts
The timeoutMs default is 20 seconds, which may be too short for a slow release build engine start. Consider making the cold-start timeout configurable or bumping it, especially given the soak notes mention very long actor_ready_timeout errors under load.
configureServerlessRunner leaks engine config details into the test harness
The harness calls PUT /runner-configs/{pool} to wire up the serverless URL. This creates a hard dependency on that particular engine API shape and means the harness won't work if the engine config API changes. Consider adding a comment noting this is an internal/dev-only API path.
CLOCK_TICKS_PER_SECOND = 100 is a Linux assumption
This constant is used to convert /proc/stat CPU ticks, which is correct on most Linux distros but not universal. Add a comment that this is the standard Linux CONFIG_HZ=100 default, or read it from sysconf(_SC_CLK_TCK) via the os module if portability matters.
summarizeCycleVfs reads the entire JSONL file into memory
For long runs this could be hundreds of MB. A streaming line reader would be more efficient, though for a dev-tooling script this is acceptable in practice.
proc-metrics-report.ts
Not reviewed in detail since it's a standalone HTML report renderer, but note that it embeds inline JavaScript for chart rendering — that's fine for a dev tool.
page-data.ts / index.ts
The wiring is clean. The new sqliteMemoryPressure entry in PAGE_GROUPS, ACTION_TEMPLATES, and SNIPPETS follows the existing pattern exactly.
Summary
This is solid investigation tooling. The main actionable items before merging:
Clean up the mixed-indentation lines in sqlite-memory-soak.ts.
Add the defensive if (!c.state) return guard in onSleep (or document the decision not to, if core guarantees onSleep is never called after a failed onMigrate).
Decide whether the large commented-out delete/VACUUM blocks should be removed or annotated.
Everything else is minor style or low-risk future polish. The agent notes doc is a good artifact to keep — the documented run IDs, error counts, and open questions are directly useful for whoever picks up the correctness investigation next.
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
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.
Description
Please include a summary of the changes and the related issue. Please also include relevant motivation and context.
Type of change
How Has This Been Tested?
Please describe the tests that you ran to verify your changes.
Checklist: