@grouparoo/core
Version:
The Grouparoo Core
204 lines (203 loc) • 8.75 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var ExportProcessor_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExportProcessor = exports.ExportProcessorStates = void 0;
const sequelize_typescript_1 = require("sequelize-typescript");
const sequelize_1 = require("sequelize");
const actionhero_1 = require("actionhero");
const Destination_1 = require("./Destination");
const apiData_1 = require("../modules/apiData");
const stateMachine_1 = require("../modules/stateMachine");
const Export_1 = require("./Export");
const errors_1 = require("../modules/errors");
const exportProcessor_1 = require("../modules/ops/exportProcessor");
const Mapping_1 = require("./Mapping");
const Option_1 = require("./Option");
const commonModel_1 = require("../classes/commonModel");
exports.ExportProcessorStates = [
"pending",
"failed",
"complete", // OK!
];
const STATE_TRANSITIONS = [
{ from: "pending", to: "failed", checks: [] },
{
from: "pending",
to: "complete",
checks: [
(instance) => instance.ensureAllExportsProcessed(),
],
},
];
let ExportProcessor = ExportProcessor_1 = class ExportProcessor extends commonModel_1.CommonModel {
idPrefix() {
return "prc";
}
async setError(error, retryDelay = actionhero_1.config.tasks.timeout) {
return exportProcessor_1.ExportProcessorOps.setError(this, error, retryDelay);
}
async retry(retryDelay = actionhero_1.config.tasks.timeout, skipCount = false) {
return exportProcessor_1.ExportProcessorOps.retry(this, retryDelay, skipCount);
}
async complete() {
this.errorMessage = null;
this.errorLevel = null;
this.completedAt = new Date();
this.state = "complete";
await this.save();
}
async apiData(includeDestination = true) {
const exportsCount = await this.$count("exports");
const destination = await this.$get("destination", {
include: includeDestination ? [Option_1.Option, Mapping_1.Mapping] : undefined,
scope: null,
});
return {
id: this.id,
destination: destination && includeDestination
? await destination.apiData(false, false)
: null,
destinationName: destination ? destination.name : null,
state: this.state,
createdAt: apiData_1.APIData.formatDate(this.createdAt),
processAt: apiData_1.APIData.formatDate(this.processAt),
startedAt: apiData_1.APIData.formatDate(this.startedAt),
completedAt: apiData_1.APIData.formatDate(this.completedAt),
remoteKey: this.remoteKey,
exportsCount,
retryCount: this.retryCount,
errorMessage: this.errorMessage,
errorLevel: this.errorLevel,
};
}
async getExportsToProcess() {
return exportProcessor_1.ExportProcessorOps.getExportsToProcess(this);
}
async ensureAllExportsProcessed() {
const pendingExportsCount = await this.$count("exports", {
where: { state: { [sequelize_1.Op.notIn]: ["complete", "failed"] } },
});
if (pendingExportsCount > 0) {
throw new Error("Cannot mark export processor as complete because some exports have not been processed");
}
}
static async updateState(instance) {
await stateMachine_1.StateMachine.transition(instance, STATE_TRANSITIONS);
}
static ensureErrorLevel(instance) {
if (instance.errorMessage && !instance.errorLevel) {
instance.errorLevel = "error";
}
}
static async sweep(limit) {
// delete export processors that don't have any exports
const rowsWithNoExports = await actionhero_1.api.sequelize.query(`
DELETE FROM "exportProcessors"
WHERE id IN (
SELECT id FROM "exportProcessors"
WHERE "state" <> 'pending'
AND 0 = (
SELECT COUNT(id)
FROM exports
WHERE
exports."exportProcessorId" = "exportProcessors"."id"
)
LIMIT ${limit}
)
${actionhero_1.config.sequelize.dialect === "postgres" ? "RETURNING id" : ""}
;`, { type: sequelize_1.QueryTypes.SELECT });
let responseCountWithNoExports = 0;
if (actionhero_1.config.sequelize.dialect === "sqlite") {
const changesRows = await actionhero_1.api.sequelize.query("SELECT changes() as count;", { type: sequelize_1.QueryTypes.SELECT });
responseCountWithNoExports = changesRows[0]["count"];
}
return actionhero_1.config.sequelize.dialect === "sqlite"
? responseCountWithNoExports
: rowsWithNoExports.length;
}
};
// --- Class Methods --- //
ExportProcessor.defaultState = "pending";
__decorate([
(0, sequelize_typescript_1.Column)({ primaryKey: true }),
__metadata("design:type", String)
], ExportProcessor.prototype, "id", void 0);
__decorate([
(0, sequelize_typescript_1.AllowNull)(false),
(0, sequelize_typescript_1.ForeignKey)(() => Destination_1.Destination),
sequelize_typescript_1.Column,
__metadata("design:type", String)
], ExportProcessor.prototype, "destinationId", void 0);
__decorate([
(0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.TEXT),
__metadata("design:type", String)
], ExportProcessor.prototype, "remoteKey", void 0);
__decorate([
(0, sequelize_typescript_1.AllowNull)(false),
(0, sequelize_typescript_1.Default)(ExportProcessor_1.defaultState),
(0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.ENUM(...exports.ExportProcessorStates)),
__metadata("design:type", Object)
], ExportProcessor.prototype, "state", void 0);
__decorate([
sequelize_typescript_1.Column,
__metadata("design:type", Date)
], ExportProcessor.prototype, "startedAt", void 0);
__decorate([
sequelize_typescript_1.Column,
__metadata("design:type", Date)
], ExportProcessor.prototype, "processAt", void 0);
__decorate([
(0, sequelize_typescript_1.Default)(0),
sequelize_typescript_1.Column,
__metadata("design:type", Number)
], ExportProcessor.prototype, "retryCount", void 0);
__decorate([
sequelize_typescript_1.Column,
__metadata("design:type", Date)
], ExportProcessor.prototype, "completedAt", void 0);
__decorate([
sequelize_typescript_1.Column,
__metadata("design:type", String)
], ExportProcessor.prototype, "errorMessage", void 0);
__decorate([
(0, sequelize_typescript_1.HasMany)(() => Export_1.Export),
__metadata("design:type", Array)
], ExportProcessor.prototype, "exports", void 0);
__decorate([
(0, sequelize_typescript_1.Is)("ofValidErrorLevel", (value) => {
if (value && !errors_1.Errors.ERROR_LEVELS.includes(value)) {
throw new Error(`errorLevel must be one of: ${errors_1.Errors.ERROR_LEVELS.join(",")}`);
}
}),
(0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.ENUM(...errors_1.Errors.ERROR_LEVELS)),
__metadata("design:type", String)
], ExportProcessor.prototype, "errorLevel", void 0);
__decorate([
(0, sequelize_typescript_1.BelongsTo)(() => Destination_1.Destination),
__metadata("design:type", Destination_1.Destination)
], ExportProcessor.prototype, "destination", void 0);
__decorate([
sequelize_typescript_1.BeforeSave,
__metadata("design:type", Function),
__metadata("design:paramtypes", [ExportProcessor]),
__metadata("design:returntype", Promise)
], ExportProcessor, "updateState", null);
__decorate([
sequelize_typescript_1.BeforeSave,
__metadata("design:type", Function),
__metadata("design:paramtypes", [ExportProcessor]),
__metadata("design:returntype", void 0)
], ExportProcessor, "ensureErrorLevel", null);
ExportProcessor = ExportProcessor_1 = __decorate([
(0, sequelize_typescript_1.Table)({ tableName: "exportProcessors", paranoid: false })
], ExportProcessor);
exports.ExportProcessor = ExportProcessor;