stackchain-dashboard/frontend/batch-find-work.js
timmy fba1f4238d
All checks were successful
CI / lint (pull_request) Successful in 1m34s
CI / build-release (pull_request) Successful in 6s
CI / release-candidate (pull_request) Has been skipped
feat: batch-claim available work into Today (Closes #671)
2026-08-12 18:58:26 +00:00

54 lines
1.8 KiB
JavaScript

function createBatchFindWork({ capacity, claim, queue, onProgress = () => {} }) {
let request = null;
function result(status, selected, available, queued = [], failed = []) {
return { status, selected, available, queued, failed };
}
function key(item) {
return String(item.repository || '') + '#' + String(item.number || '');
}
function run(items) {
if (request) return request;
const selected = Array.isArray(items) ? items.slice() : [];
const available = Math.max(0, Number(capacity()) || 0);
if (selected.length > available) {
const outcome = result('full', selected.length, available);
onProgress(outcome);
return Promise.resolve(outcome);
}
request = (async () => {
const queued = [];
const failed = [];
for (let index = 0; index < selected.length; index += 1) {
const item = selected[index];
try {
const confirmed = await claim(item);
const queueResult = await queue(confirmed);
if (queueResult === 'queued' || queueResult === 'exists') {
queued.push(key(item));
} else {
failed.push({
key: key(item),
reason: 'assigned but Today sync is unavailable',
assigned: true,
});
}
} catch (error) {
failed.push({ key: key(item), reason: error?.message || 'assignment failed' });
}
onProgress({ status: 'running', processed: index + 1, selected: selected.length });
}
const outcome = result('complete', selected.length, available, queued, failed);
onProgress({ ...outcome, processed: selected.length });
return outcome;
})().finally(() => { request = null; });
return request;
}
return { run };
}
if (typeof module !== 'undefined' && module.exports) module.exports = createBatchFindWork;