diff --git a/airbyte-cdk/java/airbyte-cdk/README.md b/airbyte-cdk/java/airbyte-cdk/README.md index 89db38e5e14a..cb2629750e26 100644 --- a/airbyte-cdk/java/airbyte-cdk/README.md +++ b/airbyte-cdk/java/airbyte-cdk/README.md @@ -144,6 +144,7 @@ Maven and Gradle will automatically reference the correct (pinned) version of th | Version | Date | Pull Request | Subject | |:--------|:-----------|:-----------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0.29.11 | 2024-04-10 | [\#36865](https://github.com/airbytehq/airbyte/pull/36865) | Sources : Remove noisy log line. | | 0.29.10 | 2024-04-10 | [\#36805](https://github.com/airbytehq/airbyte/pull/36805) | Destinations: Enhance CatalogParser name collision handling; add DV2 tests for long identifiers | | 0.29.9 | 2024-04-09 | [\#36047](https://github.com/airbytehq/airbyte/pull/36047) | Destinations: CDK updates for raw-only destinations | | 0.29.8 | 2024-04-08 | [\#36868](https://github.com/airbytehq/airbyte/pull/36868) | Destinations: s3-destinations Compilation fixes for connector | diff --git a/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties b/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties index 2fc3347f9126..dff7ca91c4b3 100644 --- a/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties +++ b/airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties @@ -1 +1 @@ -version=0.29.10 +version=0.29.11 diff --git a/airbyte-cdk/java/airbyte-cdk/db-sources/src/main/kotlin/io/airbyte/cdk/integrations/debezium/internals/DebeziumMessageProducer.kt b/airbyte-cdk/java/airbyte-cdk/db-sources/src/main/kotlin/io/airbyte/cdk/integrations/debezium/internals/DebeziumMessageProducer.kt index 4ebfb0693711..7a4c1a846494 100644 --- a/airbyte-cdk/java/airbyte-cdk/db-sources/src/main/kotlin/io/airbyte/cdk/integrations/debezium/internals/DebeziumMessageProducer.kt +++ b/airbyte-cdk/java/airbyte-cdk/db-sources/src/main/kotlin/io/airbyte/cdk/integrations/debezium/internals/DebeziumMessageProducer.kt @@ -96,8 +96,6 @@ class DebeziumMessageProducer( if (checkpointOffsetToSend.size == 1 && !message!!.isSnapshotEvent) { if (targetPosition.isEventAheadOffset(checkpointOffsetToSend, message)) { shouldEmitStateMessage = true - } else { - LOGGER.info("Encountered records with the same event offset.") } } diff --git a/airbyte-cdk/java/airbyte-cdk/db-sources/src/testFixtures/kotlin/io/airbyte/cdk/integrations/standardtest/source/AbstractSourceDatabaseTypeTest.kt b/airbyte-cdk/java/airbyte-cdk/db-sources/src/testFixtures/kotlin/io/airbyte/cdk/integrations/standardtest/source/AbstractSourceDatabaseTypeTest.kt index c06ca79eef0e..cb6cead0a7a7 100644 --- a/airbyte-cdk/java/airbyte-cdk/db-sources/src/testFixtures/kotlin/io/airbyte/cdk/integrations/standardtest/source/AbstractSourceDatabaseTypeTest.kt +++ b/airbyte-cdk/java/airbyte-cdk/db-sources/src/testFixtures/kotlin/io/airbyte/cdk/integrations/standardtest/source/AbstractSourceDatabaseTypeTest.kt @@ -28,9 +28,8 @@ import org.slf4j.LoggerFactory * type system. */ abstract class AbstractSourceDatabaseTypeTest : AbstractSourceConnectorTest() { - @JvmField val testDataHolders: MutableList = ArrayList() - - @JvmField var database: Database? = null + protected val testDataHolders: MutableList = ArrayList() + protected var database: Database? = null protected val idColumnName: String /** diff --git a/airbyte-integrations/connectors/source-postgres/build.gradle b/airbyte-integrations/connectors/source-postgres/build.gradle index 4dca778ea010..896d4d41a9dd 100644 --- a/airbyte-integrations/connectors/source-postgres/build.gradle +++ b/airbyte-integrations/connectors/source-postgres/build.gradle @@ -12,7 +12,7 @@ java { } airbyteJavaConnector { - cdkVersionRequired = '0.29.0' + cdkVersionRequired = '0.29.11' features = ['db-sources', 'datastore-postgres'] useLocalCdk = false } diff --git a/airbyte-integrations/connectors/source-postgres/gradle.properties b/airbyte-integrations/connectors/source-postgres/gradle.properties index bc88ea85ebd8..45e99e438d74 100644 --- a/airbyte-integrations/connectors/source-postgres/gradle.properties +++ b/airbyte-integrations/connectors/source-postgres/gradle.properties @@ -1,3 +1,3 @@ testExecutionConcurrency=-1 -JunitMethodExecutionTimeout=5 m \ No newline at end of file +JunitMethodExecutionTimeout=2 m \ No newline at end of file diff --git a/airbyte-integrations/connectors/source-postgres/metadata.yaml b/airbyte-integrations/connectors/source-postgres/metadata.yaml index 8d24d4241e50..71119ccdb739 100644 --- a/airbyte-integrations/connectors/source-postgres/metadata.yaml +++ b/airbyte-integrations/connectors/source-postgres/metadata.yaml @@ -9,7 +9,7 @@ data: connectorSubtype: database connectorType: source definitionId: decd338e-5647-4c0b-adf4-da0e75f5a750 - dockerImageTag: 3.3.23 + dockerImageTag: 3.3.24 dockerRepository: airbyte/source-postgres documentationUrl: https://docs.airbyte.com/integrations/sources/postgres githubIssueLabel: source-postgres diff --git a/airbyte-integrations/connectors/source-postgres/src/test-performance/java/io/airbyte/integrations/source/postgres/FillPostgresTestDbScriptTest.java b/airbyte-integrations/connectors/source-postgres/src/test-performance/java/io/airbyte/integrations/source/postgres/FillPostgresTestDbScriptTest.java deleted file mode 100644 index 64a21f76a100..000000000000 --- a/airbyte-integrations/connectors/source-postgres/src/test-performance/java/io/airbyte/integrations/source/postgres/FillPostgresTestDbScriptTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.integrations.source.postgres; - -import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.collect.ImmutableMap; -import io.airbyte.cdk.db.Database; -import io.airbyte.cdk.db.factory.DSLContextFactory; -import io.airbyte.cdk.db.factory.DatabaseDriver; -import io.airbyte.cdk.db.jdbc.JdbcUtils; -import io.airbyte.cdk.integrations.standardtest.source.TestDestinationEnv; -import io.airbyte.cdk.integrations.standardtest.source.performancetest.AbstractSourceFillDbWithTestData; -import io.airbyte.commons.json.Jsons; -import java.util.stream.Stream; -import org.jooq.DSLContext; -import org.jooq.SQLDialect; -import org.junit.jupiter.params.provider.Arguments; - -public class FillPostgresTestDbScriptTest extends AbstractSourceFillDbWithTestData { - - private JsonNode config; - private DSLContext dslContext; - - @Override - protected JsonNode getConfig() { - return config; - } - - @Override - protected void tearDown(final TestDestinationEnv testEnv) {} - - @Override - protected String getImageName() { - return "airbyte/source-postgres:dev"; - } - - @Override - protected Database setupDatabase(final String dbName) throws Exception { - final JsonNode replicationMethod = Jsons.jsonNode(ImmutableMap.builder() - .put("method", "Standard") - .build()); - - config = Jsons.jsonNode(ImmutableMap.builder() - .put(JdbcUtils.HOST_KEY, "your_host") - .put(JdbcUtils.PORT_KEY, 5432) - .put(JdbcUtils.DATABASE_KEY, dbName) - .put(JdbcUtils.USERNAME_KEY, "your_username") - .put(JdbcUtils.PASSWORD_KEY, "your_pass") - .put("replication_method", replicationMethod) - .build()); - - dslContext = DSLContextFactory.create( - config.get(JdbcUtils.USERNAME_KEY).asText(), - config.get(JdbcUtils.PASSWORD_KEY).asText(), - DatabaseDriver.POSTGRESQL.getDriverClassName(), - String.format(DatabaseDriver.POSTGRESQL.getUrlFormatString(), - config.get(JdbcUtils.HOST_KEY).asText(), - config.get(JdbcUtils.PORT_KEY).asInt(), - config.get(JdbcUtils.DATABASE_KEY).asText()), - SQLDialect.POSTGRES); - final Database database = new Database(dslContext); - - return database; - } - - /** - * This is a data provider for fill DB script, Each argument's group would be ran as a separate - * test. 1st arg - a name of DB that will be used in jdbc connection string. 2nd arg - a schemaName - * that will be ised as a NameSpace in Configured Airbyte Catalog. 3rd arg - a number of expected - * records retrieved in each stream. 4th arg - a number of messages batches - * (numberOfMessages*numberOfBatches, ex. 100*2=200 messages in total in each stream) 5th arg - a - * number of columns in each stream\table that will be use for Airbyte Cataloq configuration 6th arg - * - a number of streams to read in configured airbyte Catalog. Each stream\table in DB should be - * names like "test_0", "test_1",..., test_n. - */ - @Override - protected Stream provideParameters() { - return Stream.of(Arguments.of("postgres", "\"your_schema_name\"", 100, 2, 240, 1000)); - } - -} diff --git a/airbyte-integrations/connectors/source-postgres/src/test-performance/java/io/airbyte/integrations/source/postgres/PostgresRdsSourcePerformanceTest.java b/airbyte-integrations/connectors/source-postgres/src/test-performance/java/io/airbyte/integrations/source/postgres/PostgresRdsSourcePerformanceTest.java deleted file mode 100644 index 52cbb03e7a44..000000000000 --- a/airbyte-integrations/connectors/source-postgres/src/test-performance/java/io/airbyte/integrations/source/postgres/PostgresRdsSourcePerformanceTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.integrations.source.postgres; - -import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.collect.ImmutableMap; -import io.airbyte.cdk.db.jdbc.JdbcUtils; -import io.airbyte.cdk.integrations.standardtest.source.performancetest.AbstractSourcePerformanceTest; -import io.airbyte.commons.io.IOs; -import io.airbyte.commons.json.Jsons; -import java.nio.file.Path; -import java.util.List; -import java.util.stream.Stream; -import org.junit.jupiter.params.provider.Arguments; - -public class PostgresRdsSourcePerformanceTest extends AbstractSourcePerformanceTest { - - private static final String PERFORMANCE_SECRET_CREDS = "secrets/performance-config.json"; - private static final List SCHEMAS = List.of("t1000_c240_r200", - "t25_c8_r50k_s10kb", "t1000_c8_r10k_s500b"); - - @Override - protected String getImageName() { - return "airbyte/source-postgres:dev"; - } - - @Override - protected void setupDatabase(final String dbName) { - final JsonNode plainConfig = Jsons.deserialize(IOs.readFile(Path.of(PERFORMANCE_SECRET_CREDS))); - - final JsonNode replicationMethod = Jsons.jsonNode(ImmutableMap.builder() - .put("method", "Standard") - .build()); - - setConfig(Jsons.jsonNode(ImmutableMap.builder() - .put(JdbcUtils.HOST_KEY, plainConfig.get(JdbcUtils.HOST_KEY)) - .put(JdbcUtils.PORT_KEY, plainConfig.get(JdbcUtils.PORT_KEY)) - .put(JdbcUtils.DATABASE_KEY, dbName) - .put(JdbcUtils.SCHEMAS_KEY, List.of(dbName)) - .put(JdbcUtils.USERNAME_KEY, plainConfig.get(JdbcUtils.USERNAME_KEY)) - .put(JdbcUtils.PASSWORD_KEY, plainConfig.get(JdbcUtils.PASSWORD_KEY)) - .put(JdbcUtils.SSL_KEY, true) - .put("replication_method", replicationMethod) - .build())); - } - - /** - * This is a data provider for performance tests, Each argument's group would be ran as a separate - * test. 1st arg - a name of DB that will be used in jdbc connection string. 2nd arg - a schemaName - * that will be used as a NameSpace in Configured Airbyte Catalog. 3rd arg - a number of expected - * records retrieved in each stream. 4th arg - a number of columns in each stream\table that will be - * use for Airbyte Cataloq configuration 5th arg - a number of streams to read in configured airbyte - * Catalog. Each stream\table in DB should be names like "test_0", "test_1",..., test_n. - */ - @Override - protected Stream provideParameters() { - return Stream.of( - Arguments.of(SCHEMAS.get(0), SCHEMAS.get(0), 200, 240, 1000), - Arguments.of(SCHEMAS.get(1), SCHEMAS.get(1), 50000, 8, 25), - Arguments.of(SCHEMAS.get(2), SCHEMAS.get(2), 10000, 8, 1000)); - } - -} diff --git a/airbyte-integrations/connectors/source-postgres/src/test-performance/sql/1-create-copy-tables-procedure.sql b/airbyte-integrations/connectors/source-postgres/src/test-performance/sql/1-create-copy-tables-procedure.sql deleted file mode 100644 index 861714f0b9fc..000000000000 --- a/airbyte-integrations/connectors/source-postgres/src/test-performance/sql/1-create-copy-tables-procedure.sql +++ /dev/null @@ -1,25 +0,0 @@ -CREATE - OR replace PROCEDURE copy_table( - tablecount INT - ) LANGUAGE plpgsql AS $$ DECLARE v_max_table INT; - -v_counter_table INT; - -v_tnamee VARCHAR(255); - -BEGIN v_max_table := tablecount; - -v_counter_table := 1; - -while v_counter_table < v_max_table loop EXECUTE format( - 'create table test_%s as (select * from test t)', - v_counter_table -); - -v_counter_table := v_counter_table + 1; -END loop; - -COMMIT; -END; - -$$ diff --git a/airbyte-integrations/connectors/source-postgres/src/test-performance/sql/2-create-insert-rows-to-table-procedure.sql b/airbyte-integrations/connectors/source-postgres/src/test-performance/sql/2-create-insert-rows-to-table-procedure.sql deleted file mode 100644 index 6f8b07fc6b12..000000000000 --- a/airbyte-integrations/connectors/source-postgres/src/test-performance/sql/2-create-insert-rows-to-table-procedure.sql +++ /dev/null @@ -1,168 +0,0 @@ -CREATE - OR replace PROCEDURE insert_rows( - allrows INT, - insertcount INT, - value text - ) LANGUAGE plpgsql AS $$ DECLARE dummyIpsum VARCHAR(255); - -fieldText text; - -vmax INT; - -vmaxx INT; - -vmaxoneinsert INT; - -counter INT; - -DECLARE lastinsertcounter INT; - -lastinsert INT; - -fullloop INT; - -fullloopcounter INT; - -insertTable text; - -insertTableLasted text; - -BEGIN fieldText := value; - -dummyIpsum = '''dummy_ipsum'''; - -vmax = allrows; - -vmaxx = allrows; - -vmaxoneinsert = insertcount; - -counter = 1; - -lastinsertcounter = 1; - -lastinsert = 0; - -fullloop = 0; - -fullloopcounter = 0; - -while vmaxx <= vmaxoneinsert loop vmaxoneinsert := vmaxx; - -fullloop := fullloop + 1; - -vmaxx := vmaxx + 1; -END loop; - -COMMIT; - -while vmax > vmaxoneinsert loop fullloop := fullloop + 1; - -vmax := vmax - vmaxoneinsert; - -lastinsert := vmax; -END loop; - -COMMIT; - -insertTable := 'insert into test (varchar1, varchar2, varchar3, varchar4, varchar5, longblobfield, timestampfield) values ('; - -while counter < vmaxoneinsert loop insertTable := concat( - insertTable, - dummyIpsum, - ', ', - dummyIpsum, - ', ', - dummyIpsum, - ', ', - dummyIpsum, - ', ', - dummyIpsum, - ', ', - fieldText, - ', CURRENT_TIMESTAMP), (' -); - -counter := counter + 1; -END loop; - -COMMIT; - -insertTable := concat( - insertTable, - dummyIpsum, - ', ', - dummyIpsum, - ', ', - dummyIpsum, - ', ', - dummyIpsum, - ', ', - dummyIpsum, - ', ', - fieldText, - ', CURRENT_TIMESTAMP);' -); - -while vmax < 1 loop fullloop := 0; - -vmax := 1; -END loop; - -COMMIT; - -while fullloopcounter < fullloop loop EXECUTE insertTable; - -fullloopcounter := fullloopcounter + 1; -END loop; - -COMMIT; - -insertTableLasted := 'insert into test (varchar1, varchar2, varchar3, varchar4, varchar5, longblobfield, timestampfield) values ('; - -while lastinsertcounter < lastinsert loop insertTableLasted := concat( - insertTableLasted, - dummyIpsum, - ', ', - dummyIpsum, - ', ', - dummyIpsum, - ', ', - dummyIpsum, - ', ', - dummyIpsum, - ', ', - fieldText, - ', CURRENT_TIMESTAMP), (' -); - -lastinsertcounter := lastinsertcounter + 1; -END loop; - -COMMIT; - -insertTableLasted := concat( - insertTableLasted, - dummyIpsum, - ', ', - dummyIpsum, - ', ', - dummyIpsum, - ', ', - dummyIpsum, - ', ', - dummyIpsum, - ', ', - fieldText, - ', CURRENT_TIMESTAMP);' -); - -while lastinsert > 0 loop EXECUTE insertTableLasted; - -lastinsert := 0; -END loop; - -COMMIT; -END; - -$$ diff --git a/airbyte-integrations/connectors/source-postgres/src/test-performance/sql/3-run-script.sql b/airbyte-integrations/connectors/source-postgres/src/test-performance/sql/3-run-script.sql deleted file mode 100644 index 5eb1655c3f2e..000000000000 --- a/airbyte-integrations/connectors/source-postgres/src/test-performance/sql/3-run-script.sql +++ /dev/null @@ -1,73 +0,0 @@ -CREATE - SEQUENCE test_seq; - -CREATE - TABLE - test( - id INT CHECK( - id > 0 - ) NOT NULL DEFAULT nextval('test_seq') PRIMARY KEY, - varchar1 VARCHAR(255), - varchar2 VARCHAR(255), - varchar3 VARCHAR(255), - varchar4 VARCHAR(255), - varchar5 VARCHAR(255), - longblobfield bytea, - timestampfield TIMESTAMP(0) - ); - --- TODO: change the following @allrows to control the number of records with different sizes --- number of 50B records -CALL insert_rows( - 0, - 500000, - '''test weight 50b - some text, some text, some text''' -); - --- number of 500B records -CALL insert_rows( - 0, - 50000, - CONCAT( - '''test weight 500b - ', - repeat( - 'some text, some text, ', - 20 - ), - 'some text''' - ) -); - --- number of 10KB records -CALL insert_rows( - 0, - 5000, - CONCAT( - '''test weight 10kb - ', - repeat( - 'some text, some text, some text, some text, ', - 295 - ), - 'some text''' - ) -); - --- number of 100KB records -CALL insert_rows( - 0, - 50, - CONCAT( - '''test weight 100kb - ', - repeat( - 'some text, some text, ', - 4450 - ), - 'some text''' - ) -); - --- TODO: change the value to control the number of tables -CALL copy_table(0); - -ALTER TABLE - test RENAME TO test_0; diff --git a/docs/integrations/sources/postgres.md b/docs/integrations/sources/postgres.md index a5e669b74271..1975fce7c169 100644 --- a/docs/integrations/sources/postgres.md +++ b/docs/integrations/sources/postgres.md @@ -292,19 +292,20 @@ According to Postgres [documentation](https://www.postgresql.org/docs/14/datatyp | Version | Date | Pull Request | Subject | |---------|------------|----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 3.3.23 | 2024-04-02 | [36759](https://github.com/airbytehq/airbyte/pull/36759) | Track latest CDK | -| 3.3.22 | 2024-04-01 | [36739](https://github.com/airbytehq/airbyte/pull/36739) | Fix useLocalCdk flag. | -| 3.3.21 | 2024-03-25 | [36584](https://github.com/airbytehq/airbyte/pull/36584) | Adopt Kotlin CDK. | -| 3.3.20 | 2024-03-25 | [36432](https://github.com/airbytehq/airbyte/pull/36432) | Failure to serialize values from Postgres DB shouldn't fail sync. | -| 3.3.19 | 2024-03-12 | [36333](https://github.com/airbytehq/airbyte/pull/36333) | Use newest CDK - deprecate dbz iterator | -| 3.3.18 | 2024-03-12 | [35599](https://github.com/airbytehq/airbyte/pull/35599) | Use newest CDK | -| 3.3.17 | 2024-03-12 | [35939](https://github.com/airbytehq/airbyte/pull/35939) | Use lsn_commit value instead of lsn_proc for CDC checkpointing logic. | -| 3.3.16 | 2024-03-11 | [35904](https://github.com/airbytehq/airbyte/pull/35904) | Adopt Java CDK 0.23.1- debezium retries. | -| 3.3.15 | 2024-02-29 | [34724](https://github.com/airbytehq/airbyte/pull/34724) | Add record count in state message. | -| 3.3.14 | 2024-03-06 | [35842](https://github.com/airbytehq/airbyte/pull/35842) | Add logging to understand cases with a large number of records with the same LSN. | -| 3.3.13 | 2024-02-27 | [35675](https://github.com/airbytehq/airbyte/pull/35675) | Fix invalid cdc error message. | -| 3.3.12 | 2024-02-22 | [35569](https://github.com/airbytehq/airbyte/pull/35569) | Fix logging bug. | -| 3.3.11 | 2024-02-20 | [35304](https://github.com/airbytehq/airbyte/pull/35304) | Add config to throw an error on invalid CDC position and enable it by default. | +| 3.3.24 | 2024-04-10 | [36865](https://github.com/airbytehq/airbyte/pull/36865) | Track latest CDK | +| 3.3.23 | 2024-04-02 | [36759](https://github.com/airbytehq/airbyte/pull/36759) | Track latest CDK | +| 3.3.22 | 2024-04-01 | [36739](https://github.com/airbytehq/airbyte/pull/36739) | Fix useLocalCdk flag. | +| 3.3.21 | 2024-03-25 | [36584](https://github.com/airbytehq/airbyte/pull/36584) | Adopt Kotlin CDK. | +| 3.3.20 | 2024-03-25 | [36432](https://github.com/airbytehq/airbyte/pull/36432) | Failure to serialize values from Postgres DB shouldn't fail sync. | +| 3.3.19 | 2024-03-12 | [36333](https://github.com/airbytehq/airbyte/pull/36333) | Use newest CDK - deprecate dbz iterator | +| 3.3.18 | 2024-03-12 | [35599](https://github.com/airbytehq/airbyte/pull/35599) | Use newest CDK | +| 3.3.17 | 2024-03-12 | [35939](https://github.com/airbytehq/airbyte/pull/35939) | Use lsn_commit value instead of lsn_proc for CDC checkpointing logic. | +| 3.3.16 | 2024-03-11 | [35904](https://github.com/airbytehq/airbyte/pull/35904) | Adopt Java CDK 0.23.1- debezium retries. | +| 3.3.15 | 2024-02-29 | [34724](https://github.com/airbytehq/airbyte/pull/34724) | Add record count in state message. | +| 3.3.14 | 2024-03-06 | [35842](https://github.com/airbytehq/airbyte/pull/35842) | Add logging to understand cases with a large number of records with the same LSN. | +| 3.3.13 | 2024-02-27 | [35675](https://github.com/airbytehq/airbyte/pull/35675) | Fix invalid cdc error message. | +| 3.3.12 | 2024-02-22 | [35569](https://github.com/airbytehq/airbyte/pull/35569) | Fix logging bug. | +| 3.3.11 | 2024-02-20 | [35304](https://github.com/airbytehq/airbyte/pull/35304) | Add config to throw an error on invalid CDC position and enable it by default. | | 3.3.10 | 2024-02-13 | [35036](https://github.com/airbytehq/airbyte/pull/34751) | Emit analytics message for invalid CDC cursor. | | 3.3.9 | 2024-02-13 | [35224](https://github.com/airbytehq/airbyte/pull/35224) | Adopt CDK 0.20.4 | | 3.3.8 | 2024-02-08 | [34751](https://github.com/airbytehq/airbyte/pull/34751) | Adopt CDK 0.19.0 |