diff --git a/airbyte-integrations/connectors/source-zendesk-support/Dockerfile b/airbyte-integrations/connectors/source-zendesk-support/Dockerfile index 2736be3875d5..df289402427c 100644 --- a/airbyte-integrations/connectors/source-zendesk-support/Dockerfile +++ b/airbyte-integrations/connectors/source-zendesk-support/Dockerfile @@ -25,5 +25,5 @@ COPY source_zendesk_support ./source_zendesk_support ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py" ENTRYPOINT ["python", "/airbyte/integration_code/main.py"] -LABEL io.airbyte.version=0.10.2 +LABEL io.airbyte.version=0.10.3 LABEL io.airbyte.name=airbyte/source-zendesk-support diff --git a/airbyte-integrations/connectors/source-zendesk-support/metadata.yaml b/airbyte-integrations/connectors/source-zendesk-support/metadata.yaml index ea6af49b5621..f987721e46b4 100644 --- a/airbyte-integrations/connectors/source-zendesk-support/metadata.yaml +++ b/airbyte-integrations/connectors/source-zendesk-support/metadata.yaml @@ -7,16 +7,13 @@ data: connectorType: source maxSecondsBetweenMessages: 10800 definitionId: 79c1aa37-dae3-42ae-b333-d1c105477715 - dockerImageTag: 0.10.2 + dockerImageTag: 0.10.3 dockerRepository: airbyte/source-zendesk-support githubIssueLabel: source-zendesk-support icon: zendesk-support.svg license: ELv2 name: Zendesk Support registries: - cloud: - dockerImageTag: 0.10.0 # Fixing P0 https://github.com/airbytehq/oncall/issues/2530 - enabled: true oss: enabled: true releaseStage: generally_available diff --git a/airbyte-integrations/connectors/source-zendesk-support/source_zendesk_support/streams.py b/airbyte-integrations/connectors/source-zendesk-support/source_zendesk_support/streams.py index dea7e1277057..11bcb8075902 100644 --- a/airbyte-integrations/connectors/source-zendesk-support/source_zendesk_support/streams.py +++ b/airbyte-integrations/connectors/source-zendesk-support/source_zendesk_support/streams.py @@ -614,6 +614,20 @@ class TicketMetricEvents(CursorPaginationZendeskSupportStream): def path(self, **kwargs): return "incremental/ticket_metric_events" + def request_params( + self, + stream_state: Mapping[str, Any], + stream_slice: Mapping[str, Any] = None, + next_page_token: Mapping[str, Any] = None, + ) -> MutableMapping[str, Any]: + params = { + "start_time": self.check_stream_state(stream_state), + "page[size]": self.page_size, + } + if next_page_token: # need keep start_time for this stream + params.update(next_page_token) + return params + class Macros(SourceZendeskSupportStream): """Macros stream: https://developer.zendesk.com/api-reference/ticketing/business-rules/macros/""" diff --git a/airbyte-integrations/connectors/source-zendesk-support/unit_tests/unit_test.py b/airbyte-integrations/connectors/source-zendesk-support/unit_tests/unit_test.py index 59d9f1b7289d..99136c0bba28 100644 --- a/airbyte-integrations/connectors/source-zendesk-support/unit_tests/unit_test.py +++ b/airbyte-integrations/connectors/source-zendesk-support/unit_tests/unit_test.py @@ -415,10 +415,10 @@ def test_url_base(self, stream_cls): (Macros, {}, {"updated_at": "2022-03-17T16:03:07Z"}, {"updated_at": "2022-03-17T16:03:07Z"}), (Posts, {}, {"updated_at": "2022-03-17T16:03:07Z"}, {"updated_at": "2022-03-17T16:03:07Z"}), ( - Organizations, - {"updated_at": "2022-03-17T16:03:07Z"}, - {"updated_at": "2023-03-17T16:03:07Z"}, - {"updated_at": "2023-03-17T16:03:07Z"}, + Organizations, + {"updated_at": "2022-03-17T16:03:07Z"}, + {"updated_at": "2023-03-17T16:03:07Z"}, + {"updated_at": "2023-03-17T16:03:07Z"}, ), (Groups, {}, {"updated_at": "2022-03-17T16:03:07Z"}, {"updated_at": "2022-03-17T16:03:07Z"}), (SatisfactionRatings, {}, {"updated_at": "2022-03-17T16:03:07Z"}, {"updated_at": "2022-03-17T16:03:07Z"}), @@ -604,30 +604,37 @@ def test_get_updated_state(self, stream_cls, current_state, last_record, expecte [ (GroupMemberships, {}, None), (TicketForms, {}, None), - (TicketMetricEvents, {}, None), + (TicketMetricEvents, { + "meta": {"has_more": True, "after_cursor": "", "before_cursor": ""}, + "links": { + "prev": "https://subdomain.zendesk.com/api/v2/ticket_metrics.json?page%5Bbefore%5D=%3D&page%5Bsize%5D=2", + "next": "https://subdomain.zendesk.com/api/v2/ticket_metrics.json?page%5Bafter%5D=%3D&page%5Bsize%5D=2", + }, + }, + {"page[after]": ""}), (TicketAudits, {}, None), ( - TicketMetrics, - { - "meta": {"has_more": True, "after_cursor": "", "before_cursor": ""}, - "links": { - "prev": "https://subdomain.zendesk.com/api/v2/ticket_metrics.json?page%5Bbefore%5D=%3D&page%5Bsize%5D=2", - "next": "https://subdomain.zendesk.com/api/v2/ticket_metrics.json?page%5Bafter%5D=%3D&page%5Bsize%5D=2", + TicketMetrics, + { + "meta": {"has_more": True, "after_cursor": "", "before_cursor": ""}, + "links": { + "prev": "https://subdomain.zendesk.com/api/v2/ticket_metrics.json?page%5Bbefore%5D=%3D&page%5Bsize%5D=2", + "next": "https://subdomain.zendesk.com/api/v2/ticket_metrics.json?page%5Bafter%5D=%3D&page%5Bsize%5D=2", + }, }, - }, - {"page[after]": ""}, + {"page[after]": ""}, ), (SatisfactionRatings, {}, None), ( - OrganizationMemberships, - { - "meta": {"has_more": True, "after_cursor": "", "before_cursor": ""}, - "links": { - "prev": "https://subdomain.zendesk.com/api/v2/ticket_metrics.json?page%5Bbefore%5D=%3D&page%5Bsize%5D=2", - "next": "https://subdomain.zendesk.com/api/v2/ticket_metrics.json?page%5Bafter%5D=%3D&page%5Bsize%5D=2", + OrganizationMemberships, + { + "meta": {"has_more": True, "after_cursor": "", "before_cursor": ""}, + "links": { + "prev": "https://subdomain.zendesk.com/api/v2/ticket_metrics.json?page%5Bbefore%5D=%3D&page%5Bsize%5D=2", + "next": "https://subdomain.zendesk.com/api/v2/ticket_metrics.json?page%5Bafter%5D=%3D&page%5Bsize%5D=2", + }, }, - }, - {"page[after]": ""}, + {"page[after]": ""}, ), ( TicketSkips, @@ -655,7 +662,6 @@ def test_get_updated_state(self, stream_cls, current_state, last_record, expecte ) def test_next_page_token(self, requests_mock, stream_cls, response, expected): stream = stream_cls(**STREAM_ARGS) - # stream_name = snake_case(stream.__class__.__name__) requests_mock.get(STREAM_URL, json=response) test_response = requests.get(STREAM_URL) output = stream.next_page_token(test_response) @@ -948,3 +954,47 @@ def test_read_post_comment_votes_stream(requests_mock): stream = PostCommentVotes(subdomain="subdomain", start_date="2020-01-01T00:00:00Z") records = read_full_refresh(stream) assert records == votes + + +def test_read_ticket_metric_events_request_params(requests_mock): + first_page_response = { + "ticket_metric_events": [ + {"id": 1, "ticket_id": 123, "metric": "agent_work_time", "instance_id": 0, "type": "measure", "time": "2020-01-01T01:00:00Z"}, + {"id": 2, "ticket_id": 123, "metric": "pausable_update_time", "instance_id": 0, "type": "measure", "time": "2020-01-01T01:00:00Z"}, + {"id": 3, "ticket_id": 123, "metric": "reply_time", "instance_id": 0, "type": "measure", "time": "2020-01-01T01:00:00Z"}, + {"id": 4, "ticket_id": 123, "metric": "requester_wait_time", "instance_id": 1, "type": "activate", "time": "2020-01-01T01:00:00Z"} + ], + "meta": { + "has_more": True, + "after_cursor": "", + "before_cursor": "" + }, + "links": { + "prev": "https://subdomain.zendesk.com/api/v2/incremental/ticket_metric_events.json?page%5Bbefore%5D=&page%5Bsize%5D=100&start_time=1577836800", + "next": "https://subdomain.zendesk.com/api/v2/incremental/ticket_metric_events.json?page%5Bafter%5D=&page%5Bsize%5D=100&start_time=1577836800" + }, + "end_of_stream": False + } + + second_page_response = { + "ticket_metric_events": [ + {"id": 5163373143183, "ticket_id": 130, "metric": "reply_time", "instance_id": 1, "type": "fulfill", "time": "2022-07-18T16:39:48Z"}, + {"id": 5163373143311, "ticket_id": 130, "metric": "requester_wait_time", "instance_id": 0, "type": "measure", "time": "2022-07-18T16:39:48Z"} + ], + "meta": { + "has_more": False, + "after_cursor": "", + "before_cursor": "" + }, + "links": { + "prev": "https://subdomain.zendesk.com/api/v2/incremental/ticket_metric_events.json?page%5Bbefore%5D=&page%5Bsize%5D=100&start_time=1577836800", + "next": "https://subdomain.zendesk.com/api/v2/incremental/ticket_metric_events.json?page%5Bbefore%5D=&page%5Bsize%5D=100&start_time=1577836800" + }, + "end_of_stream": True + } + request_history = requests_mock.get("https://subdomain.zendesk.com/api/v2/incremental/ticket_metric_events", [ + {"json": first_page_response}, {"json": second_page_response}]) + stream = TicketMetricEvents(subdomain="subdomain", start_date="2020-01-01T00:00:00Z") + read_full_refresh(stream) + assert request_history.call_count == 2 + assert request_history.last_request.qs == {"page[after]": [""], "page[size]": ["100"], "start_time": ["1577836800"]} diff --git a/docs/integrations/sources/zendesk-support.md b/docs/integrations/sources/zendesk-support.md index 6ae51abfbcfb..097142e71c48 100644 --- a/docs/integrations/sources/zendesk-support.md +++ b/docs/integrations/sources/zendesk-support.md @@ -79,6 +79,7 @@ The Zendesk connector ideally should not run into Zendesk API limitations under | Version | Date | Pull Request | Subject | |:---------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `0.10.3` | 2023-07-24 | [28612](https://github.com/airbytehq/airbyte/pull/28612) | Fix pagination for stream `TicketMetricEvents` | | `0.10.2` | 2023-07-19 | [28487](https://github.com/airbytehq/airbyte/pull/28487) | Remove extra page from params | | `0.10.1` | 2023-07-10 | [28096](https://github.com/airbytehq/airbyte/pull/28096) | Replace `offset` pagination with `cursor` pagination | | `0.10.0` | 2023-07-06 | [27991](https://github.com/airbytehq/airbyte/pull/27991) | add streams: `PostVotes`, `PostCommentVotes` |