326 lines
9.4 KiB
TypeScript
326 lines
9.4 KiB
TypeScript
|
|
import { MessageConfig, MessageStatus, MessageQueue, Message } from '../types/message';
|
|||
|
|
import { logger } from '../utils/logger';
|
|||
|
|
import { v4 as uuidv4 } from 'uuid';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 消息处理服务
|
|||
|
|
* 负责管理系统中的消息,包括消息的发送、接收、处理等
|
|||
|
|
*/
|
|||
|
|
export class MessageProcessingService {
|
|||
|
|
private static messageQueues: Map<string, MessageQueue> = new Map();
|
|||
|
|
private static messages: Map<string, Message> = new Map();
|
|||
|
|
private static messageStatus: Map<string, MessageStatus> = new Map();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 创建消息队列
|
|||
|
|
* @param config 消息队列配置
|
|||
|
|
* @returns 创建结果
|
|||
|
|
*/
|
|||
|
|
static async createMessageQueue(config: MessageConfig): Promise<{ success: boolean; queueId: string; message: string }> {
|
|||
|
|
try {
|
|||
|
|
if (this.messageQueues.has(config.id)) {
|
|||
|
|
return { success: false, queueId: '', message: 'Message queue already exists' };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const queue: MessageQueue = {
|
|||
|
|
id: config.id,
|
|||
|
|
name: config.name,
|
|||
|
|
type: config.type,
|
|||
|
|
maxSize: config.maxSize || 10000,
|
|||
|
|
retentionPeriod: config.retentionPeriod || 86400000, // 24 hours
|
|||
|
|
created: new Date(),
|
|||
|
|
messages: []
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
this.messageQueues.set(config.id, queue);
|
|||
|
|
|
|||
|
|
logger.info(`Message queue ${config.id} created successfully`);
|
|||
|
|
return { success: true, queueId: config.id, message: 'Message queue created successfully' };
|
|||
|
|
} catch (error) {
|
|||
|
|
logger.error(`Error creating message queue: ${error}`);
|
|||
|
|
return { success: false, queueId: '', message: `Error creating message queue: ${error}` };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 发送消息
|
|||
|
|
* @param queueId 队列ID
|
|||
|
|
* @param payload 消息内容
|
|||
|
|
* @returns 发送结果
|
|||
|
|
*/
|
|||
|
|
static async sendMessage(queueId: string, payload: any): Promise<{ success: boolean; messageId: string; message: string }> {
|
|||
|
|
try {
|
|||
|
|
const queue = this.messageQueues.get(queueId);
|
|||
|
|
if (!queue) {
|
|||
|
|
return { success: false, messageId: '', message: 'Message queue not found' };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查队列大小
|
|||
|
|
if (queue.messages.length >= queue.maxSize) {
|
|||
|
|
return { success: false, messageId: '', message: 'Message queue is full' };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const messageId = uuidv4();
|
|||
|
|
const message: Message = {
|
|||
|
|
id: messageId,
|
|||
|
|
queueId,
|
|||
|
|
payload,
|
|||
|
|
status: 'PENDING',
|
|||
|
|
created: new Date(),
|
|||
|
|
updated: new Date()
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 添加到队列
|
|||
|
|
queue.messages.push(messageId);
|
|||
|
|
this.messages.set(messageId, message);
|
|||
|
|
this.messageStatus.set(messageId, {
|
|||
|
|
status: 'PENDING',
|
|||
|
|
lastUpdated: new Date()
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
logger.info(`Message ${messageId} sent to queue ${queueId}`);
|
|||
|
|
return { success: true, messageId, message: 'Message sent successfully' };
|
|||
|
|
} catch (error) {
|
|||
|
|
logger.error(`Error sending message: ${error}`);
|
|||
|
|
return { success: false, messageId: '', message: `Error sending message: ${error}` };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 接收消息
|
|||
|
|
* @param queueId 队列ID
|
|||
|
|
* @returns 消息
|
|||
|
|
*/
|
|||
|
|
static async receiveMessage(queueId: string): Promise<Message | null> {
|
|||
|
|
try {
|
|||
|
|
const queue = this.messageQueues.get(queueId);
|
|||
|
|
if (!queue) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (queue.messages.length === 0) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 取出第一个消息
|
|||
|
|
const messageId = queue.messages.shift();
|
|||
|
|
if (!messageId) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const message = this.messages.get(messageId);
|
|||
|
|
if (!message) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新消息状态
|
|||
|
|
message.status = 'PROCESSING';
|
|||
|
|
message.updated = new Date();
|
|||
|
|
this.messages.set(messageId, message);
|
|||
|
|
this.messageStatus.set(messageId, {
|
|||
|
|
status: 'PROCESSING',
|
|||
|
|
lastUpdated: new Date()
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
logger.info(`Message ${messageId} received from queue ${queueId}`);
|
|||
|
|
return message;
|
|||
|
|
} catch (error) {
|
|||
|
|
logger.error(`Error receiving message: ${error}`);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 确认消息处理完成
|
|||
|
|
* @param messageId 消息ID
|
|||
|
|
* @returns 确认结果
|
|||
|
|
*/
|
|||
|
|
static async acknowledgeMessage(messageId: string): Promise<{ success: boolean; message: string }> {
|
|||
|
|
try {
|
|||
|
|
const message = this.messages.get(messageId);
|
|||
|
|
if (!message) {
|
|||
|
|
return { success: false, message: 'Message not found' };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新消息状态
|
|||
|
|
message.status = 'COMPLETED';
|
|||
|
|
message.updated = new Date();
|
|||
|
|
this.messages.set(messageId, message);
|
|||
|
|
this.messageStatus.set(messageId, {
|
|||
|
|
status: 'COMPLETED',
|
|||
|
|
lastUpdated: new Date()
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
logger.info(`Message ${messageId} acknowledged`);
|
|||
|
|
return { success: true, message: 'Message acknowledged successfully' };
|
|||
|
|
} catch (error) {
|
|||
|
|
logger.error(`Error acknowledging message: ${error}`);
|
|||
|
|
return { success: false, message: `Error acknowledging message: ${error}` };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 拒绝消息
|
|||
|
|
* @param messageId 消息ID
|
|||
|
|
* @param requeue 是否重新入队
|
|||
|
|
* @returns 拒绝结果
|
|||
|
|
*/
|
|||
|
|
static async rejectMessage(messageId: string, requeue: boolean = false): Promise<{ success: boolean; message: string }> {
|
|||
|
|
try {
|
|||
|
|
const message = this.messages.get(messageId);
|
|||
|
|
if (!message) {
|
|||
|
|
return { success: false, message: 'Message not found' };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新消息状态
|
|||
|
|
message.status = 'REJECTED';
|
|||
|
|
message.updated = new Date();
|
|||
|
|
this.messages.set(messageId, message);
|
|||
|
|
this.messageStatus.set(messageId, {
|
|||
|
|
status: 'REJECTED',
|
|||
|
|
lastUpdated: new Date()
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 如果需要重新入队
|
|||
|
|
if (requeue) {
|
|||
|
|
const queue = this.messageQueues.get(message.queueId);
|
|||
|
|
if (queue) {
|
|||
|
|
queue.messages.push(messageId);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
logger.info(`Message ${messageId} rejected${requeue ? ' and requeued' : ''}`);
|
|||
|
|
return { success: true, message: 'Message rejected successfully' };
|
|||
|
|
} catch (error) {
|
|||
|
|
logger.error(`Error rejecting message: ${error}`);
|
|||
|
|
return { success: false, message: `Error rejecting message: ${error}` };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取消息状态
|
|||
|
|
* @param messageId 消息ID
|
|||
|
|
* @returns 消息状态
|
|||
|
|
*/
|
|||
|
|
static async getMessageStatus(messageId: string): Promise<MessageStatus | null> {
|
|||
|
|
try {
|
|||
|
|
const status = this.messageStatus.get(messageId);
|
|||
|
|
if (!status) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return status;
|
|||
|
|
} catch (error) {
|
|||
|
|
logger.error(`Error getting message status: ${error}`);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取队列状态
|
|||
|
|
* @param queueId 队列ID
|
|||
|
|
* @returns 队列状态
|
|||
|
|
*/
|
|||
|
|
static async getQueueStatus(queueId: string): Promise<{ queueId: string; size: number; maxSize: number; messages: Message[] } | null> {
|
|||
|
|
try {
|
|||
|
|
const queue = this.messageQueues.get(queueId);
|
|||
|
|
if (!queue) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取队列中的消息
|
|||
|
|
const queueMessages: Message[] = [];
|
|||
|
|
for (const messageId of queue.messages) {
|
|||
|
|
const message = this.messages.get(messageId);
|
|||
|
|
if (message) {
|
|||
|
|
queueMessages.push(message);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
queueId,
|
|||
|
|
size: queue.messages.length,
|
|||
|
|
maxSize: queue.maxSize,
|
|||
|
|
messages: queueMessages
|
|||
|
|
};
|
|||
|
|
} catch (error) {
|
|||
|
|
logger.error(`Error getting queue status: ${error}`);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 列出所有队列
|
|||
|
|
* @returns 队列列表
|
|||
|
|
*/
|
|||
|
|
static async listQueues(): Promise<MessageQueue[]> {
|
|||
|
|
try {
|
|||
|
|
return Array.from(this.messageQueues.values());
|
|||
|
|
} catch (error) {
|
|||
|
|
logger.error(`Error listing queues: ${error}`);
|
|||
|
|
return [];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 删除队列
|
|||
|
|
* @param queueId 队列ID
|
|||
|
|
* @returns 删除结果
|
|||
|
|
*/
|
|||
|
|
static async deleteQueue(queueId: string): Promise<{ success: boolean; message: string }> {
|
|||
|
|
try {
|
|||
|
|
const queue = this.messageQueues.get(queueId);
|
|||
|
|
if (!queue) {
|
|||
|
|
return { success: false, message: 'Message queue not found' };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 删除队列中的消息
|
|||
|
|
for (const messageId of queue.messages) {
|
|||
|
|
this.messages.delete(messageId);
|
|||
|
|
this.messageStatus.delete(messageId);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 删除队列
|
|||
|
|
this.messageQueues.delete(queueId);
|
|||
|
|
|
|||
|
|
logger.info(`Message queue ${queueId} deleted successfully`);
|
|||
|
|
return { success: true, message: 'Message queue deleted successfully' };
|
|||
|
|
} catch (error) {
|
|||
|
|
logger.error(`Error deleting queue: ${error}`);
|
|||
|
|
return { success: false, message: `Error deleting queue: ${error}` };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 清空队列
|
|||
|
|
* @param queueId 队列ID
|
|||
|
|
* @returns 清空结果
|
|||
|
|
*/
|
|||
|
|
static async clearQueue(queueId: string): Promise<{ success: boolean; clearedCount: number; message: string }> {
|
|||
|
|
try {
|
|||
|
|
const queue = this.messageQueues.get(queueId);
|
|||
|
|
if (!queue) {
|
|||
|
|
return { success: false, clearedCount: 0, message: 'Message queue not found' };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const clearedCount = queue.messages.length;
|
|||
|
|
|
|||
|
|
// 删除队列中的消息
|
|||
|
|
for (const messageId of queue.messages) {
|
|||
|
|
this.messages.delete(messageId);
|
|||
|
|
this.messageStatus.delete(messageId);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 清空队列
|
|||
|
|
queue.messages = [];
|
|||
|
|
this.messageQueues.set(queueId, queue);
|
|||
|
|
|
|||
|
|
logger.info(`Message queue ${queueId} cleared, removed ${clearedCount} messages`);
|
|||
|
|
return { success: true, clearedCount, message: 'Message queue cleared successfully' };
|
|||
|
|
} catch (error) {
|
|||
|
|
logger.error(`Error clearing queue: ${error}`);
|
|||
|
|
return { success: false, clearedCount: 0, message: `Error clearing queue: ${error}` };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|