@@ -72,6 +72,50 @@ def _schema_version_validator(cls, v: t.Any) -> int:
7272SCHEMA_VERSION : int = MIN_SCHEMA_VERSION + len (MIGRATIONS ) - 1
7373
7474
75+ class BatchBoundary (PydanticModel ):
76+ updated_ts : int
77+ name : str
78+ identifier : str
79+
80+ def to_upper_batch_boundary (self ) -> UpperBatchBoundary :
81+ return UpperBatchBoundary (
82+ updated_ts = self .updated_ts ,
83+ name = self .name ,
84+ identifier = self .identifier ,
85+ )
86+
87+ def to_lower_batch_boundary (self , batch_size : int ) -> LowerBatchBoundary :
88+ return LowerBatchBoundary (
89+ updated_ts = self .updated_ts ,
90+ name = self .name ,
91+ identifier = self .identifier ,
92+ batch_size = batch_size ,
93+ )
94+
95+
96+ class UpperBatchBoundary (BatchBoundary ):
97+ @classmethod
98+ def include_all_boundary (cls ) -> UpperBatchBoundary :
99+ # 9999-12-31T23:59:59.999Z in epoch milliseconds
100+ return UpperBatchBoundary (updated_ts = 253_402_300_799_999 , name = "" , identifier = "" )
101+
102+
103+ class LowerBatchBoundary (BatchBoundary ):
104+ batch_size : int
105+
106+ @classmethod
107+ def init_batch_boundary (cls , batch_size : int ) -> LowerBatchBoundary :
108+ return LowerBatchBoundary (updated_ts = 0 , name = "" , identifier = "" , batch_size = batch_size )
109+
110+
111+ class ExpiredSnapshotBatch (PydanticModel ):
112+ """A batch of expired snapshots to be cleaned up."""
113+
114+ expired_snapshot_ids : t .Set [SnapshotId ]
115+ cleanup_tasks : t .List [SnapshotTableCleanupTask ]
116+ batch_boundary : BatchBoundary
117+
118+
75119class PromotionResult (PydanticModel ):
76120 added : t .List [SnapshotTableInfo ]
77121 removed : t .List [SnapshotTableInfo ]
@@ -315,15 +359,23 @@ def export(self, environment_names: t.Optional[t.List[str]] = None) -> StateStre
315359
316360 @abc .abstractmethod
317361 def get_expired_snapshots (
318- self , current_ts : t .Optional [int ] = None , ignore_ttl : bool = False
319- ) -> t .List [SnapshotTableCleanupTask ]:
320- """Aggregates the id's of the expired snapshots and creates a list of table cleanup tasks.
362+ self ,
363+ * ,
364+ batch_boundary : BatchBoundary ,
365+ current_ts : t .Optional [int ] = None ,
366+ ignore_ttl : bool = False ,
367+ ) -> t .Optional [ExpiredSnapshotBatch ]:
368+ """Returns a single batch of expired snapshots ordered by (updated_ts, name, identifier).
321369
322- Expired snapshots are snapshots that have exceeded their time-to-live
323- and are no longer in use within an environment.
370+ Args:
371+ current_ts: Timestamp used to evaluate expiration.
372+ ignore_ttl: If True, include snapshots regardless of TTL (only checks if unreferenced).
373+ batch_boundary: If provided, gets snapshot relative to the given boundary.
374+ If lower boundary then snapshots later than that will be returned (exclusive).
375+ If upper boundary then snapshots earlier than that will be returned (inclusive).
324376
325377 Returns:
326- The list of table cleanup tasks .
378+ A batch describing expired snapshots or None if no snapshots are pending cleanup .
327379 """
328380
329381 @abc .abstractmethod
@@ -363,7 +415,10 @@ def delete_snapshots(self, snapshot_ids: t.Iterable[SnapshotIdLike]) -> None:
363415
364416 @abc .abstractmethod
365417 def delete_expired_snapshots (
366- self , ignore_ttl : bool = False , current_ts : t .Optional [int ] = None
418+ self ,
419+ ignore_ttl : bool = False ,
420+ current_ts : t .Optional [int ] = None ,
421+ upper_batch_boundary : t .Optional [UpperBatchBoundary ] = None ,
367422 ) -> None :
368423 """Removes expired snapshots.
369424
@@ -373,6 +428,9 @@ def delete_expired_snapshots(
373428 Args:
374429 ignore_ttl: Ignore the TTL on the snapshot when considering it expired. This has the effect of deleting
375430 all snapshots that are not referenced in any environment
431+ current_ts: Timestamp used to evaluate expiration.
432+ upper_batch_boundary: The upper boundary to delete expired snapshots till (inclusive). If not provided,
433+ deletes all expired snapshots.
376434 """
377435
378436 @abc .abstractmethod
0 commit comments