"use strict"; const Promise = require("bluebird"); const chalk = require("chalk"); const logStatus = require("./util/log-status"); module.exports = function ({ backend }) { return function runTask(task, item) { let queue = []; let itemIsDeleted = false; let api = backend.forItem({ task: task, item: item, mutationQueue: queue, onDeleteSelf: () => { itemIsDeleted = true; } }); return Promise.try(() => { // TODO: Standardize logging control/levels interface, also for library use if (!process.env.SRAP_QUIET) { logStatus(task, chalk.bold.cyan, "started", item.id); } // NOTE: We only pass in the item data itself, *not* any associated metadata like tags. If the scraping task wants access to that sort of information, it should do a `getItem` call from within its task logic where needed. // FIXME: Is that actually still true post-refactor? return task.run({ data: item.data, ... api.exposed }); }).then(() => { // NOTE: We only apply changes at the very end (outside of simulation mode), so that when a task implementation contains multiple operations, each of those operation always 'sees' the state at the start of the task, not the state after the previous mutation. This makes the model as a whole easier to reason about. In simulation mode, all calls are immediate and the queue is empty - after all, no mutation can happen in that case anyway. This is also another reason to ensure that operations in live mode always see the starting state; that makes its behaviour consistent with simulation mode. return backend.topLevel.runInTransaction(null, (tx) => { return Promise.each(queue, (operation) => { return operation(tx); }); }); }).then(async () => { if (!itemIsDeleted) { await api.internal.markTaskCompleted(); } if (!process.env.SRAP_QUIET) { logStatus(task, chalk.bold.green, "completed", item.id); } return { status: "completed", item: item }; }).catch(async (error) => { await api.internal.markTaskFailed(null, { error }); logStatus(task, chalk.bold.red, "failed", `${item.id}: ${error.stack}`); return { status: "failed", item: item, error: error }; }); }; };