2025-08-29 17:08:04 +05:30
|
|
|
import { HealthStatus } from "@waku/sdk";
|
2025-08-28 19:07:26 +05:30
|
|
|
import { OpchanMessage } from "@/types/forum";
|
2025-08-29 17:08:04 +05:30
|
|
|
import { WakuNodeManager, HealthChangeCallback } from "./core/WakuNodeManager";
|
|
|
|
|
import { CacheService } from "./services/CacheService";
|
|
|
|
|
import { MessageService, MessageStatusCallback } from "./services/MessageService";
|
|
|
|
|
import { ReliableMessaging } from "./core/ReliableMessaging";
|
2025-04-16 14:08:26 +05:30
|
|
|
|
2025-08-29 17:08:04 +05:30
|
|
|
export type { HealthChangeCallback, MessageStatusCallback };
|
2025-04-22 10:39:32 +05:30
|
|
|
|
2025-04-16 14:08:26 +05:30
|
|
|
class MessageManager {
|
2025-08-29 17:08:04 +05:30
|
|
|
private nodeManager: WakuNodeManager | null = null;
|
|
|
|
|
private cacheService: CacheService;
|
|
|
|
|
private messageService: MessageService | null = null;
|
|
|
|
|
private reliableMessaging: ReliableMessaging | null = null;
|
|
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
|
this.cacheService = new CacheService();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async create(): Promise<MessageManager> {
|
|
|
|
|
const manager = new MessageManager();
|
|
|
|
|
await manager.initialize();
|
|
|
|
|
return manager;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async initialize(): Promise<void> {
|
|
|
|
|
try {
|
|
|
|
|
this.nodeManager = await WakuNodeManager.create();
|
|
|
|
|
|
|
|
|
|
// Now create message service with proper dependencies
|
|
|
|
|
this.messageService = new MessageService(this.cacheService, this.reliableMessaging, this.nodeManager);
|
|
|
|
|
|
|
|
|
|
// Set up health-based reliable messaging initialization
|
|
|
|
|
this.nodeManager.onHealthChange((isReady) => {
|
|
|
|
|
if (isReady && !this.reliableMessaging) {
|
|
|
|
|
this.initializeReliableMessaging();
|
|
|
|
|
} else if (!isReady && this.reliableMessaging) {
|
|
|
|
|
this.cleanupReliableMessaging();
|
2025-04-22 10:39:32 +05:30
|
|
|
}
|
2025-08-29 17:08:04 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Failed to initialize MessageManager:", error);
|
|
|
|
|
throw error;
|
2025-04-16 14:08:26 +05:30
|
|
|
}
|
2025-08-29 17:08:04 +05:30
|
|
|
}
|
2025-04-16 14:08:26 +05:30
|
|
|
|
2025-08-29 17:08:04 +05:30
|
|
|
private async initializeReliableMessaging(): Promise<void> {
|
|
|
|
|
if (!this.nodeManager || this.reliableMessaging) {
|
|
|
|
|
return;
|
2025-04-22 10:39:32 +05:30
|
|
|
}
|
|
|
|
|
|
2025-08-29 17:08:04 +05:30
|
|
|
try {
|
|
|
|
|
console.log("Initializing reliable messaging...");
|
|
|
|
|
this.reliableMessaging = new ReliableMessaging(this.nodeManager.getNode());
|
|
|
|
|
this.messageService?.updateReliableMessaging(this.reliableMessaging);
|
|
|
|
|
console.log("Reliable messaging initialized successfully");
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Failed to initialize reliable messaging:", error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private cleanupReliableMessaging(): void {
|
|
|
|
|
if (this.reliableMessaging) {
|
|
|
|
|
console.log("Cleaning up reliable messaging due to health status");
|
|
|
|
|
this.reliableMessaging.cleanup();
|
|
|
|
|
this.reliableMessaging = null;
|
|
|
|
|
this.messageService?.updateReliableMessaging(null);
|
2025-04-22 10:39:32 +05:30
|
|
|
}
|
2025-08-29 17:08:04 +05:30
|
|
|
}
|
2025-08-29 15:43:10 +05:30
|
|
|
|
2025-08-29 17:08:04 +05:30
|
|
|
public async stop(): Promise<void> {
|
|
|
|
|
this.cleanupReliableMessaging();
|
|
|
|
|
this.messageService?.cleanup();
|
|
|
|
|
await this.nodeManager?.stop();
|
|
|
|
|
}
|
2025-08-29 15:43:10 +05:30
|
|
|
|
2025-08-29 17:08:04 +05:30
|
|
|
public get isReady(): boolean {
|
|
|
|
|
return this.nodeManager?.isReady ?? false;
|
|
|
|
|
}
|
2025-04-22 10:39:32 +05:30
|
|
|
|
2025-08-29 17:08:04 +05:30
|
|
|
public get currentHealth(): HealthStatus {
|
|
|
|
|
return this.nodeManager?.currentHealth ?? HealthStatus.Unhealthy;
|
|
|
|
|
}
|
2025-04-22 10:39:32 +05:30
|
|
|
|
2025-08-29 17:08:04 +05:30
|
|
|
public onHealthChange(callback: HealthChangeCallback): () => void {
|
|
|
|
|
if (!this.nodeManager) {
|
|
|
|
|
throw new Error("Node manager not initialized");
|
2025-04-22 10:39:32 +05:30
|
|
|
}
|
2025-08-29 17:08:04 +05:30
|
|
|
return this.nodeManager.onHealthChange(callback);
|
|
|
|
|
}
|
2025-04-22 10:39:32 +05:30
|
|
|
|
2025-08-30 17:25:12 +05:30
|
|
|
//TODO: return event handlers?
|
|
|
|
|
public async sendMessage(message: OpchanMessage, statusCallback?: MessageStatusCallback): Promise<void> {
|
2025-08-29 17:08:04 +05:30
|
|
|
if (!this.messageService) {
|
|
|
|
|
throw new Error("MessageManager not fully initialized");
|
2025-08-29 15:43:10 +05:30
|
|
|
}
|
2025-08-30 17:25:12 +05:30
|
|
|
this.messageService.sendMessage(message, statusCallback);
|
2025-08-29 17:08:04 +05:30
|
|
|
}
|
2025-08-29 15:43:10 +05:30
|
|
|
|
2025-08-29 17:08:04 +05:30
|
|
|
public onMessageReceived(callback: (message: OpchanMessage) => void): () => void {
|
|
|
|
|
if (!this.messageService) {
|
|
|
|
|
throw new Error("MessageManager not fully initialized");
|
2025-04-22 10:39:32 +05:30
|
|
|
}
|
2025-08-29 17:08:04 +05:30
|
|
|
return this.messageService.onMessageReceived(callback);
|
|
|
|
|
}
|
2025-04-22 10:39:32 +05:30
|
|
|
|
2025-08-29 17:08:04 +05:30
|
|
|
public get messageCache() {
|
|
|
|
|
if (!this.messageService) {
|
|
|
|
|
throw new Error("MessageManager not fully initialized");
|
2025-04-16 15:40:20 +05:30
|
|
|
}
|
2025-08-29 17:08:04 +05:30
|
|
|
return this.messageService.messageCache;
|
|
|
|
|
}
|
2025-04-16 14:08:26 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const messageManager = await MessageManager.create();
|
|
|
|
|
export default messageManager;
|