-
Notifications
You must be signed in to change notification settings - Fork 2
Add DB chaos by locking DB file #1578
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 11-13-add_streams_to_fork_test
Are you sure you want to change the base?
Add DB chaos by locking DB file #1578
Conversation
|
Warning 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.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Issue on line in workers/main.ts:815:
Rethrowing in stream handlers causes unhandled promise rejections and leaked state. Consider catching and handling: abort/cancel the controller, clear streamControllers/streamReferences, update activeStreamTypes, then break/restart the loop instead of rethrowing.
- throw error;
+ break;
@@
- throw error;
+ continue;🚀 Reply to ask Macroscope to explain or update this suggestion.
👍 Helpful? React to give us feedback.
1985c18 to
289c08c
Compare
8153581 to
9587ba2
Compare
| --streams Enable message streams on all workers [default: false] | ||
| --db-chaos-enabled Enable database locking chaos [default: false] | ||
| --db-lock-time-min <ms> Minimum DB lock duration in ms [default: 100] | ||
| --db-lock-time-max <ms> Maximum DB lock duration in ms [default: 2000] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
showHelp() lists defaults that don’t match main() (db-lock-time-max 2000 vs 6000, db-lock-interval 15000 vs 5000). Consider updating the help text to reflect the actual runtime defaults.
| --db-lock-time-max <ms> Maximum DB lock duration in ms [default: 2000] | |
| --db-lock-time-max <ms> Maximum DB lock duration in ms [default: 6000] | |
| --db-lock-interval <ms> How often to apply DB locks in ms [default: 5000] |
🚀 Reply to ask Macroscope to explain or update this suggestion.
👍 Helpful? React to give us feedback.
d8691e2 to
6aaafdf
Compare
289c08c to
24c219c
Compare
6aaafdf to
c78f6d1
Compare

