fix(newsletters): harden ActiveCampaign sends against API timeouts#269
Open
adekbadek wants to merge 6 commits into
Open
fix(newsletters): harden ActiveCampaign sends against API timeouts#269adekbadek wants to merge 6 commits into
adekbadek wants to merge 6 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens the Newspack Newsletters ActiveCampaign integration against upstream API hangs/timeouts by ensuring campaign cleanup can’t consume the full request budget and by surfacing a publisher-friendly timeout message instead of raw cURL output.
Changes:
- Add
DEFAULT_REQUEST_TIMEOUT(45s) andCLEANUP_REQUEST_TIMEOUT(15s), and plumb caller-suppliedtimeoutthroughapi_v1_request()andapi_v3_request(). - Humanize transport timeouts (e.g., cURL error 28) returned from
wp_safe_remote_request()for both v1 and v3 endpoints. - Add a PHPUnit spec covering timeout plumbing, bounded cleanup behavior, and timeout humanization.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| plugins/newspack-newsletters/includes/service-providers/active_campaign/class-newspack-newsletters-active-campaign.php | Adds configurable timeouts, bounded cleanup requests, and timeout-specific error humanization. |
| plugins/newspack-newsletters/tests/test-active-campaign-resilience.php | Adds regression tests asserting timeout propagation, cleanup timeout bounds, and user-friendly timeout errors. |
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ae0498d to
6b8efcf
Compare
Member
Author
|
Retargeted to |
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
All Submissions:
Changes proposed in this Pull Request:
Hardens ActiveCampaign newsletter sends against ActiveCampaign-side API hangs, and makes a retried send safe.
Background: a publisher hit
cURL error 28: Operation timed out after 45002ms with 0 bytes receivedwhen sending to their main list. Root cause is on ActiveCampaign's side – specific campaigns got into a state where AC's V1/admin/api.phpcalls referencing them never respond, tripping our 45s request timeout. It self-resolved with no Newspack change. We can't fix the AC hang, but we can stop it from corrupting our send flow, stop surfacing a raw cURL string to publishers, and – most importantly – make sure a retry never sends the newsletter twice.The send is a sequence of side-effectful steps (delete old campaign → upload message → create campaign → trigger send), and any step can time out. The core insight: a timed-out
campaign_status(the trigger) is ambiguous – AC may have started sending before the HTTP response hung. So the fix makes the sequence verify state before acting.Verify the stored campaign's state before resending (double-send safety). On entry,
send()reads the campaign's actual status from AC rather than blindly deleting and recreating it. If it's already scheduled/sending/sent, the send is treated as done (no resend). If it's a confirmed draft, it's safe to recreate and send. If its state can't be verified (the status check itself times out) or it's in an indeterminate paused/stopped state,send()fails safe with a publisher-facing notice and does not resend – a stranded "needs review" is far better than two newsletters to the list.Bounded cleanup timeout. Deleting a previous campaign is best-effort cleanup, so it uses a short, bounded timeout (15s) instead of the 45s default – a stuck prior campaign can't consume the request budget. Required plumbing a caller-supplied
timeoutthrough the v1/v3 request methods, which previously silently dropped it.Publisher-friendly timeout error. A cURL-28 / "timed out" transport failure is rephrased into actionable guidance instead of the raw cURL message; the original error is preserved as
WP_Errordata for logging/support tooling. Other transport errors pass through unchanged.Scope note: this is the synchronous, idempotent foundation. It does not auto-retry through a hang – the publisher still sees a failure on the spot – but the next attempt (manual re-publish, or the existing scheduled-send retry) now resumes safely instead of risking a duplicate send. A fully async/queued send with automatic retry is a larger follow-up that can sit on top of this.
Closes NPPM-2878.
How to test the changes in this Pull Request:
plugins/newspack-newsletters,n test-php --filter ActiveCampaignResilienceTest– all tests pass.n test-php --filter ActiveCampaignApiRequestsTeststill passes.Other information: