Remove in-memory cache from EncryptedManager#4645
Conversation
The previous implementation populated a syncmap.Map at construction time and served GetSecret reads from that cache. This meant writes by other processes were never visible to a long-running process. Remove the cache entirely. GetSecret now reads and decrypts the file on every call, consistent with all other Provider implementations (environment, keyring) which already read live on every access. SetSecret, DeleteSecret, and DeleteSecrets already re-read the file inside the write lock; remove the now-unnecessary cache update calls after each write. ListSecrets and Cleanup are updated to go through readFileSecrets instead of the removed map. NewEncryptedManager validates the file is readable at startup but no longer populates a cache. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
are there any concerns with increased I/O now?
So, it wasn't possible to update the cache on write/delete then? |
|
Good question! Same-process writes and deletes did update the cache — On the I/O concern: the increase is real, but the impact is minimal in practice. The secrets file is tiny (a handful of keys, a few KB), so the OS page cache keeps it in memory after the first access — actual disk reads are rare. The cost is dominated by syscall overhead, roughly microseconds on macOS. For the session auth use case this is one file read per HTTP request to the local API server, which is acceptable. Alternatives like file watching (inotify/kqueue) or mtime-based cache invalidation would preserve caching while fixing cross-process visibility, but add platform-specific complexity. Given the file is tiny and stays in the page cache, reading on every |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4645 +/- ##
==========================================
+ Coverage 68.87% 68.89% +0.02%
==========================================
Files 505 505
Lines 52380 52424 +44
==========================================
+ Hits 36076 36120 +44
+ Misses 13516 13512 -4
- Partials 2788 2792 +4 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Thanks for the reply! It makes sense, if any real issue is observed we can implement mtime-based cache invalidation later, but agree with this. Thanks |
Summary
The
EncryptedManagerloaded secrets from disk once at construction time and served allGetSecretreads from an in-memorysyncmap.Map. This meant any write or delete performed by a separate process after construction was invisible to a long-running process — the in-memory snapshot never updated.syncmap.Mapcache entirely;GetSecretnow reads and decrypts the file on every call, consistent with all otherProviderimplementations (environment,keyring) which already read live on every accessSetSecretandDeleteSecretalready re-read the file inside the write lock; remove the now-unnecessary cache update calls after each writeListSecretsandCleanupupdated to go throughreadFileSecrets/writeFileSecretsinstead of the removed mapNewEncryptedManagervalidates the file is readable at startup but no longer populates a cacheType of change
Test plan
task test)task lint-fix)Does this introduce a user-facing change?
No.
Special notes for reviewers
The
syncmap.Mapwas introduced for performance (nanosecond in-memory reads vs. a file decrypt per call). For a secrets file that is a few KB, AES-GCM decryption is fast enough that the per-call overhead is negligible compared to the correctness benefit. All otherProviderimplementations already pay this cost on every read.Generated with Claude Code