Add DB chaos to fork tests by exposing CLI flags and
workers.WorkerClient.lockDBwith defaults 100–2000 ms and 5000 ms intervalIntroduce CLI flags to enable DB file locking chaos, pass settings via environment variables, and implement
workers.WorkerClient.lockDBto acquire a write lock for a duration; add utilities to start/clear periodic locks and integrate them into the concurrent forks test while increasing group count to 10.📍Where to Start
Start with CLI parsing and env wiring in cli.ts, then follow DB chaos setup in db-chaos-utils.ts and the test integration in forks.test.ts.
📊 Macroscope summarized c78f6d1. 5 files reviewed, 20 issues evaluated, 19 issues filtered, 0 comments posted
🗂️ Filtered Issues
forks/cli.ts — 0 comments posted, 1 evaluated, 1 filtered
runForkTestunconditionally calls.toString()onoptions.dbLockTimeMin,options.dbLockTimeMax, andoptions.dbLockInterval. If a caller omits any of these newly added fields (they are not runtime-enforced),options.<field>will beundefinedand.toString()will throwTypeError: Cannot read properties of undefined. Add defaults or guard these before use, or only set the env vars whendbChaosEnabledis true and the values exist. [ Low confidence ]forks/config.ts — 0 comments posted, 2 evaluated, 2 filtered
dbLockTimeMin,dbLockTimeMax, anddbLockIntervalare parsed usingparseInt(process.env.* , 10)with string fallbacks only when the env var is undefined or empty (due to||). If an env var is set to a non-numeric value (e.g.,"abc"),parseIntreturnsNaN. These exported values can then propagate asNaN, leading to unpredictable behavior in timing/locking logic. Validate and reject non-numeric values or coerce with safe defaults. [ Low confidence ]dbLockTimeMin <= dbLockTimeMaxand that both anddbLockIntervalare positive. Misordered or negative values from env can lead to nonsensical or harmful timing (e.g., negative durations or inverted ranges) in downstream logic. Add range checks and fail fast with a clear error when constraints are violated. [ Low confidence ]forks/db-chaos-utils.ts — 0 comments posted, 1 evaluated, 1 filtered
applyDbChaos(code object2) the randomness threshold is hard-coded to 50% (Math.random() < 0.5) (line 21) and there is no way to scope selection or ensure that at-most-one worker per installation is locked. While not a crash, this can cause many workers to be locked concurrently. This is a behavioral issue with potential wide impact on tests. [ Code style ]workers/main.ts — 0 comments posted, 16 evaluated, 15 filtered
workerThreadCode(code object6): the worker thread listens onparentPort.on("worker_message", ...)(line 131) but worker thread/parent port standard message event name is'message'. Using a custom event name prevents receiving parent messages in the worker thread. This appears unused/incorrect. [ Low confidence ]6). There is no stored AbortController or check that the worker is terminating — callingterminate()on WorkerClient only stops streams but does not stop sync tasks started bystartSync, so background sync loops may continue after termination, leaking resources. [ Low confidence ]if (this.activeStreamTypes.has(streamType))logs but continues and may initialize the same stream twice (lines ~336-342). This can create duplicate streaming loops and race conditions. [ Low confidence ]WorkerClient.startStreamthe code intentionally does not return when a stream is already active (lines 337-343 in code object6), so callingstartStreamfor the samestreamTypemultiple times will create additional concurrent loops/stream handlers and duplicate behavior (memory leak, duplicated emits, multiple responses). The commented-outreturnindicates the intended guard was disabled. [ Low confidence ]getSQLiteFileSizes(code object6) the code callsfs.readdirSync(dbDir)without checking thatdbDirexists (line ~427). IfdbDirdoes not exist, this will throw synchronously and bubble up causing the caller to crash. [ Low confidence ]await this.client.conversations.list()inside a loop over filesystem entries (lines ~442-445). This queries the API repeatedly for each file instead of once, causing unnecessary IO, potential rate limits and inconsistent results if conversations change during the loop. [ Low confidence ]initMessageStreamusesconst stream = await this.client.conversations.streamAllMessages()thenfor await (const message of stream), whileinitConversationStreamdoesconst stream = this.client.conversations.stream();followed byfor await (const conversation of await stream)(lines ~582 and ~790 in code object6). If the SDK returns either a Promise or AsyncIterable directly inconsistently between APIs, one of these patterns can throw or iterate incorrectly. [ Low confidence ]initMessageStreamthe checkmessage?.senderInboxId.toLowerCase() === this.client.inboxId.toLowerCase()calls.toLowerCase()without guardingsenderInboxIdorthis.client.inboxId(lines ~595-603 in code object6), which will throw if either side is undefined/null. [ Low confidence ].toLowerCase()on values that may be undefined:message?.senderInboxId.toLowerCase()andthis.client.inboxId.toLowerCase()(lines ~599-602). Ifmessage.senderInboxIdis undefined or not a string this will throw a runtime TypeError. [ Low confidence ](message.content as string).toLowerCase()(line ~727) without verifyingmessage.contentis a string, which will throw if content is undefined or an object. [ Already posted ]handleResponsewhen calling(message.content as string).toLowerCase()without ensuringmessage.contentis a string (lines ~728-731 in code object6). If content is undefined or an object (non-string), this will throw and be caught by outer try/catch, but may cause unnecessary stack noise; more importantly, subsequent content checks rely oncontentbeing a string. [ Low confidence ]fromInboxIdparameter — whenfromInboxIdis truthy it returnsmsg.conversation.id !== undefinedinstead of checking the message's originating inbox ID (lines ~1074-1078). This likely causes incorrect filtering semantics and can return irrelevant conversations. [ Low confidence ]collectConversationsthe filter usesfromInboxId ? (msg) => { if (msg.type !== StreamCollectorType.Conversation) return false; return msg.conversation.id !== undefined; } : undefined(lines ~1075-1080 in code object6) — the filter ignoresfromInboxIdvalue (does not check that the conversation originated fromfromInboxId). This causes the collector to accept any conversation that has an id whenfromInboxIdis truthy, violating the caller's expected filter-by-sender semantics. [ Low confidence ]lockDB(code object7) the implementation callsthis.client.disconnectDatabase()synchronously and then schedules asetTimeouttoreconnectDatabase. IfdisconnectDatabaseis asynchronous in the SDK (returns a Promise) or requires awaiting, calling it without awaiting could leave the DB in an inconsistent state or race with reconnect. The method wraps this in a Promise but does not await a possible Promise fromdisconnectDatabase. [ Low confidence ]