Using multiple providers
Consuming a single capability from multiple providers is at heart of Superface. You can add as many providers as you need for every profile.
This guide will walk you through the process of configuring these providers the way you need them to work. You'll need a Node.js app with OneSDK and a capability set up. We recommend you to read through the Getting started first if you haven’t done so.
There are currently 2 different ways you might want to switch between the providers:
- Choose the specific provider for each perform: fulfill the use case by the chosen provider
- Setup automatic failover: switch to another provider when the primary fails
Manual provider selection
In integration scenarios where you need to fulfill the use case by the specific provider (e.g. because the user content is saved on their servers), you can manually choose which provider you want to use.
The provider choice is bound to a single perform. This means you can choose
different providers for different perform
calls.
It works by passing the chosen provider configuration to perform
method
on the use case. You can fetch the provider configuration in runtime using
getProvider
method exposed from OneSDK.
Example
Let's say your app lists user repositories and you want to support multiple
version control systems. You'd use vcs/user-repos
and will configure all supported VCS providers.
npx @superfaceai/cli configure github --profile=vcs/user-repos
npx @superfaceai/cli configure gitlab --profile=vcs/user-repos
npx @superfaceai/cli configure bitbucket --profile=vcs/user-repos
Then, switching between the 3 configured providers would look like this:
- GitHub
- GitLab
- Bitbucket
const { SuperfaceClient } = require('@superfaceai/one-sdk');
const sdk = new SuperfaceClient();
async function run() {
const profile = await sdk.getProfile('vcs/user-repos');
// Load the specific provider for this perform
const provider = await sdk.getProvider('github');
const result = await profile
.getUseCase('UserRepos')
.perform({ user: 'superfaceai' }, { provider });
return result.unwrap();
}
run();
const { SuperfaceClient } = require('@superfaceai/one-sdk');
const sdk = new SuperfaceClient();
async function run() {
const profile = await sdk.getProfile('vcs/user-repos');
// Load the specific provider for this perform
const provider = await sdk.getProvider('gitlab');
const result = await profile
.getUseCase('UserRepos')
.perform({ user: 'superfaceai' }, { provider });
return result.unwrap();
}
run();
const { SuperfaceClient } = require('@superfaceai/one-sdk');
const sdk = new SuperfaceClient();
async function run() {
const profile = await sdk.getProfile('vcs/user-repos');
// Load the specific provider for this perform
const provider = await sdk.getProvider('bitbucket');
const result = await profile
.getUseCase('UserRepos')
.perform({ user: 'superfaceai' }, { provider });
return result.unwrap();
}
run();
note
If there's only one provider configured for the profile, that provider is automatically used and you don't have to explicitly choose the provider in the code.
Automatic failover
When using provider failover, OneSDK will automatically switch to another provider in the case of failure.
This will give you a maximum out-of-the-box resiliency useful for integration scenarios where you don't care so much about which provider fulfills the use case but you need it to happen reliably (e.g. in commodity use cases like sending emails, SMS, etc).
Enabling failover
The failover has to be configured for each use case separately by enabling
providerFailover
option in the use case defaults.
For example, if you want to send SMS messages reliably, you'll use the
SendMessage
use case from communication/send-sms
and have two or three providers configured.
Then, the configuration of the failover for SendMessage
use case would look like this:
{
"profiles": {
"communication/send-sms": {
"version": "1.0.1",
"defaults": {
"SendMessage": {
"providerFailover": true
}
},
"priority": [
// ...
],
"providers": {
// ...
}
}
},
"providers": {
// ...
}
}
For more information about the use case defaults, please see super.json reference.
Specifying failover order
By default, OneSDK uses the first provider that was added to the application as primary, with failover to other providers in order they were added to the app. You can specify your preferred order in which OneSDK should use and fail over between the providers.
For example, you're using communication/send-sms
to send SMS reliably and have 3 providers configured (e.g. tyntec
, plivo
and twilio
).
You want to primarily use twilio
. If that fails, you prefer plivo
and if
the secondary fails as well, you want to switch to tyntec
.
The configuration of the provider priority for this case would look like this:
{
"profiles": {
"communication/send-sms": {
"version": "1.0.1",
"defaults": {
"SendMessage": {
"providerFailover": true
}
},
"priority": ["twilio", "plivo", "tyntec"],
"providers": {
// ...
}
}
},
"providers": {
// ...
}
}
Retry on failure
By default, OneSDK attempts to perform the use case with each provider exactly once.
OneSDK also ships with a configurable
circuit breaker
retry policy. The retry policy has to be configured for each provider by setting
retryPolicy
option in the use case defaults for provider.
For example, enabling the circuit breaker retry policy for twilio
when
performing SendMessage
use case (from communication/send-sms
)
would look like the snippet below.
The default circuit breaker policy makes 5 retries using an exponential backoff and times out after 30 seconds. For full retry configuration, please see super.json reference.
{
"profiles": {
"communication/send-sms": {
"version": "1.0.1",
"defaults": {
// ...
},
"priority": [
// ...
],
"providers": {
"twilio": {
"defaults": {
"SendMessage": {
"retryPolicy": "circuit-breaker"
// ...
}
}
}
}
}
},
"providers": {
// ...
}
}
Failover in code
When using automatic failover, your code doesn't need to specify anything
about the providers. The priority of providers, their behavior and failover
is configured solely in your local super.json
file.
For example, using communication/send-sms
to send SMS reliably with multiple providers configured using automatic failover,
your application code for performing SendMessage
would look like this
(note that there's no provider-specific information included):
const { SuperfaceClient } = require('@superfaceai/one-sdk');
const sdk = new SuperfaceClient();
async function run() {
// Load the installed profile
const profile = await sdk.getProfile('communication/send-sms');
// Use the profile
const result = await profile.getUseCase('SendMessage').perform({
to: '+123456789',
from: '+987654321',
text: 'Really important message!',
});
return result.unwrap();
}
run();
caution
Automatic failover cannot be combined with manual provider selection.