1616 RowBoundary ,
1717 ExpiredBatchRange ,
1818)
19- from sqlmesh .utils .errors import SQLMeshError
2019
2120
2221def cleanup_expired_views (
2322 default_adapter : EngineAdapter ,
2423 engine_adapters : t .Dict [str , EngineAdapter ],
2524 environments : t .List [Environment ],
26- warn_on_delete_failure : bool = False ,
2725 console : t .Optional [Console ] = None ,
28- ) -> None :
26+ ) -> t .List [str ]:
27+ failures : t .List [str ] = []
28+
2929 expired_schema_or_catalog_environments = [
3030 environment
3131 for environment in environments
@@ -85,10 +85,8 @@ def get_adapter(gateway_managed: bool, gateway: t.Optional[str] = None) -> Engin
8585 console .update_cleanup_progress (expired_view )
8686 except Exception as e :
8787 message = f"Failed to drop the expired environment view '{ expired_view } ': { e } "
88- if warn_on_delete_failure :
89- logger .warning (message )
90- else :
91- raise SQLMeshError (message ) from e
88+ logger .warning (message )
89+ failures .append (message )
9290
9391 # Drop the schemas for the expired environments
9492 for engine_adapter , schema in schemas_to_drop :
@@ -102,10 +100,8 @@ def get_adapter(gateway_managed: bool, gateway: t.Optional[str] = None) -> Engin
102100 console .update_cleanup_progress (schema .sql (dialect = engine_adapter .dialect ))
103101 except Exception as e :
104102 message = f"Failed to drop the expired environment schema '{ schema } ': { e } "
105- if warn_on_delete_failure :
106- logger .warning (message )
107- else :
108- raise SQLMeshError (message ) from e
103+ logger .warning (message )
104+ failures .append (message )
109105
110106 # Drop any catalogs that were associated with a snapshot where the engine adapter supports dropping catalogs
111107 # catalogs_to_drop is only populated when environment_suffix_target is set to 'catalog'
@@ -117,10 +113,10 @@ def get_adapter(gateway_managed: bool, gateway: t.Optional[str] = None) -> Engin
117113 console .update_cleanup_progress (catalog )
118114 except Exception as e :
119115 message = f"Failed to drop the expired environment catalog '{ catalog } ': { e } "
120- if warn_on_delete_failure :
121- logger . warning (message )
122- else :
123- raise SQLMeshError ( message ) from e
116+ logger . warning ( message )
117+ failures . append (message )
118+
119+ return failures
124120
125121
126122def delete_expired_snapshots (
@@ -129,9 +125,10 @@ def delete_expired_snapshots(
129125 * ,
130126 current_ts : int ,
131127 ignore_ttl : bool = False ,
128+ force_delete : bool = False ,
132129 batch_size : t .Optional [int ] = None ,
133130 console : t .Optional [Console ] = None ,
134- ) -> None :
131+ ) -> t . List [ str ] :
135132 """Delete all expired snapshots in batches.
136133
137134 This helper function encapsulates the logic for deleting expired snapshots in batches,
@@ -142,12 +139,14 @@ def delete_expired_snapshots(
142139 snapshot_evaluator: SnapshotEvaluator instance to clean up tables associated with snapshots.
143140 current_ts: Timestamp used to evaluate expiration.
144141 ignore_ttl: If True, include snapshots regardless of TTL (only checks if unreferenced).
142+ force_delete: If True, delete snapshot state records even when physical table cleanup fails.
145143 batch_size: Maximum number of snapshots to fetch per batch.
146144 console: Optional console for reporting progress.
147145
148146 Returns:
149- The total number of deleted expired snapshots .
147+ List of failure messages so callers can surface them at the end of the janitor run .
150148 """
149+ failures : t .List [str ] = []
151150 num_expired_snapshots = 0
152151 for batch in iter_expired_snapshot_batches (
153152 state_reader = state_sync ,
@@ -165,17 +164,32 @@ def delete_expired_snapshots(
165164 len (batch .expired_snapshot_ids ),
166165 end_info ,
167166 )
168- snapshot_evaluator .cleanup (
169- target_snapshots = batch .cleanup_tasks ,
170- on_complete = console .update_cleanup_progress if console else None ,
171- )
172- state_sync .delete_expired_snapshots (
173- batch_range = ExpiredBatchRange (
174- start = RowBoundary .lowest_boundary (),
175- end = batch .batch_range .end ,
176- ),
177- ignore_ttl = ignore_ttl ,
178- )
179- logger .info ("Cleaned up expired snapshots batch" )
180- num_expired_snapshots += len (batch .expired_snapshot_ids )
167+ cleanup_succeeded = True
168+ try :
169+ snapshot_evaluator .cleanup (
170+ target_snapshots = batch .cleanup_tasks ,
171+ on_complete = console .update_cleanup_progress if console else None ,
172+ )
173+ except Exception as failed_drops :
174+ message = f"Failed to clean up: { failed_drops } "
175+ logger .warning (message )
176+ failures .append (message )
177+ cleanup_succeeded = False
178+
179+ if cleanup_succeeded or force_delete :
180+ try :
181+ state_sync .delete_expired_snapshots (
182+ batch_range = ExpiredBatchRange (
183+ start = RowBoundary .lowest_boundary (),
184+ end = batch .batch_range .end ,
185+ ),
186+ ignore_ttl = ignore_ttl ,
187+ )
188+ logger .info ("Cleaned up expired snapshots batch" )
189+ num_expired_snapshots += len (batch .expired_snapshot_ids )
190+ except Exception as e :
191+ message = f"Failed to delete expired snapshot state records: { e } "
192+ logger .warning (message )
193+ failures .append (message )
181194 logger .info ("Cleaned up %s expired snapshots" , num_expired_snapshots )
195+ return failures
0 commit comments