-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
source-github: move known error handling to GithubAvailabilityStrategy (
#19978) * Rough first implememtation of AvailabilityStrategy s * Basic unit tests for AvailabilityStrategy and ScopedAvailabilityStrategy * Make availability_strategy a property, separate out tests * Remove from DeclarativeSource, remove Source parameter from methods, make default no AvailabilityStrategy * Add skip stream if not available to read() * Changes to CDK to get source-github working using AvailabilityStrategy, flakecheck * reorganize cdk class, add HTTPAvailabilityStrategy test * cleanup, docstrings * source-github working with availabilitystrategy * reorganize source-github * source-github: resolve deprecation warning * use correct import for HTTPAvailabilitystrategy * pull out error handling into separate method * use handle_http_error method * Pass source and logger to check_connection method * Add documentation links, handle 403 specifically * Fix circular import * Add AvailabilityStrategy to Stream and HTTPStream classes * Remove AS from abstract_source, add to Stream, HTTPStream, AvailabilityStrategy unit tests passing for per-stream strategies * Modify MockHttpStream to set no AvailabilityStrategy since source test mocking doesn't support this * Move AvailabilityStrategy class to sources.streams * Move HTTPAvailabilityStrategy to http module * Use pascal case for HttpAvailabilityStrategy * Remove docs message method :( and default to True availability on unhandled HTTPErrors * add check_availability method to stream class * Add optional source parameter * Add test for connector-specific documentation, small tests refactor * Add test that performs the read() function for stream with default availability strategy * Add test for read function behavior when stream is unavailable * Add 403 info in logger message * Don't return error for other HTTPErrors * Split up error handling into methods 'unavailable_error_codes' and 'get_reason_for_error' * rework overrideable list of status codes to be a dict with reasons, to enforce that users provide reasons for all listed errors * Fix incorrect typing * Move HttpAvailability to its own module, fix flake errors * Fix ScopedAvailabilityStrategy, docstrings and types for streams/availability_strategy.py * Docstrings and types for core.py and http/availability_strategy.py * Move _get_stream_slices to a StreamHelper class * Docstrings + types for stream_helpers.py, cleanup test_availability.py * Clean up test_source.py * Move logic of getting the initial record from a stream to StreamHelper class * Add changelog and bump minor version * change 'is True' and 'is False' behavior * use mocker.MagicMock * Remove ScopedAvailabilityStrategy * Don't except non-403 errors, check_stream uses availability_strategy if possible * Move AvailabilityStrategy to stream level, fix tests * make get_stream_slice public * Attempt to refactor error code handling into repository-based and organization-based * split into repository-based availabilitystrategy and organization-based availabilitystrategy * refactor organization-based availabilitystrategy * refactor repository-based availabilitystrategy, create separate ones for workflow_runs and projects * Fix workflow runs availability strategy * move availability strategies to a different module * CDK: pass error to reasons_for_error_codes * make get_stream_slice public * Revert "make get_stream_slice public" This reverts commit 9170fe5. * Add tests for raising unhandled errors and retries are handled * Add tests for CheckStream via AvailabilityStrategy * Remove moved file * bump CDK dependency * Cleanup: Address review comments * One more fix * Update changelog and dockerfile version
- Loading branch information
1 parent
82df676
commit f97db17
Showing
10 changed files
with
132 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
airbyte-integrations/connectors/source-github/source_github/availability_strategies.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# | ||
# Copyright (c) 2022 Airbyte, Inc., all rights reserved. | ||
# | ||
|
||
import logging | ||
from typing import Dict, Optional | ||
|
||
import requests | ||
from airbyte_cdk.sources import Source | ||
from airbyte_cdk.sources.streams.core import Stream | ||
from airbyte_cdk.sources.streams.http.availability_strategy import HttpAvailabilityStrategy | ||
from airbyte_cdk.sources.utils.stream_helpers import StreamHelper | ||
from requests import HTTPError | ||
|
||
|
||
class OrganizationBasedAvailabilityStrategy(HttpAvailabilityStrategy): | ||
""" | ||
Availability Strategy for organization-based streams. | ||
""" | ||
|
||
def reasons_for_unavailable_status_codes( | ||
self, stream: Stream, logger: logging.Logger, source: Optional["Source"], error: HTTPError | ||
) -> Dict[int, str]: | ||
stream_slice = StreamHelper().get_stream_slice(stream) | ||
organization = stream_slice["organization"] | ||
response_error_msg = str(error.response.json().get("message")) | ||
|
||
reasons_for_codes = { | ||
requests.codes.NOT_FOUND: f"`{stream.__class__.__name__}` stream isn't available for organization `{organization}`.", | ||
# When `403` for the stream, that has no access to the organization's teams, based on OAuth Apps Restrictions: | ||
# https://docs.github.com/en/organizations/restricting-access-to-your-organizations-data/enabling-oauth-app-access-restrictions-for-your-organization | ||
requests.codes.FORBIDDEN: f"`{stream.name}` stream isn't available for organization `{organization}`. Full error message: {response_error_msg}", | ||
} | ||
return reasons_for_codes | ||
|
||
|
||
class RepositoryBasedAvailabilityStrategy(HttpAvailabilityStrategy): | ||
""" | ||
Availability Strategy for repository-based streams. | ||
""" | ||
|
||
def reasons_for_unavailable_status_codes( | ||
self, stream: Stream, logger: logging.Logger, source: Optional["Source"], error: HTTPError | ||
) -> Dict[int, str]: | ||
stream_slice = StreamHelper().get_stream_slice(stream) | ||
repository = stream_slice["repository"] | ||
error_msg = str(error.response.json().get("message")) | ||
|
||
reasons_for_codes = { | ||
requests.codes.NOT_FOUND: f"`{stream.name}` stream isn't available for repository `{repository}`.", | ||
requests.codes.FORBIDDEN: f"`{stream.name}` stream isn't available for repository `{repository}`. Full error message: {error_msg}", | ||
requests.codes.CONFLICT: f"`{stream.name}` stream isn't available for repository `{repository}`, it seems like this repository is empty.", | ||
} | ||
return reasons_for_codes | ||
|
||
|
||
class WorkflowRunsAvailabilityStrategy(RepositoryBasedAvailabilityStrategy): | ||
""" | ||
AvailabilityStrategy for the 'WorkflowRuns' stream. | ||
""" | ||
|
||
def reasons_for_unavailable_status_codes( | ||
self, stream: Stream, logger: logging.Logger, source: Optional["Source"], error: HTTPError | ||
) -> Dict[int, str]: | ||
stream_slice = StreamHelper().get_stream_slice(stream) | ||
repository = stream_slice["repository"] | ||
reasons_for_codes = super().reasons_for_unavailable_status_codes(stream, logger, source, error).copy() | ||
server_error_msg = f"Syncing `{stream.name}` stream isn't available for repository `{repository}`." | ||
reasons_for_codes[requests.codes.SERVER_ERROR] = server_error_msg | ||
return reasons_for_codes | ||
|
||
|
||
class ProjectsAvailabilityStrategy(RepositoryBasedAvailabilityStrategy): | ||
""" | ||
AvailabilityStrategy for the 'Projects' stream. | ||
""" | ||
|
||
def reasons_for_unavailable_status_codes( | ||
self, stream: Stream, logger: logging.Logger, source: Optional["Source"], error: HTTPError | ||
) -> Dict[int, str]: | ||
stream_slice = StreamHelper().get_stream_slice(stream) | ||
repository = stream_slice["repository"] | ||
reasons_for_codes = super().reasons_for_unavailable_status_codes(stream, logger, source, error).copy() | ||
|
||
# Some repos don't have projects enabled and we we get "410 Client Error: Gone for | ||
# url: https://api.github.com/repos/xyz/projects?per_page=100" error. | ||
gone_error_msg = f"`Projects` stream isn't available for repository `{repository}`." | ||
reasons_for_codes[requests.codes.GONE] = gone_error_msg | ||
|
||
return reasons_for_codes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters