jcc-express-mvc 1.8.7 → 1.8.21
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/Core/index.d.ts +4 -0
- package/Core/index.d.ts.map +1 -1
- package/Core/index.js +5 -0
- package/__tests__/Job.test.d.ts +2 -0
- package/__tests__/Job.test.d.ts.map +1 -0
- package/__tests__/Job.test.js +205 -0
- package/__tests__/MySqlSchemaBlueprint.test.d.ts +2 -0
- package/__tests__/MySqlSchemaBlueprint.test.d.ts.map +1 -0
- package/__tests__/MySqlSchemaBlueprint.test.js +55 -0
- package/__tests__/PostgresTranslator.test.d.ts +2 -0
- package/__tests__/PostgresTranslator.test.d.ts.map +1 -0
- package/__tests__/PostgresTranslator.test.js +82 -0
- package/__tests__/SQLiteTranslator.test.d.ts +2 -0
- package/__tests__/SQLiteTranslator.test.d.ts.map +1 -0
- package/__tests__/SQLiteTranslator.test.js +125 -0
- package/__tests__/SchemaAlterBlueprint.test.d.ts +2 -0
- package/__tests__/SchemaAlterBlueprint.test.d.ts.map +1 -0
- package/__tests__/SchemaAlterBlueprint.test.js +35 -0
- package/global.d.ts +3 -1
- package/index.d.ts +28 -3
- package/index.d.ts.map +1 -1
- package/index.js +33 -75
- package/lib/Application/Application.d.ts.map +1 -1
- package/lib/Application/Application.js +2 -2
- package/lib/Application/ApplicationBuilder.d.ts.map +1 -1
- package/lib/Application/ApplicationBuilder.js +22 -11
- package/lib/Auth/AuthMiddleware.d.ts.map +1 -1
- package/lib/Auth/AuthMiddleware.js +29 -12
- package/lib/Auth/index.d.ts +17 -3
- package/lib/Auth/index.d.ts.map +1 -1
- package/lib/Auth/index.js +128 -26
- package/lib/Auth/loginRateLimit.d.ts +6 -0
- package/lib/Auth/loginRateLimit.d.ts.map +1 -0
- package/lib/Auth/loginRateLimit.js +25 -0
- package/lib/Auth/refreshTokenStore.d.ts +24 -0
- package/lib/Auth/refreshTokenStore.d.ts.map +1 -0
- package/lib/Auth/refreshTokenStore.js +46 -0
- package/lib/Command-Line/DBCommand.d.ts.map +1 -1
- package/lib/Command-Line/DBCommand.js +9 -3
- package/lib/Command-Line/KeyGenerateCommand.d.ts +6 -0
- package/lib/Command-Line/KeyGenerateCommand.d.ts.map +1 -0
- package/lib/Command-Line/KeyGenerateCommand.js +47 -0
- package/lib/Command-Line/MakeCommand.d.ts +1 -0
- package/lib/Command-Line/MakeCommand.d.ts.map +1 -1
- package/lib/Command-Line/MakeCommand.js +36 -32
- package/lib/Command-Line/NodeArtisanCommand.d.ts +2 -0
- package/lib/Command-Line/NodeArtisanCommand.d.ts.map +1 -1
- package/lib/Command-Line/NodeArtisanCommand.js +24 -6
- package/lib/Command-Line/NodeTinker/Tinker.d.ts +5 -2
- package/lib/Command-Line/NodeTinker/Tinker.d.ts.map +1 -1
- package/lib/Command-Line/NodeTinker/Tinker.js +13 -3
- package/lib/Command-Line/WatchCommand.d.ts +29 -0
- package/lib/Command-Line/WatchCommand.d.ts.map +1 -0
- package/lib/Command-Line/WatchCommand.js +234 -0
- package/lib/Command-Line/files/Models.d.ts.map +1 -1
- package/lib/Command-Line/files/Models.js +67 -0
- package/lib/Console/Command.d.ts +18 -0
- package/lib/Console/Command.d.ts.map +1 -1
- package/lib/Console/Command.js +29 -0
- package/lib/Container/index.d.ts.map +1 -1
- package/lib/Container/index.js +22 -8
- package/lib/Database/Database.d.ts +21 -0
- package/lib/Database/Database.d.ts.map +1 -0
- package/lib/Database/Database.js +55 -0
- package/lib/Database/DatabaseServiceProvider.d.ts +22 -0
- package/lib/Database/DatabaseServiceProvider.d.ts.map +1 -0
- package/lib/Database/DatabaseServiceProvider.js +50 -0
- package/lib/Database/Drivers/KnexDriver.d.ts +13 -0
- package/lib/Database/Drivers/KnexDriver.d.ts.map +1 -0
- package/lib/Database/Drivers/KnexDriver.js +29 -0
- package/lib/Database/Drivers/MongooseDriver.d.ts +20 -0
- package/lib/Database/Drivers/MongooseDriver.d.ts.map +1 -0
- package/lib/Database/Drivers/MongooseDriver.js +57 -0
- package/lib/Database/Drivers/SequelizeDriver.d.ts +24 -0
- package/lib/Database/Drivers/SequelizeDriver.d.ts.map +1 -0
- package/lib/Database/Drivers/SequelizeDriver.js +82 -0
- package/lib/Database/index.d.ts +7 -0
- package/lib/Database/index.d.ts.map +1 -0
- package/lib/Database/index.js +11 -0
- package/lib/Database/interface.d.ts +14 -0
- package/lib/Database/interface.d.ts.map +1 -0
- package/lib/Database/interface.js +2 -0
- package/lib/Database/type.d.ts +18 -0
- package/lib/Database/type.d.ts.map +1 -0
- package/lib/Database/type.js +2 -0
- package/lib/Error/DisplayErrorCode.d.ts.map +1 -1
- package/lib/Error/DisplayErrorCode.js +27 -17
- package/lib/Error/MissMatchTokenException/index.d.ts +4 -0
- package/lib/Error/MissMatchTokenException/index.d.ts.map +1 -0
- package/lib/Error/MissMatchTokenException/index.js +9 -0
- package/lib/Error/SocialiteAuthError/SocialiteAuthError.d.ts +9 -0
- package/lib/Error/SocialiteAuthError/SocialiteAuthError.d.ts.map +1 -0
- package/lib/Error/SocialiteAuthError/SocialiteAuthError.js +17 -0
- package/lib/Global/helpers.d.ts.map +1 -1
- package/lib/Global/helpers.js +7 -6
- package/lib/Http/index.d.ts +3 -1
- package/lib/Http/index.d.ts.map +1 -1
- package/lib/Http/index.js +26 -5
- package/lib/Interface/index.d.ts +17 -3
- package/lib/Interface/index.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Builder.d.ts +12 -1
- package/lib/Jcc-eloquent/lib/Builder.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Builder.js +119 -5
- package/lib/Jcc-eloquent/lib/Database/index.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Database/index.js +2 -1
- package/lib/Jcc-eloquent/lib/Interfaces/index.d.ts +37 -2
- package/lib/Jcc-eloquent/lib/Interfaces/index.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Migration.d.ts +6 -0
- package/lib/Jcc-eloquent/lib/Migration.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Migration.js +24 -2
- package/lib/Jcc-eloquent/lib/Model.d.ts +24 -7
- package/lib/Jcc-eloquent/lib/Model.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Model.js +35 -2
- package/lib/Jcc-eloquent/lib/QueryBuilder.d.ts +2 -1
- package/lib/Jcc-eloquent/lib/QueryBuilder.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/QueryBuilder.js +10 -1
- package/lib/Jcc-eloquent/lib/Rollback.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Rollback.js +9 -2
- package/lib/Jcc-eloquent/lib/Schema/BaseSchemaEntity/index.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Schema/BaseSchemaEntity/index.js +3 -3
- package/lib/Jcc-eloquent/lib/Schema/BluePrint/index.d.ts +6 -2
- package/lib/Jcc-eloquent/lib/Schema/BluePrint/index.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Schema/BluePrint/index.js +41 -12
- package/lib/Jcc-eloquent/lib/Schema/Translator/Sqlite.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Schema/Translator/Sqlite.js +21 -3
- package/lib/Jcc-eloquent/lib/Schema/Translator/postgres.d.ts +1 -0
- package/lib/Jcc-eloquent/lib/Schema/Translator/postgres.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Schema/Translator/postgres.js +70 -14
- package/lib/Jcc-eloquent/lib/Schema/index.d.ts +12 -0
- package/lib/Jcc-eloquent/lib/Schema/index.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/Schema/index.js +27 -6
- package/lib/Jcc-eloquent/lib/utils/index.d.ts +13 -0
- package/lib/Jcc-eloquent/lib/utils/index.d.ts.map +1 -1
- package/lib/Jcc-eloquent/lib/utils/index.js +62 -0
- package/lib/Middleware/index.d.ts +1 -0
- package/lib/Middleware/index.d.ts.map +1 -1
- package/lib/Middleware/index.js +20 -8
- package/lib/Model/Sequelize.d.ts +3 -0
- package/lib/Model/Sequelize.d.ts.map +1 -0
- package/lib/Model/Sequelize.js +6 -0
- package/lib/Providers/RouteServiceProvider.d.ts.map +1 -1
- package/lib/Providers/RouteServiceProvider.js +3 -0
- package/lib/Providers/SessionServiceProvider.d.ts +12 -0
- package/lib/Providers/SessionServiceProvider.d.ts.map +1 -0
- package/lib/Providers/SessionServiceProvider.js +47 -0
- package/lib/Queue/Controllers/QueueControllers.d.ts +31 -0
- package/lib/Queue/Controllers/QueueControllers.d.ts.map +1 -0
- package/lib/Queue/Controllers/QueueControllers.js +126 -0
- package/lib/Queue/Drivers/DatabaseDriver.d.ts +6 -1
- package/lib/Queue/Drivers/DatabaseDriver.d.ts.map +1 -1
- package/lib/Queue/Drivers/DatabaseDriver.js +76 -21
- package/lib/Queue/Drivers/MemoryDriver.d.ts +17 -6
- package/lib/Queue/Drivers/MemoryDriver.d.ts.map +1 -1
- package/lib/Queue/Drivers/MemoryDriver.js +323 -14
- package/lib/Queue/Drivers/RedisDriver.d.ts +48 -0
- package/lib/Queue/Drivers/RedisDriver.d.ts.map +1 -0
- package/lib/Queue/Drivers/RedisDriver.js +533 -0
- package/lib/Queue/Job.d.ts +8 -0
- package/lib/Queue/Job.d.ts.map +1 -1
- package/lib/Queue/Job.js +25 -1
- package/lib/Queue/JobsLogger.d.ts.map +1 -1
- package/lib/Queue/JobsLogger.js +6 -3
- package/lib/Queue/Queue.d.ts +17 -0
- package/lib/Queue/Queue.d.ts.map +1 -1
- package/lib/Queue/Queue.js +146 -11
- package/lib/Queue/QueueServiceProvider.d.ts +6 -0
- package/lib/Queue/QueueServiceProvider.d.ts.map +1 -0
- package/lib/Queue/QueueServiceProvider.js +18 -0
- package/lib/Queue/Route/web.d.ts +2 -0
- package/lib/Queue/Route/web.d.ts.map +1 -0
- package/lib/Queue/Route/web.js +16 -0
- package/lib/Queue/index.d.ts +1 -0
- package/lib/Queue/index.d.ts.map +1 -1
- package/lib/Queue/index.js +3 -0
- package/lib/Queue/interface.d.ts +25 -0
- package/lib/Queue/interface.d.ts.map +1 -1
- package/lib/Queue/middleware/queueDashboardGuard.d.ts +7 -0
- package/lib/Queue/middleware/queueDashboardGuard.d.ts.map +1 -0
- package/lib/Queue/middleware/queueDashboardGuard.js +43 -0
- package/lib/Queue/type.d.ts +12 -1
- package/lib/Queue/type.d.ts.map +1 -1
- package/lib/Response/index.d.ts.map +1 -1
- package/lib/Response/index.js +6 -1
- package/lib/Routes/Route.d.ts +2 -2
- package/lib/Routes/Route.d.ts.map +1 -1
- package/lib/Routes/RouteBuilder.d.ts +2 -2
- package/lib/Routes/RouteBuilder.d.ts.map +1 -1
- package/lib/Security/CsrfMiddleware.d.ts +37 -0
- package/lib/Security/CsrfMiddleware.d.ts.map +1 -0
- package/lib/Security/CsrfMiddleware.js +85 -0
- package/lib/Security/MethodSpoofingMiddleware.d.ts +36 -0
- package/lib/Security/MethodSpoofingMiddleware.d.ts.map +1 -0
- package/lib/Security/MethodSpoofingMiddleware.js +51 -0
- package/lib/Security/index.d.ts +5 -0
- package/lib/Security/index.d.ts.map +1 -0
- package/lib/Security/index.js +7 -0
- package/lib/Session/DatabaseSession.d.ts +9 -3
- package/lib/Session/DatabaseSession.d.ts.map +1 -1
- package/lib/Session/DatabaseSession.js +38 -36
- package/lib/Session/ExpressJccSession.d.ts +23 -0
- package/lib/Session/ExpressJccSession.d.ts.map +1 -0
- package/lib/Session/ExpressJccSession.js +110 -0
- package/lib/Session/RedisSession.d.ts +2 -2
- package/lib/Session/RedisSession.d.ts.map +1 -1
- package/lib/Session/RedisSession.js +19 -5
- package/lib/Session/SessionManager.d.ts +18 -4
- package/lib/Session/SessionManager.d.ts.map +1 -1
- package/lib/Session/SessionManager.js +53 -17
- package/lib/Socialite/AbstractProvider.d.ts +60 -0
- package/lib/Socialite/AbstractProvider.d.ts.map +1 -0
- package/lib/Socialite/AbstractProvider.js +136 -0
- package/lib/Socialite/Drivers/facebook/FacebookDriver.d.ts +9 -0
- package/lib/Socialite/Drivers/facebook/FacebookDriver.d.ts.map +1 -0
- package/lib/Socialite/Drivers/facebook/FacebookDriver.js +40 -0
- package/lib/Socialite/Drivers/facebook/FacebookProvider.d.ts +15 -0
- package/lib/Socialite/Drivers/facebook/FacebookProvider.d.ts.map +1 -0
- package/lib/Socialite/Drivers/facebook/FacebookProvider.js +28 -0
- package/lib/Socialite/Drivers/github/GitHubDriver.d.ts +9 -0
- package/lib/Socialite/Drivers/github/GitHubDriver.d.ts.map +1 -0
- package/lib/Socialite/Drivers/github/GitHubDriver.js +54 -0
- package/lib/Socialite/Drivers/github/GitHubProvider.d.ts +15 -0
- package/lib/Socialite/Drivers/github/GitHubProvider.d.ts.map +1 -0
- package/lib/Socialite/Drivers/github/GitHubProvider.js +28 -0
- package/lib/Socialite/Drivers/gitlab/GitLabDriver.d.ts +10 -0
- package/lib/Socialite/Drivers/gitlab/GitLabDriver.d.ts.map +1 -0
- package/lib/Socialite/Drivers/gitlab/GitLabDriver.js +37 -0
- package/lib/Socialite/Drivers/gitlab/GitLabProvider.d.ts +15 -0
- package/lib/Socialite/Drivers/gitlab/GitLabProvider.d.ts.map +1 -0
- package/lib/Socialite/Drivers/gitlab/GitLabProvider.js +28 -0
- package/lib/Socialite/Drivers/google/GoogleDriver.d.ts +9 -0
- package/lib/Socialite/Drivers/google/GoogleDriver.d.ts.map +1 -0
- package/lib/Socialite/Drivers/google/GoogleDriver.js +39 -0
- package/lib/Socialite/Drivers/google/GoogleProvider.d.ts +15 -0
- package/lib/Socialite/Drivers/google/GoogleProvider.d.ts.map +1 -0
- package/lib/Socialite/Drivers/google/GoogleProvider.js +28 -0
- package/lib/Socialite/Drivers/slack/SlackDriver.d.ts +9 -0
- package/lib/Socialite/Drivers/slack/SlackDriver.d.ts.map +1 -0
- package/lib/Socialite/Drivers/slack/SlackDriver.js +41 -0
- package/lib/Socialite/Drivers/slack/SlackProvider.d.ts +16 -0
- package/lib/Socialite/Drivers/slack/SlackProvider.d.ts.map +1 -0
- package/lib/Socialite/Drivers/slack/SlackProvider.js +37 -0
- package/lib/Socialite/Drivers/twitter/TwitterDriver.d.ts +9 -0
- package/lib/Socialite/Drivers/twitter/TwitterDriver.d.ts.map +1 -0
- package/lib/Socialite/Drivers/twitter/TwitterDriver.js +57 -0
- package/lib/Socialite/Drivers/twitter/TwitterProvider.d.ts +16 -0
- package/lib/Socialite/Drivers/twitter/TwitterProvider.d.ts.map +1 -0
- package/lib/Socialite/Drivers/twitter/TwitterProvider.js +38 -0
- package/lib/Socialite/SocialUser.d.ts +42 -0
- package/lib/Socialite/SocialUser.d.ts.map +1 -0
- package/lib/Socialite/SocialUser.js +116 -0
- package/lib/Socialite/Socialite.d.ts +13 -0
- package/lib/Socialite/Socialite.d.ts.map +1 -0
- package/lib/Socialite/Socialite.js +41 -0
- package/lib/Socialite/SocialiteProvider.d.ts +9 -0
- package/lib/Socialite/SocialiteProvider.d.ts.map +1 -0
- package/lib/Socialite/SocialiteProvider.js +15 -0
- package/lib/Socialite/config.d.ts +7 -0
- package/lib/Socialite/config.d.ts.map +1 -0
- package/lib/Socialite/config.js +44 -0
- package/lib/Socialite/constant.d.ts +18 -0
- package/lib/Socialite/constant.d.ts.map +1 -0
- package/lib/Socialite/constant.js +20 -0
- package/lib/Socialite/index.d.ts +13 -0
- package/lib/Socialite/index.d.ts.map +1 -0
- package/lib/Socialite/index.js +25 -0
- package/lib/Socialite/types.d.ts +13 -0
- package/lib/Socialite/types.d.ts.map +1 -0
- package/lib/Socialite/types.js +2 -0
- package/lib/Templating-engine/benchmark.d.ts +7 -0
- package/lib/Templating-engine/benchmark.d.ts.map +1 -0
- package/lib/Templating-engine/benchmark.js +44 -0
- package/lib/Templating-engine/engineHelper.d.ts +37 -8
- package/lib/Templating-engine/engineHelper.d.ts.map +1 -1
- package/lib/Templating-engine/engineHelper.js +203 -26
- package/lib/Templating-engine/errors.d.ts +15 -0
- package/lib/Templating-engine/errors.d.ts.map +1 -0
- package/lib/Templating-engine/errors.js +35 -0
- package/lib/Templating-engine/expressions.d.ts +24 -0
- package/lib/Templating-engine/expressions.d.ts.map +1 -1
- package/lib/Templating-engine/expressions.js +27 -5
- package/lib/Templating-engine/index.d.ts +87 -17
- package/lib/Templating-engine/index.d.ts.map +1 -1
- package/lib/Templating-engine/index.js +701 -96
- package/lib/Templating-engine/plugins.d.ts +30 -0
- package/lib/Templating-engine/plugins.d.ts.map +1 -0
- package/lib/Templating-engine/plugins.js +47 -0
- package/lib/Type/index.d.ts +1 -0
- package/lib/Type/index.d.ts.map +1 -1
- package/lib/Validation/Validator/CustomValidation.d.ts.map +1 -1
- package/lib/Validation/Validator/CustomValidation.js +2 -2
- package/lib/Validation/Validator/helper.d.ts.map +1 -1
- package/lib/Validation/Validator/helper.js +8 -1
- package/lib/util/index.d.ts +42 -1
- package/lib/util/index.d.ts.map +1 -1
- package/lib/util/index.js +154 -17
- package/package.json +1 -1
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RedisDriver = void 0;
|
|
4
|
+
function createRedisClient(config) {
|
|
5
|
+
const Redis = require("ioredis").default ?? require("ioredis");
|
|
6
|
+
if (typeof config === "string") {
|
|
7
|
+
return new Redis(config);
|
|
8
|
+
}
|
|
9
|
+
return new Redis(config);
|
|
10
|
+
}
|
|
11
|
+
class RedisDriver {
|
|
12
|
+
constructor(config) {
|
|
13
|
+
const connection = config.connection ?? "redis://127.0.0.1:6379";
|
|
14
|
+
this.redis = createRedisClient(connection);
|
|
15
|
+
this.prefix = config.prefix ?? "queue";
|
|
16
|
+
this.defaultQueue = config.queue ?? "default";
|
|
17
|
+
this.blockFor = config.blockFor ?? 5;
|
|
18
|
+
}
|
|
19
|
+
listKey(queue) {
|
|
20
|
+
return `${this.prefix}:${queue}`;
|
|
21
|
+
}
|
|
22
|
+
delayedKey(queue) {
|
|
23
|
+
return `${this.prefix}:${queue}:delayed`;
|
|
24
|
+
}
|
|
25
|
+
failedKey() {
|
|
26
|
+
return `${this.prefix}:failed`;
|
|
27
|
+
}
|
|
28
|
+
completedKey() {
|
|
29
|
+
return `${this.prefix}:completed`;
|
|
30
|
+
}
|
|
31
|
+
metaKey(jobId) {
|
|
32
|
+
return `${this.prefix}:meta:${jobId}`;
|
|
33
|
+
}
|
|
34
|
+
dataKey(jobId) {
|
|
35
|
+
return `${this.prefix}:data:${jobId}`;
|
|
36
|
+
}
|
|
37
|
+
serializeJob(job) {
|
|
38
|
+
return JSON.stringify({
|
|
39
|
+
...job,
|
|
40
|
+
status: job.status ?? "pending",
|
|
41
|
+
payload: typeof job.payload === "string"
|
|
42
|
+
? job.payload
|
|
43
|
+
: JSON.stringify(job.payload),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
deserializeJob(serialized) {
|
|
47
|
+
try {
|
|
48
|
+
const parsed = JSON.parse(serialized);
|
|
49
|
+
const payload = typeof parsed.payload === "string"
|
|
50
|
+
? parsed.payload
|
|
51
|
+
: JSON.stringify(parsed.payload);
|
|
52
|
+
return {
|
|
53
|
+
id: parsed.id,
|
|
54
|
+
queue: parsed.queue,
|
|
55
|
+
payload,
|
|
56
|
+
attempts: parsed.attempts ?? 0,
|
|
57
|
+
maxAttempts: parsed.maxAttempts ?? 3,
|
|
58
|
+
timeout: parsed.timeout ?? 60,
|
|
59
|
+
availableAt: parsed.availableAt
|
|
60
|
+
? new Date(parsed.availableAt)
|
|
61
|
+
: new Date(),
|
|
62
|
+
createdAt: parsed.createdAt ? new Date(parsed.createdAt) : new Date(),
|
|
63
|
+
status: parsed.status,
|
|
64
|
+
startedAt: parsed.startedAt ? new Date(parsed.startedAt) : undefined,
|
|
65
|
+
finishedAt: parsed.finishedAt ? new Date(parsed.finishedAt) : undefined,
|
|
66
|
+
failedAt: parsed.failedAt ? new Date(parsed.failedAt) : undefined,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async push(job, queue) {
|
|
74
|
+
const key = this.listKey(queue);
|
|
75
|
+
const serialized = this.serializeJob(job);
|
|
76
|
+
await this.redis.rpush(key, serialized);
|
|
77
|
+
}
|
|
78
|
+
async later(job, delay, queue) {
|
|
79
|
+
const availableAt = Date.now() + delay * 1000;
|
|
80
|
+
const key = this.delayedKey(queue);
|
|
81
|
+
const serialized = this.serializeJob({
|
|
82
|
+
...job,
|
|
83
|
+
availableAt: new Date(availableAt),
|
|
84
|
+
});
|
|
85
|
+
await this.redis.zadd(key, availableAt, serialized);
|
|
86
|
+
}
|
|
87
|
+
async migrateDelayedJobs(queue) {
|
|
88
|
+
const now = Date.now();
|
|
89
|
+
const delayedKey = this.delayedKey(queue);
|
|
90
|
+
const listKey = this.listKey(queue);
|
|
91
|
+
const ready = await this.redis.zrangebyscore(delayedKey, 0, now);
|
|
92
|
+
if (ready.length === 0)
|
|
93
|
+
return;
|
|
94
|
+
const pipeline = this.redis.pipeline();
|
|
95
|
+
for (const serialized of ready) {
|
|
96
|
+
pipeline.rpush(listKey, serialized);
|
|
97
|
+
}
|
|
98
|
+
pipeline.zremrangebyscore(delayedKey, 0, now);
|
|
99
|
+
await pipeline.exec();
|
|
100
|
+
}
|
|
101
|
+
async pop(queue) {
|
|
102
|
+
await this.migrateDelayedJobs(queue);
|
|
103
|
+
const key = this.listKey(queue);
|
|
104
|
+
let serialized;
|
|
105
|
+
if (this.blockFor > 0) {
|
|
106
|
+
const result = await this.redis.blpop(key, this.blockFor);
|
|
107
|
+
serialized = result ? result[1] : null;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
serialized = await this.redis.lpop(key);
|
|
111
|
+
}
|
|
112
|
+
if (!serialized)
|
|
113
|
+
return null;
|
|
114
|
+
const job = this.deserializeJob(serialized);
|
|
115
|
+
if (job) {
|
|
116
|
+
job.status = "processing";
|
|
117
|
+
job.startedAt = new Date();
|
|
118
|
+
const withStatus = {
|
|
119
|
+
...job,
|
|
120
|
+
status: "processing",
|
|
121
|
+
startedAt: job.startedAt,
|
|
122
|
+
};
|
|
123
|
+
await this.redis.set(this.dataKey(job.id), this.serializeJob(withStatus));
|
|
124
|
+
await this.redis.hset(this.metaKey(job.id), {
|
|
125
|
+
status: "processing",
|
|
126
|
+
started_at: String(Date.now()),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return job;
|
|
130
|
+
}
|
|
131
|
+
async delete(jobId) {
|
|
132
|
+
await this.redis.del(this.metaKey(jobId));
|
|
133
|
+
await this.redis.del(this.dataKey(jobId));
|
|
134
|
+
const keys = await this.redis.keys(`${this.prefix}:*`);
|
|
135
|
+
for (const key of keys) {
|
|
136
|
+
if (key.endsWith(":delayed") || key === this.failedKey())
|
|
137
|
+
continue;
|
|
138
|
+
if ((await this.redis.type(key)) !== "list")
|
|
139
|
+
continue;
|
|
140
|
+
const items = await this.redis.lrange(key, 0, -1);
|
|
141
|
+
for (const s of items) {
|
|
142
|
+
try {
|
|
143
|
+
const parsed = JSON.parse(s);
|
|
144
|
+
if (parsed.id === jobId) {
|
|
145
|
+
await this.redis.lrem(key, 1, s);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// skip
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const failedItems = await this.redis.lrange(this.failedKey(), 0, -1);
|
|
155
|
+
for (const s of failedItems) {
|
|
156
|
+
try {
|
|
157
|
+
const parsed = JSON.parse(s);
|
|
158
|
+
if (parsed.id === jobId) {
|
|
159
|
+
await this.redis.lrem(this.failedKey(), 1, s);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// skip
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const completedItems = await this.redis.lrange(this.completedKey(), 0, -1);
|
|
168
|
+
for (const s of completedItems) {
|
|
169
|
+
try {
|
|
170
|
+
const parsed = JSON.parse(s);
|
|
171
|
+
if (parsed.id === jobId) {
|
|
172
|
+
await this.redis.lrem(this.completedKey(), 1, s);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
// skip
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async updateStatus(jobId, update) {
|
|
182
|
+
const meta = { status: update.status };
|
|
183
|
+
if (update.startedAt)
|
|
184
|
+
meta.started_at = String(update.startedAt.getTime());
|
|
185
|
+
if (update.finishedAt)
|
|
186
|
+
meta.finished_at = String(update.finishedAt.getTime());
|
|
187
|
+
if (update.failedAt)
|
|
188
|
+
meta.failed_at = String(update.failedAt.getTime());
|
|
189
|
+
await this.redis.hset(this.metaKey(jobId), meta);
|
|
190
|
+
if (update.status === "completed") {
|
|
191
|
+
let serialized = await this.redis.get(this.dataKey(jobId));
|
|
192
|
+
// If the job isn't in the data key (e.g. runJob uses push, not pop),
|
|
193
|
+
// search the queue lists and pull it out.
|
|
194
|
+
if (!serialized) {
|
|
195
|
+
const keys = await this.redis.keys(`${this.prefix}:*`);
|
|
196
|
+
for (const key of keys) {
|
|
197
|
+
if (key.endsWith(":delayed") ||
|
|
198
|
+
key.includes(":meta:") ||
|
|
199
|
+
key.includes(":data:") ||
|
|
200
|
+
key === this.failedKey() ||
|
|
201
|
+
key === this.completedKey())
|
|
202
|
+
continue;
|
|
203
|
+
const type = await this.redis.type(key);
|
|
204
|
+
if (type !== "list")
|
|
205
|
+
continue;
|
|
206
|
+
const items = await this.redis.lrange(key, 0, -1);
|
|
207
|
+
for (const item of items) {
|
|
208
|
+
try {
|
|
209
|
+
const parsed = JSON.parse(item);
|
|
210
|
+
if (parsed.id === jobId) {
|
|
211
|
+
serialized = item;
|
|
212
|
+
await this.redis.lrem(key, 1, item);
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (serialized)
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (serialized) {
|
|
225
|
+
const job = this.deserializeJob(serialized);
|
|
226
|
+
if (job) {
|
|
227
|
+
const withFinished = {
|
|
228
|
+
...job,
|
|
229
|
+
status: "completed",
|
|
230
|
+
finishedAt: update.finishedAt,
|
|
231
|
+
};
|
|
232
|
+
await this.redis.rpush(this.completedKey(), this.serializeJob(withFinished));
|
|
233
|
+
}
|
|
234
|
+
await this.redis.del(this.dataKey(jobId));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (update.status === "completed" || update.status === "failed") {
|
|
238
|
+
await this.redis.del(this.metaKey(jobId));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
async release(job, delay = 0) {
|
|
242
|
+
if (delay > 0) {
|
|
243
|
+
await this.later(job, delay / 1000, job.queue);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
await this.push(job, job.queue);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async failed(job, error) {
|
|
250
|
+
const exception = error?.message + "\n" + (error?.stack || "");
|
|
251
|
+
await this.redis.del(this.dataKey(job.id));
|
|
252
|
+
await this.redis.del(this.metaKey(job.id));
|
|
253
|
+
const availableAt = job.availableAt instanceof Date
|
|
254
|
+
? job.availableAt.getTime()
|
|
255
|
+
: typeof job.availableAt === "number"
|
|
256
|
+
? job.availableAt
|
|
257
|
+
: Date.now();
|
|
258
|
+
const createdAt = job.createdAt instanceof Date
|
|
259
|
+
? job.createdAt.getTime()
|
|
260
|
+
: typeof job.createdAt === "number"
|
|
261
|
+
? job.createdAt
|
|
262
|
+
: Date.now();
|
|
263
|
+
const failedEntry = JSON.stringify({
|
|
264
|
+
id: job.id,
|
|
265
|
+
queue: job.queue,
|
|
266
|
+
payload: job.payload,
|
|
267
|
+
attempts: job.attempts,
|
|
268
|
+
availableAt,
|
|
269
|
+
createdAt,
|
|
270
|
+
error: error?.message ?? String(error),
|
|
271
|
+
stack: error?.stack,
|
|
272
|
+
exception,
|
|
273
|
+
failedAt: Date.now(),
|
|
274
|
+
status: "failed",
|
|
275
|
+
});
|
|
276
|
+
await this.redis.rpush(this.failedKey(), failedEntry);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Get all jobs from all queues (pending, processing, completed, failed).
|
|
280
|
+
* Returns array with status, started_at, finished_at, failed_at.
|
|
281
|
+
*/
|
|
282
|
+
async getQueues() {
|
|
283
|
+
const jobs = [];
|
|
284
|
+
const keys = await this.redis.keys(`${this.prefix}:*`);
|
|
285
|
+
for (const key of keys) {
|
|
286
|
+
if (key.endsWith(":delayed") ||
|
|
287
|
+
key.includes(":meta:") ||
|
|
288
|
+
key.includes(":data:"))
|
|
289
|
+
continue;
|
|
290
|
+
if (key === this.failedKey() || key === this.completedKey())
|
|
291
|
+
continue;
|
|
292
|
+
if ((await this.redis.type(key)) !== "list")
|
|
293
|
+
continue;
|
|
294
|
+
const queueName = key.replace(`${this.prefix}:`, "");
|
|
295
|
+
const items = await this.redis.lrange(key, 0, -1);
|
|
296
|
+
for (const serialized of items) {
|
|
297
|
+
const job = this.deserializeJob(serialized);
|
|
298
|
+
if (job) {
|
|
299
|
+
jobs.push(this.toJobRecord(job, queueName));
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const metaKeys = await this.redis.keys(`${this.prefix}:meta:*`);
|
|
304
|
+
for (const mk of metaKeys) {
|
|
305
|
+
const jobId = mk.replace(`${this.prefix}:meta:`, "");
|
|
306
|
+
const serialized = await this.redis.get(this.dataKey(jobId));
|
|
307
|
+
if (serialized) {
|
|
308
|
+
const job = this.deserializeJob(serialized);
|
|
309
|
+
if (job) {
|
|
310
|
+
const meta = await this.redis.hgetall(mk);
|
|
311
|
+
jobs.push(this.toJobRecord(job, job.queue, meta));
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
const completedItems = await this.redis.lrange(this.completedKey(), 0, -1);
|
|
316
|
+
for (const serialized of completedItems) {
|
|
317
|
+
const job = this.deserializeJob(serialized);
|
|
318
|
+
if (job)
|
|
319
|
+
jobs.push(this.toJobRecord(job, job.queue));
|
|
320
|
+
}
|
|
321
|
+
const failedItems = await this.redis.lrange(this.failedKey(), 0, -1);
|
|
322
|
+
for (const serialized of failedItems) {
|
|
323
|
+
try {
|
|
324
|
+
const parsed = JSON.parse(serialized);
|
|
325
|
+
jobs.push({
|
|
326
|
+
id: parsed.id,
|
|
327
|
+
queue: parsed.queue ?? "default",
|
|
328
|
+
payload: parsed.payload,
|
|
329
|
+
attempts: parsed.attempts ?? 0,
|
|
330
|
+
available_at: parsed.availableAt ?? null,
|
|
331
|
+
created_at: parsed.createdAt ?? null,
|
|
332
|
+
status: "failed",
|
|
333
|
+
started_at: null,
|
|
334
|
+
finished_at: null,
|
|
335
|
+
failed_at: parsed.failedAt ?? null,
|
|
336
|
+
exception: parsed.exception ??
|
|
337
|
+
(parsed.error ? parsed.error + "\n" + (parsed.stack || "") : null),
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
// skip
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return this.sortByLatest(jobs);
|
|
345
|
+
}
|
|
346
|
+
sortByLatest(jobs) {
|
|
347
|
+
return jobs.sort((a, b) => {
|
|
348
|
+
const tsA = a.finished_at ?? a.failed_at ?? a.created_at ?? 0;
|
|
349
|
+
const tsB = b.finished_at ?? b.failed_at ?? b.created_at ?? 0;
|
|
350
|
+
const numA = typeof tsA === "number" ? tsA : tsA?.getTime?.() ?? 0;
|
|
351
|
+
const numB = typeof tsB === "number" ? tsB : tsB?.getTime?.() ?? 0;
|
|
352
|
+
return numB - numA;
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
toJobRecord(job, queue, meta) {
|
|
356
|
+
return {
|
|
357
|
+
id: job.id,
|
|
358
|
+
queue,
|
|
359
|
+
payload: job.payload,
|
|
360
|
+
attempts: job.attempts,
|
|
361
|
+
available_at: job.availableAt,
|
|
362
|
+
created_at: job.createdAt,
|
|
363
|
+
status: meta?.status ?? job.status ?? "pending",
|
|
364
|
+
started_at: meta?.started_at
|
|
365
|
+
? parseInt(meta.started_at, 10)
|
|
366
|
+
: (job.startedAt?.getTime?.() ?? null),
|
|
367
|
+
finished_at: meta?.finished_at
|
|
368
|
+
? parseInt(meta.finished_at, 10)
|
|
369
|
+
: (job.finishedAt?.getTime?.() ?? null),
|
|
370
|
+
failed_at: meta?.failed_at
|
|
371
|
+
? parseInt(meta.failed_at, 10)
|
|
372
|
+
: (job.failedAt?.getTime?.() ?? null),
|
|
373
|
+
exception: meta?.exception ?? null,
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Find a job by ID. Scans queues, processing, completed, failed.
|
|
378
|
+
*/
|
|
379
|
+
async findQueueById(id) {
|
|
380
|
+
const serialized = await this.redis.get(this.dataKey(id));
|
|
381
|
+
if (serialized) {
|
|
382
|
+
const job = this.deserializeJob(serialized);
|
|
383
|
+
if (job) {
|
|
384
|
+
const meta = await this.redis.hgetall(this.metaKey(id));
|
|
385
|
+
return this.toJobRecord(job, job.queue, meta);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
const keys = await this.redis.keys(`${this.prefix}:*`);
|
|
389
|
+
for (const key of keys) {
|
|
390
|
+
if (key.endsWith(":delayed") ||
|
|
391
|
+
key.includes(":meta:") ||
|
|
392
|
+
key.includes(":data:") ||
|
|
393
|
+
key === this.failedKey() ||
|
|
394
|
+
key === this.completedKey())
|
|
395
|
+
continue;
|
|
396
|
+
const type = await this.redis.type(key);
|
|
397
|
+
if (type !== "list")
|
|
398
|
+
continue;
|
|
399
|
+
const items = await this.redis.lrange(key, 0, -1);
|
|
400
|
+
for (const s of items) {
|
|
401
|
+
const job = this.deserializeJob(s);
|
|
402
|
+
if (job && job.id === id)
|
|
403
|
+
return this.toJobRecord(job, key.replace(`${this.prefix}:`, ""));
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
const failedItems = await this.redis.lrange(this.failedKey(), 0, -1);
|
|
407
|
+
for (const s of failedItems) {
|
|
408
|
+
try {
|
|
409
|
+
const parsed = JSON.parse(s);
|
|
410
|
+
if (parsed.id === id) {
|
|
411
|
+
return {
|
|
412
|
+
id: parsed.id,
|
|
413
|
+
queue: parsed.queue ?? "default",
|
|
414
|
+
payload: parsed.payload,
|
|
415
|
+
attempts: parsed.attempts ?? 0,
|
|
416
|
+
available_at: parsed.availableAt ?? null,
|
|
417
|
+
created_at: parsed.createdAt ?? null,
|
|
418
|
+
status: "failed",
|
|
419
|
+
started_at: null,
|
|
420
|
+
finished_at: null,
|
|
421
|
+
failed_at: parsed.failedAt ?? null,
|
|
422
|
+
exception: parsed.exception ??
|
|
423
|
+
(parsed.error
|
|
424
|
+
? parsed.error + "\n" + (parsed.stack || "")
|
|
425
|
+
: null),
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
catch {
|
|
430
|
+
// skip
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
return null;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Find jobs by property key/value. Scans queue lists. Returns array of matches.
|
|
437
|
+
*/
|
|
438
|
+
async findQueueBy(key, value) {
|
|
439
|
+
const results = [];
|
|
440
|
+
const keys = await this.redis.keys(`${this.prefix}:*`);
|
|
441
|
+
for (const redisKey of keys) {
|
|
442
|
+
if (redisKey.endsWith(":delayed") ||
|
|
443
|
+
redisKey === this.failedKey() ||
|
|
444
|
+
redisKey === this.completedKey() ||
|
|
445
|
+
redisKey.includes(":meta:") ||
|
|
446
|
+
redisKey.includes(":data:"))
|
|
447
|
+
continue;
|
|
448
|
+
const type = await this.redis.type(redisKey);
|
|
449
|
+
if (type !== "list")
|
|
450
|
+
continue;
|
|
451
|
+
const items = await this.redis.lrange(redisKey, 0, -1);
|
|
452
|
+
for (const serialized of items) {
|
|
453
|
+
const job = this.deserializeJob(serialized);
|
|
454
|
+
if (!job)
|
|
455
|
+
continue;
|
|
456
|
+
let target = job[key];
|
|
457
|
+
if (target === undefined && typeof job.payload === "string") {
|
|
458
|
+
try {
|
|
459
|
+
const p = JSON.parse(job.payload);
|
|
460
|
+
target = p?.[key];
|
|
461
|
+
}
|
|
462
|
+
catch {
|
|
463
|
+
// ignore
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
else if (target === undefined && typeof job.payload === "object") {
|
|
467
|
+
target = job.payload?.[key];
|
|
468
|
+
}
|
|
469
|
+
if (target !== undefined && String(target) === String(value)) {
|
|
470
|
+
results.push(this.toJobRecord(job, redisKey.replace(`${this.prefix}:`, "")));
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
const completedItems = await this.redis.lrange(this.completedKey(), 0, -1);
|
|
475
|
+
for (const s of completedItems) {
|
|
476
|
+
const job = this.deserializeJob(s);
|
|
477
|
+
if (!job)
|
|
478
|
+
continue;
|
|
479
|
+
let target = job[key];
|
|
480
|
+
if (target === undefined && typeof job.payload === "string") {
|
|
481
|
+
try {
|
|
482
|
+
const p = JSON.parse(job.payload);
|
|
483
|
+
target = p?.[key];
|
|
484
|
+
}
|
|
485
|
+
catch {
|
|
486
|
+
// ignore
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
else if (target === undefined && typeof job.payload === "object") {
|
|
490
|
+
target = job.payload?.[key];
|
|
491
|
+
}
|
|
492
|
+
if (target !== undefined && String(target) === String(value)) {
|
|
493
|
+
results.push(this.toJobRecord(job, job.queue ?? "default"));
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
const failedItems = await this.redis.lrange(this.failedKey(), 0, -1);
|
|
497
|
+
for (const s of failedItems) {
|
|
498
|
+
try {
|
|
499
|
+
const parsed = JSON.parse(s);
|
|
500
|
+
let target = parsed[key];
|
|
501
|
+
if (target === undefined && parsed.payload) {
|
|
502
|
+
const p = typeof parsed.payload === "string"
|
|
503
|
+
? JSON.parse(parsed.payload)
|
|
504
|
+
: parsed.payload;
|
|
505
|
+
target = p?.[key];
|
|
506
|
+
}
|
|
507
|
+
if (target !== undefined && String(target) === String(value)) {
|
|
508
|
+
results.push({
|
|
509
|
+
id: parsed.id,
|
|
510
|
+
queue: parsed.queue ?? "default",
|
|
511
|
+
payload: parsed.payload,
|
|
512
|
+
attempts: parsed.attempts ?? 0,
|
|
513
|
+
available_at: parsed.availableAt ?? null,
|
|
514
|
+
created_at: parsed.createdAt ?? null,
|
|
515
|
+
status: "failed",
|
|
516
|
+
started_at: null,
|
|
517
|
+
finished_at: null,
|
|
518
|
+
failed_at: parsed.failedAt ?? null,
|
|
519
|
+
exception: parsed.exception ??
|
|
520
|
+
(parsed.error
|
|
521
|
+
? parsed.error + "\n" + (parsed.stack || "")
|
|
522
|
+
: null),
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
catch {
|
|
527
|
+
// skip
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return this.sortByLatest(results);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
exports.RedisDriver = RedisDriver;
|
package/lib/Queue/Job.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { JobData } from "./type";
|
|
2
2
|
export declare abstract class Job<T = any> implements JobData {
|
|
3
3
|
id?: string;
|
|
4
|
+
/** Path within app/Jobs (e.g. "ProcessEmail" or "Notifications/ProcessEmail"). Defaults to constructor name when empty. */
|
|
4
5
|
path: string;
|
|
5
6
|
displayName?: string;
|
|
6
7
|
maxAttempts: number;
|
|
@@ -9,6 +10,13 @@ export declare abstract class Job<T = any> implements JobData {
|
|
|
9
10
|
delay: number;
|
|
10
11
|
data: T;
|
|
11
12
|
constructor(data: T);
|
|
13
|
+
/** Resolved path for loading (user path or default constructor name) */
|
|
14
|
+
get jobPath(): string;
|
|
15
|
+
/**
|
|
16
|
+
* Dispatch the job to the queue. Uses delay if set.
|
|
17
|
+
* @example ProcessEmail.dispatch({ to: 'user@example.com' })
|
|
18
|
+
*/
|
|
19
|
+
static dispatch<T>(this: new (data: T) => Job<T>, data: T): Promise<string>;
|
|
12
20
|
/**
|
|
13
21
|
* Handle the job execution
|
|
14
22
|
*/
|
package/lib/Queue/Job.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Job.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Queue/Job.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEjC,8BAAsB,GAAG,CAAC,CAAC,GAAG,GAAG,CAAE,YAAW,OAAO;IAC5C,EAAE,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"Job.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Queue/Job.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEjC,8BAAsB,GAAG,CAAC,CAAC,GAAG,GAAG,CAAE,YAAW,OAAO;IAC5C,EAAE,CAAC,EAAE,MAAM,CAAC;IACnB,2HAA2H;IACpH,IAAI,EAAE,MAAM,CAAM;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAK;IACxB,OAAO,EAAE,MAAM,CAAM;IACrB,QAAQ,EAAE,MAAM,CAAK;IACrB,KAAK,EAAE,MAAM,CAAK;IAClB,IAAI,EAAE,CAAC,CAAC;gBAEH,IAAI,EAAE,CAAC;IAKnB,wEAAwE;IACxE,IAAW,OAAO,IAAI,MAAM,CAE3B;IAED;;;OAGG;WACU,QAAQ,CAAC,CAAC,EACrB,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAC7B,IAAI,EAAE,CAAC,GACN,OAAO,CAAC,MAAM,CAAC;IAgBlB;;OAEG;IACH,QAAQ,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAEhC;;OAEG;IACI,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAIvC;;OAEG;IACI,SAAS,IAAI,MAAM;IAc1B;;OAEG;WACW,cAAc,CAC1B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,GAAG,KAAK,GAAG,CAAC,GACjD,GAAG;CAkBP"}
|
package/lib/Queue/Job.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Job = void 0;
|
|
4
4
|
class Job {
|
|
5
5
|
constructor(data) {
|
|
6
|
+
/** Path within app/Jobs (e.g. "ProcessEmail" or "Notifications/ProcessEmail"). Defaults to constructor name when empty. */
|
|
6
7
|
this.path = "";
|
|
7
8
|
this.maxAttempts = 3;
|
|
8
9
|
this.timeout = 60; // seconds
|
|
@@ -10,7 +11,27 @@ class Job {
|
|
|
10
11
|
this.delay = 0;
|
|
11
12
|
this.data = data;
|
|
12
13
|
this.displayName = this.constructor.name;
|
|
13
|
-
|
|
14
|
+
}
|
|
15
|
+
/** Resolved path for loading (user path or default constructor name) */
|
|
16
|
+
get jobPath() {
|
|
17
|
+
return this.path || this.constructor.name;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Dispatch the job to the queue. Uses delay if set.
|
|
21
|
+
* @example ProcessEmail.dispatch({ to: 'user@example.com' })
|
|
22
|
+
*/
|
|
23
|
+
static async dispatch(data) {
|
|
24
|
+
const app = globalThis
|
|
25
|
+
.app;
|
|
26
|
+
const queue = app?.resolve("Queue");
|
|
27
|
+
if (!queue) {
|
|
28
|
+
throw new Error("Queue not registered. Ensure withConfig includes queue config.");
|
|
29
|
+
}
|
|
30
|
+
const job = new this(data);
|
|
31
|
+
if (job.delay > 0) {
|
|
32
|
+
return queue.later(job, job.delay);
|
|
33
|
+
}
|
|
34
|
+
return queue.push(job);
|
|
14
35
|
}
|
|
15
36
|
/**
|
|
16
37
|
* Calculate backoff time based on attempts
|
|
@@ -24,11 +45,13 @@ class Job {
|
|
|
24
45
|
serialize() {
|
|
25
46
|
return JSON.stringify({
|
|
26
47
|
job: this.constructor.name,
|
|
48
|
+
path: this.jobPath,
|
|
27
49
|
id: this.id,
|
|
28
50
|
displayName: this.displayName,
|
|
29
51
|
maxAttempts: this.maxAttempts,
|
|
30
52
|
timeout: this.timeout,
|
|
31
53
|
attempts: this.attempts,
|
|
54
|
+
delay: this.delay,
|
|
32
55
|
data: this.data,
|
|
33
56
|
});
|
|
34
57
|
}
|
|
@@ -43,6 +66,7 @@ class Job {
|
|
|
43
66
|
}
|
|
44
67
|
const job = new JobClass(parsed.data);
|
|
45
68
|
job.id = parsed.id;
|
|
69
|
+
job.path = parsed.path ?? "";
|
|
46
70
|
job.displayName = parsed.displayName;
|
|
47
71
|
job.maxAttempts = parsed.maxAttempts;
|
|
48
72
|
job.timeout = parsed.timeout;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JobsLogger.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Queue/JobsLogger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAI5B,qBAAa,SAAS;IAMR,OAAO,CAAC,GAAG;IAJvB,OAAO,CAAC,GAAG,CAC2F;IACtG,OAAO,CAAC,KAAK,CAAS;gBAEF,GAAG,EAAE,GAAG;IAI5B,UAAU;
|
|
1
|
+
{"version":3,"file":"JobsLogger.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Queue/JobsLogger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAI5B,qBAAa,SAAS;IAMR,OAAO,CAAC,GAAG;IAJvB,OAAO,CAAC,GAAG,CAC2F;IACtG,OAAO,CAAC,KAAK,CAAS;gBAEF,GAAG,EAAE,GAAG;IAI5B,UAAU;IAQV,OAAO;IAYP,MAAM,CAAC,KAAK,EAAE,GAAG;IAYjB,OAAO,CAAC,QAAQ;CAQjB"}
|
package/lib/Queue/JobsLogger.js
CHANGED
|
@@ -16,15 +16,18 @@ class JobLogger {
|
|
|
16
16
|
}
|
|
17
17
|
processing() {
|
|
18
18
|
const date = Date_1.Carbon.now().format("yyyy-MM-dd H:i:s");
|
|
19
|
-
|
|
19
|
+
const label = `app/Jobs/${this.job.jobPath}`;
|
|
20
|
+
console.log(`${date} ${label} ${colors_1.default.gray(this.dot)} ${colors_1.default.yellow("RUNNING")}`);
|
|
20
21
|
}
|
|
21
22
|
success() {
|
|
22
23
|
const date = Date_1.Carbon.now().format("yyyy-MM-dd H:i:s");
|
|
23
|
-
|
|
24
|
+
const label = `app/Jobs/${this.job.jobPath}`;
|
|
25
|
+
console.log(`${date} ${label} ${colors_1.default.gray(this.dot)} ${this.duration(performance.now() - this.start)} ${colors_1.default.green("DONE")}\n`);
|
|
24
26
|
}
|
|
25
27
|
failed(error) {
|
|
26
28
|
const date = Date_1.Carbon.now().format("yyyy-MM-dd H:i:s");
|
|
27
|
-
|
|
29
|
+
const label = `app/Jobs/${this.job.jobPath}`;
|
|
30
|
+
console.log(`${date} ${label} ${colors_1.default.gray(this.dot)} ${this.duration(performance.now() - this.start)} ${colors_1.default.red("FAILED")} \n`);
|
|
28
31
|
}
|
|
29
32
|
duration(time) {
|
|
30
33
|
return (time.toLocaleString("en-US", {
|
package/lib/Queue/Queue.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export declare class Queue {
|
|
|
6
6
|
private defaultQueue;
|
|
7
7
|
events: EventEmitter;
|
|
8
8
|
private jobClasses;
|
|
9
|
+
private processSync;
|
|
9
10
|
constructor(config: QueueConfig);
|
|
10
11
|
private resolveDriver;
|
|
11
12
|
/**
|
|
@@ -36,5 +37,21 @@ export declare class Queue {
|
|
|
36
37
|
* Run a single worker
|
|
37
38
|
*/
|
|
38
39
|
private runWorker;
|
|
40
|
+
getQueues(): Promise<any[]>;
|
|
41
|
+
findQueueById(id: string): Promise<Record<string, any>>;
|
|
42
|
+
findQueueBy(key: string, value: any): Promise<any[]>;
|
|
43
|
+
/** Delete a job by ID (for dashboard manual delete). */
|
|
44
|
+
deleteJob(jobId: string): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Retry a failed job — removes it from failed state, re-queues, and runs it immediately.
|
|
47
|
+
* Returns the new job ID on success, or null if the job was not found.
|
|
48
|
+
*/
|
|
49
|
+
retry(jobId: string): Promise<string | null>;
|
|
50
|
+
/**
|
|
51
|
+
* Run a specific job by ID immediately.
|
|
52
|
+
* Works for pending, failed, and processing jobs.
|
|
53
|
+
* Deletes the old record, executes handle(), then writes the final status.
|
|
54
|
+
*/
|
|
55
|
+
runJob(jobId: string): Promise<boolean>;
|
|
39
56
|
}
|
|
40
57
|
//# sourceMappingURL=Queue.d.ts.map
|
package/lib/Queue/Queue.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Queue.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Queue/Queue.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAIrC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAI5B,qBAAa,KAAK;IAChB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,YAAY,CAAqB;IAClC,MAAM,EAAE,YAAY,CAAsB;IACjD,OAAO,CAAC,UAAU,CAA8C;
|
|
1
|
+
{"version":3,"file":"Queue.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Queue/Queue.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAIrC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAI5B,qBAAa,KAAK;IAChB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,YAAY,CAAqB;IAClC,MAAM,EAAE,YAAY,CAAsB;IACjD,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,WAAW,CAAU;gBAEjB,MAAM,EAAE,WAAW;IAQ/B,OAAO,CAAC,aAAa;IAqBrB;;OAEG;IACI,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,IAAI,EAAE,GAAG,KAAK,GAAG,GAAG,IAAI;IAIxE;;OAEG;IACU,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA4BlE;;OAEG;IACU,KAAK,CAAC,CAAC,EAClB,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,EACX,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC;IA4BlB;;OAEG;IACU,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA4D1D;;OAEG;YACW,eAAe;IAuB7B;;OAEG;IACU,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,WAAW,GAAE,MAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IASzE;;OAEG;YACW,SAAS;IAWV,SAAS,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAI3B,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAIvD,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAIjE,wDAAwD;IAC3C,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpD;;;OAGG;IACU,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA4BzD;;;;OAIG;IACU,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAyErD"}
|