Skip to content

fix(backend): add _nile_cache_lock for thread-safe amazon games cache access - #169

Open
amir-rezaei wants to merge 3 commits into
mont127:mainfrom
amir-rezaei:fix/backend-nile-cache-thread-lock
Open

fix(backend): add _nile_cache_lock for thread-safe amazon games cache access#169
amir-rezaei wants to merge 3 commits into
mont127:mainfrom
amir-rezaei:fix/backend-nile-cache-thread-lock

Conversation

@amir-rezaei

Copy link
Copy Markdown

Description

This PR adds _nile_cache_lock in backend_server.py.

Details

  • Provides explicit lock protection for _nile_games_cache dictionary operations across background scanning and worker threads.

@realmaitreal realmaitreal left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as #168, for _nile_games_cache/_nile_cache_lock: the lock is declared but never acquired at any of the cache's read/modify/write sites, so it doesn't actually add thread-safety yet.

Separately: this PR's diff against current main already includes the _legendary_cache_lock line from #168, which means this branch was built on top of #168's commit rather than off main directly. Worth rebasing onto main (or landing #168 first) so the two PRs don't end up touching the same hunk twice.


Generated by Claude Code

@amir-rezaei
amir-rezaei force-pushed the fix/backend-nile-cache-thread-lock branch from d288516 to b7c6a39 Compare July 28, 2026 09:37

@realmaitreal realmaitreal left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for following up on this — real progress in b7c6a39. _nile_do_install's cleanup pop and _scan_nile_games's check-then-act logic are now correctly wrapped in with _nile_cache_lock: (and the refactor incidentally removes a pre-existing dead duplicate return []).

Still missing the lock at four other places that mutate the same _nile_games_cache dict, though:

  1. _refresh_nile_cache — the background thread _scan_nile_games itself spawns. It writes the cache in three spots (the disk-cache "phase 1" seed, the network-failure fallback that does entry = cache.get(...); entry["scanning"] = False; cache[prefix] = entry, and the final "phase 3" write) — none of them locked. This is the main writer and the one most worth protecting.
  2. The Nile auth-registration success path, which seeds a fresh cache entry right after register succeeds — unlocked.
  3. cmd_nile_scan_status's cache read — unlocked.
  4. cmd_nile_install_progress's own _nile_games_cache.pop(prefix, None) (a second, separate pop site from the one already fixed in _nile_do_install) — unlocked.

A lock only prevents the race if every accessor takes it. As long as _refresh_nile_cache (the main background writer) skips it, two concurrent cold-start calls to _scan_nile_games for the same prefix can still each decide to spawn their own refresh thread, and a refresh finishing mid-write can still race a cmd_nile_scan_status read. Please wrap these remaining sites too.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants