This topic explains some of the key concepts for using the SDK for TypeScript and JavaScript.
This topic explains some of the key concepts for using the SDK for TypeScript and JavaScript.
Raw Requests
Raw requests are useful, and in some cases necessary. Typical use cases are: when using your own HTTP client, making a OCI-authenticated request to an alternate endpoint, and making a request to a OCI API that is not currently supported in the SDK. The SDK for TypeScript and JavaScript exposes the DefaultRequestSigner class that you can use to create an instance and call signHttpRequest.
The Object Storage service supports multipart uploads to make large object uploads easier
by splitting the large object into parts. The SDK for TypeScript and JavaScript supports
a higher level upload class that uses the multipart upload APIs. Managing Multipart Uploads provides links to
the APIs used for multipart upload operations. Higher level multipart uploads are
implemented using the UploadManager, which will: split a large
object into parts for you, upload the parts in parallel, and then recombine and commit
the parts as a single object in storage. The UploadObject example shows how to use the
UploadManager to automatically split an object into parts for upload to simplify
interaction with the Object Storage service.
Retries 🔗
Starting with version 2.8.0, the SDK for TypeScript and JavaScript is configured by
default to retry SDK operations that fail using the default retry policy. To determine
which service operations have retries enabled by default, refer to the service
operations's description in the SDK.
Note
Default retry attempts for operations with
binary or stream bodies (for example putObject or uploadPart) are only made if the
backupBinaryBody property for the default retry configuration
is set to true, or if you do not provide the content-length in the
request.
By default, the SDK will retry operations HTTP response status codes 409 (with an
IncorrectState error code), 429, 500, 502, 503, 504, timeout errors (such as HTTP
connection and read timeouts), request connection errors, request exceptions, and
circuit breaker exceptions.
Note
The most current default retry configuration and the list of errors that can be
retried can be seen on Github.
Disabling Default Retries
To opt-out of the default retries feature, you can do one of the following :
Set the environment variable
OCI_SDK_DEFAULT_RETRY_ENABLED to
false to disable default retries globally.
Override the global default retry
configuration:
let retryConfiguration : common.RetryConfiguration = {
terminationStrategy : new common.MaxAttemptsTerminationStrategy(1)
};
common.GenericRetrier.defaultRetryConfiguration = retryConfiguration;
Override the default retries for a particular client instance. This
example shows overriding the default retries for the
objectStorageClient:
const provider: common.ConfigFileAuthenticationDetailsProvider = new common.ConfigFileAuthenticationDetailsProvider();
const client = new objectstorage.ObjectStorageClient({authenticationDetailsProvider : provider}, {
retryConfiguration : { terminationStrategy : new common.MaxAttemptsTerminationStrategy(1)
}
});
Override default retries for a particular request instance. This example
shows overriding retries for
putObjectRequest:
Any retry configuration that you explicitly define at the request level will
override the client level retry configuration or the global level default retry
configuration and the environment variable override for that specific request.
Any retry configuration explicitly defined at the client level will override the
global default retry configuration and the environment variable level override for
the particular client.
Default retry configuration set at the global level programmatically will override
the environment variable level override.
Retry Strategies 🔗
You can specify the strategy to use for how retries are handled, including the number
of times to retry, the condition under which the SDK should retry an operation, and when
to stop retrying an operation. You can set these parameters at the client level and at
the individual request level.
Delay Strategy
The delayStrategy parameter determines how long to wait between each
retry call. There are two options for this parameter:
FixedTimeDelayStrategy (seconds) - Each retry is delayed by a
specified number of seconds.
ExponentialBackoffStrategy (seconds) - The delay time for
subsequent retry calls increases by an exponential factor of 2 until it reaches
the defined maximum delay (in seconds), with a base value of one second.
The default delay strategy is set to ExponentialBackoffDelayStrategy
with a jitter value between 0-1000 milliseconds and a maximum wait time between calls of
30 seconds.
Retry Condition
The retryCondition defines a function with an error argument that
returns a boolean indicating whether to retry or not. The operation will be retried if
this function returns true.
Note
For all requests with binary/stream
bodies, retries are only attempted if
RetryConfiguration.backupBinaryBody is set to
true, or if the original stream body is able to be retried. By
default, stream bodies will be not be backed up. Stream bodies will only be backed
up if backupBinaryBody is set to true or if you
don't provide the content-length in the request.
Termination Strategy
The terminationStrategy parameter defines when to terminate the
retry attempts. This parameter supports the following options:
MaxTimeTerminationStrategy (seconds) - Defines total duration
in seconds for which the retry attempts.
MaxAttemptsTerminationStrategy (attempts) - Defines the total
number of retry attempts.
The default termination strategy for OCI SDKs is a
MaxAttemptsTerminationStrategy value of 8.
Retry Examples 🔗
TypeScript
This example sets the retry configuration at the client level:
const provider: common.ConfigFileAuthenticationDetailsProvider = new common.ConfigFileAuthenticationDetailsProvider();
const client = new objectstorage.ObjectStorageClient({authenticationDetailsProvider : provider}, {
retryConfiguration : {
delayStrategy : new common.FixedTimeDelayStrategy(5),
terminationStrategy : new common.MaxTimeTerminationStrategy(30),
retryCondition : (error) => { return error.statusCode >= 500;
}
}
This example sets the retry configuration at the request
level:
To change the default retry condition
programmatically:
let retryConfiguration = {
terminationStrategy : new common.MaxAttemptsTerminationStrategy(1)
};
common.GenericRetrier.defaultRetryConfiguration = retryConfiguration;
Polling with Waiters 🔗
The OCI SDK for TypeScript offers waiters that allow your code to wait until a
specific resource reaches a desired state. A waiter will wait until either the desired
state is reached or a timeout is exceeded. Waiters abstract the polling logic you would
otherwise have to write into an easy-to-use single method call.
Waiters are obtained through the service client client.createWaiter().
Waiters take in an optional configuration object for users to control over how long to
wait and how much time between polling attempts. The following example demonstrates how
to create a waiter with the optional configuration:
// The waiter configuration used when creating our waiters.
import common = require("oci-common");
import identity = require("oci-identity");
const maxTimeInSeconds = 60 * 60; // The duration for waiter configuration before failing. Currently set to 1 hour.
const maxDelayInSeconds = 30; // The max delay for the waiter configuration. Currently set to 30 seconds
const waiterConfiguration: common.WaiterConfiguration = {
terminationStrategy: new common.MaxTimeTerminationStrategy(maxTimeInSeconds),
delayStrategy: new common.ExponentialBackoffDelayStrategy(maxDelayInSeconds)
};
const identityClient = new identity.identityClient({ authenticationDetailsProvider: provider });
const identityWaiter = identityClient.createWaiters(waiterConfiguration);
Circuit Breakers 🔗
Starting with version 2.8.0, the SDK for Typescript and Javascript provides default
support for circuit breakers. Circuit breakers help prevent the client from
overwhelming the service by blocking the requests from being sent to the service after a
certain failure threshold is reached. For default circuit breakers, all errors that can
be retried will be treated as failures for the circuit breakers.
Note
The default circuit breaker configuration can be viewed on Github.
The following parameters define a circuit breaker:
Failure Rate Threshold - the state of the circuit breaker changes from CLOSED to
OPEN when the failure rate is equal or greater than this hreshold. For example, when
more than 50% of the recorded calls have failed, the circuit breaker will open.
Reset Timeout - the timeout after which an open circuit breaker will attempt a
request if a request is made
Failure Exceptions - the list of exceptions that will be regarded as failures for
the circuit
Minimum number of calls/ Volume threshold - the minimum number of calls which are
required (per sliding window period) before the circuit breaker can calculate the
error rate
Default Circuit Breaker Configuration
The following is the default circuit breaker configuration:
Failure Rate Threshold: 80%. When 80% of the requests calculated for a
time window of 120 seconds have failed, the circuit will transition from closed
to open.
Minimum number of calls / volume threshold: 10, for the above defined
time window of 120 seconds.
Reset Timeout: The circuit breaker will wait 30 seconds before setting
the breaker to the halfOpen state and trying the action
again.
Failure Exceptions : The failures for the circuit will only be recorded
for retryable or transient exceptions. HTTP response codes 409 (with an
IncorrectState), 429, 500, 502, 503, and 504, HTTP request and other timeouts,
request connection errors and exceptions are all treated as failures that will
trigger a circuit breaker.
Disabling the Default Circuit Breaker
To opt out of the default circuit breaker feature, you can do one of the following:
Set the environment variable
OCI_SDK_DEFAULT_CIRCUITBREAKER_ENABLED to
false to disable default circuit breakers globally.
Disable the global default circuit breakers
programmatically:
Override the global default circuit breaker
configuration:
let customDefaultCircuitBreakerConfig = {
timeout: 10000, // If our function takes longer than 10 seconds, trigger a failure
errorThresholdPercentage: 80, // When 80% of requests fail, trip the circuit
resetTimeout: 30000, // After 30 seconds, try again.
rollingCountTimeout: 120000, // the duration of the statistical rolling window, in milliseconds
rollingCountBuckets: 120, // the number of buckets the rolling statistical window is divided into
volumeThreshold: 10, // minimum number of failures in the circuit
errorFilter: defaultErrorFilterFunction // defines the failure filter for the circuit
};
common.CircuitBreaker.defaultConfiguration = customDefaultCircuitBreakerConfig;
Note
Overriding
the global default retry configuration will enable circuit breakers with the
defined configuration for all the service clients.
Override the default circuit breaker configuration for a particular client
instance. This example shows overriding the default circuit breaker for the
objectStorageClient:
let customDefaultCircuitBreakerConfig = {
timeout: 10000, // If our function takes longer than 10 seconds, trigger a failure
errorThresholdPercentage: 80, // When 80% of requests fail, trip the circuit
resetTimeout: 30000, // After 30 seconds, try again.
rollingCountTimeout: 120000, // the duration of the statistical rolling window, in milliseconds
rollingCountBuckets: 120, // the number of buckets the rolling statistical window is divided into
volumeThreshold: 10, // minimum number of failures in the circuit
errorFilter: defaultErrorFilterFunction, // defines the failure filter for the circuit
};
const client = new objectstorage.ObjectStorageClient({authenticationDetailsProvider : provider}, {
circuitBreaker : new common.CircuitBreaker(customDefaultCircuitBreakerConfig)});
Circuit Breaker Behavior Precedence
Any circuit breaker configuration that you explicitly define at the client level will
override the global default circuit breaker configuration and the environment level
override for that particular client.
Set .endpoint = '<YOUR_ENDPOINT>' on the service instance. This lets you specify a full host name (for example, https://www.example.com).
Set .region = '<YOUR_REGION_ID> on the service instance. This selects the appropriate host name for the service for the given region. However, if the service is not supported in the region you set, the SDK for TypeScript and JavaScript returns an error. You can refer to the list of regionIds in: ./oci-typescript-sdk/common/lib/region.ts
Pass the region in the configuration file. For more information, see SDK and CLI Configuration File.
Note that a service instance cannot be used to communicate with different regions. If you need to make requests to different regions, create multiple service instances.
Dedicated Endpoints 🔗
Dedicated endpoints are the endpoint templates defined by the service for a specific
realm at the client level. The OCI TypeScript and JavaScript SDK allows you to enable
the use of this realm-specific endpoint templates feature at both the application level
and at the client level. This feature is disabled by default.
Note
The value set at client level takes precedence over the value set at the
application level.
Enabling realm-specific endpoint templates at the application level:
To enable the realm-specific endpoint templates feature at the application level, set the
environment variable
OCI_REALM_SPECIFIC_SERVICE_ENDPOINT_TEMPLATE_ENABLED to
true.
Note
The boolean value is
case-insensitive.
Enabling realm-specific endpoint templates at the client level:
To enable the realm-specific endpoint templates feature at the client level, set the flag
in code as shown
below:
If you are using a version of the SDK released prior to the announcement of a new region, you can use a workaround to reach it.
A region is a localized geographic area. For more information on regions and how to
identify them, see Regions and Availability Domains.
A realm is a set of regions that share entities. You can identify your realm by looking at the domain name at the end of the network address. For example, the realm for xyz.abc.123.oraclecloud.com is oraclecloud.com.
You must first call Region.register to register the new region, and then you can set the region by either using the configuration file or by set .region = <Your_new_registered_region>.
oraclecloud.com Realm 🔗
For regions in the oraclecloud.com realm, you can pass new region names just as you would pass ones that are already defined in the Region enum for your SDK version.
For regions in realms other than oraclecloud.com, you can use the following workarounds to reach new regions with earlier versions of the SDK.
To set the endpoint:
Copy
// Instantiate an identity client
identityClient = await new identity.IdentityClient({ authenticationDetailsProvider: provider });
identityClient.endpoint = 'https://<your_endpoint>.com'
Paginated Responses 🔗
Sometimes it is better to lazy load a result. In order to retrieve more data from lazy load, you have to continue to make calls to the list operation, passing in the value of the most recent response's next token. The pagination module allows you:
Eagerly load all possible results from a list call
Lazily load results
For an example on how to use these functions, please check GitHub.
Exception Handling 🔗
When handling an exception, you can get more information about the HTTP request that caused it, such as the status code or timeout. You can also get the request ID when handling an exception by looking at the opcRequestId property of the error object.
The SDK for Typescript and JavaScript enables you to integrate your own logger. Logging
in the SDK is done through the Logger interface. This interface is a logging
abstraction that allows the use of a user-supplied logging library, such as log4js,
bunyan, or winston.
// TypeScript
// Download the logger that you want to use with the SDK (like bunyan)
import { LOG } from "oci-sdk";
var bunyan = require("bunyan");
// Set the logger here
var bunLog = bunyan.createLogger({ name: "LoggingExample", level: "debug" });
LOG.logger = bunLog;
// Javascript
import { LOG } from "oci-sdk";
var bunyan = require("bunyan");
// Set the logger here.
var bunLog = bunyan.createLogger({ name: "LoggingExample", level: "debug" });
LOG.logger = bunLog;