Skip to content

fix(source-bing-ads): refresh report download URLs at download time to avoid expired SAS URLs (AI-Triage PR)#75428

Closed
devin-ai-integration[bot] wants to merge 7 commits into
masterfrom
devin/1774393261-bing-ads-refresh-sas-url
Closed

fix(source-bing-ads): refresh report download URLs at download time to avoid expired SAS URLs (AI-Triage PR)#75428
devin-ai-integration[bot] wants to merge 7 commits into
masterfrom
devin/1774393261-bing-ads-refresh-sas-url

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot commented Mar 24, 2026

What

Resolves https://github.com/airbytehq/airbyte-internal-issues/issues/16105

Report streams using the AsyncRetriever cache the ReportDownloadUrl from the polling response when a job completes. This URL is an Azure SAS URL with a short TTL (~5 minutes). When many report jobs complete concurrently, the download queue can cause delays that exceed the TTL, resulting in 403 errors from expired URLs.

Related: airbytehq/airbyte-python-cdk#961 (CDK-side mitigation that reclassified these from config_error to system_error to enable retries).

How

  1. New custom component BingAdsReportUrlRefresher (components.py): Implements the Requester interface. When called as a download_target_requester, it:

    • Extracts the ReportRequestId from the cached polling_response in the stream slice
    • Extracts CustomerId/CustomerAccountId from the original polling request's headers
    • Makes a fresh POST to GenerateReport/Poll to obtain a new ReportDownloadUrl
    • Returns the response so the existing download_target_extractor can extract the fresh URL
    • Includes retry logic with exponential backoff (3 attempts) for transient HTTP errors (429, 5xx) and connection errors
  2. Manifest wiring (manifest.yaml): Adds download_target_requester to basic_async_retriever, referencing the new component with the connector's OAuth authenticator.

Review guide

  1. components.py — The BingAdsReportUrlRefresher class. Key areas to scrutinize:
    • ⚠️ Raw HTTP call: send_request() makes a raw requests.post() call, bypassing the CDK's HTTP client. This means no CDK-level logging or error classification. Manual retry logic (3 attempts, exponential backoff) partially mitigates this — verify this is acceptable for a download-target-requester that runs once per job.
    • ⚠️ CDK internal dependency: Auth context extraction pulls CustomerId/CustomerAccountId from the cached PreparedRequest.headers via polling_response["request"]. This is populated by the CDK's _get_polling_response_interpolation_context() (http_job_repository.py:301-322) but is not part of any public contract. If the CDK changes this structure, the component silently falls back to empty strings.
    • ⚠️ Silent fallback: If CustomerId/CustomerAccountId headers can't be extracted from the cached request, the code falls back to empty strings. This could cause opaque auth failures at the Bing Ads API — worth verifying whether the API rejects requests without these headers or silently degrades.
    • The polling_response structure assumption: expects ReportRequestStatus.ReportRequestId and a request object with headers.
  2. manifest.yaml — 4-line addition wiring the download_target_requester. Verify the existing download_target_extractor (DPath: ReportRequestStatus.ReportDownloadUrl) will correctly extract from the re-poll response.

Reviewer checklist

  • Confirm that bypassing the CDK HTTP client (raw requests.post()) is acceptable here, given the manual retry logic
  • Verify polling_response["request"] contract with CDK team — silent fallback to empty CustomerId/CustomerAccountId if CDK internals change
  • Validate that the retry logic (specific HTTPError + ConnectionError catches) covers expected transient failure modes
  • Confirm the Bing Ads API behavior when CustomerId/CustomerAccountId headers are empty strings (auth error vs. silent degradation)
  • No unit tests were added — the connector test suite requires live Bing Ads API credentials. Verify whether mock-based tests should be required before merge.

User Impact

Report streams should no longer fail with expired SAS URL errors when multiple report jobs queue for download. This is especially impactful for customers with many enabled report streams.

No user-facing configuration changes; no schema, state, or spec changes.

Can this PR be safely reverted and rolled back?

  • YES 💚

Link to Devin session: https://app.devin.ai/sessions/85cd0c285ac8496d8744d7f5a103cec7


