Default the RocksDB WriteBufferManager on at 1/3 of block cache#1251
Conversation
Enable the WriteBufferManager by default (size = blockCacheSize / 3, costToCache and allowStall true), bounding total memtable memory across column families and applying write backpressure so bulk ingest can't outrun the memtable flush/conflict-check window. An explicit size of 0 still disables it. Extracts the block-cache/WBM defaulting out of openRocksDatabase into a pure resolveRocksMemoryConfig helper so the branching is unit-testable without opening a database. Part of HarperFast/harper-pro#348. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Floor the computed block-cache and WriteBufferManager sizes (RocksDB expects integer byte counts; the percentage/third math produced fractions). Switch the test to node:assert/strict per Harper conventions and add integer-flooring cases. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Reviewed; no blockers found. |
There was a problem hiding this comment.
Code Review
This pull request refactors the RocksDB memory configuration logic by extracting it from resources/databases.ts into a dedicated, pure utility function resolveRocksMemoryConfig in utility/rocksMemoryConfig.ts, accompanied by a comprehensive suite of unit tests. The feedback recommends moving defensive runtime checks for configuration parameters like configuredBlockCacheSize and configuredWriteBufferManagerSize into the Joi validation schema to ensure proper validation and keep the resolver code clean.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| // Block cache: an explicit positive number wins, otherwise 25% of available memory. Floored | ||
| // because RocksDB expects integer byte counts and the percentage math produces fractions. | ||
| const blockCacheSize = Math.floor( | ||
| typeof configuredBlockCacheSize === 'number' && configuredBlockCacheSize > 0 | ||
| ? configuredBlockCacheSize | ||
| : availableMemory * 0.25 | ||
| ); |
There was a problem hiding this comment.
Instead of adding defensive runtime checks for configuredBlockCacheSize in the resolver, ensure this configuration parameter is explicitly defined and validated in the Joi validation schema. This prevents invalid values like Infinity or non-numbers from bypassing validation while keeping the implementation free of redundant guards.
References
- Ensure all new configuration parameters are explicitly defined in the Joi validation schema, as they may otherwise bypass validation if
allowUnknown: trueis enabled, potentially leading to runtime errors. - Avoid adding defensive checks or guards for states, properties, or methods that are guaranteed to exist or cannot occur in practice.
| // WriteBufferManager size: an explicit number is honored (0 disables); any other value | ||
| // (unset/misconfigured) defaults to 1/3 of the block cache. Floored for the same reason. | ||
| const writeBufferManagerSize = Math.floor( | ||
| typeof configuredWriteBufferManagerSize === 'number' ? configuredWriteBufferManagerSize : blockCacheSize / 3 | ||
| ); |
There was a problem hiding this comment.
Instead of adding inline defensive checks for configuredWriteBufferManagerSize to handle negative, NaN, or Infinity values, ensure that this parameter is explicitly validated in the Joi schema. This avoids redundant runtime guards in the resolver code.
References
- Ensure all new configuration parameters are explicitly defined in the Joi validation schema, as they may otherwise bypass validation if
allowUnknown: trueis enabled, potentially leading to runtime errors. - Avoid adding defensive checks or guards for states, properties, or methods that are guaranteed to exist or cannot occur in practice.
|
Thanks for the review! On the suggestion to move the — Claude Sonnet 4.6 |
Summary
Makes the RocksDB WriteBufferManager (WBM) on by default in core (it was opt-in). Defaults, applied in
openRocksDatabase:writeBufferManagerSize=blockCacheSize / 3(floored)writeBufferManagerCostToCache=truewriteBufferManagerAllowStall=true0still disables the WBM; any explicitly configured value/boolean is honored.The block-cache + WBM defaulting was extracted out of
openRocksDatabaseinto a pureresolveRocksMemoryConfighelper (utility/rocksMemoryConfig.ts) so the branching is unit-testable without opening a database or hitting the process-globalRocksDatabase.config.Purpose
Bound total memtable memory across column families and apply write backpressure (
allowStall) so bulk ingest can't outrun the memtable flush/conflict-check window. This is the throughput/memory half of HarperFast/harper-pro#348 (the data-safety floor — not silently dropping on retry-cap exhaustion — is a separate follow-up PR).Where to look
utility/rocksMemoryConfig.ts— the defaulting rules (3-way size logic: unset → default,0→ disabled,>0→ used).resources/databases.ts— now just calls the helper.Notes for the reviewer
STORAGE_ROCKS_*env vars explicitly (block cache 15%, WBM 5%,costToCachetrue,allowStallfalse). Those explicit values are typed and honored over these new defaults, so Fabric keeps its Phase-1allowStall: false— no regression.availableMemorybeingInfinity/NaN.availableMemory = min(constrainedMemory ?? Infinity, totalmem())is always finite becauseos.totalmem()is, so guarding it would be validating an unreachable state. Negative configured sizes already disable safely via the> 0gate. Flag if you'd prefer a defensive guard anyway.Cross-model review (Codex + Gemini/agy) run pre-PR; float-flooring, strict-assert, and edge tests were added in response.
🤖 Generated with Claude Code — model: Claude Sonnet 4.6