airbyte-cdk 6.31.2.dev0__py3-none-any.whl → 6.33.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- airbyte_cdk/cli/source_declarative_manifest/_run.py +9 -3
- airbyte_cdk/connector_builder/connector_builder_handler.py +3 -2
- airbyte_cdk/sources/declarative/async_job/job_orchestrator.py +7 -7
- airbyte_cdk/sources/declarative/auth/jwt.py +17 -11
- airbyte_cdk/sources/declarative/auth/oauth.py +89 -23
- airbyte_cdk/sources/declarative/auth/token_provider.py +4 -5
- airbyte_cdk/sources/declarative/checks/check_dynamic_stream.py +19 -9
- airbyte_cdk/sources/declarative/concurrent_declarative_source.py +145 -43
- airbyte_cdk/sources/declarative/declarative_component_schema.yaml +51 -2
- airbyte_cdk/sources/declarative/declarative_stream.py +3 -1
- airbyte_cdk/sources/declarative/extractors/record_filter.py +3 -5
- airbyte_cdk/sources/declarative/incremental/__init__.py +6 -0
- airbyte_cdk/sources/declarative/incremental/concurrent_partition_cursor.py +400 -0
- airbyte_cdk/sources/declarative/incremental/global_substream_cursor.py +3 -0
- airbyte_cdk/sources/declarative/incremental/per_partition_cursor.py +35 -3
- airbyte_cdk/sources/declarative/manifest_declarative_source.py +20 -7
- airbyte_cdk/sources/declarative/models/declarative_component_schema.py +41 -5
- airbyte_cdk/sources/declarative/parsers/custom_code_compiler.py +143 -0
- airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +313 -30
- airbyte_cdk/sources/declarative/partition_routers/async_job_partition_router.py +5 -5
- airbyte_cdk/sources/declarative/partition_routers/substream_partition_router.py +46 -12
- airbyte_cdk/sources/declarative/requesters/error_handlers/composite_error_handler.py +22 -0
- airbyte_cdk/sources/declarative/requesters/error_handlers/http_response_filter.py +4 -4
- airbyte_cdk/sources/declarative/retrievers/async_retriever.py +6 -12
- airbyte_cdk/sources/declarative/retrievers/simple_retriever.py +1 -1
- airbyte_cdk/sources/declarative/schema/__init__.py +2 -0
- airbyte_cdk/sources/declarative/schema/dynamic_schema_loader.py +44 -5
- airbyte_cdk/sources/http_logger.py +1 -1
- airbyte_cdk/sources/streams/concurrent/clamping.py +99 -0
- airbyte_cdk/sources/streams/concurrent/cursor.py +51 -57
- airbyte_cdk/sources/streams/concurrent/cursor_types.py +32 -0
- airbyte_cdk/sources/streams/concurrent/state_converters/datetime_stream_state_converter.py +22 -13
- airbyte_cdk/sources/streams/core.py +6 -6
- airbyte_cdk/sources/streams/http/http.py +1 -2
- airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py +231 -62
- airbyte_cdk/sources/streams/http/requests_native_auth/oauth.py +171 -88
- airbyte_cdk/sources/types.py +4 -2
- airbyte_cdk/sources/utils/transform.py +23 -2
- airbyte_cdk/test/utils/manifest_only_fixtures.py +1 -2
- airbyte_cdk/utils/datetime_helpers.py +499 -0
- airbyte_cdk/utils/slice_hasher.py +8 -1
- airbyte_cdk-6.33.0.dist-info/LICENSE_SHORT +1 -0
- {airbyte_cdk-6.31.2.dev0.dist-info → airbyte_cdk-6.33.0.dist-info}/METADATA +6 -6
- {airbyte_cdk-6.31.2.dev0.dist-info → airbyte_cdk-6.33.0.dist-info}/RECORD +47 -41
- {airbyte_cdk-6.31.2.dev0.dist-info → airbyte_cdk-6.33.0.dist-info}/WHEEL +1 -1
- {airbyte_cdk-6.31.2.dev0.dist-info → airbyte_cdk-6.33.0.dist-info}/LICENSE.txt +0 -0
- {airbyte_cdk-6.31.2.dev0.dist-info → airbyte_cdk-6.33.0.dist-info}/entry_points.txt +0 -0
@@ -19,7 +19,11 @@ from airbyte_cdk.sources.declarative.extractors import RecordSelector
|
|
19
19
|
from airbyte_cdk.sources.declarative.extractors.record_filter import (
|
20
20
|
ClientSideIncrementalRecordFilterDecorator,
|
21
21
|
)
|
22
|
+
from airbyte_cdk.sources.declarative.incremental import ConcurrentPerPartitionCursor
|
22
23
|
from airbyte_cdk.sources.declarative.incremental.datetime_based_cursor import DatetimeBasedCursor
|
24
|
+
from airbyte_cdk.sources.declarative.incremental.per_partition_with_global import (
|
25
|
+
PerPartitionWithGlobalCursor,
|
26
|
+
)
|
23
27
|
from airbyte_cdk.sources.declarative.interpolation import InterpolatedString
|
24
28
|
from airbyte_cdk.sources.declarative.manifest_declarative_source import ManifestDeclarativeSource
|
25
29
|
from airbyte_cdk.sources.declarative.models.declarative_component_schema import (
|
@@ -31,8 +35,9 @@ from airbyte_cdk.sources.declarative.models.declarative_component_schema import
|
|
31
35
|
from airbyte_cdk.sources.declarative.parsers.model_to_component_factory import (
|
32
36
|
ModelToComponentFactory,
|
33
37
|
)
|
38
|
+
from airbyte_cdk.sources.declarative.partition_routers import AsyncJobPartitionRouter
|
34
39
|
from airbyte_cdk.sources.declarative.requesters import HttpRequester
|
35
|
-
from airbyte_cdk.sources.declarative.retrievers import SimpleRetriever
|
40
|
+
from airbyte_cdk.sources.declarative.retrievers import AsyncRetriever, Retriever, SimpleRetriever
|
36
41
|
from airbyte_cdk.sources.declarative.stream_slicers.declarative_partition_generator import (
|
37
42
|
DeclarativePartitionFactory,
|
38
43
|
StreamSlicerPartitionGenerator,
|
@@ -45,7 +50,7 @@ from airbyte_cdk.sources.streams.concurrent.abstract_stream import AbstractStrea
|
|
45
50
|
from airbyte_cdk.sources.streams.concurrent.availability_strategy import (
|
46
51
|
AlwaysAvailableAvailabilityStrategy,
|
47
52
|
)
|
48
|
-
from airbyte_cdk.sources.streams.concurrent.cursor import FinalStateCursor
|
53
|
+
from airbyte_cdk.sources.streams.concurrent.cursor import ConcurrentCursor, FinalStateCursor
|
49
54
|
from airbyte_cdk.sources.streams.concurrent.default_stream import DefaultStream
|
50
55
|
from airbyte_cdk.sources.streams.concurrent.helpers import get_primary_key_from_stream
|
51
56
|
|
@@ -66,6 +71,10 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
|
|
66
71
|
component_factory: Optional[ModelToComponentFactory] = None,
|
67
72
|
**kwargs: Any,
|
68
73
|
) -> None:
|
74
|
+
# todo: We could remove state from initialization. Now that streams are grouped during the read(), a source
|
75
|
+
# no longer needs to store the original incoming state. But maybe there's an edge case?
|
76
|
+
self._connector_state_manager = ConnectorStateManager(state=state) # type: ignore # state is always in the form of List[AirbyteStateMessage]. The ConnectorStateManager should use generics, but this can be done later
|
77
|
+
|
69
78
|
# To reduce the complexity of the concurrent framework, we are not enabling RFR with synthetic
|
70
79
|
# cursors. We do this by no longer automatically instantiating RFR cursors when converting
|
71
80
|
# the declarative models into runtime components. Concurrent sources will continue to checkpoint
|
@@ -73,19 +82,17 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
|
|
73
82
|
component_factory = component_factory or ModelToComponentFactory(
|
74
83
|
emit_connector_builder_messages=emit_connector_builder_messages,
|
75
84
|
disable_resumable_full_refresh=True,
|
85
|
+
connector_state_manager=self._connector_state_manager,
|
76
86
|
)
|
77
87
|
|
78
88
|
super().__init__(
|
79
89
|
source_config=source_config,
|
90
|
+
config=config,
|
80
91
|
debug=debug,
|
81
92
|
emit_connector_builder_messages=emit_connector_builder_messages,
|
82
93
|
component_factory=component_factory,
|
83
94
|
)
|
84
95
|
|
85
|
-
# todo: We could remove state from initialization. Now that streams are grouped during the read(), a source
|
86
|
-
# no longer needs to store the original incoming state. But maybe there's an edge case?
|
87
|
-
self._state = state
|
88
|
-
|
89
96
|
concurrency_level_from_manifest = self._source_config.get("concurrency_level")
|
90
97
|
if concurrency_level_from_manifest:
|
91
98
|
concurrency_level_component = self._constructor.create_component(
|
@@ -175,8 +182,6 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
|
|
175
182
|
concurrent_streams: List[AbstractStream] = []
|
176
183
|
synchronous_streams: List[Stream] = []
|
177
184
|
|
178
|
-
state_manager = ConnectorStateManager(state=self._state) # type: ignore # state is always in the form of List[AirbyteStateMessage]. The ConnectorStateManager should use generics, but this can be done later
|
179
|
-
|
180
185
|
# Combine streams and dynamic_streams. Note: both cannot be empty at the same time,
|
181
186
|
# and this is validated during the initialization of the source.
|
182
187
|
streams = self._stream_configs(self._source_config) + self._dynamic_stream_configs(
|
@@ -216,45 +221,52 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
|
|
216
221
|
if self._is_datetime_incremental_without_partition_routing(
|
217
222
|
declarative_stream, incremental_sync_component_definition
|
218
223
|
):
|
219
|
-
stream_state =
|
224
|
+
stream_state = self._connector_state_manager.get_stream_state(
|
220
225
|
stream_name=declarative_stream.name, namespace=declarative_stream.namespace
|
221
226
|
)
|
222
227
|
|
223
|
-
|
224
|
-
state_manager=state_manager,
|
225
|
-
model_type=DatetimeBasedCursorModel,
|
226
|
-
component_definition=incremental_sync_component_definition, # type: ignore # Not None because of the if condition above
|
227
|
-
stream_name=declarative_stream.name,
|
228
|
-
stream_namespace=declarative_stream.namespace,
|
229
|
-
config=config or {},
|
230
|
-
stream_state=stream_state,
|
231
|
-
)
|
228
|
+
retriever = self._get_retriever(declarative_stream, stream_state)
|
232
229
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
if declarative_stream and isinstance(retriever, SimpleRetriever):
|
238
|
-
# Also a temporary hack. In the legacy Stream implementation, as part of the read,
|
239
|
-
# set_initial_state() is called to instantiate incoming state on the cursor. Although we no
|
240
|
-
# longer rely on the legacy low-code cursor for concurrent checkpointing, low-code components
|
241
|
-
# like StopConditionPaginationStrategyDecorator and ClientSideIncrementalRecordFilterDecorator
|
242
|
-
# still rely on a DatetimeBasedCursor that is properly initialized with state.
|
243
|
-
if retriever.cursor:
|
244
|
-
retriever.cursor.set_initial_state(stream_state=stream_state)
|
245
|
-
# We zero it out here, but since this is a cursor reference, the state is still properly
|
246
|
-
# instantiated for the other components that reference it
|
247
|
-
retriever.cursor = None
|
230
|
+
if isinstance(declarative_stream.retriever, AsyncRetriever) and isinstance(
|
231
|
+
declarative_stream.retriever.stream_slicer, AsyncJobPartitionRouter
|
232
|
+
):
|
233
|
+
cursor = declarative_stream.retriever.stream_slicer.stream_slicer
|
248
234
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
235
|
+
if not isinstance(cursor, ConcurrentCursor | ConcurrentPerPartitionCursor):
|
236
|
+
# This should never happen since we instantiate ConcurrentCursor in
|
237
|
+
# model_to_component_factory.py
|
238
|
+
raise ValueError(
|
239
|
+
f"Expected AsyncJobPartitionRouter stream_slicer to be of type ConcurrentCursor, but received{cursor.__class__}"
|
240
|
+
)
|
241
|
+
|
242
|
+
partition_generator = StreamSlicerPartitionGenerator(
|
243
|
+
partition_factory=DeclarativePartitionFactory(
|
244
|
+
declarative_stream.name,
|
245
|
+
declarative_stream.get_json_schema(),
|
246
|
+
retriever,
|
247
|
+
self.message_repository,
|
248
|
+
),
|
249
|
+
stream_slicer=declarative_stream.retriever.stream_slicer,
|
250
|
+
)
|
251
|
+
else:
|
252
|
+
cursor = (
|
253
|
+
self._constructor.create_concurrent_cursor_from_datetime_based_cursor(
|
254
|
+
model_type=DatetimeBasedCursorModel,
|
255
|
+
component_definition=incremental_sync_component_definition, # type: ignore # Not None because of the if condition above
|
256
|
+
stream_name=declarative_stream.name,
|
257
|
+
stream_namespace=declarative_stream.namespace,
|
258
|
+
config=config or {},
|
259
|
+
)
|
260
|
+
)
|
261
|
+
partition_generator = StreamSlicerPartitionGenerator(
|
262
|
+
partition_factory=DeclarativePartitionFactory(
|
263
|
+
declarative_stream.name,
|
264
|
+
declarative_stream.get_json_schema(),
|
265
|
+
retriever,
|
266
|
+
self.message_repository,
|
267
|
+
),
|
268
|
+
stream_slicer=cursor,
|
269
|
+
)
|
258
270
|
|
259
271
|
concurrent_streams.append(
|
260
272
|
DefaultStream(
|
@@ -304,6 +316,60 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
|
|
304
316
|
cursor=final_state_cursor,
|
305
317
|
)
|
306
318
|
)
|
319
|
+
elif (
|
320
|
+
incremental_sync_component_definition
|
321
|
+
and incremental_sync_component_definition.get("type", "")
|
322
|
+
== DatetimeBasedCursorModel.__name__
|
323
|
+
and self._stream_supports_concurrent_partition_processing(
|
324
|
+
declarative_stream=declarative_stream
|
325
|
+
)
|
326
|
+
and hasattr(declarative_stream.retriever, "stream_slicer")
|
327
|
+
and isinstance(
|
328
|
+
declarative_stream.retriever.stream_slicer, PerPartitionWithGlobalCursor
|
329
|
+
)
|
330
|
+
):
|
331
|
+
stream_state = self._connector_state_manager.get_stream_state(
|
332
|
+
stream_name=declarative_stream.name, namespace=declarative_stream.namespace
|
333
|
+
)
|
334
|
+
partition_router = declarative_stream.retriever.stream_slicer._partition_router
|
335
|
+
|
336
|
+
perpartition_cursor = (
|
337
|
+
self._constructor.create_concurrent_cursor_from_perpartition_cursor(
|
338
|
+
state_manager=self._connector_state_manager,
|
339
|
+
model_type=DatetimeBasedCursorModel,
|
340
|
+
component_definition=incremental_sync_component_definition,
|
341
|
+
stream_name=declarative_stream.name,
|
342
|
+
stream_namespace=declarative_stream.namespace,
|
343
|
+
config=config or {},
|
344
|
+
stream_state=stream_state,
|
345
|
+
partition_router=partition_router,
|
346
|
+
)
|
347
|
+
)
|
348
|
+
|
349
|
+
retriever = self._get_retriever(declarative_stream, stream_state)
|
350
|
+
|
351
|
+
partition_generator = StreamSlicerPartitionGenerator(
|
352
|
+
DeclarativePartitionFactory(
|
353
|
+
declarative_stream.name,
|
354
|
+
declarative_stream.get_json_schema(),
|
355
|
+
retriever,
|
356
|
+
self.message_repository,
|
357
|
+
),
|
358
|
+
perpartition_cursor,
|
359
|
+
)
|
360
|
+
|
361
|
+
concurrent_streams.append(
|
362
|
+
DefaultStream(
|
363
|
+
partition_generator=partition_generator,
|
364
|
+
name=declarative_stream.name,
|
365
|
+
json_schema=declarative_stream.get_json_schema(),
|
366
|
+
availability_strategy=AlwaysAvailableAvailabilityStrategy(),
|
367
|
+
primary_key=get_primary_key_from_stream(declarative_stream.primary_key),
|
368
|
+
cursor_field=perpartition_cursor.cursor_field.cursor_field_key,
|
369
|
+
logger=self.logger,
|
370
|
+
cursor=perpartition_cursor,
|
371
|
+
)
|
372
|
+
)
|
307
373
|
else:
|
308
374
|
synchronous_streams.append(declarative_stream)
|
309
375
|
else:
|
@@ -325,7 +391,10 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
|
|
325
391
|
declarative_stream=declarative_stream
|
326
392
|
)
|
327
393
|
and hasattr(declarative_stream.retriever, "stream_slicer")
|
328
|
-
and
|
394
|
+
and (
|
395
|
+
isinstance(declarative_stream.retriever.stream_slicer, DatetimeBasedCursor)
|
396
|
+
or isinstance(declarative_stream.retriever.stream_slicer, AsyncJobPartitionRouter)
|
397
|
+
)
|
329
398
|
)
|
330
399
|
|
331
400
|
def _stream_supports_concurrent_partition_processing(
|
@@ -394,6 +463,39 @@ class ConcurrentDeclarativeSource(ManifestDeclarativeSource, Generic[TState]):
|
|
394
463
|
return False
|
395
464
|
return True
|
396
465
|
|
466
|
+
@staticmethod
|
467
|
+
def _get_retriever(
|
468
|
+
declarative_stream: DeclarativeStream, stream_state: Mapping[str, Any]
|
469
|
+
) -> Retriever:
|
470
|
+
retriever = declarative_stream.retriever
|
471
|
+
|
472
|
+
# This is an optimization so that we don't invoke any cursor or state management flows within the
|
473
|
+
# low-code framework because state management is handled through the ConcurrentCursor.
|
474
|
+
if declarative_stream and isinstance(retriever, SimpleRetriever):
|
475
|
+
# Also a temporary hack. In the legacy Stream implementation, as part of the read,
|
476
|
+
# set_initial_state() is called to instantiate incoming state on the cursor. Although we no
|
477
|
+
# longer rely on the legacy low-code cursor for concurrent checkpointing, low-code components
|
478
|
+
# like StopConditionPaginationStrategyDecorator still rely on a DatetimeBasedCursor that is
|
479
|
+
# properly initialized with state.
|
480
|
+
if retriever.cursor:
|
481
|
+
retriever.cursor.set_initial_state(stream_state=stream_state)
|
482
|
+
|
483
|
+
# Similar to above, the ClientSideIncrementalRecordFilterDecorator cursor is a separate instance
|
484
|
+
# from the one initialized on the SimpleRetriever, so it also must also have state initialized
|
485
|
+
# for semi-incremental streams using is_client_side_incremental to filter properly
|
486
|
+
if isinstance(retriever.record_selector, RecordSelector) and isinstance(
|
487
|
+
retriever.record_selector.record_filter, ClientSideIncrementalRecordFilterDecorator
|
488
|
+
):
|
489
|
+
retriever.record_selector.record_filter._cursor.set_initial_state(
|
490
|
+
stream_state=stream_state
|
491
|
+
) # type: ignore # After non-concurrent cursors are deprecated we can remove these cursor workarounds
|
492
|
+
|
493
|
+
# We zero it out here, but since this is a cursor reference, the state is still properly
|
494
|
+
# instantiated for the other components that reference it
|
495
|
+
retriever.cursor = None
|
496
|
+
|
497
|
+
return retriever
|
498
|
+
|
397
499
|
@staticmethod
|
398
500
|
def _select_streams(
|
399
501
|
streams: List[AbstractStream], configured_catalog: ConfiguredAirbyteCatalog
|
@@ -320,6 +320,11 @@ definitions:
|
|
320
320
|
title: Stream Count
|
321
321
|
description: Numbers of the streams to try reading from when running a check operation.
|
322
322
|
type: integer
|
323
|
+
use_check_availability:
|
324
|
+
title: Use Check Availability
|
325
|
+
description: Enables stream check availability. This field is automatically set by the CDK.
|
326
|
+
type: boolean
|
327
|
+
default: true
|
323
328
|
CompositeErrorHandler:
|
324
329
|
title: Composite Error Handler
|
325
330
|
description: Error handler that sequentially iterates over a list of error handlers.
|
@@ -784,6 +789,29 @@ definitions:
|
|
784
789
|
type:
|
785
790
|
type: string
|
786
791
|
enum: [DatetimeBasedCursor]
|
792
|
+
clamping:
|
793
|
+
title: Date Range Clamping
|
794
|
+
description: This option is used to adjust the upper and lower boundaries of each datetime window to beginning and end of the provided target period (day, week, month)
|
795
|
+
type: object
|
796
|
+
required:
|
797
|
+
- target
|
798
|
+
properties:
|
799
|
+
target:
|
800
|
+
title: Target
|
801
|
+
description: The period of time that datetime windows will be clamped by
|
802
|
+
# This should ideally be an enum. However, we don't use an enum because we want to allow for connectors
|
803
|
+
# to support interpolation on the connector config to get the target which is an arbitrary string
|
804
|
+
type: string
|
805
|
+
interpolation_context:
|
806
|
+
- config
|
807
|
+
examples:
|
808
|
+
- "DAY"
|
809
|
+
- "WEEK"
|
810
|
+
- "MONTH"
|
811
|
+
- "{{ config['target'] }}"
|
812
|
+
target_details:
|
813
|
+
type: object
|
814
|
+
additionalProperties: true
|
787
815
|
cursor_field:
|
788
816
|
title: Cursor Field
|
789
817
|
description: The location of the value on a record that will be used as a bookmark during sync. To ensure no data loss, the API must return records in ascending order based on the cursor field. Nested fields are not supported, so the field must be at the top level of the record. You can use a combination of Add Field and Remove Field transformations to move the nested field to the top.
|
@@ -1058,8 +1086,6 @@ definitions:
|
|
1058
1086
|
type: object
|
1059
1087
|
required:
|
1060
1088
|
- type
|
1061
|
-
- client_id
|
1062
|
-
- client_secret
|
1063
1089
|
properties:
|
1064
1090
|
type:
|
1065
1091
|
type: string
|
@@ -1254,6 +1280,15 @@ definitions:
|
|
1254
1280
|
default: []
|
1255
1281
|
examples:
|
1256
1282
|
- ["invalid_grant", "invalid_permissions"]
|
1283
|
+
profile_assertion:
|
1284
|
+
title: Profile Assertion
|
1285
|
+
description: The authenticator being used to authenticate the client authenticator.
|
1286
|
+
"$ref": "#/definitions/JwtAuthenticator"
|
1287
|
+
use_profile_assertion:
|
1288
|
+
title: Use Profile Assertion
|
1289
|
+
description: Enable using profile assertion as a flow for OAuth authorization.
|
1290
|
+
type: boolean
|
1291
|
+
default: false
|
1257
1292
|
$parameters:
|
1258
1293
|
type: object
|
1259
1294
|
additionalProperties: true
|
@@ -1770,6 +1805,19 @@ definitions:
|
|
1770
1805
|
$parameters:
|
1771
1806
|
type: object
|
1772
1807
|
additionalProperties: true
|
1808
|
+
ComplexFieldType:
|
1809
|
+
title: Schema Field Type
|
1810
|
+
description: (This component is experimental. Use at your own risk.) Represents a complex field type.
|
1811
|
+
type: object
|
1812
|
+
required:
|
1813
|
+
- field_type
|
1814
|
+
properties:
|
1815
|
+
field_type:
|
1816
|
+
type: string
|
1817
|
+
items:
|
1818
|
+
anyOf:
|
1819
|
+
- type: string
|
1820
|
+
- "$ref": "#/definitions/ComplexFieldType"
|
1773
1821
|
TypesMap:
|
1774
1822
|
title: Types Map
|
1775
1823
|
description: (This component is experimental. Use at your own risk.) Represents a mapping between a current type and its corresponding target type.
|
@@ -1784,6 +1832,7 @@ definitions:
|
|
1784
1832
|
- type: array
|
1785
1833
|
items:
|
1786
1834
|
type: string
|
1835
|
+
- "$ref": "#/definitions/ComplexFieldType"
|
1787
1836
|
current_type:
|
1788
1837
|
anyOf:
|
1789
1838
|
- type: string
|
@@ -138,7 +138,9 @@ class DeclarativeStream(Stream):
|
|
138
138
|
"""
|
139
139
|
:param: stream_state We knowingly avoid using stream_state as we want cursors to manage their own state.
|
140
140
|
"""
|
141
|
-
if stream_slice is None or
|
141
|
+
if stream_slice is None or (
|
142
|
+
not isinstance(stream_slice, StreamSlice) and stream_slice == {}
|
143
|
+
):
|
142
144
|
# As the parameter is Optional, many would just call `read_records(sync_mode)` during testing without specifying the field
|
143
145
|
# As part of the declarative model without custom components, this should never happen as the CDK would wire up a
|
144
146
|
# SinglePartitionRouter that would create this StreamSlice properly
|
@@ -59,13 +59,11 @@ class ClientSideIncrementalRecordFilterDecorator(RecordFilter):
|
|
59
59
|
|
60
60
|
def __init__(
|
61
61
|
self,
|
62
|
-
|
63
|
-
substream_cursor: Optional[Union[PerPartitionWithGlobalCursor, GlobalSubstreamCursor]],
|
62
|
+
cursor: Union[DatetimeBasedCursor, PerPartitionWithGlobalCursor, GlobalSubstreamCursor],
|
64
63
|
**kwargs: Any,
|
65
64
|
):
|
66
65
|
super().__init__(**kwargs)
|
67
|
-
self.
|
68
|
-
self._substream_cursor = substream_cursor
|
66
|
+
self._cursor = cursor
|
69
67
|
|
70
68
|
def filter_records(
|
71
69
|
self,
|
@@ -77,7 +75,7 @@ class ClientSideIncrementalRecordFilterDecorator(RecordFilter):
|
|
77
75
|
records = (
|
78
76
|
record
|
79
77
|
for record in records
|
80
|
-
if
|
78
|
+
if self._cursor.should_be_synced(
|
81
79
|
# Record is created on the fly to align with cursors interface; stream name is ignored as we don't need it here
|
82
80
|
# Record stream name is empty cause it is not used durig the filtering
|
83
81
|
Record(data=record, associated_slice=stream_slice, stream_name="")
|
@@ -2,6 +2,10 @@
|
|
2
2
|
# Copyright (c) 2022 Airbyte, Inc., all rights reserved.
|
3
3
|
#
|
4
4
|
|
5
|
+
from airbyte_cdk.sources.declarative.incremental.concurrent_partition_cursor import (
|
6
|
+
ConcurrentCursorFactory,
|
7
|
+
ConcurrentPerPartitionCursor,
|
8
|
+
)
|
5
9
|
from airbyte_cdk.sources.declarative.incremental.datetime_based_cursor import DatetimeBasedCursor
|
6
10
|
from airbyte_cdk.sources.declarative.incremental.declarative_cursor import DeclarativeCursor
|
7
11
|
from airbyte_cdk.sources.declarative.incremental.global_substream_cursor import (
|
@@ -21,6 +25,8 @@ from airbyte_cdk.sources.declarative.incremental.resumable_full_refresh_cursor i
|
|
21
25
|
|
22
26
|
__all__ = [
|
23
27
|
"CursorFactory",
|
28
|
+
"ConcurrentCursorFactory",
|
29
|
+
"ConcurrentPerPartitionCursor",
|
24
30
|
"DatetimeBasedCursor",
|
25
31
|
"DeclarativeCursor",
|
26
32
|
"GlobalSubstreamCursor",
|