@aiscene/aiserver 1.0.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/dist/api/callback.d.ts +7 -0
- package/dist/api/callback.d.ts.map +1 -0
- package/dist/api/callback.js +116 -0
- package/dist/api/callback.js.map +1 -0
- package/dist/api/device-api.d.ts +13 -0
- package/dist/api/device-api.d.ts.map +1 -0
- package/dist/api/device-api.js +98 -0
- package/dist/api/device-api.js.map +1 -0
- package/dist/api/task-api.d.ts +9 -0
- package/dist/api/task-api.d.ts.map +1 -0
- package/dist/api/task-api.js +47 -0
- package/dist/api/task-api.js.map +1 -0
- package/dist/config/cli.d.ts +30 -0
- package/dist/config/cli.d.ts.map +1 -0
- package/dist/config/cli.js +129 -0
- package/dist/config/cli.js.map +1 -0
- package/dist/config/index.d.ts +6 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +142 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/schema.d.ts +66 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +2 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/core/event-bus.d.ts +14 -0
- package/dist/core/event-bus.d.ts.map +1 -0
- package/dist/core/event-bus.js +33 -0
- package/dist/core/event-bus.js.map +1 -0
- package/dist/core/logger.d.ts +24 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +52 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/types.d.ts +134 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/debug/dump-manager.d.ts +10 -0
- package/dist/debug/dump-manager.d.ts.map +1 -0
- package/dist/debug/dump-manager.js +52 -0
- package/dist/debug/dump-manager.js.map +1 -0
- package/dist/debug/screencast.d.ts +11 -0
- package/dist/debug/screencast.d.ts.map +1 -0
- package/dist/debug/screencast.js +88 -0
- package/dist/debug/screencast.js.map +1 -0
- package/dist/debug/session-manager.d.ts +14 -0
- package/dist/debug/session-manager.d.ts.map +1 -0
- package/dist/debug/session-manager.js +76 -0
- package/dist/debug/session-manager.js.map +1 -0
- package/dist/debug/types.d.ts +76 -0
- package/dist/debug/types.d.ts.map +1 -0
- package/dist/debug/types.js +2 -0
- package/dist/debug/types.js.map +1 -0
- package/dist/debug/web-screencast.d.ts +60 -0
- package/dist/debug/web-screencast.d.ts.map +1 -0
- package/dist/debug/web-screencast.js +146 -0
- package/dist/debug/web-screencast.js.map +1 -0
- package/dist/debug/websocket-server.d.ts +27 -0
- package/dist/debug/websocket-server.d.ts.map +1 -0
- package/dist/debug/websocket-server.js +681 -0
- package/dist/debug/websocket-server.js.map +1 -0
- package/dist/device/detector.d.ts +10 -0
- package/dist/device/detector.d.ts.map +1 -0
- package/dist/device/detector.js +100 -0
- package/dist/device/detector.js.map +1 -0
- package/dist/device/heartbeat.d.ts +26 -0
- package/dist/device/heartbeat.d.ts.map +1 -0
- package/dist/device/heartbeat.js +225 -0
- package/dist/device/heartbeat.js.map +1 -0
- package/dist/device/status-manager.d.ts +15 -0
- package/dist/device/status-manager.d.ts.map +1 -0
- package/dist/device/status-manager.js +58 -0
- package/dist/device/status-manager.js.map +1 -0
- package/dist/device/types.d.ts +30 -0
- package/dist/device/types.d.ts.map +1 -0
- package/dist/device/types.js +2 -0
- package/dist/device/types.js.map +1 -0
- package/dist/executor/action-executor.d.ts +25 -0
- package/dist/executor/action-executor.d.ts.map +1 -0
- package/dist/executor/action-executor.js +261 -0
- package/dist/executor/action-executor.js.map +1 -0
- package/dist/executor/android-executor.d.ts +12 -0
- package/dist/executor/android-executor.d.ts.map +1 -0
- package/dist/executor/android-executor.js +127 -0
- package/dist/executor/android-executor.js.map +1 -0
- package/dist/executor/base.d.ts +20 -0
- package/dist/executor/base.d.ts.map +1 -0
- package/dist/executor/base.js +91 -0
- package/dist/executor/base.js.map +1 -0
- package/dist/executor/cli-executor.d.ts +12 -0
- package/dist/executor/cli-executor.d.ts.map +1 -0
- package/dist/executor/cli-executor.js +94 -0
- package/dist/executor/cli-executor.js.map +1 -0
- package/dist/executor/code-executor.d.ts +13 -0
- package/dist/executor/code-executor.d.ts.map +1 -0
- package/dist/executor/code-executor.js +52 -0
- package/dist/executor/code-executor.js.map +1 -0
- package/dist/executor/code-instrument.d.ts +12 -0
- package/dist/executor/code-instrument.d.ts.map +1 -0
- package/dist/executor/code-instrument.js +116 -0
- package/dist/executor/code-instrument.js.map +1 -0
- package/dist/executor/executor-factory.d.ts +7 -0
- package/dist/executor/executor-factory.d.ts.map +1 -0
- package/dist/executor/executor-factory.js +24 -0
- package/dist/executor/executor-factory.js.map +1 -0
- package/dist/executor/ios-executor.d.ts +10 -0
- package/dist/executor/ios-executor.d.ts.map +1 -0
- package/dist/executor/ios-executor.js +91 -0
- package/dist/executor/ios-executor.js.map +1 -0
- package/dist/executor/types.d.ts +14 -0
- package/dist/executor/types.d.ts.map +1 -0
- package/dist/executor/types.js +2 -0
- package/dist/executor/types.js.map +1 -0
- package/dist/executor/worker-entry.d.ts +2 -0
- package/dist/executor/worker-entry.d.ts.map +1 -0
- package/dist/executor/worker-entry.js +61 -0
- package/dist/executor/worker-entry.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +157 -0
- package/dist/index.js.map +1 -0
- package/dist/node/service.d.ts +21 -0
- package/dist/node/service.d.ts.map +1 -0
- package/dist/node/service.js +178 -0
- package/dist/node/service.js.map +1 -0
- package/dist/node/types.d.ts +45 -0
- package/dist/node/types.d.ts.map +1 -0
- package/dist/node/types.js +3 -0
- package/dist/node/types.js.map +1 -0
- package/dist/storage/database.d.ts +6 -0
- package/dist/storage/database.d.ts.map +1 -0
- package/dist/storage/database.js +154 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/repositories/debug-log-repo.d.ts +29 -0
- package/dist/storage/repositories/debug-log-repo.d.ts.map +1 -0
- package/dist/storage/repositories/debug-log-repo.js +90 -0
- package/dist/storage/repositories/debug-log-repo.js.map +1 -0
- package/dist/storage/repositories/device-repo.d.ts +12 -0
- package/dist/storage/repositories/device-repo.d.ts.map +1 -0
- package/dist/storage/repositories/device-repo.js +87 -0
- package/dist/storage/repositories/device-repo.js.map +1 -0
- package/dist/storage/repositories/execution-log-repo.d.ts +9 -0
- package/dist/storage/repositories/execution-log-repo.d.ts.map +1 -0
- package/dist/storage/repositories/execution-log-repo.js +49 -0
- package/dist/storage/repositories/execution-log-repo.js.map +1 -0
- package/dist/storage/repositories/task-repo.d.ts +13 -0
- package/dist/storage/repositories/task-repo.d.ts.map +1 -0
- package/dist/storage/repositories/task-repo.js +109 -0
- package/dist/storage/repositories/task-repo.js.map +1 -0
- package/dist/task/poller.d.ts +25 -0
- package/dist/task/poller.d.ts.map +1 -0
- package/dist/task/poller.js +153 -0
- package/dist/task/poller.js.map +1 -0
- package/dist/task/queue.d.ts +13 -0
- package/dist/task/queue.d.ts.map +1 -0
- package/dist/task/queue.js +38 -0
- package/dist/task/queue.js.map +1 -0
- package/dist/task/scheduler.d.ts +25 -0
- package/dist/task/scheduler.d.ts.map +1 -0
- package/dist/task/scheduler.js +274 -0
- package/dist/task/scheduler.js.map +1 -0
- package/dist/task/types.d.ts +31 -0
- package/dist/task/types.d.ts.map +1 -0
- package/dist/task/types.js +37 -0
- package/dist/task/types.js.map +1 -0
- package/dist/web/server.d.ts +14 -0
- package/dist/web/server.d.ts.map +1 -0
- package/dist/web/server.js +478 -0
- package/dist/web/server.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { getDatabase } from '../database.js';
|
|
2
|
+
function parseUTCDate(val) {
|
|
3
|
+
if (!val)
|
|
4
|
+
return undefined;
|
|
5
|
+
const s = String(val);
|
|
6
|
+
if (s.endsWith('Z') || /[+-]\d{2}:\d{2}$/.test(s))
|
|
7
|
+
return new Date(s);
|
|
8
|
+
return new Date(s + 'Z');
|
|
9
|
+
}
|
|
10
|
+
function mapSession(row) {
|
|
11
|
+
return {
|
|
12
|
+
id: row.id,
|
|
13
|
+
sessionId: (row.session_id ?? row.sessionId),
|
|
14
|
+
taskId: (row.task_id ?? row.taskId),
|
|
15
|
+
deviceId: (row.device_id ?? row.deviceId),
|
|
16
|
+
platform: (row.platform ?? undefined),
|
|
17
|
+
status: (row.status ?? 'idle'),
|
|
18
|
+
startedAt: parseUTCDate(row.started_at),
|
|
19
|
+
completedAt: parseUTCDate(row.completed_at),
|
|
20
|
+
createdAt: parseUTCDate(row.created_at),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function mapLog(row) {
|
|
24
|
+
return {
|
|
25
|
+
id: row.id,
|
|
26
|
+
sessionId: (row.session_id ?? row.sessionId),
|
|
27
|
+
type: (row.type ?? ''),
|
|
28
|
+
content: (row.content ?? ''),
|
|
29
|
+
createdAt: parseUTCDate(row.created_at),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export class DebugLogRepo {
|
|
33
|
+
createSession(session) {
|
|
34
|
+
const db = getDatabase();
|
|
35
|
+
db.prepare(`
|
|
36
|
+
INSERT INTO debug_sessions (session_id, task_id, device_id, platform, status, started_at)
|
|
37
|
+
VALUES (@sessionId, @taskId, @deviceId, @platform, @status, @startedAt)
|
|
38
|
+
`).run({
|
|
39
|
+
sessionId: session.sessionId,
|
|
40
|
+
taskId: session.taskId || null,
|
|
41
|
+
deviceId: session.deviceId || null,
|
|
42
|
+
platform: session.platform || null,
|
|
43
|
+
status: session.status,
|
|
44
|
+
startedAt: session.startedAt?.toISOString() || null,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
updateSessionStatus(sessionId, status) {
|
|
48
|
+
const db = getDatabase();
|
|
49
|
+
const updates = status === 'completed' || status === 'failed' || status === 'stopped'
|
|
50
|
+
? 'status = @status, completed_at = CURRENT_TIMESTAMP'
|
|
51
|
+
: 'status = @status';
|
|
52
|
+
db.prepare(`UPDATE debug_sessions SET ${updates} WHERE session_id = @sessionId`).run({
|
|
53
|
+
sessionId,
|
|
54
|
+
status,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
getSession(sessionId) {
|
|
58
|
+
const db = getDatabase();
|
|
59
|
+
const row = db.prepare('SELECT * FROM debug_sessions WHERE session_id = ?').get(sessionId);
|
|
60
|
+
return row ? mapSession(row) : undefined;
|
|
61
|
+
}
|
|
62
|
+
getAllSessions(limit = 100) {
|
|
63
|
+
const db = getDatabase();
|
|
64
|
+
const rows = db.prepare('SELECT * FROM debug_sessions ORDER BY created_at DESC LIMIT ?').all(limit);
|
|
65
|
+
return rows.map(r => mapSession(r));
|
|
66
|
+
}
|
|
67
|
+
addLog(entry) {
|
|
68
|
+
const db = getDatabase();
|
|
69
|
+
db.prepare(`
|
|
70
|
+
INSERT INTO debug_logs (session_id, type, content)
|
|
71
|
+
VALUES (@sessionId, @type, @content)
|
|
72
|
+
`).run({
|
|
73
|
+
sessionId: entry.sessionId,
|
|
74
|
+
type: entry.type,
|
|
75
|
+
content: entry.content,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
getLogsBySession(sessionId, limit = 1000) {
|
|
79
|
+
const db = getDatabase();
|
|
80
|
+
const rows = db.prepare('SELECT * FROM debug_logs WHERE session_id = ? ORDER BY created_at ASC LIMIT ?').all(sessionId, limit);
|
|
81
|
+
return rows.map(r => mapLog(r));
|
|
82
|
+
}
|
|
83
|
+
deleteSession(sessionId) {
|
|
84
|
+
const db = getDatabase();
|
|
85
|
+
db.prepare('DELETE FROM debug_logs WHERE session_id = ?').run(sessionId);
|
|
86
|
+
db.prepare('DELETE FROM debug_sessions WHERE session_id = ?').run(sessionId);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export const debugLogRepo = new DebugLogRepo();
|
|
90
|
+
//# sourceMappingURL=debug-log-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-log-repo.js","sourceRoot":"","sources":["../../../src/storage/repositories/debug-log-repo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Device } from '../../core/types.js';
|
|
2
|
+
export declare class DeviceRepo {
|
|
3
|
+
upsert(device: Omit<Device, 'id' | 'createdAt' | 'updatedAt'>): Device;
|
|
4
|
+
getBySerial(serialNumber: string): Device | undefined;
|
|
5
|
+
updateStatus(serialNumber: string, status: 'online' | 'offline'): void;
|
|
6
|
+
updateHeartbeat(serialNumber: string): void;
|
|
7
|
+
getAll(): Device[];
|
|
8
|
+
getOnline(): Device[];
|
|
9
|
+
delete(serialNumber: string): void;
|
|
10
|
+
}
|
|
11
|
+
export declare const deviceRepo: DeviceRepo;
|
|
12
|
+
//# sourceMappingURL=device-repo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-repo.d.ts","sourceRoot":"","sources":["../../../src/storage/repositories/device-repo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA6BlD,qBAAa,UAAU;IACrB,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC,GAAG,MAAM;IAuBtE,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAMrD,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,IAAI;IAQtE,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAQ3C,MAAM,IAAI,MAAM,EAAE;IAMlB,SAAS,IAAI,MAAM,EAAE;IAMrB,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;CAInC;AAED,eAAO,MAAM,UAAU,YAAmB,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { getDatabase } from '../database.js';
|
|
2
|
+
// SQLite CURRENT_TIMESTAMP is UTC but lacks timezone suffix (e.g. "2026-05-07 03:05:12").
|
|
3
|
+
// new Date() treats such strings as local time, causing an 8h offset in UTC+8.
|
|
4
|
+
// Append 'Z' so JS parses it as UTC.
|
|
5
|
+
function parseUTCDate(val) {
|
|
6
|
+
if (!val)
|
|
7
|
+
return undefined;
|
|
8
|
+
const s = String(val);
|
|
9
|
+
// Already has timezone info (ISO with Z or offset)
|
|
10
|
+
if (s.endsWith('Z') || /[+-]\d{2}:\d{2}$/.test(s))
|
|
11
|
+
return new Date(s);
|
|
12
|
+
// SQLite format: "2026-05-07 03:05:12" or "2026-05-07T03:05:12"
|
|
13
|
+
return new Date(s + 'Z');
|
|
14
|
+
}
|
|
15
|
+
// Map DB snake_case row to camelCase Device
|
|
16
|
+
function mapRow(row) {
|
|
17
|
+
return {
|
|
18
|
+
id: row.id,
|
|
19
|
+
serialNumber: (row.serial_number ?? row.serialNumber),
|
|
20
|
+
model: (row.model ?? null),
|
|
21
|
+
brand: (row.brand ?? null),
|
|
22
|
+
platform: (row.platform ?? 'android'),
|
|
23
|
+
status: (row.status ?? 'offline'),
|
|
24
|
+
lastHeartbeatAt: parseUTCDate(row.last_heartbeat_at),
|
|
25
|
+
createdAt: parseUTCDate(row.created_at),
|
|
26
|
+
updatedAt: parseUTCDate(row.updated_at),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export class DeviceRepo {
|
|
30
|
+
upsert(device) {
|
|
31
|
+
const db = getDatabase();
|
|
32
|
+
const stmt = db.prepare(`
|
|
33
|
+
INSERT INTO devices (serial_number, model, brand, platform, status, last_heartbeat_at)
|
|
34
|
+
VALUES (@serialNumber, @model, @brand, @platform, @status, @lastHeartbeatAt)
|
|
35
|
+
ON CONFLICT(serial_number) DO UPDATE SET
|
|
36
|
+
model = @model,
|
|
37
|
+
brand = @brand,
|
|
38
|
+
status = @status,
|
|
39
|
+
last_heartbeat_at = @lastHeartbeatAt,
|
|
40
|
+
updated_at = CURRENT_TIMESTAMP
|
|
41
|
+
`);
|
|
42
|
+
stmt.run({
|
|
43
|
+
serialNumber: device.serialNumber,
|
|
44
|
+
model: device.model || null,
|
|
45
|
+
brand: device.brand || null,
|
|
46
|
+
platform: device.platform,
|
|
47
|
+
status: device.status,
|
|
48
|
+
lastHeartbeatAt: device.lastHeartbeatAt?.toISOString() || null,
|
|
49
|
+
});
|
|
50
|
+
return this.getBySerial(device.serialNumber);
|
|
51
|
+
}
|
|
52
|
+
getBySerial(serialNumber) {
|
|
53
|
+
const db = getDatabase();
|
|
54
|
+
const row = db.prepare('SELECT * FROM devices WHERE serial_number = ?').get(serialNumber);
|
|
55
|
+
return row ? mapRow(row) : undefined;
|
|
56
|
+
}
|
|
57
|
+
updateStatus(serialNumber, status) {
|
|
58
|
+
const db = getDatabase();
|
|
59
|
+
db.prepare(`
|
|
60
|
+
UPDATE devices SET status = ?, updated_at = CURRENT_TIMESTAMP
|
|
61
|
+
WHERE serial_number = ?
|
|
62
|
+
`).run(status, serialNumber);
|
|
63
|
+
}
|
|
64
|
+
updateHeartbeat(serialNumber) {
|
|
65
|
+
const db = getDatabase();
|
|
66
|
+
db.prepare(`
|
|
67
|
+
UPDATE devices SET last_heartbeat_at = CURRENT_TIMESTAMP, status = 'online', updated_at = CURRENT_TIMESTAMP
|
|
68
|
+
WHERE serial_number = ?
|
|
69
|
+
`).run(serialNumber);
|
|
70
|
+
}
|
|
71
|
+
getAll() {
|
|
72
|
+
const db = getDatabase();
|
|
73
|
+
const rows = db.prepare('SELECT * FROM devices ORDER BY updated_at DESC').all();
|
|
74
|
+
return rows.map(r => mapRow(r));
|
|
75
|
+
}
|
|
76
|
+
getOnline() {
|
|
77
|
+
const db = getDatabase();
|
|
78
|
+
const rows = db.prepare("SELECT * FROM devices WHERE status = 'online'").all();
|
|
79
|
+
return rows.map(r => mapRow(r));
|
|
80
|
+
}
|
|
81
|
+
delete(serialNumber) {
|
|
82
|
+
const db = getDatabase();
|
|
83
|
+
db.prepare('DELETE FROM devices WHERE serial_number = ?').run(serialNumber);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export const deviceRepo = new DeviceRepo();
|
|
87
|
+
//# sourceMappingURL=device-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-repo.js","sourceRoot":"","sources":["../../../src/storage/repositories/device-repo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LogEntry } from '../../core/types.js';
|
|
2
|
+
export declare class ExecutionLogRepo {
|
|
3
|
+
create(entry: Omit<LogEntry, 'id' | 'createdAt'>): void;
|
|
4
|
+
getByTaskId(taskId: string, limit?: number): LogEntry[];
|
|
5
|
+
getBySessionId(sessionId: string, limit?: number): LogEntry[];
|
|
6
|
+
deleteByTaskId(taskId: string): void;
|
|
7
|
+
}
|
|
8
|
+
export declare const executionLogRepo: ExecutionLogRepo;
|
|
9
|
+
//# sourceMappingURL=execution-log-repo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-log-repo.d.ts","sourceRoot":"","sources":["../../../src/storage/repositories/execution-log-repo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAoBpD,qBAAa,gBAAgB;IAC3B,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,WAAW,CAAC,GAAG,IAAI;IAavD,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAa,GAAG,QAAQ,EAAE;IAQ7D,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,GAAE,MAAa,GAAG,QAAQ,EAAE;IAQnE,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;CAIrC;AAED,eAAO,MAAM,gBAAgB,kBAAyB,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { getDatabase } from '../database.js';
|
|
2
|
+
function parseUTCDate(val) {
|
|
3
|
+
if (!val)
|
|
4
|
+
return undefined;
|
|
5
|
+
const s = String(val);
|
|
6
|
+
if (s.endsWith('Z') || /[+-]\d{2}:\d{2}$/.test(s))
|
|
7
|
+
return new Date(s);
|
|
8
|
+
return new Date(s + 'Z');
|
|
9
|
+
}
|
|
10
|
+
function mapRow(row) {
|
|
11
|
+
return {
|
|
12
|
+
id: row.id,
|
|
13
|
+
taskId: (row.task_id ?? row.taskId),
|
|
14
|
+
sessionId: (row.session_id ?? row.sessionId),
|
|
15
|
+
level: (row.level ?? 'info'),
|
|
16
|
+
content: (row.content ?? ''),
|
|
17
|
+
createdAt: parseUTCDate(row.created_at),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export class ExecutionLogRepo {
|
|
21
|
+
create(entry) {
|
|
22
|
+
const db = getDatabase();
|
|
23
|
+
db.prepare(`
|
|
24
|
+
INSERT INTO execution_logs (task_id, session_id, level, content)
|
|
25
|
+
VALUES (@taskId, @sessionId, @level, @content)
|
|
26
|
+
`).run({
|
|
27
|
+
taskId: entry.taskId || null,
|
|
28
|
+
sessionId: entry.sessionId || null,
|
|
29
|
+
level: entry.level,
|
|
30
|
+
content: entry.content,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
getByTaskId(taskId, limit = 1000) {
|
|
34
|
+
const db = getDatabase();
|
|
35
|
+
const rows = db.prepare('SELECT * FROM execution_logs WHERE task_id = ? ORDER BY created_at ASC LIMIT ?').all(taskId, limit);
|
|
36
|
+
return rows.map(r => mapRow(r));
|
|
37
|
+
}
|
|
38
|
+
getBySessionId(sessionId, limit = 1000) {
|
|
39
|
+
const db = getDatabase();
|
|
40
|
+
const rows = db.prepare('SELECT * FROM execution_logs WHERE session_id = ? ORDER BY created_at ASC LIMIT ?').all(sessionId, limit);
|
|
41
|
+
return rows.map(r => mapRow(r));
|
|
42
|
+
}
|
|
43
|
+
deleteByTaskId(taskId) {
|
|
44
|
+
const db = getDatabase();
|
|
45
|
+
db.prepare('DELETE FROM execution_logs WHERE task_id = ?').run(taskId);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export const executionLogRepo = new ExecutionLogRepo();
|
|
49
|
+
//# sourceMappingURL=execution-log-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-log-repo.js","sourceRoot":"","sources":["../../../src/storage/repositories/execution-log-repo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,SAAS,YAAY,CAAC,GAAY;IAChC,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;IACtE,OAAO,IAAI,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,MAAM,CAAC,GAA4B;IAC1C,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAY;QACpB,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,MAAM,CAAuB;QACzD,SAAS,EAAE,CAAC,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,SAAS,CAAuB;QAClE,KAAK,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,MAAM,CAAsB;QACjD,OAAO,EAAE,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAW;QACtC,SAAS,EAAE,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC;KACxC,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,gBAAgB;IAC3B,MAAM,CAAC,KAAyC;QAC9C,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;QACzB,EAAE,CAAC,OAAO,CAAC;;;KAGV,CAAC,CAAC,GAAG,CAAC;YACL,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;YAC5B,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI;YAClC,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC;IACL,CAAC;IAED,WAAW,CAAC,MAAc,EAAE,QAAgB,IAAI;QAC9C,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CACrB,gFAAgF,CACjF,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAA4B,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,cAAc,CAAC,SAAiB,EAAE,QAAgB,IAAI;QACpD,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CACrB,mFAAmF,CACpF,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAA4B,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,cAAc,CAAC,MAAc;QAC3B,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;QACzB,EAAE,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACzE,CAAC;CACF;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Task, TaskStatus } from '../../core/types.js';
|
|
2
|
+
export declare class TaskRepo {
|
|
3
|
+
create(task: Omit<Task, 'id' | 'createdAt' | 'updatedAt'>): Task;
|
|
4
|
+
updateStatus(taskId: string, status: TaskStatus, errorMessage?: string, result?: string): void;
|
|
5
|
+
getById(taskId: string): Task | undefined;
|
|
6
|
+
getByStatus(status: TaskStatus): Task[];
|
|
7
|
+
getRunningTasks(): Task[];
|
|
8
|
+
getAll(limit?: number, offset?: number): Task[];
|
|
9
|
+
count(): number;
|
|
10
|
+
delete(taskId: string): void;
|
|
11
|
+
}
|
|
12
|
+
export declare const taskRepo: TaskRepo;
|
|
13
|
+
//# sourceMappingURL=task-repo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-repo.d.ts","sourceRoot":"","sources":["../../../src/storage/repositories/task-repo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAqC5D,qBAAa,QAAQ;IACnB,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC,GAAG,IAAI;IAqBhE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAuB9F,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAMzC,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE;IAMvC,eAAe,IAAI,IAAI,EAAE;IAMzB,MAAM,CAAC,KAAK,GAAE,MAAY,EAAE,MAAM,GAAE,MAAU,GAAG,IAAI,EAAE;IAMvD,KAAK,IAAI,MAAM;IAMf,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;CAI7B;AAED,eAAO,MAAM,QAAQ,UAAiB,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { getDatabase } from '../database.js';
|
|
2
|
+
function parseUTCDate(val) {
|
|
3
|
+
if (!val)
|
|
4
|
+
return undefined;
|
|
5
|
+
const s = String(val);
|
|
6
|
+
if (s.endsWith('Z') || /[+-]\d{2}:\d{2}$/.test(s))
|
|
7
|
+
return new Date(s);
|
|
8
|
+
return new Date(s + 'Z');
|
|
9
|
+
}
|
|
10
|
+
function mapRow(row) {
|
|
11
|
+
let device = undefined;
|
|
12
|
+
const deviceStr = (row.allocated_device ?? null);
|
|
13
|
+
if (deviceStr) {
|
|
14
|
+
try {
|
|
15
|
+
device = JSON.parse(deviceStr);
|
|
16
|
+
}
|
|
17
|
+
catch { /* ignore */ }
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
id: row.id,
|
|
21
|
+
taskId: (row.task_id ?? row.taskId),
|
|
22
|
+
executionId: (row.execution_id ?? row.executionId),
|
|
23
|
+
type: (row.type ?? 'android'),
|
|
24
|
+
status: (row.status ?? 'pending'),
|
|
25
|
+
priority: (row.priority ?? 0),
|
|
26
|
+
config: (row.config ?? null),
|
|
27
|
+
result: (row.result ?? null),
|
|
28
|
+
errorMessage: (row.error_message ?? row.errorMessage ?? null),
|
|
29
|
+
reportFilePath: (row.report_file_path ?? row.reportFilePath ?? null),
|
|
30
|
+
device,
|
|
31
|
+
startedAt: parseUTCDate(row.started_at),
|
|
32
|
+
completedAt: parseUTCDate(row.completed_at),
|
|
33
|
+
createdAt: parseUTCDate(row.created_at),
|
|
34
|
+
updatedAt: parseUTCDate(row.updated_at),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export class TaskRepo {
|
|
38
|
+
create(task) {
|
|
39
|
+
const db = getDatabase();
|
|
40
|
+
const stmt = db.prepare(`
|
|
41
|
+
INSERT INTO tasks (task_id, execution_id, type, status, priority, config, error_message, report_file_path, allocated_device, started_at)
|
|
42
|
+
VALUES (@taskId, @executionId, @type, @status, @priority, @config, @errorMessage, @reportFilePath, @allocatedDevice, @startedAt)
|
|
43
|
+
`);
|
|
44
|
+
const result = stmt.run({
|
|
45
|
+
taskId: task.taskId,
|
|
46
|
+
executionId: task.executionId || null,
|
|
47
|
+
type: task.type,
|
|
48
|
+
status: task.status,
|
|
49
|
+
priority: task.priority || 0,
|
|
50
|
+
config: task.config || null,
|
|
51
|
+
errorMessage: task.errorMessage || null,
|
|
52
|
+
reportFilePath: task.reportFilePath || null,
|
|
53
|
+
allocatedDevice: task.device ? JSON.stringify(task.device) : null,
|
|
54
|
+
startedAt: task.startedAt?.toISOString() || null,
|
|
55
|
+
});
|
|
56
|
+
return { ...task, id: result.lastInsertRowid };
|
|
57
|
+
}
|
|
58
|
+
updateStatus(taskId, status, errorMessage, result) {
|
|
59
|
+
const db = getDatabase();
|
|
60
|
+
const updates = ['status = @status', 'updated_at = CURRENT_TIMESTAMP'];
|
|
61
|
+
const params = { taskId, status };
|
|
62
|
+
if (errorMessage !== undefined) {
|
|
63
|
+
updates.push('error_message = @errorMessage');
|
|
64
|
+
params.errorMessage = errorMessage;
|
|
65
|
+
}
|
|
66
|
+
if (result !== undefined) {
|
|
67
|
+
updates.push('result = @result');
|
|
68
|
+
params.result = result;
|
|
69
|
+
}
|
|
70
|
+
if (status === 'completed' || status === 'failed' || status === 'stopped') {
|
|
71
|
+
updates.push('completed_at = CURRENT_TIMESTAMP');
|
|
72
|
+
}
|
|
73
|
+
if (status === 'running') {
|
|
74
|
+
updates.push('started_at = CURRENT_TIMESTAMP');
|
|
75
|
+
}
|
|
76
|
+
db.prepare(`UPDATE tasks SET ${updates.join(', ')} WHERE task_id = @taskId`).run(params);
|
|
77
|
+
}
|
|
78
|
+
getById(taskId) {
|
|
79
|
+
const db = getDatabase();
|
|
80
|
+
const row = db.prepare('SELECT * FROM tasks WHERE task_id = ?').get(taskId);
|
|
81
|
+
return row ? mapRow(row) : undefined;
|
|
82
|
+
}
|
|
83
|
+
getByStatus(status) {
|
|
84
|
+
const db = getDatabase();
|
|
85
|
+
const rows = db.prepare('SELECT * FROM tasks WHERE status = ? ORDER BY priority DESC, created_at ASC').all(status);
|
|
86
|
+
return rows.map(r => mapRow(r));
|
|
87
|
+
}
|
|
88
|
+
getRunningTasks() {
|
|
89
|
+
const db = getDatabase();
|
|
90
|
+
const rows = db.prepare("SELECT * FROM tasks WHERE status = 'running'").all();
|
|
91
|
+
return rows.map(r => mapRow(r));
|
|
92
|
+
}
|
|
93
|
+
getAll(limit = 100, offset = 0) {
|
|
94
|
+
const db = getDatabase();
|
|
95
|
+
const rows = db.prepare('SELECT * FROM tasks ORDER BY created_at DESC LIMIT ? OFFSET ?').all(limit, offset);
|
|
96
|
+
return rows.map(r => mapRow(r));
|
|
97
|
+
}
|
|
98
|
+
count() {
|
|
99
|
+
const db = getDatabase();
|
|
100
|
+
const row = db.prepare('SELECT COUNT(*) as count FROM tasks').get();
|
|
101
|
+
return row.count;
|
|
102
|
+
}
|
|
103
|
+
delete(taskId) {
|
|
104
|
+
const db = getDatabase();
|
|
105
|
+
db.prepare('DELETE FROM tasks WHERE task_id = ?').run(taskId);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export const taskRepo = new TaskRepo();
|
|
109
|
+
//# sourceMappingURL=task-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-repo.js","sourceRoot":"","sources":["../../../src/storage/repositories/task-repo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TaskConfig, CallbackConfig } from '../config/schema.js';
|
|
2
|
+
import type { Task } from '../core/types.js';
|
|
3
|
+
export declare class TaskPollerService {
|
|
4
|
+
private interval;
|
|
5
|
+
private queue;
|
|
6
|
+
private scheduler;
|
|
7
|
+
private config;
|
|
8
|
+
private running;
|
|
9
|
+
private consecutiveFailures;
|
|
10
|
+
private taskRetryCount;
|
|
11
|
+
start(config: TaskConfig, callbackConfig: CallbackConfig): Promise<void>;
|
|
12
|
+
private poll;
|
|
13
|
+
/**
|
|
14
|
+
* Fetch next task from server using POST /rest/execution-queue/tasks/next
|
|
15
|
+
* Consistent with reference project (electron-shadcn)
|
|
16
|
+
* Returns a single task with allocated device information
|
|
17
|
+
*/
|
|
18
|
+
private fetchNextTask;
|
|
19
|
+
private scheduleNext;
|
|
20
|
+
getQueue(): Task[];
|
|
21
|
+
getSchedulerStats(): import("./types.js").SchedulerStats;
|
|
22
|
+
stop(): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
export declare const taskPollerService: TaskPollerService;
|
|
25
|
+
//# sourceMappingURL=poller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poller.d.ts","sourceRoot":"","sources":["../../src/task/poller.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGtE,OAAO,KAAK,EAAE,IAAI,EAAmB,MAAM,kBAAkB,CAAC;AAM9D,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,SAAS,CAAsC;IACvD,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,mBAAmB,CAAa;IACxC,OAAO,CAAC,cAAc,CAAkC;IAElD,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;YAmBhE,IAAI;IAkDlB;;;;OAIG;YACW,aAAa;IAoD3B,OAAO,CAAC,YAAY;IASpB,QAAQ,IAAI,IAAI,EAAE;IAIlB,iBAAiB;IAIX,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAU5B;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { createLogger } from '../core/logger.js';
|
|
3
|
+
import { taskRepo } from '../storage/repositories/task-repo.js';
|
|
4
|
+
import { TaskQueue } from './queue.js';
|
|
5
|
+
import { TaskScheduler } from './scheduler.js';
|
|
6
|
+
import { nextTaskResponseToTask } from './types.js';
|
|
7
|
+
const logger = createLogger('TaskPoller');
|
|
8
|
+
const MAX_RETRY_COUNT = 3;
|
|
9
|
+
export class TaskPollerService {
|
|
10
|
+
interval = null;
|
|
11
|
+
queue = new TaskQueue();
|
|
12
|
+
scheduler = new TaskScheduler();
|
|
13
|
+
config;
|
|
14
|
+
running = false;
|
|
15
|
+
consecutiveFailures = 0;
|
|
16
|
+
taskRetryCount = new Map();
|
|
17
|
+
async start(config, callbackConfig) {
|
|
18
|
+
this.config = config;
|
|
19
|
+
this.running = true;
|
|
20
|
+
// Start the scheduler
|
|
21
|
+
await this.scheduler.start(config, callbackConfig);
|
|
22
|
+
// Start polling
|
|
23
|
+
this.interval = setInterval(async () => {
|
|
24
|
+
if (!this.running)
|
|
25
|
+
return;
|
|
26
|
+
await this.poll();
|
|
27
|
+
}, config.pollInterval);
|
|
28
|
+
logger.info(`Task poller started (interval: ${config.pollInterval}ms, nodeId: ${config.nodeId})`);
|
|
29
|
+
// Do an initial poll immediately
|
|
30
|
+
await this.poll();
|
|
31
|
+
}
|
|
32
|
+
async poll() {
|
|
33
|
+
try {
|
|
34
|
+
const result = await this.fetchNextTask();
|
|
35
|
+
if (!result || !result.task)
|
|
36
|
+
return;
|
|
37
|
+
logger.info(`Polled task: ${result.task.taskId}, device: ${result.device?.deviceId || 'none'}`);
|
|
38
|
+
const taskDef = nextTaskResponseToTask(result.task, result.device);
|
|
39
|
+
// Check if task already exists
|
|
40
|
+
const existing = taskRepo.getById(taskDef.taskId);
|
|
41
|
+
if (existing) {
|
|
42
|
+
if (existing.status === 'running') {
|
|
43
|
+
logger.info(`Task ${taskDef.taskId} is already running, skipping`);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (existing.status === 'completed') {
|
|
47
|
+
logger.info(`Task ${taskDef.taskId} already completed, skipping (server status may be delayed)`);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (existing.status === 'failed') {
|
|
51
|
+
const retryCount = this.taskRetryCount.get(taskDef.taskId) || 0;
|
|
52
|
+
if (retryCount >= MAX_RETRY_COUNT) {
|
|
53
|
+
logger.warn(`Task ${taskDef.taskId} already failed ${retryCount} times, not re-executing`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this.taskRetryCount.set(taskDef.taskId, retryCount + 1);
|
|
57
|
+
logger.info(`Task ${taskDef.taskId} failed (retry ${retryCount + 1}/${MAX_RETRY_COUNT}), re-executing`);
|
|
58
|
+
taskRepo.updateStatus(taskDef.taskId, 'pending');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Save to database (create only if not existing)
|
|
62
|
+
const task = existing
|
|
63
|
+
? { ...existing, status: 'pending', config: taskDef.config, priority: taskDef.priority, device: taskDef.device }
|
|
64
|
+
: taskRepo.create(taskDef);
|
|
65
|
+
logger.info(`Task ${task.taskId} ready for scheduling, type=${task.type}, config=${task.config?.substring(0, 200)}`);
|
|
66
|
+
// Enqueue for scheduling
|
|
67
|
+
this.queue.enqueue(task);
|
|
68
|
+
logger.info(`Task ${task.taskId} enqueued, queue size: ${this.queue.getAll().length}`);
|
|
69
|
+
// Try to schedule
|
|
70
|
+
this.scheduleNext();
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
logger.error(`Task poll error: ${error.message}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Fetch next task from server using POST /rest/execution-queue/tasks/next
|
|
78
|
+
* Consistent with reference project (electron-shadcn)
|
|
79
|
+
* Returns a single task with allocated device information
|
|
80
|
+
*/
|
|
81
|
+
async fetchNextTask() {
|
|
82
|
+
try {
|
|
83
|
+
const url = `${this.config.apiUrl}/rest/execution-queue/tasks/next`;
|
|
84
|
+
logger.info(`Fetching next task: POST ${url}?nodeId=${this.config.nodeId}`);
|
|
85
|
+
const response = await axios.post(url, null, {
|
|
86
|
+
params: {
|
|
87
|
+
nodeId: this.config.nodeId,
|
|
88
|
+
},
|
|
89
|
+
timeout: 10000,
|
|
90
|
+
});
|
|
91
|
+
logger.info(`Fetch next task response: HTTP ${response.status}, data: ${JSON.stringify(response.data)?.substring(0, 500)}`);
|
|
92
|
+
if (response.status === 200 && response.data) {
|
|
93
|
+
this.consecutiveFailures = 0;
|
|
94
|
+
// Parse response structure:
|
|
95
|
+
// { data: { task: {...}, allocatedDevice: {...} } }
|
|
96
|
+
// or { task: {...}, allocatedDevice: {...} }
|
|
97
|
+
const d = response.data;
|
|
98
|
+
const data = d.data && typeof d.data === 'object' ? d.data : d;
|
|
99
|
+
const task = (data.task || d.task);
|
|
100
|
+
const device = (data.allocatedDevice ||
|
|
101
|
+
data.availableMobileDevice ||
|
|
102
|
+
data.availableMobileDevices?.[0] ||
|
|
103
|
+
d.allocatedDevice ||
|
|
104
|
+
d.availableMobileDevice);
|
|
105
|
+
if (task) {
|
|
106
|
+
logger.info(`Fetched task: ${task.taskId}, device: ${device?.deviceId || 'none'}`);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
logger.info(`No pending tasks found (rawData keys: ${Object.keys(d).join(',')})`);
|
|
110
|
+
}
|
|
111
|
+
return { task, device };
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
this.consecutiveFailures++;
|
|
117
|
+
const axiosErr = error;
|
|
118
|
+
if (axiosErr.response) {
|
|
119
|
+
logger.warn(`Failed to fetch next task (#${this.consecutiveFailures}): HTTP ${axiosErr.response.status} - ${JSON.stringify(axiosErr.response.data)}`);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
logger.warn(`Failed to fetch next task (#${this.consecutiveFailures}): ${axiosErr.message || error.message}`);
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
scheduleNext() {
|
|
128
|
+
while (!this.queue.isEmpty() && this.scheduler.canAcceptMore()) {
|
|
129
|
+
const task = this.queue.dequeue();
|
|
130
|
+
if (task) {
|
|
131
|
+
this.scheduler.schedule(task);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
getQueue() {
|
|
136
|
+
return this.queue.getAll();
|
|
137
|
+
}
|
|
138
|
+
getSchedulerStats() {
|
|
139
|
+
return this.scheduler.getStats();
|
|
140
|
+
}
|
|
141
|
+
async stop() {
|
|
142
|
+
this.running = false;
|
|
143
|
+
if (this.interval) {
|
|
144
|
+
clearInterval(this.interval);
|
|
145
|
+
this.interval = null;
|
|
146
|
+
}
|
|
147
|
+
await this.scheduler.stop();
|
|
148
|
+
this.queue.clear();
|
|
149
|
+
logger.info('Task poller stopped');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
export const taskPollerService = new TaskPollerService();
|
|
153
|
+
//# sourceMappingURL=poller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poller.js","sourceRoot":"","sources":["../../src/task/poller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Task } from '../core/types.js';
|
|
2
|
+
export declare class TaskQueue {
|
|
3
|
+
private queue;
|
|
4
|
+
enqueue(task: Task): void;
|
|
5
|
+
dequeue(): Task | undefined;
|
|
6
|
+
peek(): Task | undefined;
|
|
7
|
+
remove(taskId: string): void;
|
|
8
|
+
size(): number;
|
|
9
|
+
isEmpty(): boolean;
|
|
10
|
+
getAll(): Task[];
|
|
11
|
+
clear(): void;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/task/queue.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAI7C,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAAc;IAE3B,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAYzB,OAAO,IAAI,IAAI,GAAG,SAAS;IAI3B,IAAI,IAAI,IAAI,GAAG,SAAS;IAIxB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI5B,IAAI,IAAI,MAAM;IAId,OAAO,IAAI,OAAO;IAIlB,MAAM,IAAI,IAAI,EAAE;IAIhB,KAAK,IAAI,IAAI;CAGd"}
|