-
-
Notifications
You must be signed in to change notification settings - Fork 364
Adding secondary cache to settings #1156
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
Conversation
Caching get_setting_value independent from what backend is used.
WalkthroughIntroduces a secondary in-memory cache for settings and updates get_setting and get_setting_value to use a two-tier caching strategy. Enhances file-change invalidation to clear both caches. Refactors JSON loading with with-open and explicit error handling, updating the last cache date only after successful parsing. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Caller
participant Helper as helper.get_setting_value
participant SecCache as Secondary Cache
participant Conf as conf.mySettings
participant Prim as helper.get_setting
participant FS as table_settings.json
Caller->>Helper: get_setting_value(key)
Helper->>SecCache: Lookup key
alt Hit in secondary cache
SecCache-->>Helper: value
Helper-->>Caller: value
else Miss in secondary cache
Helper->>Conf: Read mySettings[key]
alt Found in conf
Conf-->>Helper: value
Helper->>SecCache: Store key=value
Helper-->>Caller: value
else Not in conf
Helper->>Prim: get_setting(key)
Prim->>FS: Check mtime / read JSON
alt File changed
Prim->>SecCache: Clear all
Prim->>Prim: Clear primary cache
end
Prim->>FS: Parse JSON (with-open)
alt Parse success
Prim->>Prim: Update primary cache + last cache date
Prim-->>Helper: value or None
Helper->>SecCache: Store key=value
Helper-->>Caller: value
else Parse error
Prim-->>Helper: None
Helper-->>Caller: None
end
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
server/helper.py (1)
331-349: Do not preemptively wipe caches; use transactional reload + in-place update.Reassigning to {} drops existing objects (breaking external refs) and clearing before a successful parse causes avoidable outages on transient JSON errors. Load into a temporary map, then replace contents atomically; fall back to old cache on errors.
Apply:
- # invalidate CACHE - SETTINGS_CACHE = {} - SETTINGS_SECONDARYCACHE={} - - # Load JSON and populate cache - try: - with open(settingsFile, 'r') as json_file: - data = json.load(json_file) - SETTINGS_CACHE = {item["setKey"]: item for item in data.get("data", [])} - except json.JSONDecodeError: - mylog('none', [f'[Settings] ⚠ JSON decode error in file {settingsFile}']) - return None - except ValueError as e: - mylog('none', [f'[Settings] ⚠ Value error: {e} in file {settingsFile}']) - return None - - # Only update file date when we successfully parsed the file - SETTINGS_LASTCACHEDATE = fileModifiedTime + # Load JSON and populate cache (transactional) + try: + with open(settingsFile, 'r') as json_file: + data = json.load(json_file) + new_cache = {item["setKey"]: item for item in data.get("data", [])} + except json.JSONDecodeError: + mylog('none', [f'[Settings] ⚠ JSON decode error in file {settingsFile}']) + # Keep serving from the previous cache instead of dropping values + return SETTINGS_CACHE.get(key) + except ValueError as e: + mylog('none', [f'[Settings] ⚠ Value error: {e} in file {settingsFile}']) + return SETTINGS_CACHE.get(key) + + # Only update global caches after successful parse (in-place to preserve references) + SETTINGS_CACHE.clear() + SETTINGS_CACHE.update(new_cache) + SETTINGS_SECONDARYCACHE.clear() + SETTINGS_LASTCACHEDATE = fileModifiedTimeOptional concurrency hardening (outside this hunk): protect this critical section with a module-level RLock if the app runs multi-threaded.
🧹 Nitpick comments (2)
server/helper.py (2)
293-294: Good addition: secondary in-memory cache introduced.Adds a fast path for get_setting_value; sensible for hot settings. Consider documenting expected key cardinality and lifetime to make it clear this is bounded by number of settings.
397-398: Typo in comment.“retrive” → “retrieve”.
- # Otherwise fall back to retrive from json + # Otherwise fall back to retrieve from json
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
server/helper.py(7 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: docker_dev
🔇 Additional comments (4)
server/helper.py (4)
347-349: Nice: timestamp updated only after successful parse.This fixes an edge case where a bad read could pin an invalid cache state.
394-395: Good: populate secondary cache from conf.mySettings path.Ensures hot lookups bypass tuple scanning on subsequent calls.
409-412: Good: also cache JSON-derived values.Keeps secondary cache coherent across both sources.
311-313: Cache stability concern appears unfounded: no external references to SETTINGS_CACHE/SETTINGS_SECONDARYCACHE found
Ranrg -nP -C2 '\bSETTINGS_(SECONDARY)?CACHE\b' -g '!server/helper.py'— no matches. These globals aren’t imported elsewhere, so reassigning them in server/helper.py won’t break external code. Please manually confirm there are no dynamic imports before proceeding.
|
@ingoratsdorf amazing! Seems like we've managed to lower the CPU usage by 40-50% (14% -> 7%) which is amazing. Let me know if this is ready to be merged |
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
|
Merged suggestion by CodeRabbit. |
Caching get_setting_value independent of what backend is used.
Summary by CodeRabbit
Performance
Bug Fixes