Problem: Retry Failed Requests with Custom Policies
Problem statement
Your team’s backend frequently calls unreliable third-party APIs. Sometimes requests fail due to timeouts, rate limits, or random network errors.
Many API clients hardcode retry logic directly into their request functions, making them rigid and difficult to adapt across services. A common implementation might look like this:
async function fetchData() {try {return await callExternalAPI();} catch (err) {console.log('Retrying in 1 second...');await delay(1000);return await callExternalAPI();}}
This approach doesn’t scale. Different services need different retry policies:
Some endpoints want no retries.
Others need a fixed delay between retries.
Critical services prefer exponential backoff for network resilience.
You’ve decided to apply the Strategy Pattern so retry behavior can change without modifying the core request logic.
You’ll be given:
A simulated unstable API function
unstableRequest()that randomly fails.The utility
delay(ms)to simulate waiting.A
RequestServiceclass that delegates retry behavior to a pluggable strategy.
You must implement the retry strategies and configure them dynamically.
Goal
Implement the missing strategies and complete the retry mechanism.
NoRetryPolicy: Attempts the request once—no retries on failure.FixedDelayPolicy: Retries up to 3 times, waiting 1 second between each attempt.ExponentialBackoffPolicy: Retries up to 3 times, waiting 0.5s, 1s, and 2s between attempts.
Each defines an async .execute(requestFn) method that:
Calls the provided async function
requestFn().Retries according to its policy.
Logs retry attempts to the console.
Constraints
Do not modify
RequestServiceorunstableRequest().Each retry policy must handle its own loop and delay logic.
Use
await delay(ms)for pauses between retries.Log each retry attempt with
[RetryPolicyName] Retry #n after Xms.The final success or failure message should come from
RequestService.
Sample output
The examples below illustrate what the output should look like:
(async () => {const service = new RequestService(new NoRetryPolicy());console.log('Using NoRetryPolicy...');await service.fetch();/* Expected output (will vary due to randomness):Using NoRetryPolicy...Request failed after all retries*/service.setStrategy(new FixedDelayPolicy());console.log('Using FixedDelayPolicy...');await service.fetch();/* Expected output (will vary due to randomness):Using FixedDelayPolicy...[FixedDelayPolicy] Retry #1 after 1000ms[FixedDelayPolicy] Retry #2 after 1000msFinal result: Request succeeded*/service.setStrategy(new ExponentialBackoffPolicy());console.log('Using ExponentialBackoffPolicy...');await service.fetch();/* Expected output (will vary due to randomness):Using ExponentialBackoffPolicy...[ExponentialBackoffPolicy] Retry #1 after 500ms[ExponentialBackoffPolicy] Retry #2 after 1000ms[ExponentialBackoffPolicy] Retry #3 after 2000msRequest failed after all retries*/})();
Good luck trying the problem! If you’re unsure how to proceed, check the “Solution” tab above.
Problem: Retry Failed Requests with Custom Policies
Problem statement
Your team’s backend frequently calls unreliable third-party APIs. Sometimes requests fail due to timeouts, rate limits, or random network errors.
Many API clients hardcode retry logic directly into their request functions, making them rigid and difficult to adapt across services. A common implementation might look like this:
async function fetchData() {try {return await callExternalAPI();} catch (err) {console.log('Retrying in 1 second...');await delay(1000);return await callExternalAPI();}}
This approach doesn’t scale. Different services need different retry policies:
Some endpoints want no retries.
Others need a fixed delay between retries.
Critical services prefer exponential backoff for network resilience.
You’ve decided to apply the Strategy Pattern so retry behavior can change without modifying the core request logic.
You’ll be given:
A simulated unstable API function
unstableRequest()that randomly fails.The utility
delay(ms)to simulate waiting.A
RequestServiceclass that delegates retry behavior to a pluggable strategy.
You must implement the retry strategies and configure them dynamically.
Goal
Implement the missing strategies and complete the retry mechanism.
NoRetryPolicy: Attempts the request once—no retries on failure.FixedDelayPolicy: Retries up to 3 times, waiting 1 second between each attempt.ExponentialBackoffPolicy: Retries up to 3 times, waiting 0.5s, 1s, and 2s between attempts.
Each defines an async .execute(requestFn) method that:
Calls the provided async function
requestFn().Retries according to its policy.
Logs retry attempts to the console.
Constraints
Do not modify
RequestServiceorunstableRequest().Each retry policy must handle its own loop and delay logic.
Use
await delay(ms)for pauses between retries.Log each retry attempt with
[RetryPolicyName] Retry #n after Xms.The final success or failure message should come from
RequestService.
Sample output
The examples below illustrate what the output should look like:
(async () => {const service = new RequestService(new NoRetryPolicy());console.log('Using NoRetryPolicy...');await service.fetch();/* Expected output (will vary due to randomness):Using NoRetryPolicy...Request failed after all retries*/service.setStrategy(new FixedDelayPolicy());console.log('Using FixedDelayPolicy...');await service.fetch();/* Expected output (will vary due to randomness):Using FixedDelayPolicy...[FixedDelayPolicy] Retry #1 after 1000ms[FixedDelayPolicy] Retry #2 after 1000msFinal result: Request succeeded*/service.setStrategy(new ExponentialBackoffPolicy());console.log('Using ExponentialBackoffPolicy...');await service.fetch();/* Expected output (will vary due to randomness):Using ExponentialBackoffPolicy...[ExponentialBackoffPolicy] Retry #1 after 500ms[ExponentialBackoffPolicy] Retry #2 after 1000ms[ExponentialBackoffPolicy] Retry #3 after 2000msRequest failed after all retries*/})();
Good luck trying the problem! If you’re unsure how to proceed, check the “Solution” tab above.