Skip to content

[claude] Keep the fwdata LcmCache alive during long syncs - #2500

Merged
myieye merged 5 commits into
developfrom
fwdata-cache-keepalive
Jul 30, 2026
Merged

[claude] Keep the fwdata LcmCache alive during long syncs#2500
myieye merged 5 commits into
developfrom
fwdata-cache-keepalive

Conversation

@myieye

@myieye myieye commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

[Claude, autonomous]

The LcmCache's 30-minute sliding expiration only resets when a new FwDataMiniLcmApi first touches the memory cache, so a sync that outlives it (large project, or paused in a debugger) gets its cache disposed mid-run. FwDataFactory.PreventEviction returns a disposable timer that touches the cache entry every 5 minutes; the sync service holds one for the duration of a sync. TryGetValue never creates or reloads, so a project explicitly closed for FieldWorks stays closed.

🤖 Generated with Claude Code

The LcmCache's 30-minute sliding expiration only resets when a new
FwDataMiniLcmApi first touches the memory cache, so a sync that runs
longer than that can have the cache disposed out from under it.
FwDataFactory.PreventEviction returns a disposable timer that touches
the cache entry every 5 minutes; the sync service holds one per sync.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added 💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related 📦 Lexbox issues related to any server side code, fw-headless included labels Jul 29, 2026
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 82897a42-fb9f-4417-8abe-5d4ed725d2ef

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Changes

Synchronization Cache Guard

Layer / File(s) Summary
Add cache keepalive helper
backend/FwLite/FwDataMiniLcmBridge/FwDataFactory.cs
Adds PreventEviction, which periodically accesses a project's cached LcmCache entry and returns a disposable timer guard.
Integrate eviction guard into sync
backend/FwLite/FwLiteProjectSync/CrdtFwdataProjectSyncService.cs, backend/Testing/FwHeadless/Services/SyncWorkerTestHarness.cs
Injects FwDataFactory, applies the guard during synchronization, and updates the test harness constructor arguments.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

I’m a rabbit guarding cache,
Tapping keys through every dash.
Sync runs long, the timer sings,
No eviction clips its wings.
Hop, hop—dispose when done!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: keeping LcmCache alive during long syncs.
Description check ✅ Passed The description directly explains the keep-alive timer and its use during syncs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fwdata-cache-keepalive

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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)
backend/Testing/FwHeadless/Services/SyncWorkerTestHarness.cs (1)

251-256: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Add integration coverage for the keepalive path.

This harness mocks CrdtFwdataProjectSyncService and supplies null! for FwDataFactory, so the new PreventEviction call is never exercised. Add a targeted integration or round-trip test using the real sync service and a real FwData project, or a focused test that verifies the keepalive is created and disposed.

As per coding guidelines, backend/FwLite/FwLiteProjectSync/**/*.cs synchronization changes must be covered with integration or round-trip tests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/Testing/FwHeadless/Services/SyncWorkerTestHarness.cs` around lines
251 - 256, Extend the sync worker test coverage around the
CrdtFwdataProjectSyncService setup to exercise the keepalive path introduced by
PreventEviction. Prefer a targeted integration or round-trip test using a real
sync service and FwData project; otherwise verify that the keepalive is created
and disposed, rather than relying on the existing Strict mock with null
FwDataFactory.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/FwLite/FwDataMiniLcmBridge/FwDataFactory.cs`:
- Around line 138-143: Update PreventEviction to touch the cache entry
immediately by invoking cache.TryGetValue with the computed key before creating
and returning the periodic Timer. Keep the existing 5-minute refresh interval
and callback behavior unchanged.

---

Outside diff comments:
In `@backend/Testing/FwHeadless/Services/SyncWorkerTestHarness.cs`:
- Around line 251-256: Extend the sync worker test coverage around the
CrdtFwdataProjectSyncService setup to exercise the keepalive path introduced by
PreventEviction. Prefer a targeted integration or round-trip test using a real
sync service and FwData project; otherwise verify that the keepalive is created
and disposed, rather than relying on the existing Strict mock with null
FwDataFactory.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ee4cedf4-e34d-47be-8f8a-3ddba03c9ef0

📥 Commits

Reviewing files that changed from the base of the PR and between bb3f331 and db77397.

📒 Files selected for processing (3)
  • backend/FwLite/FwDataMiniLcmBridge/FwDataFactory.cs
  • backend/FwLite/FwLiteProjectSync/CrdtFwdataProjectSyncService.cs
  • backend/Testing/FwHeadless/Services/SyncWorkerTestHarness.cs

Comment thread backend/FwLite/FwDataMiniLcmBridge/FwDataFactory.cs
@argos-ci

argos-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Jul 30, 2026, 10:57 AM
e2e (Inspect) ✅ No changes detected - Jul 30, 2026, 11:04 AM

myieye and others added 4 commits July 30, 2026 10:38
CrdtFwdataProjectSyncService gained a FwDataFactory constructor parameter;
the SyncWorker test harness mock was still passing four args, so Moq could
not find a matching constructor and every SyncWorkerTests case failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…expiration

PreventEviction waited a full period before its first touch, so an entry with
little of its 30-minute window left could be evicted before the first refresh.
The refresh period was also an independent magic number that could silently
exceed the sliding expiration if either changed.

Fire the timer immediately (TimeSpan.Zero due-time), and derive the period from
a shared CacheSlidingExpiration constant (half the window) so a refresh is
guaranteed to land inside every window by construction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The timer's cache lookup runs on a ThreadPool thread. If the shared MemoryCache
is disposed during host shutdown while a sync is still finishing, TryGetValue
throws ObjectDisposedException, and an unhandled throw there crashes the process.
Swallow it so the keepalive stays best-effort, matching how a missing entry is
already tolerated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@myieye

myieye commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator Author

@hahn-kev Regarding the discussion about moving the PreventEviction higher up in the call stack: I agree that everything up there should easily happen fast enough for it to not be relevant. So, I left it where it is. It went through a few tiny refactors since you approved, but it's essentially still the same thing.

@myieye
myieye merged commit 599a7bb into develop Jul 30, 2026
31 checks passed
@myieye
myieye deleted the fwdata-cache-keepalive branch July 30, 2026 13:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related 📦 Lexbox issues related to any server side code, fw-headless included

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants