"use strict"; const Promise = require("bluebird"); // const { UniqueViolationError } = require("objection"); const pipe = require("@promistream/pipe"); const map = require("@promistream/map"); const mapFilter = require("@promistream/map-filter"); module.exports = function ({ backend }) { return function processTaskSafely(task, processHandler) { let lockStream = mapFilter((item) => { return Promise.try(() => { return backend.lock(null, { id: item.id, task: task }); }).then((success) => { if (success) { return item; } else { return mapFilter.NoValue; } }); }); let processUnlockStream = map((item) => { return Promise.try(() => { return backend.runInTransaction((tx) => { return processHandler(item, tx); }); }).finally(() => { // NOTE: The unlock deliberately happens outside of a transaction, so that it can always succeed, even if a task and its associated database changes failed return backend.unlock(null, { id: item.id, task: task }); }).then(() => { return item; }); }); return pipe([ lockStream, processUnlockStream ]); }; };