Problem: Hybrid Service Adapter for Fallback APIs

Hard
40 min
Create an adapter that wraps two APIs (primary and fallback) and automatically retries the fallback if the primary fails—all under a single consistent interface.

Problem statement

Suppose your application relies on a third-party API for currency conversion. It also has a backup provider that can take over if the primary API fails or times out. Currently, different parts of the codebase call these providers directly, leading to repeated error handling and branching logic, such as:

try {
return await primary.convert(amount, from, to);
} catch {
return await fallback.convert(amount, from, to);
}

You need a cleaner, more reliable abstraction. Your task is to create a hybrid adapter that hides this fallback behavior behind a single, consistent interface.

Goal

Implement a HybridCurrencyAdapter that exposes a single async method:

async convert(amount, from, to)

It should:

  • Try the primary provider first.

  • If the primary fails (throws or rejects), automatically use the fallback provider.

  • Return the normalized response object in the format:

{ success: true, rate, provider }

If both providers fail, return:

{ success: false, message }

Constraints

  • You cannot modify the providers.

  • The adapter must handle asynchronous errors gracefully.

  • Both providers may have slightly different response formats.

  • The final response must always follow the unified shape above.

Sample output

The examples below illustrate what the output should look like:

(async () => {
const hybrid = new HybridCurrencyAdapter(primaryApi, fallbackApi);
for (let i = 0; i < 3; i++) {
const result = await hybrid.convert(100, 'USD', 'EUR');
console.log(result);
}
})();
/* Expected output (may vary):
Primary API failed, switching to fallback: Primary API unavailable
{ success: true, rate: 1.08, provider: 'Fallback' }
{ success: true, rate: 1.09, provider: 'Primary' }
Primary API failed, switching to fallback: Primary API unavailable
{ success: false, message: 'Both providers failed' }
*/

Good luck trying the problem! If you’re unsure how to proceed, check the “Solution” tab above.

Problem: Hybrid Service Adapter for Fallback APIs

Hard
40 min
Create an adapter that wraps two APIs (primary and fallback) and automatically retries the fallback if the primary fails—all under a single consistent interface.

Problem statement

Suppose your application relies on a third-party API for currency conversion. It also has a backup provider that can take over if the primary API fails or times out. Currently, different parts of the codebase call these providers directly, leading to repeated error handling and branching logic, such as:

try {
return await primary.convert(amount, from, to);
} catch {
return await fallback.convert(amount, from, to);
}

You need a cleaner, more reliable abstraction. Your task is to create a hybrid adapter that hides this fallback behavior behind a single, consistent interface.

Goal

Implement a HybridCurrencyAdapter that exposes a single async method:

async convert(amount, from, to)

It should:

  • Try the primary provider first.

  • If the primary fails (throws or rejects), automatically use the fallback provider.

  • Return the normalized response object in the format:

{ success: true, rate, provider }

If both providers fail, return:

{ success: false, message }

Constraints

  • You cannot modify the providers.

  • The adapter must handle asynchronous errors gracefully.

  • Both providers may have slightly different response formats.

  • The final response must always follow the unified shape above.

Sample output

The examples below illustrate what the output should look like:

(async () => {
const hybrid = new HybridCurrencyAdapter(primaryApi, fallbackApi);
for (let i = 0; i < 3; i++) {
const result = await hybrid.convert(100, 'USD', 'EUR');
console.log(result);
}
})();
/* Expected output (may vary):
Primary API failed, switching to fallback: Primary API unavailable
{ success: true, rate: 1.08, provider: 'Fallback' }
{ success: true, rate: 1.09, provider: 'Primary' }
Primary API failed, switching to fallback: Primary API unavailable
{ success: false, message: 'Both providers failed' }
*/

Good luck trying the problem! If you’re unsure how to proceed, check the “Solution” tab above.

Node.js
// Simulated primary API (fails intermittently)
const primaryApi = {
async convert(amount, from, to) {
if (Math.random() < 0.5) throw new Error('Primary API unavailable');
return { ok: true, rate: 1.09, vendor: 'Primary' };
}
};
// Simulated fallback API (always succeeds)
const fallbackApi = {
async convert(amount, from, to) {
return { success: true, conversionRate: 1.08, source: 'Fallback' };
}
};
// Your code here
// Example usage
(async () => {
const hybrid = new HybridCurrencyAdapter(primaryApi, fallbackApi);
for (let i = 0; i < 3; i++) {
const result = await hybrid.convert(100, 'USD', 'EUR');
console.log(result);
}
})();
/* Expected output (may vary):
Primary API failed, switching to fallback: Primary API unavailable
{ success: true, rate: 1.08, provider: 'Fallback' }
{ success: true, rate: 1.09, provider: 'Primary' }
Primary API failed, switching to fallback: Primary API unavailable
{ success: false, message: 'Both providers failed' }
*/