@nvent-addon/app 0.5.15 → 1.0.0-alpha.2
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/dist/module.json +1 -1
- package/dist/module.mjs +3 -2
- package/dist/runtime/app/components/DashboardCard.d.vue.ts +1 -1
- package/dist/runtime/app/components/DashboardCard.vue.d.ts +1 -1
- package/dist/runtime/app/composables/useWorkers.d.ts +57 -0
- package/dist/runtime/app/composables/useWorkers.js +42 -0
- package/dist/runtime/app/pages/dashboard.vue +1 -654
- package/dist/runtime/app/pages/index.vue +25 -41
- package/dist/runtime/app/pages/workers.vue +458 -0
- package/dist/runtime/server/api/_workers/index.get.d.ts +8 -0
- package/dist/runtime/server/api/_workers/index.get.js +14 -0
- package/package.json +12 -11
- package/dist/runtime/app/components/ComponentRouter.d.vue.ts +0 -46
- package/dist/runtime/app/components/ComponentRouter.vue +0 -26
- package/dist/runtime/app/components/ComponentRouter.vue.d.ts +0 -46
- package/dist/runtime/app/components/ComponentShell.d.vue.ts +0 -23
- package/dist/runtime/app/components/ComponentShell.vue +0 -97
- package/dist/runtime/app/components/ComponentShell.vue.d.ts +0 -23
- package/dist/runtime/app/components/ConfirmDialog.d.vue.ts +0 -33
- package/dist/runtime/app/components/ConfirmDialog.vue +0 -120
- package/dist/runtime/app/components/ConfirmDialog.vue.d.ts +0 -33
- package/dist/runtime/app/composables/useComponentRouter.d.ts +0 -46
- package/dist/runtime/app/composables/useComponentRouter.js +0 -248
- package/dist/runtime/app/pages/flows/[name].vue +0 -750
- package/dist/runtime/app/pages/flows/index.d.vue.ts +0 -3
- package/dist/runtime/app/pages/flows/index.vue +0 -381
- package/dist/runtime/app/pages/flows/index.vue.d.ts +0 -3
- package/dist/runtime/app/pages/queues/index.d.vue.ts +0 -3
- package/dist/runtime/app/pages/queues/index.vue +0 -236
- package/dist/runtime/app/pages/queues/index.vue.d.ts +0 -3
- package/dist/runtime/app/pages/queues/job.d.vue.ts +0 -3
- package/dist/runtime/app/pages/queues/job.vue +0 -261
- package/dist/runtime/app/pages/queues/job.vue.d.ts +0 -3
- package/dist/runtime/app/pages/queues/jobs.d.vue.ts +0 -3
- package/dist/runtime/app/pages/queues/jobs.vue +0 -595
- package/dist/runtime/app/pages/queues/jobs.vue.d.ts +0 -3
- package/dist/runtime/app/pages/settings/scheduler.d.vue.ts +0 -3
- package/dist/runtime/app/pages/settings/scheduler.vue +0 -310
- package/dist/runtime/app/pages/settings/scheduler.vue.d.ts +0 -3
- package/dist/runtime/app/pages/triggers/[name]/edit.d.vue.ts +0 -3
- package/dist/runtime/app/pages/triggers/[name]/edit.vue +0 -429
- package/dist/runtime/app/pages/triggers/[name]/edit.vue.d.ts +0 -3
- package/dist/runtime/app/pages/triggers/[name].d.vue.ts +0 -3
- package/dist/runtime/app/pages/triggers/[name].vue +0 -870
- package/dist/runtime/app/pages/triggers/[name].vue.d.ts +0 -3
- package/dist/runtime/app/pages/triggers/index.d.vue.ts +0 -3
- package/dist/runtime/app/pages/triggers/index.vue +0 -525
- package/dist/runtime/app/pages/triggers/index.vue.d.ts +0 -3
- package/dist/runtime/app/pages/triggers/new.d.vue.ts +0 -3
- package/dist/runtime/app/pages/triggers/new.vue +0 -610
- package/dist/runtime/app/pages/triggers/new.vue.d.ts +0 -3
- package/dist/runtime/server/api/_flows/[name]/clear-history.delete.d.ts +0 -10
- package/dist/runtime/server/api/_flows/[name]/clear-history.delete.js +0 -49
- package/dist/runtime/server/api/_flows/[name]/runs/[runId]/cancel.post.d.ts +0 -2
- package/dist/runtime/server/api/_flows/[name]/runs/[runId]/cancel.post.js +0 -21
- package/dist/runtime/server/api/_flows/[name]/runs/[runId]/restart.post.d.ts +0 -2
- package/dist/runtime/server/api/_flows/[name]/runs/[runId]/restart.post.js +0 -21
- package/dist/runtime/server/api/_flows/[name]/runs.get.d.ts +0 -17
- package/dist/runtime/server/api/_flows/[name]/runs.get.js +0 -64
- package/dist/runtime/server/api/_flows/[name]/start.post.d.ts +0 -2
- package/dist/runtime/server/api/_flows/[name]/start.post.js +0 -9
- package/dist/runtime/server/api/_flows/index.get.d.ts +0 -7
- package/dist/runtime/server/api/_flows/index.get.js +0 -5
- package/dist/runtime/server/api/_flows/recent-runs.get.d.ts +0 -15
- package/dist/runtime/server/api/_flows/recent-runs.get.js +0 -67
- package/dist/runtime/server/api/_flows/ws.d.ts +0 -80
- package/dist/runtime/server/api/_flows/ws.js +0 -309
- package/dist/runtime/server/api/_queues/[name]/job/[id].get.d.ts +0 -2
- package/dist/runtime/server/api/_queues/[name]/job/[id].get.js +0 -14
- package/dist/runtime/server/api/_queues/[name]/job/index.get.d.ts +0 -2
- package/dist/runtime/server/api/_queues/[name]/job/index.get.js +0 -39
- package/dist/runtime/server/api/_queues/index.get.d.ts +0 -2
- package/dist/runtime/server/api/_queues/index.get.js +0 -106
- package/dist/runtime/server/api/_queues/ws.d.ts +0 -48
- package/dist/runtime/server/api/_queues/ws.js +0 -215
- package/dist/runtime/server/api/_scheduler/jobs.get.d.ts +0 -19
- package/dist/runtime/server/api/_scheduler/jobs.get.js +0 -36
- package/dist/runtime/server/api/_triggers/[name]/events.get.d.ts +0 -6
- package/dist/runtime/server/api/_triggers/[name]/events.get.js +0 -43
- package/dist/runtime/server/api/_triggers/[name]/index.get.d.ts +0 -6
- package/dist/runtime/server/api/_triggers/[name]/index.get.js +0 -76
- package/dist/runtime/server/api/_triggers/[name].delete.d.ts +0 -7
- package/dist/runtime/server/api/_triggers/[name].delete.js +0 -37
- package/dist/runtime/server/api/_triggers/[name].patch.d.ts +0 -7
- package/dist/runtime/server/api/_triggers/[name].patch.js +0 -117
- package/dist/runtime/server/api/_triggers/index.get.d.ts +0 -6
- package/dist/runtime/server/api/_triggers/index.get.js +0 -44
- package/dist/runtime/server/api/_triggers/index.post.d.ts +0 -7
- package/dist/runtime/server/api/_triggers/index.post.js +0 -124
- package/dist/runtime/server/api/_triggers/stats.get.d.ts +0 -6
- package/dist/runtime/server/api/_triggers/stats.get.js +0 -41
- package/dist/runtime/server/api/_triggers/ws.d.ts +0 -74
- package/dist/runtime/server/api/_triggers/ws.js +0 -315
- /package/dist/runtime/app/pages/{flows/[name].d.vue.ts → workers.d.vue.ts} +0 -0
- /package/dist/runtime/app/pages/{flows/[name].vue.d.ts → workers.vue.d.ts} +0 -0
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { defineEventHandler, getRouterParam, getQuery, useQueueAdapter, createError } from "#imports";
|
|
2
|
-
export default defineEventHandler(async (event) => {
|
|
3
|
-
const name = getRouterParam(event, "name");
|
|
4
|
-
if (!name) {
|
|
5
|
-
throw createError({ statusCode: 400, statusMessage: "Missing queue name" });
|
|
6
|
-
}
|
|
7
|
-
const query = getQuery(event);
|
|
8
|
-
const state = query.state;
|
|
9
|
-
const limit = query.limit ? Number.parseInt(query.limit, 10) : 50;
|
|
10
|
-
const offset = query.offset ? Number.parseInt(query.offset, 10) : 0;
|
|
11
|
-
let queue;
|
|
12
|
-
try {
|
|
13
|
-
queue = useQueueAdapter();
|
|
14
|
-
} catch {
|
|
15
|
-
throw createError({
|
|
16
|
-
statusCode: 503,
|
|
17
|
-
statusMessage: "Server initializing",
|
|
18
|
-
data: "Queue adapter not ready yet, please retry"
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
const allJobs = await queue.getJobs(name, {
|
|
22
|
-
state: state ? [state] : void 0,
|
|
23
|
-
limit: 1e4
|
|
24
|
-
// Large number to get all for counting
|
|
25
|
-
});
|
|
26
|
-
const totalCount = allJobs?.length || 0;
|
|
27
|
-
const sortedJobs = (allJobs || []).sort((a, b) => {
|
|
28
|
-
const aTime = a.timestamp || 0;
|
|
29
|
-
const bTime = b.timestamp || 0;
|
|
30
|
-
return bTime - aTime;
|
|
31
|
-
});
|
|
32
|
-
const paginatedJobs = sortedJobs.slice(offset, offset + limit);
|
|
33
|
-
return {
|
|
34
|
-
jobs: paginatedJobs,
|
|
35
|
-
count: paginatedJobs.length,
|
|
36
|
-
total: totalCount,
|
|
37
|
-
hasMore: offset + limit < totalCount
|
|
38
|
-
};
|
|
39
|
-
});
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { defineEventHandler, useRuntimeConfig, $useFunctionRegistry, useQueueAdapter, useNventLogger } from "#imports";
|
|
2
|
-
const logger = useNventLogger("api-queues-index");
|
|
3
|
-
export default defineEventHandler(async () => {
|
|
4
|
-
const rc = useRuntimeConfig();
|
|
5
|
-
const registry = $useFunctionRegistry();
|
|
6
|
-
let queue;
|
|
7
|
-
try {
|
|
8
|
-
queue = useQueueAdapter();
|
|
9
|
-
} catch (err) {
|
|
10
|
-
logger.error("[queues/index] Adapters not initialized yet:", { error: err });
|
|
11
|
-
return [];
|
|
12
|
-
}
|
|
13
|
-
const globalQueueConfig = rc?.nvent?.queue || {};
|
|
14
|
-
const globalWorkerDefaults = globalQueueConfig.worker || {};
|
|
15
|
-
const globalQueueDefaults = {
|
|
16
|
-
prefix: globalQueueConfig.prefix,
|
|
17
|
-
defaultJobOptions: globalQueueConfig.defaultJobOptions,
|
|
18
|
-
limiter: globalQueueConfig.limiter
|
|
19
|
-
};
|
|
20
|
-
const names = /* @__PURE__ */ new Set();
|
|
21
|
-
if (registry?.workers?.length) {
|
|
22
|
-
for (const w of registry.workers) names.add(w.queue.name);
|
|
23
|
-
}
|
|
24
|
-
const queuesWithCounts = await Promise.all(
|
|
25
|
-
Array.from(names).map(async (name) => {
|
|
26
|
-
try {
|
|
27
|
-
const counts = await queue.getJobCounts(name);
|
|
28
|
-
const isPaused = await queue.isPaused(name);
|
|
29
|
-
const workers = registry?.workers?.filter((w) => w.queue.name === name) || [];
|
|
30
|
-
const mergedQueueConfig = workers.reduce((acc, w) => {
|
|
31
|
-
if (!w.queue) return acc;
|
|
32
|
-
const result = {
|
|
33
|
-
...acc,
|
|
34
|
-
name: w.queue.name
|
|
35
|
-
};
|
|
36
|
-
if (w.queue.prefix && w.queue.prefix !== acc.prefix) {
|
|
37
|
-
result.prefix = w.queue.prefix;
|
|
38
|
-
}
|
|
39
|
-
if (w.queue.limiter) {
|
|
40
|
-
result.limiter = w.queue.limiter;
|
|
41
|
-
}
|
|
42
|
-
if (w.queue.defaultJobOptions) {
|
|
43
|
-
result.defaultJobOptions = { ...acc.defaultJobOptions };
|
|
44
|
-
const wOpts = w.queue.defaultJobOptions;
|
|
45
|
-
const accOpts = acc.defaultJobOptions || {};
|
|
46
|
-
if (typeof wOpts.attempts === "number") {
|
|
47
|
-
result.defaultJobOptions.attempts = Math.max(wOpts.attempts, accOpts.attempts || 0);
|
|
48
|
-
}
|
|
49
|
-
if (wOpts.backoff) {
|
|
50
|
-
if (!accOpts.backoff || wOpts.backoff.delay && wOpts.backoff.delay !== globalQueueDefaults.defaultJobOptions?.backoff?.delay) {
|
|
51
|
-
result.defaultJobOptions.backoff = wOpts.backoff;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (typeof wOpts.priority === "number") result.defaultJobOptions.priority = wOpts.priority;
|
|
55
|
-
if (typeof wOpts.timeout === "number") result.defaultJobOptions.timeout = wOpts.timeout;
|
|
56
|
-
if (typeof wOpts.delay === "number") result.defaultJobOptions.delay = wOpts.delay;
|
|
57
|
-
if (typeof wOpts.lifo === "boolean") result.defaultJobOptions.lifo = wOpts.lifo;
|
|
58
|
-
if (wOpts.removeOnComplete !== void 0) result.defaultJobOptions.removeOnComplete = wOpts.removeOnComplete;
|
|
59
|
-
if (wOpts.removeOnFail !== void 0) result.defaultJobOptions.removeOnFail = wOpts.removeOnFail;
|
|
60
|
-
}
|
|
61
|
-
return result;
|
|
62
|
-
}, { ...globalQueueDefaults, name });
|
|
63
|
-
const mergedWorkerConfig = workers.reduce((acc, w) => {
|
|
64
|
-
if (!w.worker) return acc;
|
|
65
|
-
return {
|
|
66
|
-
concurrency: Math.max(acc.concurrency || 0, w.worker.concurrency || 0),
|
|
67
|
-
// Use max concurrency
|
|
68
|
-
lockDurationMs: w.worker.lockDurationMs ?? acc.lockDurationMs,
|
|
69
|
-
maxStalledCount: w.worker.maxStalledCount ?? acc.maxStalledCount,
|
|
70
|
-
drainDelayMs: w.worker.drainDelayMs ?? acc.drainDelayMs,
|
|
71
|
-
autorun: w.worker.autorun ?? acc.autorun,
|
|
72
|
-
pollingIntervalMs: w.worker.pollingIntervalMs ?? acc.pollingIntervalMs
|
|
73
|
-
};
|
|
74
|
-
}, { ...globalWorkerDefaults });
|
|
75
|
-
return {
|
|
76
|
-
name,
|
|
77
|
-
counts,
|
|
78
|
-
isPaused,
|
|
79
|
-
config: {
|
|
80
|
-
queue: mergedQueueConfig,
|
|
81
|
-
worker: mergedWorkerConfig
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
} catch (err) {
|
|
85
|
-
logger.error(`Failed to get counts for queue ${name}:`, { error: err });
|
|
86
|
-
return {
|
|
87
|
-
name,
|
|
88
|
-
counts: {
|
|
89
|
-
active: 0,
|
|
90
|
-
completed: 0,
|
|
91
|
-
failed: 0,
|
|
92
|
-
delayed: 0,
|
|
93
|
-
waiting: 0,
|
|
94
|
-
paused: 0
|
|
95
|
-
},
|
|
96
|
-
isPaused: false,
|
|
97
|
-
config: {
|
|
98
|
-
queue: globalQueueDefaults,
|
|
99
|
-
worker: globalWorkerDefaults
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
})
|
|
104
|
-
);
|
|
105
|
-
return queuesWithCounts;
|
|
106
|
-
});
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WebSocket endpoint for queue events
|
|
3
|
-
* Supports subscribing to specific queues and receiving real-time job updates
|
|
4
|
-
*
|
|
5
|
-
* Message format (client -> server):
|
|
6
|
-
* {
|
|
7
|
-
* "type": "subscribe",
|
|
8
|
-
* "queueName": "test"
|
|
9
|
-
* }
|
|
10
|
-
*
|
|
11
|
-
* {
|
|
12
|
-
* "type": "unsubscribe",
|
|
13
|
-
* "queueName": "test"
|
|
14
|
-
* }
|
|
15
|
-
*
|
|
16
|
-
* {
|
|
17
|
-
* "type": "ping"
|
|
18
|
-
* }
|
|
19
|
-
*
|
|
20
|
-
* Message format (server -> client):
|
|
21
|
-
* {
|
|
22
|
-
* "type": "event",
|
|
23
|
-
* "queueName": "test",
|
|
24
|
-
* "event": { eventType: "waiting|active|completed|failed", jobId: "...", ... }
|
|
25
|
-
* }
|
|
26
|
-
*
|
|
27
|
-
* {
|
|
28
|
-
* "type": "subscribed",
|
|
29
|
-
* "queueName": "test"
|
|
30
|
-
* }
|
|
31
|
-
*
|
|
32
|
-
* {
|
|
33
|
-
* "type": "unsubscribed",
|
|
34
|
-
* "queueName": "test"
|
|
35
|
-
* }
|
|
36
|
-
*
|
|
37
|
-
* {
|
|
38
|
-
* "type": "pong",
|
|
39
|
-
* "timestamp": 1234567890
|
|
40
|
-
* }
|
|
41
|
-
*
|
|
42
|
-
* {
|
|
43
|
-
* "type": "error",
|
|
44
|
-
* "message": "error description"
|
|
45
|
-
* }
|
|
46
|
-
*/
|
|
47
|
-
declare const _default: any;
|
|
48
|
-
export default _default;
|
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
defineWebSocketHandler,
|
|
3
|
-
useQueueAdapter,
|
|
4
|
-
usePeerManager,
|
|
5
|
-
useNventLogger
|
|
6
|
-
} from "#imports";
|
|
7
|
-
const peerContexts = /* @__PURE__ */ new WeakMap();
|
|
8
|
-
function safeSend(peer, data) {
|
|
9
|
-
try {
|
|
10
|
-
peer.send(JSON.stringify(data));
|
|
11
|
-
return true;
|
|
12
|
-
} catch {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
export default defineWebSocketHandler({
|
|
17
|
-
open(peer) {
|
|
18
|
-
const logger = useNventLogger("api-queues-ws");
|
|
19
|
-
logger.info("[ws:queues] client connected:", peer.id);
|
|
20
|
-
const { registerWsPeer } = usePeerManager();
|
|
21
|
-
registerWsPeer(peer);
|
|
22
|
-
peerContexts.set(peer, {
|
|
23
|
-
subscriptions: /* @__PURE__ */ new Map()
|
|
24
|
-
});
|
|
25
|
-
safeSend(peer, {
|
|
26
|
-
type: "connected",
|
|
27
|
-
timestamp: Date.now()
|
|
28
|
-
});
|
|
29
|
-
},
|
|
30
|
-
async message(peer, message) {
|
|
31
|
-
const logger = useNventLogger("api-queues-ws");
|
|
32
|
-
const context = peerContexts.get(peer);
|
|
33
|
-
if (!context) {
|
|
34
|
-
logger.error("[ws:queues] no context for peer:", peer.id);
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
let data;
|
|
38
|
-
try {
|
|
39
|
-
data = JSON.parse(message.text());
|
|
40
|
-
} catch {
|
|
41
|
-
safeSend(peer, {
|
|
42
|
-
type: "error",
|
|
43
|
-
message: "Invalid JSON"
|
|
44
|
-
});
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
const { type, queueName } = data;
|
|
48
|
-
if (type === "subscribe") {
|
|
49
|
-
if (!queueName) {
|
|
50
|
-
safeSend(peer, {
|
|
51
|
-
type: "error",
|
|
52
|
-
message: "Missing queueName"
|
|
53
|
-
});
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
let queue;
|
|
57
|
-
try {
|
|
58
|
-
queue = useQueueAdapter();
|
|
59
|
-
} catch (err) {
|
|
60
|
-
logger.error("[ws:queues] Adapters not initialized yet:", err);
|
|
61
|
-
safeSend(peer, {
|
|
62
|
-
type: "error",
|
|
63
|
-
message: "Server initializing, please retry"
|
|
64
|
-
});
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
const existingUnsub = context.subscriptions.get(queueName);
|
|
68
|
-
if (existingUnsub) {
|
|
69
|
-
try {
|
|
70
|
-
existingUnsub();
|
|
71
|
-
} catch (err) {
|
|
72
|
-
logger.error("[ws:queues] error unsubscribing:", err);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const events = [
|
|
76
|
-
"waiting",
|
|
77
|
-
"active",
|
|
78
|
-
"completed",
|
|
79
|
-
"failed",
|
|
80
|
-
"progress"
|
|
81
|
-
];
|
|
82
|
-
const unsubs = events.map(
|
|
83
|
-
(eventType) => queue.on(queueName, eventType, async (payload) => {
|
|
84
|
-
safeSend(peer, {
|
|
85
|
-
type: "event",
|
|
86
|
-
queueName,
|
|
87
|
-
event: {
|
|
88
|
-
eventType,
|
|
89
|
-
...payload
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
if (["waiting", "active", "completed", "failed"].includes(eventType)) {
|
|
93
|
-
try {
|
|
94
|
-
const counts = await queue.getJobCounts(queueName);
|
|
95
|
-
safeSend(peer, {
|
|
96
|
-
type: "counts",
|
|
97
|
-
queueName,
|
|
98
|
-
counts
|
|
99
|
-
});
|
|
100
|
-
} catch (err) {
|
|
101
|
-
logger.error("[ws:queues] error fetching counts after event:", err);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
})
|
|
105
|
-
);
|
|
106
|
-
const unsub = () => {
|
|
107
|
-
for (const u of unsubs) {
|
|
108
|
-
try {
|
|
109
|
-
u();
|
|
110
|
-
} catch (err) {
|
|
111
|
-
logger.error("[ws:queues] error unsubscribing:", err);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
context.subscriptions.set(queueName, unsub);
|
|
116
|
-
try {
|
|
117
|
-
const counts = await queue.getJobCounts(queueName);
|
|
118
|
-
safeSend(peer, {
|
|
119
|
-
type: "counts",
|
|
120
|
-
queueName,
|
|
121
|
-
counts
|
|
122
|
-
});
|
|
123
|
-
} catch (err) {
|
|
124
|
-
logger.error("[ws:queues] error fetching counts:", err);
|
|
125
|
-
}
|
|
126
|
-
safeSend(peer, {
|
|
127
|
-
type: "subscribed",
|
|
128
|
-
queueName
|
|
129
|
-
});
|
|
130
|
-
} else if (type === "unsubscribe") {
|
|
131
|
-
if (!queueName) {
|
|
132
|
-
safeSend(peer, {
|
|
133
|
-
type: "error",
|
|
134
|
-
message: "Missing queueName"
|
|
135
|
-
});
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
const unsub = context.subscriptions.get(queueName);
|
|
139
|
-
if (unsub) {
|
|
140
|
-
try {
|
|
141
|
-
unsub();
|
|
142
|
-
context.subscriptions.delete(queueName);
|
|
143
|
-
safeSend(peer, {
|
|
144
|
-
type: "unsubscribed",
|
|
145
|
-
queueName
|
|
146
|
-
});
|
|
147
|
-
} catch (err) {
|
|
148
|
-
logger.error("[ws:queues] error unsubscribing:", err);
|
|
149
|
-
safeSend(peer, {
|
|
150
|
-
type: "error",
|
|
151
|
-
message: "Failed to unsubscribe"
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
} else if (type === "ping") {
|
|
156
|
-
safeSend(peer, {
|
|
157
|
-
type: "pong",
|
|
158
|
-
timestamp: Date.now()
|
|
159
|
-
});
|
|
160
|
-
} else {
|
|
161
|
-
safeSend(peer, {
|
|
162
|
-
type: "error",
|
|
163
|
-
message: `Unknown message type: ${type}`
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
},
|
|
167
|
-
close(peer, event) {
|
|
168
|
-
const logger = useNventLogger("api-queues-ws");
|
|
169
|
-
const isNormalClosure = event?.code === 1e3 || event?.code === 1001;
|
|
170
|
-
if (!isNormalClosure) {
|
|
171
|
-
logger.info("[ws:queues] client disconnected:", {
|
|
172
|
-
peerId: peer.id,
|
|
173
|
-
code: event?.code,
|
|
174
|
-
reason: event?.reason
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
const { unregisterWsPeer } = usePeerManager();
|
|
178
|
-
unregisterWsPeer(peer);
|
|
179
|
-
const context = peerContexts.get(peer);
|
|
180
|
-
if (context) {
|
|
181
|
-
for (const unsub of Array.from(context.subscriptions.values())) {
|
|
182
|
-
try {
|
|
183
|
-
unsub();
|
|
184
|
-
} catch (err) {
|
|
185
|
-
if (!isNormalClosure) {
|
|
186
|
-
logger.error("[ws:queues] error unsubscribing on close:", err);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
context.subscriptions.clear();
|
|
191
|
-
peerContexts.delete(peer);
|
|
192
|
-
}
|
|
193
|
-
},
|
|
194
|
-
error(peer, error) {
|
|
195
|
-
const logger = useNventLogger("api-queues-ws");
|
|
196
|
-
logger.error("[ws:queues] error for peer:", {
|
|
197
|
-
peerId: peer.id,
|
|
198
|
-
error
|
|
199
|
-
});
|
|
200
|
-
const { unregisterWsPeer } = usePeerManager();
|
|
201
|
-
unregisterWsPeer(peer);
|
|
202
|
-
const context = peerContexts.get(peer);
|
|
203
|
-
if (context) {
|
|
204
|
-
for (const unsub of Array.from(context.subscriptions.values())) {
|
|
205
|
-
try {
|
|
206
|
-
unsub();
|
|
207
|
-
} catch (err) {
|
|
208
|
-
logger.error("[ws:queues] error unsubscribing on error:", { error: err });
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
context.subscriptions.clear();
|
|
212
|
-
peerContexts.delete(peer);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
});
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Get all scheduled jobs
|
|
3
|
-
* Returns list of jobs with their metadata and execution info
|
|
4
|
-
*/
|
|
5
|
-
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
|
|
6
|
-
jobs: any;
|
|
7
|
-
stats: {
|
|
8
|
-
total: any;
|
|
9
|
-
active: any;
|
|
10
|
-
lastRun: any;
|
|
11
|
-
};
|
|
12
|
-
} | {
|
|
13
|
-
jobs: never[];
|
|
14
|
-
stats: {
|
|
15
|
-
total: number;
|
|
16
|
-
active: number;
|
|
17
|
-
};
|
|
18
|
-
}>>;
|
|
19
|
-
export default _default;
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { defineEventHandler } from "h3";
|
|
2
|
-
import { useScheduler } from "#imports";
|
|
3
|
-
export default defineEventHandler(async () => {
|
|
4
|
-
try {
|
|
5
|
-
const scheduler = useScheduler();
|
|
6
|
-
const allJobs = await scheduler.getAllPersistedJobs();
|
|
7
|
-
const stats = {
|
|
8
|
-
total: allJobs.length,
|
|
9
|
-
active: allJobs.filter((job) => {
|
|
10
|
-
if (job.type === "one-time") {
|
|
11
|
-
return job.executeAt && job.executeAt > Date.now();
|
|
12
|
-
}
|
|
13
|
-
return job.enabled !== false;
|
|
14
|
-
}).length,
|
|
15
|
-
lastRun: allJobs.reduce((latest, job) => {
|
|
16
|
-
if (job.lastRun && (!latest || job.lastRun > latest)) {
|
|
17
|
-
return job.lastRun;
|
|
18
|
-
}
|
|
19
|
-
return latest;
|
|
20
|
-
}, 0)
|
|
21
|
-
};
|
|
22
|
-
return {
|
|
23
|
-
jobs: allJobs,
|
|
24
|
-
stats
|
|
25
|
-
};
|
|
26
|
-
} catch (error) {
|
|
27
|
-
console.error("Failed to get scheduler jobs:", error);
|
|
28
|
-
return {
|
|
29
|
-
jobs: [],
|
|
30
|
-
stats: {
|
|
31
|
-
total: 0,
|
|
32
|
-
active: 0
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
});
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { defineEventHandler, getRouterParam, getQuery, useTrigger, createError } from "#imports";
|
|
2
|
-
export default defineEventHandler(async (event) => {
|
|
3
|
-
const name = getRouterParam(event, "name");
|
|
4
|
-
const query = getQuery(event);
|
|
5
|
-
if (!name) {
|
|
6
|
-
throw createError({
|
|
7
|
-
statusCode: 400,
|
|
8
|
-
statusMessage: "Trigger name is required"
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
const { getTrigger, getTriggerHistory } = useTrigger();
|
|
12
|
-
const trigger = getTrigger(name);
|
|
13
|
-
if (!trigger) {
|
|
14
|
-
throw createError({
|
|
15
|
-
statusCode: 404,
|
|
16
|
-
statusMessage: `Trigger '${name}' not found`
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
const limit = query.limit ? Number.parseInt(query.limit, 10) : 50;
|
|
20
|
-
const offset = query.offset ? Number.parseInt(query.offset, 10) : 0;
|
|
21
|
-
const types = query.types ? query.types.split(",") : void 0;
|
|
22
|
-
const allEventsForCount = await getTriggerHistory(name, {
|
|
23
|
-
limit: 1e4,
|
|
24
|
-
// Large number to get all events for counting
|
|
25
|
-
types
|
|
26
|
-
});
|
|
27
|
-
const totalCount = allEventsForCount?.length || 0;
|
|
28
|
-
const allEvents = await getTriggerHistory(name, {
|
|
29
|
-
limit: Math.min(limit + offset, 1e3),
|
|
30
|
-
// Fetch enough to cover offset + limit
|
|
31
|
-
types
|
|
32
|
-
});
|
|
33
|
-
const events = allEvents?.slice(offset, offset + limit) || [];
|
|
34
|
-
return {
|
|
35
|
-
triggerName: name,
|
|
36
|
-
events,
|
|
37
|
-
count: events.length,
|
|
38
|
-
total: totalCount,
|
|
39
|
-
// Actual total count of all events matching filter
|
|
40
|
-
hasMore: offset + limit < totalCount
|
|
41
|
-
// More data available if offset+limit < total
|
|
42
|
-
};
|
|
43
|
-
});
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { defineEventHandler, getRouterParam, useTrigger, createError, getRequestURL } from "#imports";
|
|
2
|
-
export default defineEventHandler(async (event) => {
|
|
3
|
-
const name = getRouterParam(event, "name");
|
|
4
|
-
if (!name) {
|
|
5
|
-
throw createError({
|
|
6
|
-
statusCode: 400,
|
|
7
|
-
statusMessage: "Trigger name is required"
|
|
8
|
-
});
|
|
9
|
-
}
|
|
10
|
-
const { getTrigger, getSubscribedFlows, getTriggerStats, getAllSubscriptions, getTriggerHistory } = useTrigger();
|
|
11
|
-
const requestURL = getRequestURL(event);
|
|
12
|
-
const baseURL = `${requestURL.protocol}//${requestURL.host}`;
|
|
13
|
-
const trigger = getTrigger(name);
|
|
14
|
-
if (!trigger) {
|
|
15
|
-
throw createError({
|
|
16
|
-
statusCode: 404,
|
|
17
|
-
statusMessage: `Trigger '${name}' not found`
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
const subscribedFlows = getSubscribedFlows(name);
|
|
21
|
-
const stats = await getTriggerStats(name);
|
|
22
|
-
const allSubscriptions = getAllSubscriptions();
|
|
23
|
-
const subscriptions = allSubscriptions.filter((sub) => sub.triggerName === name);
|
|
24
|
-
const now = Date.now();
|
|
25
|
-
const last24h = now - 24 * 60 * 60 * 1e3;
|
|
26
|
-
let fires24h = 0;
|
|
27
|
-
try {
|
|
28
|
-
const recentEvents = await getTriggerHistory(name, { limit: 100, types: ["trigger.fired"] });
|
|
29
|
-
if (recentEvents) {
|
|
30
|
-
for (const event2 of recentEvents) {
|
|
31
|
-
if ((event2.ts || 0) >= last24h) {
|
|
32
|
-
fires24h++;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
} catch {
|
|
37
|
-
}
|
|
38
|
-
const webhookConfig = trigger.webhook ? {
|
|
39
|
-
...trigger.webhook,
|
|
40
|
-
path: trigger.webhook.path || `/api/_webhook/trigger/${name}`,
|
|
41
|
-
fullUrl: `${baseURL}/api/_webhook/trigger/${name}`
|
|
42
|
-
} : void 0;
|
|
43
|
-
return {
|
|
44
|
-
name: trigger.name,
|
|
45
|
-
type: trigger.type,
|
|
46
|
-
scope: trigger.scope,
|
|
47
|
-
displayName: trigger.displayName,
|
|
48
|
-
description: trigger.description,
|
|
49
|
-
source: trigger.source,
|
|
50
|
-
status: trigger.status || "active",
|
|
51
|
-
registeredAt: trigger.registeredAt,
|
|
52
|
-
registeredBy: trigger.registeredBy,
|
|
53
|
-
lastActivityAt: trigger.lastActivityAt,
|
|
54
|
-
webhook: webhookConfig,
|
|
55
|
-
schedule: trigger.schedule,
|
|
56
|
-
config: trigger.config,
|
|
57
|
-
version: trigger.version,
|
|
58
|
-
subscribedFlows,
|
|
59
|
-
subscriptions,
|
|
60
|
-
subscriptionCount: subscribedFlows.length,
|
|
61
|
-
stats: {
|
|
62
|
-
totalFires: stats?.totalFires || 0,
|
|
63
|
-
last24h: fires24h,
|
|
64
|
-
successCount: 0,
|
|
65
|
-
// Not tracked yet
|
|
66
|
-
failureCount: 0,
|
|
67
|
-
// Not tracked yet
|
|
68
|
-
activeSubscribers: stats?.activeSubscribers || subscribedFlows.length,
|
|
69
|
-
avgResponseTime: 0,
|
|
70
|
-
// Not tracked yet
|
|
71
|
-
successRate: 100,
|
|
72
|
-
// Default to 100% since failures not tracked yet
|
|
73
|
-
lastFiredAt: stats?.lastFiredAt
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
});
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { defineEventHandler, getRouterParam, useTrigger } from "#imports";
|
|
2
|
-
export default defineEventHandler(async (event) => {
|
|
3
|
-
const logger = {
|
|
4
|
-
info: console.log,
|
|
5
|
-
error: console.error
|
|
6
|
-
};
|
|
7
|
-
const trigger = useTrigger();
|
|
8
|
-
const name = getRouterParam(event, "name");
|
|
9
|
-
if (!name) {
|
|
10
|
-
return {
|
|
11
|
-
error: "Missing trigger name",
|
|
12
|
-
statusCode: 400
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
try {
|
|
16
|
-
logger.info("Deleting trigger", { name });
|
|
17
|
-
if (!trigger.hasTrigger(name)) {
|
|
18
|
-
return {
|
|
19
|
-
error: "Trigger not found",
|
|
20
|
-
statusCode: 404
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
await trigger.deleteTrigger(name);
|
|
24
|
-
logger.info(`Successfully deleted trigger '${name}'`);
|
|
25
|
-
return {
|
|
26
|
-
success: true,
|
|
27
|
-
message: `Trigger '${name}' deleted successfully`
|
|
28
|
-
};
|
|
29
|
-
} catch (err) {
|
|
30
|
-
logger.error("Failed to delete trigger", { error: err });
|
|
31
|
-
return {
|
|
32
|
-
error: "Failed to delete trigger",
|
|
33
|
-
message: err instanceof Error ? err.message : String(err),
|
|
34
|
-
statusCode: 500
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
});
|