@stemy/backend 2.9.8 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundles/stemy-backend.umd.js +355 -281
- package/bundles/stemy-backend.umd.js.map +1 -1
- package/bundles/stemy-backend.umd.min.js +1 -1
- package/bundles/stemy-backend.umd.min.js.map +1 -1
- package/common-types.d.ts +15 -4
- package/esm2015/common-types.js +1 -1
- package/esm2015/public_api.js +6 -17
- package/esm2015/rest-controllers/assets.controller.js +4 -2
- package/esm2015/services/entities/asset.js +17 -24
- package/esm2015/services/entities/lazy-asset.js +6 -7
- package/esm2015/services/entities/progress.js +18 -6
- package/esm2015/services/job-manager.js +92 -86
- package/esm2015/services/lazy-assets.js +7 -5
- package/esm2015/services/progresses.js +54 -30
- package/esm2015/utilities/lazy-asset-generator.js +4 -3
- package/esm2015/utils.js +74 -4
- package/fesm2015/stemy-backend.js +266 -170
- package/fesm2015/stemy-backend.js.map +1 -1
- package/package.json +2 -3
- package/public_api.d.ts +2 -2
- package/services/entities/lazy-asset.d.ts +2 -4
- package/services/entities/progress.d.ts +6 -4
- package/services/job-manager.d.ts +20 -15
- package/services/progresses.d.ts +9 -7
- package/stemy-backend.metadata.json +1 -1
- package/utilities/lazy-asset-generator.d.ts +3 -3
- package/utils.d.ts +39 -1
|
@@ -23,10 +23,9 @@ import sharp_ from 'sharp';
|
|
|
23
23
|
import axios from 'axios';
|
|
24
24
|
import { GridFSBucket } from 'mongodb';
|
|
25
25
|
import dotenv from 'dotenv';
|
|
26
|
-
import { Queue, Worker, Scheduler } from 'node-resque';
|
|
27
26
|
import { validate, schedule } from 'node-cron';
|
|
28
|
-
import
|
|
29
|
-
import
|
|
27
|
+
import { socket } from 'zeromq';
|
|
28
|
+
import { filter as filter$1, map } from 'rxjs/operators';
|
|
30
29
|
import { createServer } from 'http';
|
|
31
30
|
import express_, { static as static$1 } from 'express';
|
|
32
31
|
import socket_io from 'socket.io';
|
|
@@ -363,10 +362,14 @@ function writeFile(path, data) {
|
|
|
363
362
|
function valueToPromise(value) {
|
|
364
363
|
return value instanceof Promise ? value : Promise.resolve(value);
|
|
365
364
|
}
|
|
366
|
-
function promiseTimeout(timeout = 1000) {
|
|
367
|
-
return new Promise((resolve) => {
|
|
365
|
+
function promiseTimeout(timeout = 1000, error = false) {
|
|
366
|
+
return new Promise((resolve, reject) => {
|
|
368
367
|
setTimeout(() => {
|
|
369
|
-
|
|
368
|
+
if (error) {
|
|
369
|
+
reject(`Timeout exceeded: ${timeout}ms`);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
resolve(`Timeout: ${timeout}ms`);
|
|
370
373
|
}, timeout);
|
|
371
374
|
});
|
|
372
375
|
}
|
|
@@ -640,6 +643,72 @@ function runCommand(scriptPath, expectedCode = 0) {
|
|
|
640
643
|
console.error(data.toString());
|
|
641
644
|
});
|
|
642
645
|
});
|
|
646
|
+
}
|
|
647
|
+
var ConsoleColor;
|
|
648
|
+
(function (ConsoleColor) {
|
|
649
|
+
ConsoleColor["Reset"] = "\u001B[0m";
|
|
650
|
+
ConsoleColor["Bright"] = "\u001B[1m";
|
|
651
|
+
ConsoleColor["Dim"] = "\u001B[2m";
|
|
652
|
+
ConsoleColor["Underscore"] = "\u001B[4m";
|
|
653
|
+
ConsoleColor["Blink"] = "\u001B[5m";
|
|
654
|
+
ConsoleColor["Reverse"] = "\u001B[7m";
|
|
655
|
+
ConsoleColor["Hidden"] = "\u001B[8m";
|
|
656
|
+
ConsoleColor["FgBlack"] = "\u001B[30m";
|
|
657
|
+
ConsoleColor["FgRed"] = "\u001B[31m";
|
|
658
|
+
ConsoleColor["FgGreen"] = "\u001B[32m";
|
|
659
|
+
ConsoleColor["FgYellow"] = "\u001B[33m";
|
|
660
|
+
ConsoleColor["FgBlue"] = "\u001B[34m";
|
|
661
|
+
ConsoleColor["FgMagenta"] = "\u001B[35m";
|
|
662
|
+
ConsoleColor["FgCyan"] = "\u001B[36m";
|
|
663
|
+
ConsoleColor["FgWhite"] = "\u001B[37m";
|
|
664
|
+
ConsoleColor["FgDefault"] = "\u001B[38m";
|
|
665
|
+
ConsoleColor["BgBlack"] = "\u001B[40m";
|
|
666
|
+
ConsoleColor["BgRed"] = "\u001B[41m";
|
|
667
|
+
ConsoleColor["BgGreen"] = "\u001B[42m";
|
|
668
|
+
ConsoleColor["BgYellow"] = "\u001B[43m";
|
|
669
|
+
ConsoleColor["BgBlue"] = "\u001B[44m";
|
|
670
|
+
ConsoleColor["BgMagenta"] = "\u001B[45m";
|
|
671
|
+
ConsoleColor["BgCyan"] = "\u001B[46m";
|
|
672
|
+
ConsoleColor["BgWhite"] = "\u001B[47m";
|
|
673
|
+
ConsoleColor["BgDefault"] = "\u001B[48m";
|
|
674
|
+
})(ConsoleColor || (ConsoleColor = {}));
|
|
675
|
+
const defaultColors = {
|
|
676
|
+
keyColor: ConsoleColor.FgWhite,
|
|
677
|
+
numberColor: ConsoleColor.FgBlue,
|
|
678
|
+
stringColor: ConsoleColor.FgYellow,
|
|
679
|
+
trueColor: ConsoleColor.FgGreen,
|
|
680
|
+
falseColor: ConsoleColor.FgRed,
|
|
681
|
+
nullColor: ConsoleColor.BgMagenta
|
|
682
|
+
};
|
|
683
|
+
const MAX_TIMEOUT = 120000;
|
|
684
|
+
function colorize(input, color) {
|
|
685
|
+
return `${color}${input}${ConsoleColor.Reset}`;
|
|
686
|
+
}
|
|
687
|
+
function jsonHighlight(input, colorOptions) {
|
|
688
|
+
const colors = Object.assign({}, defaultColors, colorOptions);
|
|
689
|
+
const json = (isString(input) ? input : JSON.stringify(input, null, 2)).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
690
|
+
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+]?\d+)?)/g, (match) => {
|
|
691
|
+
let color = colors.numberColor;
|
|
692
|
+
if (/^"/.test(match)) {
|
|
693
|
+
if (/:$/.test(match)) {
|
|
694
|
+
color = colors.keyColor;
|
|
695
|
+
}
|
|
696
|
+
else {
|
|
697
|
+
color = colors.stringColor;
|
|
698
|
+
match = '"' + match.substr(1, match.length - 2) + '"';
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
else {
|
|
702
|
+
color = /true/.test(match)
|
|
703
|
+
? colors.trueColor
|
|
704
|
+
: /false/.test(match)
|
|
705
|
+
? colors.falseColor
|
|
706
|
+
: /null/.test(match)
|
|
707
|
+
? colors.nullColor
|
|
708
|
+
: color;
|
|
709
|
+
}
|
|
710
|
+
return `${color}${match}${ConsoleColor.Reset}`;
|
|
711
|
+
});
|
|
643
712
|
}
|
|
644
713
|
|
|
645
714
|
var __decorate$x = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
@@ -1058,9 +1127,10 @@ class Asset extends BaseEntity {
|
|
|
1058
1127
|
params = params || {};
|
|
1059
1128
|
// Get default crop info
|
|
1060
1129
|
const crop = Asset.toCropRegion(meta.crop);
|
|
1061
|
-
// Return
|
|
1062
|
-
if (Object.keys(params).length == 0 && !crop)
|
|
1130
|
+
// Return the stream if there is no params and no default crop exists
|
|
1131
|
+
if ((meta === null || meta === void 0 ? void 0 : meta.extension) === "svg" || (Object.keys(params).length == 0 && !crop)) {
|
|
1063
1132
|
return stream;
|
|
1133
|
+
}
|
|
1064
1134
|
// Parse params
|
|
1065
1135
|
params.rotation = isNaN(params.rotation) ? 0 : Math.round(params.rotation / 90) * 90;
|
|
1066
1136
|
params.canvasScaleX = isNaN(params.canvasScaleX) ? 1 : Number(params.canvasScaleX);
|
|
@@ -1075,51 +1145,43 @@ class Asset extends BaseEntity {
|
|
|
1075
1145
|
const cropBefore = Asset.toCropRegion(params.cropBefore || (params.crop ? meta.cropBefore : null));
|
|
1076
1146
|
const cropAfter = Asset.toCropRegion(params.cropAfter || (params.crop ? meta.cropAfter : null));
|
|
1077
1147
|
// Get metadata
|
|
1078
|
-
|
|
1079
|
-
let width =
|
|
1080
|
-
let height = imgMeta.height;
|
|
1148
|
+
let img = sharp$2(buffer);
|
|
1149
|
+
let { width, height } = yield img.metadata();
|
|
1081
1150
|
// Crop before resize
|
|
1082
1151
|
if (cropBefore) {
|
|
1083
|
-
buffer = yield sharp$2(buffer)
|
|
1084
|
-
.extract(cropBefore)
|
|
1085
|
-
.toBuffer();
|
|
1086
1152
|
width = cropBefore.width;
|
|
1087
1153
|
height = cropBefore.height;
|
|
1154
|
+
img = img.extract(cropBefore);
|
|
1088
1155
|
}
|
|
1089
1156
|
else if (crop) {
|
|
1090
|
-
buffer = yield sharp$2(buffer)
|
|
1091
|
-
.extract(crop)
|
|
1092
|
-
.toBuffer();
|
|
1093
1157
|
width = crop.width;
|
|
1094
1158
|
height = crop.height;
|
|
1159
|
+
img = img.extract(crop);
|
|
1095
1160
|
}
|
|
1096
1161
|
// Resize canvas
|
|
1097
|
-
|
|
1162
|
+
const canvasScaleX = (meta === null || meta === void 0 ? void 0 : meta.canvasScaleX) || 1;
|
|
1163
|
+
const canvasScaleY = (meta === null || meta === void 0 ? void 0 : meta.canvasScaleY) || 1;
|
|
1164
|
+
if (params.canvasScaleX !== canvasScaleX || params.canvasScaleY !== canvasScaleY) {
|
|
1098
1165
|
width = Math.round(width * params.canvasScaleX);
|
|
1099
1166
|
height = Math.round(height * params.canvasScaleY);
|
|
1100
|
-
|
|
1101
|
-
.resize({ width, height, background: "#00000000", fit: "contain" })
|
|
1102
|
-
.toBuffer();
|
|
1167
|
+
img = img.resize({ width, height, background: "#00000000", fit: "contain" });
|
|
1103
1168
|
}
|
|
1104
1169
|
// Resize image
|
|
1105
1170
|
if (params.scaleX !== 1 || params.scaleY !== 1) {
|
|
1106
1171
|
width = Math.round(width * params.scaleX);
|
|
1107
1172
|
height = Math.round(height * params.scaleY);
|
|
1108
|
-
|
|
1109
|
-
.resize({ width, height, background: "#00000000", fit: "fill" })
|
|
1110
|
-
.toBuffer();
|
|
1173
|
+
img = img.resize({ width, height, background: "#00000000", fit: "fill" });
|
|
1111
1174
|
}
|
|
1112
1175
|
// Crop after resize
|
|
1113
1176
|
if (cropAfter) {
|
|
1114
|
-
|
|
1115
|
-
.extract(cropAfter)
|
|
1116
|
-
.toBuffer();
|
|
1177
|
+
img = img.extract(cropAfter);
|
|
1117
1178
|
}
|
|
1118
1179
|
// Rotate
|
|
1119
1180
|
if (params.rotation !== 0) {
|
|
1120
|
-
buffer = yield
|
|
1181
|
+
buffer = yield img.toBuffer();
|
|
1182
|
+
img = sharp$2(buffer).rotate(params.rotation);
|
|
1121
1183
|
}
|
|
1122
|
-
return bufferToStream(
|
|
1184
|
+
return bufferToStream(yield img.toBuffer());
|
|
1123
1185
|
}
|
|
1124
1186
|
catch (e) {
|
|
1125
1187
|
console.log("Asset image conversion error", e);
|
|
@@ -1401,11 +1463,10 @@ var __awaiter$p = (this && this.__awaiter) || function (thisArg, _arguments, P,
|
|
|
1401
1463
|
});
|
|
1402
1464
|
};
|
|
1403
1465
|
class LazyAsset extends BaseEntity {
|
|
1404
|
-
constructor(id, data, collection, assets, progresses
|
|
1466
|
+
constructor(id, data, collection, assets, progresses) {
|
|
1405
1467
|
super(id, data, collection);
|
|
1406
1468
|
this.assets = assets;
|
|
1407
1469
|
this.progresses = progresses;
|
|
1408
|
-
this.jobMan = jobMan;
|
|
1409
1470
|
}
|
|
1410
1471
|
get jobName() {
|
|
1411
1472
|
return this.data.jobName;
|
|
@@ -1438,7 +1499,7 @@ class LazyAsset extends BaseEntity {
|
|
|
1438
1499
|
this.progresses.get(this.progressId).then(p => {
|
|
1439
1500
|
p === null || p === void 0 ? void 0 : p.cancel();
|
|
1440
1501
|
});
|
|
1441
|
-
this.startWorkingOnAsset().then(() => {
|
|
1502
|
+
this.startWorkingOnAsset(false).then(() => {
|
|
1442
1503
|
console.log(`Started working on lazy asset: ${this.id}`);
|
|
1443
1504
|
}).catch(reason => {
|
|
1444
1505
|
console.log(`Can't start working on lazy asset: ${this.id}\nReason: ${reason}`);
|
|
@@ -1457,7 +1518,7 @@ class LazyAsset extends BaseEntity {
|
|
|
1457
1518
|
yield this.progresses.waitToFinish(this.progressId);
|
|
1458
1519
|
return this.loadAsset();
|
|
1459
1520
|
}
|
|
1460
|
-
yield this.startWorkingOnAsset();
|
|
1521
|
+
yield this.startWorkingOnAsset(true);
|
|
1461
1522
|
return this.loadAsset();
|
|
1462
1523
|
});
|
|
1463
1524
|
}
|
|
@@ -1468,12 +1529,12 @@ class LazyAsset extends BaseEntity {
|
|
|
1468
1529
|
return asset;
|
|
1469
1530
|
});
|
|
1470
1531
|
}
|
|
1471
|
-
startWorkingOnAsset() {
|
|
1532
|
+
startWorkingOnAsset(fromLoad) {
|
|
1472
1533
|
return __awaiter$p(this, void 0, void 0, function* () {
|
|
1473
1534
|
this.data.progressId = (yield this.progresses.create()).id;
|
|
1474
1535
|
this.data.assetId = null;
|
|
1475
1536
|
yield this.save();
|
|
1476
|
-
yield this.jobMan.enqueueWithName(this.data.jobName, Object.assign(Object.assign({}, this.data.jobParams), { lazyId: this.id }));
|
|
1537
|
+
yield this.progresses.jobMan.enqueueWithName(this.data.jobName, Object.assign(Object.assign({}, this.data.jobParams), { lazyId: this.id, fromLoad }));
|
|
1477
1538
|
});
|
|
1478
1539
|
}
|
|
1479
1540
|
}
|
|
@@ -1499,18 +1560,30 @@ var __awaiter$o = (this && this.__awaiter) || function (thisArg, _arguments, P,
|
|
|
1499
1560
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1500
1561
|
});
|
|
1501
1562
|
};
|
|
1502
|
-
const IORedis = ioredis;
|
|
1503
1563
|
let JobManager = class JobManager {
|
|
1504
1564
|
constructor(config, container, jobTypes) {
|
|
1505
1565
|
this.config = config;
|
|
1506
1566
|
this.container = container;
|
|
1507
1567
|
this.jobTypes = jobTypes || [];
|
|
1508
1568
|
this.jobs = this.jobTypes.reduce((res, jobType) => {
|
|
1509
|
-
res[getConstructorName(jobType)] = {
|
|
1510
|
-
|
|
1569
|
+
res[getConstructorName(jobType)] = (jobParams) => {
|
|
1570
|
+
const job = this.resolveJobInstance(jobType, jobParams);
|
|
1571
|
+
return job.process(this.messageBridge);
|
|
1511
1572
|
};
|
|
1512
1573
|
return res;
|
|
1513
1574
|
}, {});
|
|
1575
|
+
this.messages = new Subject();
|
|
1576
|
+
this.messageBridge = {
|
|
1577
|
+
sendMessage: (message, params) => {
|
|
1578
|
+
this.workerPush.send([message, JSON.stringify(params)]);
|
|
1579
|
+
}
|
|
1580
|
+
};
|
|
1581
|
+
this.processing = false;
|
|
1582
|
+
}
|
|
1583
|
+
on(message, cb) {
|
|
1584
|
+
return this.messages
|
|
1585
|
+
.pipe(filter$1(t => t.message === message))
|
|
1586
|
+
.pipe(map(t => t.params)).subscribe(cb);
|
|
1514
1587
|
}
|
|
1515
1588
|
process(jobType, params = {}) {
|
|
1516
1589
|
return __awaiter$o(this, void 0, void 0, function* () {
|
|
@@ -1525,31 +1598,17 @@ let JobManager = class JobManager {
|
|
|
1525
1598
|
return instance.process();
|
|
1526
1599
|
});
|
|
1527
1600
|
}
|
|
1528
|
-
enqueueWithName(name, params = {}
|
|
1529
|
-
return __awaiter$o(this, void 0, void 0, function* () {
|
|
1530
|
-
const jobName = yield this.tryResolveFromName(name, params);
|
|
1531
|
-
yield this.queue.enqueue(que, jobName, [params]);
|
|
1532
|
-
});
|
|
1533
|
-
}
|
|
1534
|
-
enqueue(jobType, params = {}, que = "main") {
|
|
1535
|
-
return __awaiter$o(this, void 0, void 0, function* () {
|
|
1536
|
-
const jobName = yield this.tryResolveAndConnect(jobType, params);
|
|
1537
|
-
yield this.queue.enqueue(que, jobName, [params]);
|
|
1538
|
-
});
|
|
1539
|
-
}
|
|
1540
|
-
enqueueAt(timestamp, jobType, params = {}, que = "main") {
|
|
1601
|
+
enqueueWithName(name, params = {}) {
|
|
1541
1602
|
return __awaiter$o(this, void 0, void 0, function* () {
|
|
1542
|
-
|
|
1543
|
-
yield this.queue.enqueueAt(timestamp, que, jobName, [params]);
|
|
1603
|
+
return this.sendToWorkers(this.tryResolveFromName(name, params), params);
|
|
1544
1604
|
});
|
|
1545
1605
|
}
|
|
1546
|
-
|
|
1606
|
+
enqueue(jobType, params = {}) {
|
|
1547
1607
|
return __awaiter$o(this, void 0, void 0, function* () {
|
|
1548
|
-
|
|
1549
|
-
yield this.queue.enqueueIn(time, que, jobName, [params]);
|
|
1608
|
+
return this.sendToWorkers(this.tryResolveAndInit(jobType, params), params);
|
|
1550
1609
|
});
|
|
1551
1610
|
}
|
|
1552
|
-
schedule(minute, hour, dayOfMonth, month, dayOfWeek, jobType, params = {}
|
|
1611
|
+
schedule(minute, hour, dayOfMonth, month, dayOfWeek, jobType, params = {}) {
|
|
1553
1612
|
const expression = [minute, hour, dayOfMonth, month, dayOfWeek].map(t => {
|
|
1554
1613
|
if (isObject(t)) {
|
|
1555
1614
|
const range = t;
|
|
@@ -1566,18 +1625,52 @@ let JobManager = class JobManager {
|
|
|
1566
1625
|
return null;
|
|
1567
1626
|
}
|
|
1568
1627
|
return schedule(expression, () => {
|
|
1569
|
-
this.enqueue(jobType, params
|
|
1628
|
+
this.enqueue(jobType, params).catch(e => {
|
|
1570
1629
|
console.log(`Can't enqueue job: '${jobName}' because: ${e}`);
|
|
1571
1630
|
});
|
|
1572
1631
|
});
|
|
1573
1632
|
}
|
|
1574
1633
|
startProcessing() {
|
|
1575
1634
|
return __awaiter$o(this, void 0, void 0, function* () {
|
|
1576
|
-
this.
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1635
|
+
if (this.processing)
|
|
1636
|
+
return null;
|
|
1637
|
+
this.processing = true;
|
|
1638
|
+
if (!this.config.resolve("isWorker")) {
|
|
1639
|
+
console.log(colorize(`Processing can not be started because this is NOT a worker process!`, ConsoleColor.FgRed));
|
|
1640
|
+
return null;
|
|
1641
|
+
}
|
|
1642
|
+
const host = this.config.resolve("zmqRemoteHost");
|
|
1643
|
+
const pushHost = `${host}:${this.config.resolve("zmqBackPort")}`;
|
|
1644
|
+
this.workerPush = socket("push");
|
|
1645
|
+
yield this.workerPush.connect(pushHost);
|
|
1646
|
+
console.log(`Worker producer connected to: ${pushHost}`);
|
|
1647
|
+
const pullHost = `${host}:${this.config.resolve("zmqPort")}`;
|
|
1648
|
+
this.workerPull = socket("pull");
|
|
1649
|
+
yield this.workerPull.connect(pullHost);
|
|
1650
|
+
console.log(`Worker consumer connected to: ${pullHost}`);
|
|
1651
|
+
this.workerPull.on("message", (name, args, uniqueId) => __awaiter$o(this, void 0, void 0, function* () {
|
|
1652
|
+
try {
|
|
1653
|
+
const jobName = name.toString("utf8");
|
|
1654
|
+
const jobParams = JSON.parse(args.toString("utf8"));
|
|
1655
|
+
const timerId = uniqueId === null || uniqueId === void 0 ? void 0 : uniqueId.toString("utf8");
|
|
1656
|
+
const jobNameLog = `\x1b[36m"${jobName}"\x1b[0m`;
|
|
1657
|
+
const jobArgsLog = `\n${jsonHighlight(jobParams)}`;
|
|
1658
|
+
console.time(timerId);
|
|
1659
|
+
console.timeLog(timerId, `Started working on background job: ${jobNameLog} with args: ${jobArgsLog}\n\n`);
|
|
1660
|
+
this.messageBridge.sendMessage(`job-started`, { name: jobName });
|
|
1661
|
+
try {
|
|
1662
|
+
yield Promise.race([this.jobs[jobName](jobParams), promiseTimeout(MAX_TIMEOUT, true)]);
|
|
1663
|
+
console.timeLog(timerId, `Finished working on background job: ${jobNameLog}\n\n`);
|
|
1664
|
+
}
|
|
1665
|
+
catch (e) {
|
|
1666
|
+
console.timeLog(timerId, `Background job failed: ${jobNameLog}\n${e.message}\n\n`);
|
|
1667
|
+
}
|
|
1668
|
+
console.timeEnd(timerId);
|
|
1669
|
+
}
|
|
1670
|
+
catch (e) {
|
|
1671
|
+
console.log(`Failed to start job: ${e.message}`);
|
|
1672
|
+
}
|
|
1673
|
+
}));
|
|
1581
1674
|
});
|
|
1582
1675
|
}
|
|
1583
1676
|
tryResolve(jobType, params) {
|
|
@@ -1593,47 +1686,6 @@ let JobManager = class JobManager {
|
|
|
1593
1686
|
}
|
|
1594
1687
|
return jobName;
|
|
1595
1688
|
}
|
|
1596
|
-
initialize() {
|
|
1597
|
-
if (this.queue)
|
|
1598
|
-
return;
|
|
1599
|
-
const config = this.config;
|
|
1600
|
-
const options = { password: config.resolve("redisPassword") };
|
|
1601
|
-
const sentinels = config.resolve("redisSentinels");
|
|
1602
|
-
const redis = !sentinels
|
|
1603
|
-
? null
|
|
1604
|
-
: new IORedis({
|
|
1605
|
-
sentinels,
|
|
1606
|
-
name: config.resolve("redisCluster"),
|
|
1607
|
-
});
|
|
1608
|
-
const connection = {
|
|
1609
|
-
pkg: "ioredis",
|
|
1610
|
-
host: config.resolve("redisHost"),
|
|
1611
|
-
password: options.password,
|
|
1612
|
-
port: config.resolve("redisPort"),
|
|
1613
|
-
namespace: config.resolve("redisNamespace"),
|
|
1614
|
-
redis,
|
|
1615
|
-
options
|
|
1616
|
-
};
|
|
1617
|
-
const queues = config.resolve("workQueues");
|
|
1618
|
-
this.queue = new Queue({ connection }, this.jobs);
|
|
1619
|
-
this.worker = new Worker({ connection, queues }, this.jobs);
|
|
1620
|
-
this.worker.on("job", (queue, job) => {
|
|
1621
|
-
console.log(`working job ${queue} ${JSON.stringify(job)}`);
|
|
1622
|
-
});
|
|
1623
|
-
this.worker.on("reEnqueue", (queue, job, plugin) => {
|
|
1624
|
-
console.log(`reEnqueue job (${plugin}) ${queue} ${JSON.stringify(job)}`);
|
|
1625
|
-
});
|
|
1626
|
-
this.worker.on("success", (queue, job, result, duration) => {
|
|
1627
|
-
console.log(`job success ${queue} ${JSON.stringify(job)} >> ${result} (${duration}ms)`);
|
|
1628
|
-
});
|
|
1629
|
-
this.worker.on("failure", (queue, job, failure, duration) => {
|
|
1630
|
-
console.log(`job failure ${queue} ${JSON.stringify(job)} >> ${failure} (${duration}ms)`);
|
|
1631
|
-
});
|
|
1632
|
-
this.worker.on("error", (error, queue, job) => {
|
|
1633
|
-
console.log(`error ${queue} ${JSON.stringify(job)} >> ${error}`);
|
|
1634
|
-
});
|
|
1635
|
-
this.scheduler = new Scheduler({ connection }, this.jobs);
|
|
1636
|
-
}
|
|
1637
1689
|
tryResolveFromName(jobName, params) {
|
|
1638
1690
|
const jobType = this.jobTypes.find(type => {
|
|
1639
1691
|
return getConstructorName(type) == jobName;
|
|
@@ -1641,15 +1693,28 @@ let JobManager = class JobManager {
|
|
|
1641
1693
|
if (!jobType) {
|
|
1642
1694
|
throw `Can't find job type with name: ${jobName} so it can't be enqueued!`;
|
|
1643
1695
|
}
|
|
1644
|
-
return this.
|
|
1645
|
-
}
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
this.
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
}
|
|
1696
|
+
return this.tryResolveAndInit(jobType, params);
|
|
1697
|
+
}
|
|
1698
|
+
tryResolveAndInit(jobType, params) {
|
|
1699
|
+
if (!this.apiPush) {
|
|
1700
|
+
const port = this.config.resolve("zmqPort");
|
|
1701
|
+
this.apiPush = socket("push");
|
|
1702
|
+
this.apiPush.bind(`tcp://0.0.0.0:${port}`);
|
|
1703
|
+
console.log(`API producer bound to port: ${port}`);
|
|
1704
|
+
}
|
|
1705
|
+
if (!this.apiPull) {
|
|
1706
|
+
const backPort = this.config.resolve("zmqBackPort");
|
|
1707
|
+
this.apiPull = socket("pull");
|
|
1708
|
+
this.apiPull.bind(`tcp://0.0.0.0:${backPort}`);
|
|
1709
|
+
this.apiPull.on("message", (name, args) => {
|
|
1710
|
+
const message = name.toString("utf8");
|
|
1711
|
+
const params = JSON.parse((args === null || args === void 0 ? void 0 : args.toString("utf8")) || "{}");
|
|
1712
|
+
console.log(`Received a message from worker: "${colorize(message, ConsoleColor.FgCyan)}" with args: ${jsonHighlight(params)}\n\n`);
|
|
1713
|
+
this.messages.next({ message, params });
|
|
1714
|
+
});
|
|
1715
|
+
console.log(`API consumer bound to port: ${backPort}`);
|
|
1716
|
+
}
|
|
1717
|
+
return this.tryResolve(jobType, params);
|
|
1653
1718
|
}
|
|
1654
1719
|
resolveJobInstance(jobType, params) {
|
|
1655
1720
|
const container = this.container.createChildContainer();
|
|
@@ -1659,11 +1724,11 @@ let JobManager = class JobManager {
|
|
|
1659
1724
|
container.register(jobType, jobType);
|
|
1660
1725
|
return container.resolve(jobType);
|
|
1661
1726
|
}
|
|
1662
|
-
|
|
1663
|
-
return (
|
|
1664
|
-
const
|
|
1665
|
-
|
|
1666
|
-
};
|
|
1727
|
+
sendToWorkers(jobName, params) {
|
|
1728
|
+
return __awaiter$o(this, void 0, void 0, function* () {
|
|
1729
|
+
const publisher = yield this.apiPush;
|
|
1730
|
+
yield publisher.send([jobName, JSON.stringify(params), new ObjectId().toHexString()]);
|
|
1731
|
+
});
|
|
1667
1732
|
}
|
|
1668
1733
|
};
|
|
1669
1734
|
JobManager = __decorate$s([
|
|
@@ -1683,9 +1748,8 @@ var __awaiter$n = (this && this.__awaiter) || function (thisArg, _arguments, P,
|
|
|
1683
1748
|
});
|
|
1684
1749
|
};
|
|
1685
1750
|
class Progress extends BaseEntity {
|
|
1686
|
-
constructor(id, data, collection
|
|
1751
|
+
constructor(id, data, collection) {
|
|
1687
1752
|
super(id, data, collection);
|
|
1688
|
-
this.client = client;
|
|
1689
1753
|
}
|
|
1690
1754
|
get current() {
|
|
1691
1755
|
return this.data.current;
|
|
@@ -1708,6 +1772,10 @@ class Progress extends BaseEntity {
|
|
|
1708
1772
|
get remaining() {
|
|
1709
1773
|
return this.max > 0 ? this.max - this.current : 0;
|
|
1710
1774
|
}
|
|
1775
|
+
setMessageBridge(messageBridge) {
|
|
1776
|
+
this.messageBridge = messageBridge || this.messageBridge;
|
|
1777
|
+
return this;
|
|
1778
|
+
}
|
|
1711
1779
|
createSubProgress(progressValue, max, message) {
|
|
1712
1780
|
return __awaiter$n(this, void 0, void 0, function* () {
|
|
1713
1781
|
if (max <= 0 && progressValue > 0) {
|
|
@@ -1751,9 +1819,6 @@ class Progress extends BaseEntity {
|
|
|
1751
1819
|
return null;
|
|
1752
1820
|
this.data.current = Math.min(this.max, this.current + value);
|
|
1753
1821
|
yield this.save();
|
|
1754
|
-
if (!this.client)
|
|
1755
|
-
return;
|
|
1756
|
-
this.client.emit("background-progress", this.id);
|
|
1757
1822
|
});
|
|
1758
1823
|
}
|
|
1759
1824
|
cancel() {
|
|
@@ -1762,6 +1827,12 @@ class Progress extends BaseEntity {
|
|
|
1762
1827
|
yield this.save();
|
|
1763
1828
|
});
|
|
1764
1829
|
}
|
|
1830
|
+
save() {
|
|
1831
|
+
if (this.messageBridge) {
|
|
1832
|
+
this.messageBridge.sendMessage(`progress-changed`, this.toJSON());
|
|
1833
|
+
}
|
|
1834
|
+
return super.save();
|
|
1835
|
+
}
|
|
1765
1836
|
}
|
|
1766
1837
|
class SubProgress {
|
|
1767
1838
|
constructor(parent, progressFrom, progressValue, mMax = 100) {
|
|
@@ -1801,6 +1872,12 @@ class SubProgress {
|
|
|
1801
1872
|
get canceled() {
|
|
1802
1873
|
return !this.parent || this.parent.canceled;
|
|
1803
1874
|
}
|
|
1875
|
+
setMessageBridge(messageBridge) {
|
|
1876
|
+
if (!this.parent)
|
|
1877
|
+
return this;
|
|
1878
|
+
this.parent.setMessageBridge(messageBridge);
|
|
1879
|
+
return this;
|
|
1880
|
+
}
|
|
1804
1881
|
createSubProgress(progressValue, max, message) {
|
|
1805
1882
|
return __awaiter$n(this, void 0, void 0, function* () {
|
|
1806
1883
|
if (max <= 0 && progressValue > 0) {
|
|
@@ -1889,33 +1966,34 @@ var __awaiter$m = (this && this.__awaiter) || function (thisArg, _arguments, P,
|
|
|
1889
1966
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1890
1967
|
});
|
|
1891
1968
|
};
|
|
1892
|
-
const socketIOClient = socket_io_client;
|
|
1893
1969
|
let Progresses = class Progresses {
|
|
1894
|
-
constructor(connector,
|
|
1970
|
+
constructor(connector, jobMan) {
|
|
1895
1971
|
this.connector = connector;
|
|
1896
|
-
this.
|
|
1897
|
-
const mainEndpoint = this.config.resolve("mainEndpoint");
|
|
1898
|
-
this.client = !mainEndpoint ? null : socketIOClient(mainEndpoint, { path: "/socket" });
|
|
1972
|
+
this.jobMan = jobMan;
|
|
1899
1973
|
this.collection = connector.database.collection("progresses");
|
|
1974
|
+
this.progresses = {};
|
|
1975
|
+
this.jobMan.on("progress-changed", progress => {
|
|
1976
|
+
const id = progress.id;
|
|
1977
|
+
this.progresses[id] = new Progress(new ObjectId(id), progress, this.collection);
|
|
1978
|
+
});
|
|
1900
1979
|
}
|
|
1901
1980
|
waitToFinish(id) {
|
|
1902
1981
|
return __awaiter$m(this, void 0, void 0, function* () {
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
}
|
|
1917
|
-
|
|
1918
|
-
return progress;
|
|
1982
|
+
return Promise.race([
|
|
1983
|
+
this.waitForProgress(id, () => __awaiter$m(this, void 0, void 0, function* () {
|
|
1984
|
+
let progress = this.progresses[id];
|
|
1985
|
+
if (!progress || progress.percent < 100) {
|
|
1986
|
+
progress = yield this.get(id);
|
|
1987
|
+
}
|
|
1988
|
+
if (!progress) {
|
|
1989
|
+
throw new Error(`Progress does not exists with id: ${id}`);
|
|
1990
|
+
}
|
|
1991
|
+
return progress;
|
|
1992
|
+
}), 500),
|
|
1993
|
+
this.waitForProgress(id, () => __awaiter$m(this, void 0, void 0, function* () {
|
|
1994
|
+
return this.progresses[id] || null;
|
|
1995
|
+
}), 25)
|
|
1996
|
+
]);
|
|
1919
1997
|
});
|
|
1920
1998
|
}
|
|
1921
1999
|
get(id) {
|
|
@@ -1926,13 +2004,13 @@ let Progresses = class Progresses {
|
|
|
1926
2004
|
find(where) {
|
|
1927
2005
|
return __awaiter$m(this, void 0, void 0, function* () {
|
|
1928
2006
|
const data = yield this.collection.findOne(where);
|
|
1929
|
-
return !data ? null : new Progress(data._id, data, this.collection
|
|
2007
|
+
return !data ? null : new Progress(data._id, data, this.collection);
|
|
1930
2008
|
});
|
|
1931
2009
|
}
|
|
1932
2010
|
create(max = 100) {
|
|
1933
2011
|
return __awaiter$m(this, void 0, void 0, function* () {
|
|
1934
2012
|
if (isNaN(max) || max <= 0) {
|
|
1935
|
-
throw
|
|
2013
|
+
throw new Error(`Max progress value must be bigger than zero`);
|
|
1936
2014
|
}
|
|
1937
2015
|
const data = {
|
|
1938
2016
|
current: 0,
|
|
@@ -1942,7 +2020,7 @@ let Progresses = class Progresses {
|
|
|
1942
2020
|
canceled: false
|
|
1943
2021
|
};
|
|
1944
2022
|
const res = yield this.collection.insertOne(data);
|
|
1945
|
-
return new Progress(res.insertedId, data, this.collection
|
|
2023
|
+
return new Progress(res.insertedId, data, this.collection);
|
|
1946
2024
|
});
|
|
1947
2025
|
}
|
|
1948
2026
|
remove(id) {
|
|
@@ -1951,11 +2029,35 @@ let Progresses = class Progresses {
|
|
|
1951
2029
|
return id;
|
|
1952
2030
|
});
|
|
1953
2031
|
}
|
|
2032
|
+
waitForProgress(id, cb, delay) {
|
|
2033
|
+
return __awaiter$m(this, void 0, void 0, function* () {
|
|
2034
|
+
let isFinished = false;
|
|
2035
|
+
let progress = null;
|
|
2036
|
+
let waitTime = 0;
|
|
2037
|
+
while (!isFinished) {
|
|
2038
|
+
progress = yield cb();
|
|
2039
|
+
waitTime += delay;
|
|
2040
|
+
if (progress) {
|
|
2041
|
+
if (progress.error) {
|
|
2042
|
+
throw new Error(progress.error);
|
|
2043
|
+
}
|
|
2044
|
+
isFinished = progress.percent >= 100;
|
|
2045
|
+
}
|
|
2046
|
+
if (!isFinished) {
|
|
2047
|
+
if (waitTime >= MAX_TIMEOUT) {
|
|
2048
|
+
throw new Error(`Progress with id: ${id} probably never will be finished!`);
|
|
2049
|
+
}
|
|
2050
|
+
yield promiseTimeout(delay);
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
return progress;
|
|
2054
|
+
});
|
|
2055
|
+
}
|
|
1954
2056
|
};
|
|
1955
2057
|
Progresses = __decorate$r([
|
|
1956
2058
|
injectable(),
|
|
1957
2059
|
singleton(),
|
|
1958
|
-
__metadata$l("design:paramtypes", [MongoConnector,
|
|
2060
|
+
__metadata$l("design:paramtypes", [MongoConnector, JobManager])
|
|
1959
2061
|
], Progresses);
|
|
1960
2062
|
|
|
1961
2063
|
var __decorate$q = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
@@ -1996,7 +2098,7 @@ let LazyAssets = class LazyAssets {
|
|
|
1996
2098
|
if (existingAsset)
|
|
1997
2099
|
return existingAsset;
|
|
1998
2100
|
const res = yield this.collection.insertOne(data);
|
|
1999
|
-
return new LazyAsset(res.insertedId, data, this.collection, this.assets, this.progresses
|
|
2101
|
+
return new LazyAsset(res.insertedId, data, this.collection, this.assets, this.progresses);
|
|
2000
2102
|
});
|
|
2001
2103
|
}
|
|
2002
2104
|
read(id) {
|
|
@@ -2009,7 +2111,7 @@ let LazyAssets = class LazyAssets {
|
|
|
2009
2111
|
const data = yield this.collection.findOne(where);
|
|
2010
2112
|
return !data
|
|
2011
2113
|
? null
|
|
2012
|
-
: new LazyAsset(data._id, data, this.collection, this.assets, this.progresses
|
|
2114
|
+
: new LazyAsset(data._id, data, this.collection, this.assets, this.progresses);
|
|
2013
2115
|
});
|
|
2014
2116
|
}
|
|
2015
2117
|
unlink(id) {
|
|
@@ -2024,8 +2126,10 @@ let LazyAssets = class LazyAssets {
|
|
|
2024
2126
|
LazyAssets = __decorate$q([
|
|
2025
2127
|
injectable(),
|
|
2026
2128
|
scoped(Lifecycle.ContainerScoped),
|
|
2027
|
-
__metadata$k("design:paramtypes", [MongoConnector,
|
|
2028
|
-
|
|
2129
|
+
__metadata$k("design:paramtypes", [MongoConnector,
|
|
2130
|
+
Assets,
|
|
2131
|
+
Progresses,
|
|
2132
|
+
JobManager])
|
|
2029
2133
|
], LazyAssets);
|
|
2030
2134
|
|
|
2031
2135
|
var __decorate$p = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
@@ -2986,7 +3090,9 @@ let AssetsController = class AssetsController {
|
|
|
2986
3090
|
getImageRotation(id, params, res, rotation = 0) {
|
|
2987
3091
|
return __awaiter$7(this, void 0, void 0, function* () {
|
|
2988
3092
|
const asset = yield this.getAsset("Image", id, params.lazy, res);
|
|
2989
|
-
|
|
3093
|
+
if (rotation !== 0) {
|
|
3094
|
+
params.rotation = params.rotation || rotation;
|
|
3095
|
+
}
|
|
2990
3096
|
return asset.downloadImage(params);
|
|
2991
3097
|
});
|
|
2992
3098
|
}
|
|
@@ -3724,14 +3830,15 @@ class LazyAssetGenerator {
|
|
|
3724
3830
|
get lazyAssets() {
|
|
3725
3831
|
return this.assetResolver.lazyAssets;
|
|
3726
3832
|
}
|
|
3727
|
-
process() {
|
|
3833
|
+
process(messaging) {
|
|
3728
3834
|
return __awaiter$1(this, void 0, void 0, function* () {
|
|
3729
3835
|
const lazyAsset = yield this.lazyAssets.read(this.lazyId);
|
|
3730
3836
|
let progress = yield this.progresses.get(lazyAsset.progressId);
|
|
3731
3837
|
if (!progress || progress.canceled)
|
|
3732
3838
|
return null;
|
|
3839
|
+
progress.setMessageBridge(messaging);
|
|
3733
3840
|
try {
|
|
3734
|
-
const asset = yield this.generate(progress);
|
|
3841
|
+
const asset = yield this.generate(progress, messaging);
|
|
3735
3842
|
progress = yield progress.load();
|
|
3736
3843
|
if (!progress || progress.canceled)
|
|
3737
3844
|
return null;
|
|
@@ -3797,20 +3904,9 @@ function createServices() {
|
|
|
3797
3904
|
new Parameter("mongoPassword", null),
|
|
3798
3905
|
new Parameter("nodeEnv", "development"),
|
|
3799
3906
|
new Parameter("appPort", 80),
|
|
3800
|
-
new Parameter("
|
|
3801
|
-
new Parameter("
|
|
3802
|
-
new Parameter("
|
|
3803
|
-
new Parameter("redisNamespace", "resque"),
|
|
3804
|
-
new Parameter("redisCluster", "mymaster"),
|
|
3805
|
-
new Parameter("redisSentinels", null, value => {
|
|
3806
|
-
if (!value)
|
|
3807
|
-
return null;
|
|
3808
|
-
return value.split(", ").map(item => {
|
|
3809
|
-
const values = item.split(":");
|
|
3810
|
-
return { host: values[0], port: Number(values[1]) };
|
|
3811
|
-
});
|
|
3812
|
-
}),
|
|
3813
|
-
new Parameter("workQueues", ["main"]),
|
|
3907
|
+
new Parameter("zmqPort", 3000),
|
|
3908
|
+
new Parameter("zmqBackPort", 3100),
|
|
3909
|
+
new Parameter("zmqRemoteHost", "tcp://127.0.0.1"),
|
|
3814
3910
|
new Parameter("isWorker", false),
|
|
3815
3911
|
new Parameter("mainEndpoint", ""),
|
|
3816
3912
|
new Parameter("idChars", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
|
|
@@ -4016,5 +4112,5 @@ function setupBackend(config, providers, parent) {
|
|
|
4016
4112
|
* Generated bundle index. Do not edit.
|
|
4017
4113
|
*/
|
|
4018
4114
|
|
|
4019
|
-
export { AssetProcessor, AssetResolver, Assets, AuthController, BackendProvider, Cache, CacheProcessor, Configuration, DI_CONTAINER, EXPRESS, EndpointProvider, ErrorHandlerMiddleware, FIXTURE, Fixtures, Gallery, GalleryCache, GalleryController, HTTP_SERVER, IdGenerator, IsFile, IsObjectId, JOB, JobManager, LanguageMiddleware, LazyAssetGenerator, LazyAssets, MailSender, MemoryCache, MongoConnector, PARAMETER, Parameter, Progresses, ResolveEntity, SOCKET_SERVER, TemplateRenderer, TranslationProvider, Translator, Type, UserManager, assign, broadcast, bufferToStream, convertValue, copy, copyStream, createServices, createTransformer, deleteFile, deleteFromBucket, filter, firstItem, getConstructorName, getExtension, getFileName, getFunctionParams, getType, getValue, groupBy, hydratePopulated, idToString, injectServices, isArray, isBoolean, isConstructor, isDate, isDefined, isFunction, isInterface, isNullOrUndefined, isObject, isPrimitive, isString, isType, lastItem, lcFirst, lookupPipelines, md5, mkdirRecursive, multiSubscription, observableFromFunction, padLeft, padRight, paginate, paginateAggregations, promiseTimeout, proxyFunction, proxyFunctions, rand, random, readAndDeleteFile, readFile, runCommand, setupBackend, streamToBuffer, ucFirst, valueToPromise, writeFile };
|
|
4115
|
+
export { AssetProcessor, AssetResolver, Assets, AuthController, BackendProvider, Cache, CacheProcessor, Configuration, ConsoleColor, DI_CONTAINER, EXPRESS, EndpointProvider, ErrorHandlerMiddleware, FIXTURE, Fixtures, Gallery, GalleryCache, GalleryController, HTTP_SERVER, IdGenerator, IsFile, IsObjectId, JOB, JobManager, LanguageMiddleware, LazyAssetGenerator, LazyAssets, MailSender, MemoryCache, MongoConnector, PARAMETER, Parameter, Progresses, ResolveEntity, SOCKET_SERVER, TemplateRenderer, TranslationProvider, Translator, Type, UserManager, assign, broadcast, bufferToStream, colorize, convertValue, copy, copyStream, createServices, createTransformer, deleteFile, deleteFromBucket, filter, firstItem, getConstructorName, getExtension, getFileName, getFunctionParams, getType, getValue, groupBy, hydratePopulated, idToString, injectServices, isArray, isBoolean, isConstructor, isDate, isDefined, isFunction, isInterface, isNullOrUndefined, isObject, isPrimitive, isString, isType, jsonHighlight, lastItem, lcFirst, lookupPipelines, md5, mkdirRecursive, multiSubscription, observableFromFunction, padLeft, padRight, paginate, paginateAggregations, promiseTimeout, proxyFunction, proxyFunctions, rand, random, readAndDeleteFile, readFile, runCommand, setupBackend, streamToBuffer, ucFirst, valueToPromise, writeFile };
|
|
4020
4116
|
//# sourceMappingURL=stemy-backend.js.map
|