Concepts

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 Raw Request example on GitHub shows how to create an instance of DefaultRequestSigner and call signHttpRequest.

Uploading Large Objects

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 :
  1. Set the environment variable OCI_SDK_DEFAULT_RETRY_ENABLED to false to disable default retries globally.
  2. Override the global default retry configuration:
    let retryConfiguration : common.RetryConfiguration = {
        terminationStrategy : new common.MaxAttemptsTerminationStrategy(1)
        };
      common.GenericRetrier.defaultRetryConfiguration = retryConfiguration;
  3. 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)
        }
    });
  4. Override default retries for a particular request instance. This example shows overriding retries for putObjectRequest:
    const putObjectRequest : objectstorage.requests.PutObjectRequest = {
        objectName : objectName,
        bucketName : bucketName,
        namespaceName : namespaceName,
        putObjectBody : stream,
        retryConfiguration : { terminationStrategy : new common.MaxAttemptsTerminationStrategy(1) }
    }

Retry Behavior Precedence

  • 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:
const request: identity.requests.ListAvailabilityDomainsRequest = {
    compartmentId: tenancyId,
    retryConfiguration : {
        terminationStrategy : new common.MaxAttemptsTerminationStrategy(6),
    }
};
To change the default retry condition programmatically:
let retryConfiguration : common.RetryConfiguration = {
    terminationStrategy : new common.MaxAttemptsTerminationStrategy(1)
};
common.GenericRetrier.defaultRetryConfiguration = retryConfiguration; 

JavaScript

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:

    const request = {
        compartmentId: tenancyId,
        retryConfiguration : {
            terminationStrategy : new common.MaxAttemptsTerminationStrategy(6),
        }
    };
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:

  1. Set the environment variable OCI_SDK_DEFAULT_CIRCUITBREAKER_ENABLED to false to disable default circuit breakers globally.
  2. Disable the global default circuit breakers programmatically:
    common.CircuitBreaker.EnableGlobalCircuitBreaker = false
  3. 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.
  4. 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.

Circuit Breaker Examples

For TypeScript examples, see Github.

For JavaScript examples, see Github.

Setting Endpoints

Service endpoints can be set in three ways:

  • 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:
const client = new os.ObjectStorageClient({ authenticationDetailsProvider: provider });
client.useRealmSpecificEndpointTemplate = true;

For full examples, see the TypeScript and JavaScript examples on GitHub.

New Region Support

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.

To set the region:

identityClient = await new identity.IdentityClient({ authenticationDetailsProvider: provider });
identityClient.region = 'us-phoenix-1'

Other Realms

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:

// 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.

try {
  const response = await identityClient.listAllUsersResponses(listUserReq);
} catch (err) {
  console.log('requestId: ', err.opcRequestId);
}

Logging

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.

For more information, see the logging example on GitHub.

To enable logging:
// 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;