Open with Devin

…o avoid expired SAS URLs

Add BingAdsReportUrlRefresher custom component that re-polls
GenerateReport/Poll at download time to obtain a fresh ReportDownloadUrl,
preventing SAS URL expiration failures when many report jobs queue for
download concurrently.

Co-Authored-By: bot_apk <apk@cognition.ai>
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@github-actions
Copy link
Copy Markdown
Contributor

👋 Greetings, Airbyte Team Member!

Here are some helpful tips and reminders for your convenience.

💡 Show Tips and Tricks

PR Slash Commands

Airbyte Maintainers (that's you!) can execute the following slash commands on your PR:

  • 🛠️ Quick Fixes
    • /format-fix - Fixes most formatting issues.
    • /bump-version - Bumps connector versions, scraping changelog description from the PR title.
  • ❇️ AI Testing and Review (internal link: AI-SDLC Docs):
    • /ai-prove-fix - Runs prerelease readiness checks, including testing against customer connections.
    • /ai-canary-prerelease - Rolls out prerelease to 5-10 connections for canary testing.
    • /ai-review - AI-powered PR review for connector safety and quality gates.
  • 🚀 Connector Releases:
    • /publish-connectors-prerelease - Publishes pre-release connector builds (tagged as {version}-preview.{git-sha}) for all modified connectors in the PR.
    • /bump-progressive-rollout-version - Bumps connector version with an RC suffix (2.16.10-rc.1) for progressive rollouts (enableProgressiveRollout: true).
      • Example: /bump-progressive-rollout-version changelog="Add new feature for progressive rollout"
  • ☕️ JVM connectors:
    • /update-connector-cdk-version connector=<CONNECTOR_NAME> - Updates the specified connector to the latest CDK version.
      Example: /update-connector-cdk-version connector=destination-bigquery
  • 🐍 Python connectors:
    • /poe connector source-example lock - Run the Poe lock task on the source-example connector, committing the results back to the branch.
    • /poe source example lock - Alias for /poe connector source-example lock.
    • /poe source example use-cdk-branch my/branch - Pin the source-example CDK reference to the branch name specified.
    • /poe source example use-cdk-latest - Update the source-example CDK dependency to the latest available version.
  • ⚙️ Admin commands:
    • /force-merge reason="<REASON>" - Force merges the PR using admin privileges, bypassing CI checks. Requires a reason.
      Example: /force-merge reason="CI is flaky, tests pass locally"
📚 Show Repo Guidance

Helpful Resources

📝 Edit this welcome message.

Co-Authored-By: bot_apk <apk@cognition.ai>
Copy link
Copy Markdown
Contributor Author

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

View 4 additional findings in Devin Review.

Open in Devin Review

Comment thread airbyte-integrations/connectors/source-bing-ads/components.py
Comment thread airbyte-integrations/connectors/source-bing-ads/components.py
Comment thread airbyte-integrations/connectors/source-bing-ads/components.py Fixed
Comment thread airbyte-integrations/connectors/source-bing-ads/components.py Fixed
devin-ai-integration Bot and others added 4 commits March 24, 2026 23:11
… request context

Co-Authored-By: bot_apk <apk@cognition.ai>
Co-Authored-By: bot_apk <apk@cognition.ai>
Co-Authored-By: bot_apk <apk@cognition.ai>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 25, 2026

source-bing-ads Connector Test Results

496 tests    88 ✅  58m 23s ⏱️
  1 suites  117 💤
  1 files    291 ❌

For more details on these failures, see this check.

Results for commit c1a143e.

♻️ This comment has been updated with latest results.

@pnilan
Copy link
Copy Markdown
Contributor

resolve merge conflicts

…der from master)

Co-Authored-By: bot_apk <apk@cognition.ai>
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

Merge conflicts resolved — merged latest master which brought in the new BingAdsReportZipCsvDecoder class alongside our BingAdsReportUrlRefresher. Both classes and their imports (tempfile, time, zipfile) are now included.


Devin session

@pnilan Patrick Nilan (pnilan) marked this pull request as ready for review April 1, 2026 01:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants