Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/controller-utils/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Allow overriding `isServiceFailure` in `createServicePolicy` ([#9123](https://github.com/MetaMask/core/pull/9123))

### Changed

- Bump `@metamask/utils` from `^11.9.0` to `^11.11.0` ([#9074](https://github.com/MetaMask/core/pull/9074))
Expand Down
7 changes: 6 additions & 1 deletion packages/controller-utils/src/create-service-policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ export type CreateServicePolicyOptions = {
* regarded as degraded (affecting when `onDegraded` is called).
*/
degradedThreshold?: number;
/**
* Predicate function for when an error should be considered a service failure.
*/
isServiceFailure?: (error: unknown) => boolean;
/**
* The maximum number of times that the service is allowed to fail before
* pausing further retries.
Expand Down Expand Up @@ -189,7 +193,7 @@ export const DEFAULT_CIRCUIT_BREAK_DURATION = 30 * 60 * 1000;
*/
export const DEFAULT_DEGRADED_THRESHOLD = 5_000;

const isServiceFailure = (error: unknown): boolean => {
const defaultIsServiceFailure = (error: unknown): boolean => {
if (
typeof error === 'object' &&
error !== null &&
Expand Down Expand Up @@ -283,6 +287,7 @@ export function createServicePolicy(
circuitBreakDuration = DEFAULT_CIRCUIT_BREAK_DURATION,
degradedThreshold = DEFAULT_DEGRADED_THRESHOLD,
backoff = new ExponentialBackoff(),
isServiceFailure = defaultIsServiceFailure,
} = options;

let availabilityStatus: AvailabilityStatus = AVAILABILITY_STATUSES.Unknown;
Expand Down
1 change: 1 addition & 0 deletions packages/network-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The constructor argument `isRpcFailoverEnabled` is no longer available.
- `RemoteFeatureFlagController:stateChange` and `RemoteFeatureFlagController:getState` are now required.
- Drop `async-mutex` dependency, which was no longer used in source ([#9064](https://github.com/MetaMask/core/pull/9064))
- Consider all HTTP errors as service failures except `429` ([#9123](https://github.com/MetaMask/core/pull/9123))

### Removed

Expand Down
23 changes: 20 additions & 3 deletions packages/network-controller/src/rpc-service/rpc-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,13 @@ export type RpcServiceOptions = {
*/
logger?: Pick<Logger, 'warn'>;
/**
* Options to pass to `createServicePolicy`. Note that `retryFilterPolicy` is
* not accepted, as it is overwritten. See {@link createServicePolicy}.
* Options to pass to `createServicePolicy`. Note that `retryFilterPolicy` and `isServiceFailure`
* are not accepted, as they are overwritten. See {@link createServicePolicy}.
*/
policyOptions?: Omit<CreateServicePolicyOptions, 'retryFilterPolicy'>;
policyOptions?: Omit<
CreateServicePolicyOptions,
'retryFilterPolicy' | 'isServiceFailure'
>;
/**
* A function that checks if the user is currently offline. If it returns true,
* connection errors will not be retried, preventing degraded and break
Expand Down Expand Up @@ -372,6 +375,20 @@ export class RpcService {
maxRetries: DEFAULT_MAX_RETRIES,
maxConsecutiveFailures: DEFAULT_MAX_CONSECUTIVE_FAILURES,
...policyOptions,
isServiceFailure: (error) => {
if (
typeof error === 'object' &&
error !== null &&
hasProperty(error, 'httpStatus') &&
typeof error.httpStatus === 'number'
) {
return error.httpStatus !== 429;
}

// If the error is not an object, or doesn't have a numeric code property,
// consider it a service failure (e.g., network errors, timeouts, etc.)
return true;
},
retryFilterPolicy: handleWhen((error) => {
// If user is offline, don't retry any errors
// This prevents degraded/break callbacks from being triggered
Expand Down
Loading