import { PollTimeout } from "../error.js";
import { constructParams } from "../util.js";
function job(j) {
return {
...j,
created: new Date(j.created),
assets: j.assets.map((a) => ({
...a,
created: new Date(a.created),
modified: new Date(a.modified),
}))
};
}
/** Metafold jobs endpoint. */
export class Jobs {
client;
constructor(client) {
this.client = client;
}
/**
* List jobs.
*
* @param {Object} [params] - Optional list parameters.
* @param {string} [params.sort] - Sort string. For details on syntax see the Metafold API docs.
* Supported sorting fields are: "id", "name", or "created".
* @param {string} [params.q] - Query string. For details on syntax see the Metafold API docs.
* Supported search fields are: "id", "name", "type", and "state".
* @returns List of job resources.
*/
async list({ sort, q } = {}) {
const params = constructParams({ sort, q });
const r = await this.client.get(`/projects/${this.client.projectID}/jobs`, { params });
return r.data.map(job);
}
/**
* Get a job.
*
* @param {string} id - ID of job to get.
* @returns Job resource.
*/
async get(id) {
const r = await this.client.get(`/projects/${this.client.projectID}/jobs/${id}`);
return job(r.data);
}
/**
* Dispatch a new job and wait for the result.
*
* See Metafold API docs for the full list of jobs.
*
* @param {string} type - Job type.
* @param {Object} params - Job parameters.
* @param {string} [name] - Job name.
* @param {number} [timeout=12000] - Time in seconds to wait for a result.
* @returns Completed job resource.
*/
async run(type, params, name, timeout = 1000 * 60 * 2) {
const url = await this.runStatus(type, params, name);
let r = null;
try {
r = await this.poll(url, timeout);
}
catch (e) {
if (e instanceof PollTimeout) {
throw new Error(`Job '${name ?? type}' failed to complete within ${timeout} ms`, { cause: e });
}
else {
throw e;
}
}
return job(r.data);
}
/**
* Dispatch a new job and return immediately without waiting for result.
*
* See Metafold API docs for the full list of jobs.
*
* @param {string} type - Job type.
* @param {Object} params - Job parameters.
* @param {string} [name] - Job name.
* @returns {string} Job status url.
*/
async runStatus(type, params, name) {
const data = constructParams({ type, parameters: params, name });
const r = await this.client.post(`/projects/${this.client.projectID}/jobs`, data, {
headers: { "Content-Type": "application/json" },
});
return r.data.link;
}
/**
* Poll the given URL every one second.
*
* Helpful for waiting on job results given a status URL.
*
* @param {string} url - Job status url.
* @param {number} [timeout=12000] - Time in seconds to wait for a result.
* @param {number} [every=1] - Frequency in seconds.
* @returns HTTP response.
*/
poll(url, timeout = 1000 * 60 * 2, every = 1) {
return new Promise((resolve, reject) => {
/* eslint-disable prefer-const */
let intervalID;
let timeoutID;
/* eslint-enable prefer-const */
const clearTimers = () => {
clearInterval(intervalID);
clearTimeout(timeoutID);
};
intervalID = setInterval(() => {
this.client.get(url)
.then((r) => {
if (r.status === 202) {
return;
}
clearTimers();
resolve(r);
})
.catch((e) => {
clearTimers();
reject(e);
});
}, 1000 * every);
timeoutID = setTimeout(() => {
clearInterval(intervalID);
reject(new PollTimeout("Job timed out"));
}, timeout);
});
}
/**
* Update a job.
*
* @param {string} id - ID of job to update.
* @param {Object} [params] - Optional update parameters.
* @param {string} [params.name] - New job name. The existing name remains unchanged if undefined.
* @returns Updated job resource.
*/
async update(id, { name } = {}) {
const data = constructParams({ name });
const r = await this.client.patch(`/projects/${this.client.projectID}/jobs/${id}`, data);
return job(r.data);
}
}