2929)
3030
3131import attrs
32- from sqlalchemy import select
32+ from sqlalchemy import and_ , select
3333
3434from airflow .models .asset import (
35+ AssetAliasModel ,
36+ AssetEvent ,
3537 AssetModel ,
3638)
39+ from airflow .sdk .definitions .asset import (
40+ Asset ,
41+ AssetAlias ,
42+ AssetAliasUniqueKey ,
43+ AssetNameRef ,
44+ AssetRef ,
45+ AssetUniqueKey ,
46+ AssetUriRef ,
47+ )
3748from airflow .sdk .definitions .context import Context
3849from airflow .sdk .execution_time .context import (
3950 ConnectionAccessor as ConnectionAccessorSDK ,
4051 InletEventsAccessors as InletEventsAccessorsSDK ,
4152 OutletEventAccessors as OutletEventAccessorsSDK ,
4253 VariableAccessor as VariableAccessorSDK ,
4354)
55+ from airflow .utils .db import LazySelectSequence
4456from airflow .utils .session import create_session
4557from airflow .utils .types import NOTSET
4658
4759if TYPE_CHECKING :
60+ from sqlalchemy .engine import Row
61+ from sqlalchemy .sql .expression import Select , TextClause
62+
4863 from airflow .sdk .types import OutletEventAccessorsProtocol
4964
5065# NOTE: Please keep this in sync with the following:
@@ -150,6 +165,22 @@ def _get_asset_from_db(name: str | None = None, uri: str | None = None) -> Asset
150165 return asset .to_public ()
151166
152167
168+ class LazyAssetEventSelectSequence (LazySelectSequence [AssetEvent ]):
169+ """
170+ List-like interface to lazily access AssetEvent rows.
171+
172+ :meta private:
173+ """
174+
175+ @staticmethod
176+ def _rebuild_select (stmt : TextClause ) -> Select :
177+ return select (AssetEvent ).from_statement (stmt )
178+
179+ @staticmethod
180+ def _process_row (row : Row ) -> AssetEvent :
181+ return row [0 ]
182+
183+
153184@attrs .define (init = False )
154185class InletEventsAccessors (InletEventsAccessorsSDK ):
155186 """
@@ -158,6 +189,37 @@ class InletEventsAccessors(InletEventsAccessorsSDK):
158189 :meta private:
159190 """
160191
192+ def _get_asset_events_from_db (self , obj : Asset | AssetAlias | AssetRef ):
193+ if isinstance (obj , Asset ):
194+ asset = self ._assets [AssetUniqueKey .from_asset (obj )]
195+ join_clause = AssetEvent .asset
196+ where_clause = and_ (AssetModel .name == asset .name , AssetModel .uri == asset .uri )
197+ elif isinstance (obj , AssetAlias ):
198+ asset_alias = self ._asset_aliases [AssetAliasUniqueKey .from_asset_alias (obj )]
199+ join_clause = AssetEvent .source_aliases
200+ where_clause = AssetAliasModel .name == asset_alias .name
201+ elif isinstance (obj , AssetNameRef ):
202+ try :
203+ asset = next (a for k , a in self ._assets .items () if k .name == obj .name )
204+ except StopIteration :
205+ raise KeyError (obj ) from None
206+ join_clause = AssetEvent .asset
207+ where_clause = and_ (AssetModel .name == asset .name , AssetModel .active .has ())
208+ elif isinstance (obj , AssetUriRef ):
209+ try :
210+ asset = next (a for k , a in self ._assets .items () if k .uri == obj .uri )
211+ except StopIteration :
212+ raise KeyError (obj ) from None
213+ join_clause = AssetEvent .asset
214+ where_clause = and_ (AssetModel .uri == asset .uri , AssetModel .active .has ())
215+
216+ with create_session () as session :
217+ return LazyAssetEventSelectSequence .from_select (
218+ select (AssetEvent ).join (join_clause ).where (where_clause ),
219+ order_by = [AssetEvent .timestamp ],
220+ session = session ,
221+ )
222+
161223
162224def context_merge (context : Context , * args : Any , ** kwargs : Any ) -> None :
163225 """
0 commit comments