@@ -195,10 +195,6 @@ def __init__(
195195 # Thread synchronization
196196 self ._lock = threading .RLock ()
197197
198- # True if the data in the memory store may be written to the persistent
199- # store. Set on each apply from its persist flag.
200- self ._persist = False
201-
202198 def selector (self ) -> Selector :
203199 """Returns the current selector."""
204200 with self ._lock :
@@ -212,30 +208,19 @@ def _on_memory_store_active(self) -> None:
212208 """
213209 pass
214210
215- def _should_persist (self ) -> bool :
216- """
217- Returns whether the current data should be written to the persistent
218- store. The base engine has no persistent store, so it never persists;
219- subclasses override this based on their store.
220- """
221- return False
222-
223211 def _set_basis (
224- self , collections : Collections , selector : Selector , persist : bool
225- ) -> Optional [ Collections ] :
212+ self , collections : Collections , selector : Selector
213+ ) -> bool :
226214 """
227215 Set the basis of the store. Any existing data is discarded.
228216
229217 Args:
230218 collections: The new basis data
231219 selector: The selector identifying the data
232- persist: Whether to persist the data to the persistent store
233220
234221 Returns:
235- The collections to persist, or None if there is nothing to persist .
222+ True if the in-memory store was updated, False if it was not .
236223 """
237- self ._persist = persist
238-
239224 # Take snapshot for change detection if we have flag listeners
240225 old_data : Optional [Collections ] = None
241226 if self ._flag_change_listeners .has_listeners ():
@@ -245,7 +230,7 @@ def _set_basis(
245230
246231 ok = self ._memory_store .set_basis (collections )
247232 if ok is False :
248- return None
233+ return False
249234
250235 # Update dependency tracker
251236 self ._reset_dependency_tracker (collections )
@@ -267,27 +252,24 @@ def _set_basis(
267252 )
268253 self ._send_change_events (affected_items )
269254
270- return collections if self . _should_persist () else None
255+ return True
271256
272257 def _apply_delta (
273- self , collections : Collections , selector : Selector , persist : bool
274- ) -> Optional [ Collections ] :
258+ self , collections : Collections , selector : Selector
259+ ) -> bool :
275260 """
276261 Apply a delta update to the store.
277262
278263 Args:
279264 collections: The delta changes
280265 selector: The selector identifying the data
281- persist: Whether to persist the changes to the persistent store
282266
283267 Returns:
284- The collections to persist, or None if there is nothing to persist .
268+ True if the in-memory store was updated, False if it was not .
285269 """
286- self ._persist = persist
287-
288270 ok = self ._memory_store .apply_delta (collections )
289271 if ok is False :
290- return None
272+ return False
291273
292274 has_listeners = self ._flag_change_listeners .has_listeners ()
293275 affected_items : Set [KindAndKey ] = set ()
@@ -311,7 +293,7 @@ def _apply_delta(
311293 if affected_items :
312294 self ._send_change_events (affected_items )
313295
314- return collections if self . _should_persist () else None
296+ return True
315297
316298 def _changes_to_store_data (self , changes : List [Change ]) -> Collections :
317299 """
@@ -412,6 +394,10 @@ def __init__(
412394 self ._persistent_store_status_provider : Optional [DataStoreStatusProvider ] = None
413395 self ._persistent_store_writable = False
414396
397+ # True if the data in the memory store may be written to the persistent
398+ # store. Set on each successful apply from its persist flag.
399+ self ._persist = False
400+
415401 def with_persistence (
416402 self ,
417403 persistent_store : FeatureStore ,
@@ -450,34 +436,38 @@ def apply(self, change_set: ChangeSet, persist: bool) -> None:
450436 """
451437 collections = self ._changes_to_store_data (change_set .changes )
452438
453- pending : Optional [ Collections ] = None
439+ applied = False
454440 is_full = False
455441
456442 with self ._lock :
457443 try :
458444 if change_set .intent_code == IntentCode .TRANSFER_FULL :
459- pending = self ._set_basis (collections , change_set .selector , persist )
445+ applied = self ._set_basis (collections , change_set .selector )
460446 is_full = True
461447 elif change_set .intent_code == IntentCode .TRANSFER_CHANGES :
462- pending = self ._apply_delta (collections , change_set .selector , persist )
448+ applied = self ._apply_delta (collections , change_set .selector )
463449 elif change_set .intent_code == IntentCode .TRANSFER_NONE :
464450 # No-op, no changes to apply
465451 return
466452
467453 # Notify changeset listeners
468454 self ._change_set_listeners .notify (change_set )
469455
470- # Persist synchronously, inline under the lock
471- if pending is not None :
472- store = self ._persistent_store
473- assert store is not None
474- if is_full :
475- store .init (pending )
476- else :
477- for kind in pending :
478- kind_data = pending [kind ]
479- for key in kind_data :
480- store .upsert (kind , kind_data [key ])
456+ if applied :
457+ # Memory now holds this data, so it may be persisted.
458+ self ._persist = persist
459+
460+ # Persist synchronously, inline under the lock
461+ if self ._should_persist ():
462+ store = self ._persistent_store
463+ assert store is not None
464+ if is_full :
465+ store .init (collections )
466+ else :
467+ for kind in collections :
468+ kind_data = collections [kind ]
469+ for key in kind_data :
470+ store .upsert (kind , kind_data [key ])
481471
482472 except Exception as e :
483473 # Log error but don't re-raise - matches Go behavior
0 commit comments