@softtynet/zplus-worker 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.
Files changed (36) hide show
  1. package/README.md +136 -0
  2. package/dist/automation/HeadlessAutomationEngine.d.ts +12 -0
  3. package/dist/automation/HeadlessAutomationEngine.js +34 -0
  4. package/dist/channels/ChannelRunnerRegistry.d.ts +14 -0
  5. package/dist/channels/ChannelRunnerRegistry.js +65 -0
  6. package/dist/channels/IChannelRunner.d.ts +10 -0
  7. package/dist/channels/IChannelRunner.js +2 -0
  8. package/dist/channels/index.d.ts +6 -0
  9. package/dist/channels/index.js +22 -0
  10. package/dist/channels/runners/FacebookChannelRunner.d.ts +19 -0
  11. package/dist/channels/runners/FacebookChannelRunner.js +47 -0
  12. package/dist/channels/runners/TelegramChannelRunner.d.ts +19 -0
  13. package/dist/channels/runners/TelegramChannelRunner.js +47 -0
  14. package/dist/channels/runners/WhatsAppChannelRunner.d.ts +19 -0
  15. package/dist/channels/runners/WhatsAppChannelRunner.js +47 -0
  16. package/dist/channels/runners/ZaloChannelRunner.d.ts +22 -0
  17. package/dist/channels/runners/ZaloChannelRunner.js +50 -0
  18. package/dist/cli.d.ts +6 -0
  19. package/dist/cli.js +1409 -0
  20. package/dist/config/WorkerConfig.d.ts +16 -0
  21. package/dist/config/WorkerConfig.js +21 -0
  22. package/dist/engine/WorkerEngine.d.ts +38 -0
  23. package/dist/engine/WorkerEngine.js +157 -0
  24. package/dist/index.d.ts +9 -0
  25. package/dist/index.js +25 -0
  26. package/dist/lock/DistributedLockManager.d.ts +40 -0
  27. package/dist/lock/DistributedLockManager.js +113 -0
  28. package/dist/notifications/PushNotificationDispatcher.d.ts +14 -0
  29. package/dist/notifications/PushNotificationDispatcher.js +31 -0
  30. package/dist/server/WorkerHttpServer.d.ts +25 -0
  31. package/dist/server/WorkerHttpServer.js +205 -0
  32. package/dist/sync/CloudPendingMessageQueue.d.ts +27 -0
  33. package/dist/sync/CloudPendingMessageQueue.js +69 -0
  34. package/dist/sync/CloudSyncWorker.d.ts +19 -0
  35. package/dist/sync/CloudSyncWorker.js +53 -0
  36. package/package.json +32 -0
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 🏛️ Worker Configuration Loader
3
+ */
4
+ export interface WorkerEnvironmentConfig {
5
+ workerId: string;
6
+ port: number;
7
+ appwriteEndpoint?: string;
8
+ appwriteProjectId?: string;
9
+ appwriteApiKey?: string;
10
+ databaseId?: string;
11
+ heartbeatIntervalMs: number;
12
+ logLevel: "debug" | "info" | "warn" | "error";
13
+ }
14
+ export declare class WorkerConfig {
15
+ static loadFromEnv(): WorkerEnvironmentConfig;
16
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ /**
3
+ * 🏛️ Worker Configuration Loader
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WorkerConfig = void 0;
7
+ class WorkerConfig {
8
+ static loadFromEnv() {
9
+ return {
10
+ workerId: process.env.WORKER_ID || `worker_${process.pid}`,
11
+ port: Number(process.env.PORT || 8080),
12
+ appwriteEndpoint: process.env.APPWRITE_ENDPOINT,
13
+ appwriteProjectId: process.env.APPWRITE_PROJECT_ID,
14
+ appwriteApiKey: process.env.APPWRITE_API_KEY,
15
+ databaseId: process.env.APPWRITE_DATABASE_ID || "zplus_app",
16
+ heartbeatIntervalMs: Number(process.env.HEARTBEAT_INTERVAL_MS || 30000),
17
+ logLevel: process.env.LOG_LEVEL || "info",
18
+ };
19
+ }
20
+ }
21
+ exports.WorkerConfig = WorkerConfig;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * 🏛️ ZPlus Headless Worker Engine
3
+ * Quản lý vòng đời chạy ngầm 24/7 (WSS listeners, HTTP Ingress, Distributed Lock, Delta Sync, AI automation, Heartbeats)
4
+ */
5
+ import { WorkerMetrics, ChannelAccount, UnifiedMessage } from "@zplus/contracts";
6
+ import { WorkerEnvironmentConfig } from "../config/WorkerConfig";
7
+ import { ChannelRunnerRegistry } from "../channels/ChannelRunnerRegistry";
8
+ import { DistributedLockManager } from "../lock/DistributedLockManager";
9
+ import { CloudPendingMessageQueue } from "../sync/CloudPendingMessageQueue";
10
+ import { HeadlessAutomationEngine } from "../automation/HeadlessAutomationEngine";
11
+ import { PushNotificationDispatcher } from "../notifications/PushNotificationDispatcher";
12
+ import { WorkerHttpServer } from "../server/WorkerHttpServer";
13
+ import { IChannelRunner } from "../channels/IChannelRunner";
14
+ export declare class WorkerEngine {
15
+ private config;
16
+ private logger;
17
+ readonly channelRunnerRegistry: ChannelRunnerRegistry;
18
+ readonly lockManager: DistributedLockManager;
19
+ readonly deltaQueue: CloudPendingMessageQueue;
20
+ readonly automationEngine: HeadlessAutomationEngine;
21
+ readonly pushDispatcher: PushNotificationDispatcher;
22
+ readonly httpServer: WorkerHttpServer;
23
+ private status;
24
+ private startTime;
25
+ private activeAccounts;
26
+ private messagesProcessed;
27
+ private heartbeatTimer?;
28
+ constructor(config: WorkerEnvironmentConfig);
29
+ start(): Promise<void>;
30
+ stop(): Promise<void>;
31
+ registerRunner(runner: IChannelRunner): void;
32
+ registerAccount(account: ChannelAccount): void;
33
+ unregisterAccount(accountId: string): void;
34
+ recordMessageProcessed(): void;
35
+ handleIncomingMessage(message: UnifiedMessage, runner?: IChannelRunner): Promise<void>;
36
+ getMetrics(): WorkerMetrics;
37
+ private sendHeartbeat;
38
+ }
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ /**
3
+ * 🏛️ ZPlus Headless Worker Engine
4
+ * Quản lý vòng đời chạy ngầm 24/7 (WSS listeners, HTTP Ingress, Distributed Lock, Delta Sync, AI automation, Heartbeats)
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.WorkerEngine = void 0;
8
+ const core_1 = require("@zplus/core");
9
+ const ChannelRunnerRegistry_1 = require("../channels/ChannelRunnerRegistry");
10
+ const DistributedLockManager_1 = require("../lock/DistributedLockManager");
11
+ const CloudPendingMessageQueue_1 = require("../sync/CloudPendingMessageQueue");
12
+ const HeadlessAutomationEngine_1 = require("../automation/HeadlessAutomationEngine");
13
+ const PushNotificationDispatcher_1 = require("../notifications/PushNotificationDispatcher");
14
+ const WorkerHttpServer_1 = require("../server/WorkerHttpServer");
15
+ class WorkerEngine {
16
+ config;
17
+ logger;
18
+ channelRunnerRegistry;
19
+ lockManager;
20
+ deltaQueue;
21
+ automationEngine;
22
+ pushDispatcher;
23
+ httpServer;
24
+ status = "idle";
25
+ startTime = 0;
26
+ activeAccounts = new Map();
27
+ messagesProcessed = 0;
28
+ heartbeatTimer;
29
+ constructor(config) {
30
+ this.config = config;
31
+ this.logger = (0, core_1.createLogger)(`WorkerEngine:${config.workerId}`);
32
+ this.channelRunnerRegistry = new ChannelRunnerRegistry_1.ChannelRunnerRegistry(this.logger);
33
+ this.lockManager = new DistributedLockManager_1.DistributedLockManager(60000, this.logger);
34
+ this.deltaQueue = new CloudPendingMessageQueue_1.CloudPendingMessageQueue(10000, this.logger);
35
+ this.automationEngine = new HeadlessAutomationEngine_1.HeadlessAutomationEngine(this.logger);
36
+ this.pushDispatcher = new PushNotificationDispatcher_1.PushNotificationDispatcher(this.logger);
37
+ this.httpServer = new WorkerHttpServer_1.WorkerHttpServer(config.port, this, this.lockManager, this.deltaQueue, this.logger);
38
+ // Khi Master Preemption xảy ra, buộc Worker ngắt WSS lập tức
39
+ this.lockManager.onPreempt(async (accountId) => {
40
+ this.logger.info(`Preemption callback: stopping WSS for account ${accountId}...`);
41
+ const allRunners = this.channelRunnerRegistry.getAll();
42
+ for (const r of allRunners) {
43
+ if (r.accountId === accountId) {
44
+ await r.stop();
45
+ }
46
+ }
47
+ });
48
+ }
49
+ async start() {
50
+ if (this.status === "running") {
51
+ this.logger.warn("Worker is already running.");
52
+ return;
53
+ }
54
+ this.logger.info("Starting ZPlus 24/7 Headless Worker Engine...");
55
+ this.status = "initializing";
56
+ this.startTime = Date.now();
57
+ // 1. Khởi động HTTP Ingress Server
58
+ try {
59
+ await this.httpServer.start();
60
+ }
61
+ catch (err) {
62
+ this.logger.error("Failed to start Worker HTTP Ingress Server:", err);
63
+ }
64
+ // 2. Khởi tạo vòng lặp heartbeat định kỳ
65
+ this.heartbeatTimer = setInterval(() => {
66
+ this.sendHeartbeat();
67
+ }, this.config.heartbeatIntervalMs);
68
+ this.status = "running";
69
+ this.logger.info(`✅ ZPlus Worker Engine started successfully [ID: ${this.config.workerId}, Port: ${this.config.port}]`);
70
+ }
71
+ async stop() {
72
+ this.logger.info("Stopping ZPlus Worker Engine...");
73
+ if (this.heartbeatTimer) {
74
+ clearInterval(this.heartbeatTimer);
75
+ this.heartbeatTimer = undefined;
76
+ }
77
+ // Dừng HTTP Ingress
78
+ await this.httpServer.stop();
79
+ // Dừng tất cả runners
80
+ await this.channelRunnerRegistry.stopAll();
81
+ this.status = "stopped";
82
+ this.logger.info("ZPlus Worker Engine stopped.");
83
+ }
84
+ registerRunner(runner) {
85
+ runner.onMessage?.((msg) => {
86
+ this.handleIncomingMessage(msg, runner);
87
+ });
88
+ this.channelRunnerRegistry.register(runner);
89
+ }
90
+ registerAccount(account) {
91
+ this.activeAccounts.set(account.id, account);
92
+ this.logger.info(`Registered active account: ${account.accountName} [${account.platform}]`);
93
+ }
94
+ unregisterAccount(accountId) {
95
+ this.activeAccounts.delete(accountId);
96
+ this.logger.info(`Unregistered account: ${accountId}`);
97
+ }
98
+ recordMessageProcessed() {
99
+ this.messagesProcessed++;
100
+ }
101
+ async handleIncomingMessage(message, runner) {
102
+ this.recordMessageProcessed();
103
+ // 1. Lưu vào hàng đợi Delta Sync để Desktop sáng mai kéo về
104
+ this.deltaQueue.enqueue(message);
105
+ // 2. Đánh giá AI Auto-reply ca đêm
106
+ try {
107
+ const autoReplyText = await this.automationEngine.evaluateIncomingMessage(message);
108
+ if (autoReplyText && runner) {
109
+ this.logger.info(`[NightAutoReply] Sending automated reply to thread ${message.threadId}: "${autoReplyText}"`);
110
+ const replyMsg = {
111
+ id: `reply_${Date.now()}`,
112
+ platform: message.platform,
113
+ conversationId: message.conversationId,
114
+ threadId: message.threadId,
115
+ accountId: message.accountId,
116
+ senderId: message.accountId,
117
+ senderName: "ZPlus Night Assistant",
118
+ senderType: "agent",
119
+ messageType: "text",
120
+ content: autoReplyText,
121
+ timestamp: Date.now(),
122
+ isSelf: true,
123
+ status: "sent",
124
+ };
125
+ await runner.sendMessage(replyMsg);
126
+ }
127
+ }
128
+ catch (err) {
129
+ this.logger.warn("Auto-reply evaluation notice:", err);
130
+ }
131
+ // 3. Bắn Push Notification về ZPlus Mobile
132
+ try {
133
+ await this.pushDispatcher.dispatchMessageAlert("fcm_token_mobile_owner", message);
134
+ }
135
+ catch (err) {
136
+ this.logger.debug("Push notification dispatch notice:", err);
137
+ }
138
+ }
139
+ getMetrics() {
140
+ const uptime = this.startTime > 0 ? Math.floor((Date.now() - this.startTime) / 1000) : 0;
141
+ const memUsage = process.memoryUsage().rss / (1024 * 1024);
142
+ return {
143
+ workerId: this.config.workerId,
144
+ status: this.status,
145
+ uptimeSeconds: uptime,
146
+ activeAccountsCount: this.activeAccounts.size,
147
+ totalMessagesProcessed: this.messagesProcessed,
148
+ memoryUsageMb: Math.round(memUsage * 100) / 100,
149
+ lastHeartbeat: new Date().toISOString(),
150
+ };
151
+ }
152
+ sendHeartbeat() {
153
+ const metrics = this.getMetrics();
154
+ this.logger.info(`💓 Heartbeat: status=${metrics.status}, accounts=${metrics.activeAccountsCount}, msgs=${metrics.totalMessagesProcessed}, pendingDelta=${this.deltaQueue.getCount()}, uptime=${metrics.uptimeSeconds}s`);
155
+ }
156
+ }
157
+ exports.WorkerEngine = WorkerEngine;
@@ -0,0 +1,9 @@
1
+ export * from "./engine/WorkerEngine";
2
+ export * from "./config/WorkerConfig";
3
+ export * from "./channels";
4
+ export * from "./lock/DistributedLockManager";
5
+ export * from "./sync/CloudSyncWorker";
6
+ export * from "./sync/CloudPendingMessageQueue";
7
+ export * from "./server/WorkerHttpServer";
8
+ export * from "./automation/HeadlessAutomationEngine";
9
+ export * from "./notifications/PushNotificationDispatcher";
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./engine/WorkerEngine"), exports);
18
+ __exportStar(require("./config/WorkerConfig"), exports);
19
+ __exportStar(require("./channels"), exports);
20
+ __exportStar(require("./lock/DistributedLockManager"), exports);
21
+ __exportStar(require("./sync/CloudSyncWorker"), exports);
22
+ __exportStar(require("./sync/CloudPendingMessageQueue"), exports);
23
+ __exportStar(require("./server/WorkerHttpServer"), exports);
24
+ __exportStar(require("./automation/HeadlessAutomationEngine"), exports);
25
+ __exportStar(require("./notifications/PushNotificationDispatcher"), exports);
@@ -0,0 +1,40 @@
1
+ /**
2
+ * 🔐 Distributed Mutex Lock Manager
3
+ * Quản lý khóa loại trừ tương hỗ, chống xung đột 2 kết nối WSS song song (Desktop & Worker)
4
+ * Hỗ trợ Master Preemption: Desktop luôn có quyền tối thượng thu hồi lock trong < 1.000ms.
5
+ */
6
+ import { ILogger } from "@zplus/core";
7
+ export interface LockRecord {
8
+ accountId: string;
9
+ ownerId: string;
10
+ acquiredAt: number;
11
+ expiresAt: number;
12
+ }
13
+ export type LockPreemptCallback = (accountId: string, newOwnerId: string) => Promise<void> | void;
14
+ export declare class DistributedLockManager {
15
+ private readonly defaultTtlMs;
16
+ private readonly logger;
17
+ private readonly locks;
18
+ private readonly preemptCallbacks;
19
+ constructor(defaultTtlMs?: number, logger?: ILogger);
20
+ onPreempt(cb: LockPreemptCallback): void;
21
+ /**
22
+ * Xin giữ lock cho tài khoản
23
+ */
24
+ acquireLock(accountId: string, ownerId: string, ttlMs?: number): boolean;
25
+ /**
26
+ * Desktop chiếm lại quyền tối thượng (Master Preemption)
27
+ * Buộc Worker nhả socket WSS trong vòng tối đa 1.000ms
28
+ */
29
+ preemptLock(accountId: string, preemptorId: string): Promise<boolean>;
30
+ /**
31
+ * Giải phóng khóa
32
+ */
33
+ releaseLock(accountId: string, ownerId?: string): boolean;
34
+ /**
35
+ * Giải phóng toàn bộ khóa thuộc sở hữu của ownerId
36
+ */
37
+ releaseAllForOwner(ownerId: string): number;
38
+ isLocked(accountId: string): boolean;
39
+ getLockOwner(accountId: string): string | null;
40
+ }
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ /**
3
+ * 🔐 Distributed Mutex Lock Manager
4
+ * Quản lý khóa loại trừ tương hỗ, chống xung đột 2 kết nối WSS song song (Desktop & Worker)
5
+ * Hỗ trợ Master Preemption: Desktop luôn có quyền tối thượng thu hồi lock trong < 1.000ms.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.DistributedLockManager = void 0;
9
+ const core_1 = require("@zplus/core");
10
+ class DistributedLockManager {
11
+ defaultTtlMs;
12
+ logger;
13
+ locks = new Map();
14
+ preemptCallbacks = [];
15
+ constructor(defaultTtlMs = 60000, logger) {
16
+ this.defaultTtlMs = defaultTtlMs;
17
+ this.logger = logger || (0, core_1.createLogger)("DistributedLockManager");
18
+ }
19
+ onPreempt(cb) {
20
+ this.preemptCallbacks.push(cb);
21
+ }
22
+ /**
23
+ * Xin giữ lock cho tài khoản
24
+ */
25
+ acquireLock(accountId, ownerId, ttlMs = this.defaultTtlMs) {
26
+ const now = Date.now();
27
+ const existing = this.locks.get(accountId);
28
+ if (existing && existing.expiresAt > now && existing.ownerId !== ownerId) {
29
+ this.logger.warn(`Lock denied for account ${accountId}: currently held by ${existing.ownerId} (expires in ${existing.expiresAt - now}ms)`);
30
+ return false;
31
+ }
32
+ this.locks.set(accountId, {
33
+ accountId,
34
+ ownerId,
35
+ acquiredAt: now,
36
+ expiresAt: now + ttlMs,
37
+ });
38
+ this.logger.info(`✅ Lock granted: account=${accountId}, owner=${ownerId}, ttl=${ttlMs}ms`);
39
+ return true;
40
+ }
41
+ /**
42
+ * Desktop chiếm lại quyền tối thượng (Master Preemption)
43
+ * Buộc Worker nhả socket WSS trong vòng tối đa 1.000ms
44
+ */
45
+ async preemptLock(accountId, preemptorId) {
46
+ const existing = this.locks.get(accountId);
47
+ this.logger.info(`⚡ Preemption triggered for account ${accountId} by master ${preemptorId} (previous owner: ${existing?.ownerId || "none"})`);
48
+ // Kích hoạt tất cả callback giải phóng socket WSS khẩn cấp
49
+ const callbackPromises = this.preemptCallbacks.map((cb) => {
50
+ try {
51
+ return Promise.resolve(cb(accountId, preemptorId));
52
+ }
53
+ catch (err) {
54
+ this.logger.error(`Error in preempt callback for ${accountId}:`, err);
55
+ return Promise.resolve();
56
+ }
57
+ });
58
+ await Promise.race([
59
+ Promise.all(callbackPromises),
60
+ new Promise((resolve) => setTimeout(resolve, 1000)),
61
+ ]);
62
+ const now = Date.now();
63
+ this.locks.set(accountId, {
64
+ accountId,
65
+ ownerId: preemptorId,
66
+ acquiredAt: now,
67
+ expiresAt: now + this.defaultTtlMs,
68
+ });
69
+ this.logger.info(`✅ Account ${accountId} preempted successfully by ${preemptorId}.`);
70
+ return true;
71
+ }
72
+ /**
73
+ * Giải phóng khóa
74
+ */
75
+ releaseLock(accountId, ownerId) {
76
+ const existing = this.locks.get(accountId);
77
+ if (!existing)
78
+ return true;
79
+ if (ownerId && existing.ownerId !== ownerId) {
80
+ this.logger.warn(`Attempted unauthorized lock release for ${accountId} by ${ownerId} (real owner: ${existing.ownerId})`);
81
+ return false;
82
+ }
83
+ this.locks.delete(accountId);
84
+ this.logger.info(`🔓 Lock released for account ${accountId}.`);
85
+ return true;
86
+ }
87
+ /**
88
+ * Giải phóng toàn bộ khóa thuộc sở hữu của ownerId
89
+ */
90
+ releaseAllForOwner(ownerId) {
91
+ let released = 0;
92
+ for (const [accountId, lock] of this.locks.entries()) {
93
+ if (lock.ownerId === ownerId) {
94
+ this.locks.delete(accountId);
95
+ released++;
96
+ }
97
+ }
98
+ return released;
99
+ }
100
+ isLocked(accountId) {
101
+ const existing = this.locks.get(accountId);
102
+ if (!existing)
103
+ return false;
104
+ return existing.expiresAt > Date.now();
105
+ }
106
+ getLockOwner(accountId) {
107
+ const existing = this.locks.get(accountId);
108
+ if (!existing || existing.expiresAt <= Date.now())
109
+ return null;
110
+ return existing.ownerId;
111
+ }
112
+ }
113
+ exports.DistributedLockManager = DistributedLockManager;
@@ -0,0 +1,14 @@
1
+ import { ILogger } from "@zplus/core";
2
+ import { UnifiedMessage } from "@zplus/contracts";
3
+ export interface PushNotificationPayload {
4
+ recipientToken: string;
5
+ title: string;
6
+ body: string;
7
+ data?: Record<string, any>;
8
+ }
9
+ export declare class PushNotificationDispatcher {
10
+ private readonly logger;
11
+ constructor(logger?: ILogger);
12
+ dispatchMessageAlert(token: string, message: UnifiedMessage): Promise<boolean>;
13
+ sendNotification(payload: PushNotificationPayload): Promise<boolean>;
14
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PushNotificationDispatcher = void 0;
4
+ const core_1 = require("@zplus/core");
5
+ class PushNotificationDispatcher {
6
+ logger;
7
+ constructor(logger) {
8
+ this.logger = logger || (0, core_1.createLogger)("PushNotificationDispatcher");
9
+ }
10
+ async dispatchMessageAlert(token, message) {
11
+ const title = `${message.senderName} (${message.platform.toUpperCase()})`;
12
+ const body = message.content || "New multimedia message received";
13
+ return this.sendNotification({
14
+ recipientToken: token,
15
+ title,
16
+ body,
17
+ data: {
18
+ messageId: message.id,
19
+ threadId: message.threadId,
20
+ platform: message.platform,
21
+ accountId: message.accountId,
22
+ },
23
+ });
24
+ }
25
+ async sendNotification(payload) {
26
+ this.logger.debug(`Dispatching push notification to device token: ${payload.recipientToken.slice(0, 8)}...`);
27
+ // Integrates with Firebase Cloud Messaging / APNs gateway
28
+ return true;
29
+ }
30
+ }
31
+ exports.PushNotificationDispatcher = PushNotificationDispatcher;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 🌐 ZPlus Worker HTTP Ingress Server
3
+ * Cung cấp các endpoint REST cho Desktop Client giao tiếp với 24/7 Cloud Worker:
4
+ * - GET /health: Kiểm tra tình trạng nhịp tim & tài nguyên
5
+ * - POST /api/v1/sentinel/handover: Bàn giao session từ Desktop sang Worker khi tắt máy
6
+ * - POST /api/v1/sentinel/reclaim: Thu hồi quyền phiên khi Desktop mở lại máy tính
7
+ * - GET /api/v1/sync/delta: Trả về tin nhắn phát sinh trong đêm (Delta Sync)
8
+ */
9
+ import { ILogger } from "@zplus/core";
10
+ import { WorkerEngine } from "../engine/WorkerEngine";
11
+ import { DistributedLockManager } from "../lock/DistributedLockManager";
12
+ import { CloudPendingMessageQueue } from "../sync/CloudPendingMessageQueue";
13
+ export declare class WorkerHttpServer {
14
+ private readonly port;
15
+ private readonly engine;
16
+ private readonly lockManager;
17
+ private readonly deltaQueue;
18
+ private readonly logger;
19
+ private server;
20
+ constructor(port: number, engine: WorkerEngine, lockManager: DistributedLockManager, deltaQueue: CloudPendingMessageQueue, logger?: ILogger);
21
+ start(): Promise<void>;
22
+ stop(): Promise<void>;
23
+ private handleRequest;
24
+ private readJsonBody;
25
+ }