@grouparoo/core
Version:
The Grouparoo Core
137 lines (136 loc) • 6.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ImportRecordProperties = void 0;
const retryableTask_1 = require("../../classes/tasks/retryableTask");
const GrouparooRecord_1 = require("../../models/GrouparooRecord");
const RecordProperty_1 = require("../../models/RecordProperty");
const sequelize_1 = require("sequelize");
const actionhero_1 = require("actionhero");
const cls_1 = require("../../modules/cls");
const property_1 = require("../../modules/ops/property");
const import_1 = require("../../modules/ops/import");
const record_1 = require("../../modules/ops/record");
const apiData_1 = require("../../modules/apiData");
const propertiesCache_1 = require("../../modules/caches/propertiesCache");
const sourcesCache_1 = require("../../modules/caches/sourcesCache");
class ImportRecordProperties extends retryableTask_1.RetryableTask {
constructor() {
super(...arguments);
this.name = "recordProperty:importRecordProperties";
this.description = "Import the GrouparooRecord Properties for a Property";
this.frequency = 0;
this.queue = "recordProperties";
this.inputs = {
recordIds: { required: true, formatter: apiData_1.APIData.ensureArray },
propertyIds: { required: true, formatter: apiData_1.APIData.ensureArray },
};
}
async runWithinTransaction({ recordIds, propertyIds, }) {
const records = await GrouparooRecord_1.GrouparooRecord.findAll({
where: { id: { [sequelize_1.Op.in]: recordIds } },
include: RecordProperty_1.RecordProperty,
});
if (records.length === 0)
return;
const allProperties = await propertiesCache_1.PropertiesCache.findAllWithCache(undefined, "ready");
const properties = allProperties.filter((p) => propertyIds.includes(p.id));
if (properties.length === 0)
return;
const sourceIds = properties
.map((p) => p.sourceId)
.filter((v, i, a) => a.indexOf(v) === i);
if (sourceIds.length > 1) {
throw new Error(`More than one source for properties ${propertyIds.join(", ")}`);
}
const source = await sourcesCache_1.SourcesCache.findOneWithCache(properties[0].sourceId);
const recordsToImport = [];
const recordsNotReady = [];
const dependencies = {};
for (const property of properties) {
dependencies[property.id] = await property_1.PropertyOps.dependencies(property);
}
for (const record of records) {
let mode = "ready";
// all already (wrongly) ready?
if (record.recordProperties.filter((p) => p.state === "ready").length ===
record.recordProperties.length) {
mode = "notReady";
}
for (const property of properties) {
// dependencies are not ready
dependencies[property.id]
.filter((dep) => !propertyIds.includes(dep.id))
.forEach((dep) => {
var _a;
if (((_a = record.recordProperties.find((p) => p.propertyId === dep.id)) === null || _a === void 0 ? void 0 : _a.state) !== "ready") {
mode = "notReady";
}
});
}
switch (mode) {
case "ready":
recordsToImport.push(record);
break;
case "notReady":
recordsNotReady.push(record);
break;
}
}
if (recordsNotReady.length > 0) {
await RecordProperty_1.RecordProperty.update({ startedAt: import_1.ImportOps.retryStartedAt() }, {
where: {
propertyId: { [sequelize_1.Op.in]: properties.map((p) => p.id) },
recordId: {
[sequelize_1.Op.in]: recordsNotReady.map((p) => p.id),
},
state: "pending",
},
});
}
if (recordsToImport.length === 0)
return;
try {
const propertyValuesBatch = await source.importRecordProperties(recordsToImport, properties);
const orderedRecords = [];
const orderedHashes = [];
for (const recordId in propertyValuesBatch) {
const record = recordsToImport.find((p) => p.id === recordId);
orderedRecords.push(record);
orderedHashes.push(propertyValuesBatch[recordId]);
}
if (orderedRecords.length > 0) {
await record_1.RecordOps.addOrUpdateProperties(orderedRecords, orderedHashes, false // we are disabling the record lock here because the transaction will be saved out-of-band from the lock check
);
}
// update the properties that got no data back
await RecordProperty_1.RecordProperty.update({
state: "ready",
rawValue: null,
stateChangedAt: new Date(),
confirmedAt: new Date(),
startedAt: null,
}, {
where: {
propertyId: { [sequelize_1.Op.in]: properties.map((p) => p.id) },
recordId: {
[sequelize_1.Op.in]: recordsToImport.map((p) => p.id),
},
state: "pending",
},
});
}
catch (error) {
// if something goes wrong with the batch import, fall-back to per-record/property imports
for (const record of recordsToImport) {
for (const property of properties) {
await cls_1.CLS.enqueueTask("recordProperty:importRecordProperty", {
recordId: record.id,
propertyId: property.id,
});
}
}
(0, actionhero_1.log)(error.stack, "error");
}
}
}
exports.ImportRecordProperties = ImportRecordProperties;