UNPKG

@grouparoo/core

Version:
204 lines (203 loc) 8.75 kB
"use strict"; 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;