@@ -42,6 +42,9 @@ type MemoryAccountWithDataUpdateHandler struct {
42
42
lastSuccessfulSlotUpdateMu sync.RWMutex
43
43
lastSuccessfulSlotUpdate map [string ]uint64
44
44
45
+ highestQueuedSlotUpdateMu sync.RWMutex
46
+ highestQueuedSlotUpdate map [string ]uint64
47
+
45
48
backupWorkerInterval time.Duration
46
49
}
47
50
@@ -60,6 +63,7 @@ func NewMemoryAccountWithDataUpdateHandler(solanaClient solana.Client, ramStore
60
63
observableVmAccounts : observableVmAccounts ,
61
64
cachedMemoryAccountState : make (map [string ]map [int ]* cachedVirtualAccount ),
62
65
lastSuccessfulSlotUpdate : make (map [string ]uint64 ),
66
+ highestQueuedSlotUpdate : make (map [string ]uint64 ),
63
67
backupWorkerInterval : backupWorkerInterval ,
64
68
}
65
69
}
@@ -168,9 +172,38 @@ func (h *MemoryAccountWithDataUpdateHandler) onStateObserved(ctx context.Context
168
172
}
169
173
h .lastSuccessfulSlotUpdateMu .RUnlock ()
170
174
175
+ // Check if there's an update for a higher slot
176
+ h .highestQueuedSlotUpdateMu .Lock ()
177
+ highestQueuedSlotUpdate := h .highestQueuedSlotUpdate [base58MemoryAccountAddress ]
178
+ if observedAtSlot <= highestQueuedSlotUpdate {
179
+ h .highestQueuedSlotUpdateMu .Unlock ()
180
+ return nil
181
+ }
182
+ h .highestQueuedSlotUpdate [base58MemoryAccountAddress ] = observedAtSlot
183
+ h .highestQueuedSlotUpdateMu .Unlock ()
184
+
171
185
h .cachedMemoryAccountStateMu .Lock ()
172
186
defer h .cachedMemoryAccountStateMu .Unlock ()
173
187
188
+ // Check (again after acquiring cached memory state mutex) if the state
189
+ // is stale relative to the last successful update
190
+ h .lastSuccessfulSlotUpdateMu .RLock ()
191
+ lastSuccessfulSlotUpdate = h .lastSuccessfulSlotUpdate [base58MemoryAccountAddress ]
192
+ if observedAtSlot <= lastSuccessfulSlotUpdate {
193
+ h .lastSuccessfulSlotUpdateMu .RUnlock ()
194
+ return nil
195
+ }
196
+ h .lastSuccessfulSlotUpdateMu .RUnlock ()
197
+
198
+ // Check (again after acquiring cached memory state mutex) if there's an
199
+ // update queued for a higher slot
200
+ h .highestQueuedSlotUpdateMu .RLock ()
201
+ highestQueuedSlotUpdate = h .highestQueuedSlotUpdate [base58MemoryAccountAddress ]
202
+ if observedAtSlot < highestQueuedSlotUpdate {
203
+ return nil
204
+ }
205
+ h .highestQueuedSlotUpdateMu .RUnlock ()
206
+
174
207
cachedState , ok := h .cachedMemoryAccountState [base58MemoryAccountAddress ]
175
208
if ! ok {
176
209
// Load entire memory account state from the DB into the cache
0 commit comments