@fal-ai/client
Version:
The fal.ai client for JavaScript and TypeScript
225 lines • 11.4 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createQueueClient = void 0;
const request_1 = require("./request");
const response_1 = require("./response");
const streaming_1 = require("./streaming");
const utils_1 = require("./utils");
const DEFAULT_POLL_INTERVAL = 500;
const createQueueClient = ({ config, storage, }) => {
const ref = {
submit(endpointId, options) {
return __awaiter(this, void 0, void 0, function* () {
const { webhookUrl, priority } = options, runOptions = __rest(options, ["webhookUrl", "priority"]);
const input = options.input
? yield storage.transformInput(options.input)
: undefined;
return (0, request_1.dispatchRequest)({
method: options.method,
targetUrl: (0, request_1.buildUrl)(endpointId, Object.assign(Object.assign({}, runOptions), { subdomain: "queue", query: webhookUrl ? { fal_webhook: webhookUrl } : undefined })),
headers: {
"x-fal-queue-priority": priority !== null && priority !== void 0 ? priority : "normal",
},
input: input,
config,
options: {
signal: options.abortSignal,
},
});
});
},
status(endpointId_1, _a) {
return __awaiter(this, arguments, void 0, function* (endpointId, { requestId, logs = false, abortSignal }) {
const appId = (0, utils_1.parseEndpointId)(endpointId);
const prefix = appId.namespace ? `${appId.namespace}/` : "";
return (0, request_1.dispatchRequest)({
method: "get",
targetUrl: (0, request_1.buildUrl)(`${prefix}${appId.owner}/${appId.alias}`, {
subdomain: "queue",
query: { logs: logs ? "1" : "0" },
path: `/requests/${requestId}/status`,
}),
config,
options: {
signal: abortSignal,
},
});
});
},
streamStatus(endpointId_1, _a) {
return __awaiter(this, arguments, void 0, function* (endpointId, { requestId, logs = false, connectionMode }) {
const appId = (0, utils_1.parseEndpointId)(endpointId);
const prefix = appId.namespace ? `${appId.namespace}/` : "";
const queryParams = {
logs: logs ? "1" : "0",
};
const url = (0, request_1.buildUrl)(`${prefix}${appId.owner}/${appId.alias}`, {
subdomain: "queue",
path: `/requests/${requestId}/status/stream`,
query: queryParams,
});
return new streaming_1.FalStream(endpointId, config, {
url,
method: "get",
connectionMode,
queryParams,
});
});
},
subscribeToStatus(endpointId, options) {
return __awaiter(this, void 0, void 0, function* () {
const requestId = options.requestId;
const timeout = options.timeout;
let timeoutId = undefined;
const handleCancelError = () => {
// Ignore errors as the client will follow through with the timeout
// regardless of the server response. In case cancelation fails, we
// still want to reject the promise and consider the client call canceled.
};
if (options.mode === "streaming") {
const status = yield ref.streamStatus(endpointId, {
requestId,
logs: options.logs,
connectionMode: "connectionMode" in options
? options.connectionMode
: undefined,
});
const logs = [];
if (timeout) {
timeoutId = setTimeout(() => {
status.abort();
ref.cancel(endpointId, { requestId }).catch(handleCancelError);
// TODO this error cannot bubble up to the user since it's thrown in
// a closure in the global scope due to setTimeout behavior.
// User will get a platform error instead. We should find a way to
// make this behavior aligned with polling.
throw new Error(`Client timed out waiting for the request to complete after ${timeout}ms`);
}, timeout);
}
status.on("data", (data) => {
if (options.onQueueUpdate) {
// accumulate logs to match previous polling behavior
if ("logs" in data &&
Array.isArray(data.logs) &&
data.logs.length > 0) {
logs.push(...data.logs);
}
options.onQueueUpdate("logs" in data ? Object.assign(Object.assign({}, data), { logs }) : data);
}
});
const doneStatus = yield status.done();
if (timeoutId) {
clearTimeout(timeoutId);
}
return doneStatus;
}
// default to polling until status streaming is stable and faster
return new Promise((resolve, reject) => {
var _a;
let pollingTimeoutId;
// type resolution isn't great in this case, so check for its presence
// and and type so the typechecker behaves as expected
const pollInterval = "pollInterval" in options && typeof options.pollInterval === "number"
? ((_a = options.pollInterval) !== null && _a !== void 0 ? _a : DEFAULT_POLL_INTERVAL)
: DEFAULT_POLL_INTERVAL;
const clearScheduledTasks = () => {
if (timeoutId) {
clearTimeout(timeoutId);
}
if (pollingTimeoutId) {
clearTimeout(pollingTimeoutId);
}
};
if (timeout) {
timeoutId = setTimeout(() => {
clearScheduledTasks();
ref.cancel(endpointId, { requestId }).catch(handleCancelError);
reject(new Error(`Client timed out waiting for the request to complete after ${timeout}ms`));
}, timeout);
}
const poll = () => __awaiter(this, void 0, void 0, function* () {
var _a;
try {
const requestStatus = yield ref.status(endpointId, {
requestId,
logs: (_a = options.logs) !== null && _a !== void 0 ? _a : false,
abortSignal: options.abortSignal,
});
if (options.onQueueUpdate) {
options.onQueueUpdate(requestStatus);
}
if (requestStatus.status === "COMPLETED") {
clearScheduledTasks();
resolve(requestStatus);
return;
}
pollingTimeoutId = setTimeout(poll, pollInterval);
}
catch (error) {
clearScheduledTasks();
reject(error);
}
});
poll().catch(reject);
});
});
},
result(endpointId_1, _a) {
return __awaiter(this, arguments, void 0, function* (endpointId, { requestId, abortSignal }) {
const appId = (0, utils_1.parseEndpointId)(endpointId);
const prefix = appId.namespace ? `${appId.namespace}/` : "";
return (0, request_1.dispatchRequest)({
method: "get",
targetUrl: (0, request_1.buildUrl)(`${prefix}${appId.owner}/${appId.alias}`, {
subdomain: "queue",
path: `/requests/${requestId}`,
}),
config: Object.assign(Object.assign({}, config), { responseHandler: response_1.resultResponseHandler }),
options: {
signal: abortSignal,
},
});
});
},
cancel(endpointId_1, _a) {
return __awaiter(this, arguments, void 0, function* (endpointId, { requestId, abortSignal }) {
const appId = (0, utils_1.parseEndpointId)(endpointId);
const prefix = appId.namespace ? `${appId.namespace}/` : "";
yield (0, request_1.dispatchRequest)({
method: "put",
targetUrl: (0, request_1.buildUrl)(`${prefix}${appId.owner}/${appId.alias}`, {
subdomain: "queue",
path: `/requests/${requestId}/cancel`,
}),
config,
options: {
signal: abortSignal,
},
});
});
},
};
return ref;
};
exports.createQueueClient = createQueueClient;
//# sourceMappingURL=queue.js.map