Skip to content

Add retry middleware support for transient cURL connection errors (52/55/56)#614

Merged
ksvirkou-hubspot merged 2 commits into
HubSpot:masterfrom
AScriver:master
May 11, 2026
Merged

Add retry middleware support for transient cURL connection errors (52/55/56)#614
ksvirkou-hubspot merged 2 commits into
HubSpot:masterfrom
AScriver:master

Conversation

@AScriver

@AScriver AScriver commented May 4, 2026

Copy link
Copy Markdown
Contributor

Fixes #597.

Adds opt-in retry support for transient transport-level cURL failures that currently bypass HTTP-status retry middleware.

Changes

  • Add createConnectionErrorsMiddleware(...)
  • Add getRetryFunctionByConnectionErrors(...)
  • Default retriable cURL error codes: 52, 55, 56
  • Add unit tests for:
    • retriable errno/message cases
    • non-retriable case
    • max-retry cutoff
  • Update README retry example to include connection-error middleware

@ksvirkou-hubspot

Copy link
Copy Markdown
Collaborator

I noticed 4 test failures in the CI run. Could you please fix them?

@ksvirkou-hubspot

Copy link
Copy Markdown
Collaborator

Would it make sense to add a default delay function here?
Retrying transient cURL connection errors immediately might be a bit aggressive, so an exponential backoff could be a safer default.
For example:

$delayFunction = function (int $retries): int {
    return min(1000 * (2 ** $retries), 10000);
};

@AScriver

AScriver commented May 8, 2026

Copy link
Copy Markdown
Contributor Author

Would it make sense to add a default delay function here? Retrying transient cURL connection errors immediately might be a bit aggressive, so an exponential backoff could be a safer default. For example:

$delayFunction = function (int $retries): int {
    return min(1000 * (2 ** $retries), 10000);
};

I checked this, and Guzzle already applies an exponential backoff when the delay function is null.

createConnectionErrorsMiddleware() passes $delayFunction through to Middleware::retry(). Guzzle's RetryMiddleware constructor then defaults a missing delay to RetryMiddleware::exponentialDelay, which returns 2 ** ($retries - 1) * 1000 milliseconds.

So the default sequence is already 1000ms, 2000ms, 4000ms, etc. I think leaving this delegated to Guzzle is preferable here because adding our own default would duplicate existing behavior and could subtly diverge over time.

That said, I'm open to making the default explicit here as well if that's preferred.

@ksvirkou-hubspot ksvirkou-hubspot merged commit 7a14c0a into HubSpot:master May 11, 2026
2 checks passed
@ksvirkou-hubspot

Copy link
Copy Markdown
Collaborator

Thanks for the contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cURL errors in contact search via email

2 participants