Javascript client for the Adobe Asset Compute Service. Currently only tested with Nodejs. The Javascript API is separated in 3 parts:
- AssetCompute - A light-weight wrapper around the AssetCompute API.
- AssetComputeEventEmitter - Listens to an I/O event journal and converts the events to
rendition_createdandrendition_failedevents. - AssetComputeClient - A higher level client that provides a simpler API
- by default, uses
node-fetch-retryfor retrying on other HTTP responses - by default, provides custom, smarter retry behavior on HTTP status code 429 (Too many requests).
- by default, uses
AssetComputeClient has the following capabilities:
- Fully initialize Asset Compute through a previously provisioned integration
- Listens to I/O events on the integration
- Invoke Asset Compute process asynchronously
- Wait for a single Asset Compute process request to finish (default timeout is 60s)
- Wait for all Asset Compute process requests to finish (default timeout is 60s)
retry has the following capabilities:
- additional features to retry on 429s for
/unregister,/register, and/process - Looks at the
retry-afterheader in the HTTP response to determine how long to wait (in seconds) before retrying - If no
retry-afteris present, choose a random wait time between 30-60 seconds - Configurable retry count via
max429RetryCountoption. (Defaults to 4 retries) - Disable completely via the
disable429Retryoption. (Defaults to 4 retries)
npm i @adobe/asset-compute-client
After the client is set up, you must call .register() once before the first call to .process().
If the integration does not already have an I/O Events journal registered, it may take some time after calling .register() to be able to recieve and send I/O Events so it is recommended to add some wait time before calling .process().
If the integration already has an I/O Events journal registered, it is recommended to not wait before calling .process().
const { AssetComputeClient, getIntegrationConfiguration } = require("@adobe/asset-compute-client");
const sleep = require('util').promisify(setTimeout);
//If integration file is json, a private key file must also be provided
const integrationFilePath = "/path/to/integration/file"; // Either json or yaml format
const integration = await getIntegrationConfiguration(integrationFilePath[, privateKeyFile]);
const assetCompute = new AssetComputeClient(integration);
// Call register before first call the process
await assetCompute.register();
// add wait time for events provider to set up
await sleep(45000); // 30s
const { requestId } = await assetCompute.process(
"https://presigned-source-url", [
{
name: "rendition.png",
url: "https://presigned-target-url",
fmt: "png",
width: 200,
height: 200
}
]
)
const events = await assetCompute.waitActivation(requestId);
if (events[0].type === "rendition_created") {
// use the rendition
} else {
// failed to process
}Note that any errors while polling the I/O Event journal will be logged before it retries:
Error polling event journal: request to https://events-va6.adobe.io/.... failed, reason: connect ECONNREFUSED 54.81.231.29:443
To add custom error message handling, listen for the error event:
assetCompute.on("error", error => console.log("custom error message", error.message));Or disable any error message output:
assetCompute.on("error", () => {});This function creates a new instance of AssetComputeClient and calls the .register() method.
const { AssetComputeClient, getIntegrationConfiguration } = require("@adobe/asset-compute-client");
//If integration file is json, a private key file must also be provided
const integrationFilePath = "/path/to/integration/file"; // Either json or yaml format
const integration = await getIntegrationConfiguration(integrationFilePath[, privateKeyFile]);
const assetCompute = await AssetComputeClient.create(integration);
// add wait time if needed
const { requestId } = await assetCompute.process(
"https://presigned-source-url", [
{
name: "rendition.png",
url: "https://presigned-target-url",
fmt: "png",
width: 200,
height: 200
}
]
)
const events = await assetCompute.waitActivation(requestId);
if (events[0].type === "rendition_created") {
// use the rendition
} else {
// failed to process
}After setting up the client, it is necessary to call .register() once before calling .process().
If the integration already has an I/O Events journal registered, you still must call register. The journal url returned from register is necessary for the client to retrieve I/O Events.
If the integration does not have an I/O Events journal registered, make sure to add some wait time after calling .register() before calling .process(). (It is recommended to wait around ~45 seconds)
const assetCompute = new AssetComputeClient(integration);
await assetCompute.register();The unregister method will remove the I/O Events Journal created in .register(). It is necessary to call .register() again before attempting to use the client after unregistering.
Example usage:
const assetCompute = new AssetComputeClient(integration);
await assetCompute.register();
await assetCompute.process(..renditions);
// unregister journal
await assetCompute.unregister();
// call to process will fail, must call `register()` again first
try {
await assetCompute.process(..renditions);
} catch (e) {
// expected error, must call `register()` first
}
await assetCompute.register();
sleep(45000); // sleep after registering to give time for journal to set up
await assetCompute.process(..renditions);By default, AssetComputeClient will retry 4 times (with smart backpressure) on 429s.
Retry 10 times on 429s:
const assetCompute = new AssetComputeClient(integration, {
max429RetryCount: 10
});Disable retry on 429s:
const assetCompute = new AssetComputeClient(integration, {
disable429Retry: false
});Fetch retry options are documented here. The default options are used on each fetch request.
Note: these do not cover retrying on 429s since this requires the custom retry logic (retry.js) (ie, retrying every 1s with backoff could worsen the issue in a situation when the endpoint is overloaded)
Contributions are welcomed! Read the Contributing Guide for more information.
This project is licensed under the Apache V2 License. See LICENSE for more information.