49
49
from airbyte_cdk .sources .streams .concurrent .availability_strategy import (
50
50
AlwaysAvailableAvailabilityStrategy ,
51
51
)
52
+ from airbyte_cdk .sources .streams .concurrent .cursor import FinalStateCursor
52
53
from airbyte_cdk .sources .streams .concurrent .default_stream import DefaultStream
53
54
from airbyte_cdk .sources .streams .concurrent .helpers import get_primary_key_from_stream
54
55
from airbyte_cdk .sources .types import Config , StreamState
@@ -69,6 +70,15 @@ def __init__(
69
70
component_factory : Optional [ModelToComponentFactory ] = None ,
70
71
** kwargs : Any ,
71
72
) -> None :
73
+ # To reduce the complexity of the concurrent framework, we are not enabling RFR with synthetic
74
+ # cursors. We do this by no longer automatically instantiating RFR cursors when converting
75
+ # the declarative models into runtime components. Concurrent sources will continue to checkpoint
76
+ # incremental streams running in full refresh.
77
+ component_factory = component_factory or ModelToComponentFactory (
78
+ emit_connector_builder_messages = emit_connector_builder_messages ,
79
+ disable_resumable_full_refresh = True ,
80
+ )
81
+
72
82
super ().__init__ (
73
83
source_config = source_config ,
74
84
debug = debug ,
@@ -191,13 +201,24 @@ def _group_streams(
191
201
# these legacy Python streams the way we do low-code streams to determine if they are concurrent compatible,
192
202
# so we need to treat them as synchronous
193
203
if isinstance (declarative_stream , DeclarativeStream ):
194
- datetime_based_cursor_component_definition = name_to_stream_mapping [
204
+ incremental_sync_component_definition = name_to_stream_mapping [
195
205
declarative_stream .name
196
206
].get ("incremental_sync" )
197
207
208
+ partition_router_component_definition = (
209
+ name_to_stream_mapping [declarative_stream .name ]
210
+ .get ("retriever" )
211
+ .get ("partition_router" )
212
+ )
213
+
214
+ is_substream_without_incremental = (
215
+ partition_router_component_definition
216
+ and not incremental_sync_component_definition
217
+ )
218
+
198
219
if (
199
- datetime_based_cursor_component_definition
200
- and datetime_based_cursor_component_definition .get ("type" , "" )
220
+ incremental_sync_component_definition
221
+ and incremental_sync_component_definition .get ("type" , "" )
201
222
== DatetimeBasedCursorModel .__name__
202
223
and self ._stream_supports_concurrent_partition_processing (
203
224
declarative_stream = declarative_stream
@@ -213,7 +234,7 @@ def _group_streams(
213
234
self ._constructor .create_concurrent_cursor_from_datetime_based_cursor (
214
235
state_manager = state_manager ,
215
236
model_type = DatetimeBasedCursorModel ,
216
- component_definition = datetime_based_cursor_component_definition ,
237
+ component_definition = incremental_sync_component_definition ,
217
238
stream_name = declarative_stream .name ,
218
239
stream_namespace = declarative_stream .namespace ,
219
240
config = config or {},
@@ -247,6 +268,41 @@ def _group_streams(
247
268
cursor = cursor ,
248
269
)
249
270
)
271
+ elif is_substream_without_incremental and hasattr (
272
+ declarative_stream .retriever , "stream_slicer"
273
+ ):
274
+ partition_generator = StreamSlicerPartitionGenerator (
275
+ DeclarativePartitionFactory (
276
+ declarative_stream .name ,
277
+ declarative_stream .get_json_schema (),
278
+ self ._retriever_factory (
279
+ name_to_stream_mapping [declarative_stream .name ],
280
+ config ,
281
+ {},
282
+ ),
283
+ self .message_repository ,
284
+ ),
285
+ declarative_stream .retriever .stream_slicer ,
286
+ )
287
+
288
+ final_state_cursor = FinalStateCursor (
289
+ stream_name = declarative_stream .name ,
290
+ stream_namespace = declarative_stream .namespace ,
291
+ message_repository = self .message_repository ,
292
+ )
293
+
294
+ concurrent_streams .append (
295
+ DefaultStream (
296
+ partition_generator = partition_generator ,
297
+ name = declarative_stream .name ,
298
+ json_schema = declarative_stream .get_json_schema (),
299
+ availability_strategy = AlwaysAvailableAvailabilityStrategy (),
300
+ primary_key = get_primary_key_from_stream (declarative_stream .primary_key ),
301
+ cursor_field = None ,
302
+ logger = self .logger ,
303
+ cursor = final_state_cursor ,
304
+ )
305
+ )
250
306
else :
251
307
synchronous_streams .append (declarative_stream )
252
308
else :
0 commit comments