fix: address review feedback on cache invalidation
- Fix cache not repopulated after invalidation: Always update cache with fresh data instead of just deleting on mismatch - Fix race condition: Hold mutex lock during entire fetch operation to prevent SaveEvent from running between fetch and cache update - Improve test: Add second GetLatestVersion call to verify cache was properly repopulated after invalidation Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -303,17 +303,22 @@ func (jes *JetStreamEventStore) getEventsWithErrorsInternal(actorID string, from
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetLatestVersion returns the latest version for an actor, invalidating cache
|
||||
// if the actual version in JetStream is newer than cached version.
|
||||
// This strategy ensures cache consistency even if external processes write to
|
||||
// GetLatestVersion returns the latest version for an actor, repopulating cache
|
||||
// with fresh data to ensure consistency even if external processes write to
|
||||
// the same JetStream stream.
|
||||
func (jes *JetStreamEventStore) GetLatestVersion(actorID string) (int64, error) {
|
||||
// Hold lock during fetch to prevent race condition with SaveEvent
|
||||
jes.mu.Lock()
|
||||
defer jes.mu.Unlock()
|
||||
|
||||
events, err := jes.GetEvents(actorID, 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if len(events) == 0 {
|
||||
// No events for this actor - ensure cache is cleared
|
||||
delete(jes.versions, actorID)
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -324,17 +329,10 @@ func (jes *JetStreamEventStore) GetLatestVersion(actorID string) (int64, error)
|
||||
}
|
||||
}
|
||||
|
||||
// Invalidate cache if actual version differs from cached version
|
||||
// This handles the case where external writers modify the stream
|
||||
jes.mu.Lock()
|
||||
if cachedVersion, ok := jes.versions[actorID]; ok && latestVersion > cachedVersion {
|
||||
// Cache was stale - invalidate it by deleting
|
||||
delete(jes.versions, actorID)
|
||||
} else if !ok {
|
||||
// Update cache for future calls
|
||||
jes.versions[actorID] = latestVersion
|
||||
}
|
||||
jes.mu.Unlock()
|
||||
// Always repopulate cache with the fresh data just fetched
|
||||
// This ensures cache is in sync with actual state, whether from local writes
|
||||
// or external writes detected by version comparison
|
||||
jes.versions[actorID] = latestVersion
|
||||
|
||||
return latestVersion, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user