training_data/apps/server/src/socket/collaboration/callback.ts

171 lines
4.1 KiB
TypeScript
Raw Normal View History

2024-12-30 08:26:40 +08:00
/**
*
* (ArrayMapTextXML等)HTTP POST请求发送到指定的回调URL
*
*/
import http from 'http';
import { parseInt as libParseInt } from 'lib0/number';
import { WSSharedDoc } from './ws-shared-doc';
/**
* URL配置,
* null
*/
2025-03-31 20:44:33 +08:00
const CALLBACK_URL = process.env.CALLBACK_URL
? new URL(process.env.CALLBACK_URL)
: null;
2024-12-30 08:26:40 +08:00
/**
* ,
* 5000
*/
const CALLBACK_TIMEOUT = libParseInt(process.env.CALLBACK_TIMEOUT || '5000');
/**
*
* CALLBACK_OBJECTS中解析JSON格式的配置
*/
2025-03-31 20:44:33 +08:00
const CALLBACK_OBJECTS: Record<string, string> = process.env.CALLBACK_OBJECTS
? JSON.parse(process.env.CALLBACK_OBJECTS)
: {};
2024-12-30 08:26:40 +08:00
/**
* URL是否已配置的标志
*/
export const isCallbackSet = !!CALLBACK_URL;
/**
*
*/
interface DataToSend {
room: string; // 房间/文档标识
2025-03-31 20:44:33 +08:00
data: Record<
string,
{
type: string; // 数据类型
content: any; // 数据内容
}
>;
2024-12-30 08:26:40 +08:00
}
/**
*
*/
type UpdateType = Uint8Array;
/**
*
*/
type OriginType = any;
/**
*
* @param update -
* @param origin -
* @param doc -
*/
2025-03-31 20:44:33 +08:00
export const callbackHandler = (
update: UpdateType,
origin: OriginType,
doc: WSSharedDoc,
): void => {
2024-12-30 08:26:40 +08:00
// 获取文档名称作为房间标识
const room = doc.name;
2025-03-31 20:44:33 +08:00
2024-12-30 08:26:40 +08:00
// 初始化要发送的数据对象
const dataToSend: DataToSend = {
room,
2025-03-31 20:44:33 +08:00
data: {},
2024-12-30 08:26:40 +08:00
};
// 获取所有需要监听的共享对象名称
const sharedObjectList = Object.keys(CALLBACK_OBJECTS);
2025-03-31 20:44:33 +08:00
2024-12-30 08:26:40 +08:00
// 遍历所有共享对象,获取它们的最新内容
2025-03-31 20:44:33 +08:00
sharedObjectList.forEach((sharedObjectName) => {
2024-12-30 08:26:40 +08:00
const sharedObjectType = CALLBACK_OBJECTS[sharedObjectName];
dataToSend.data[sharedObjectName] = {
type: sharedObjectType,
2025-03-31 20:44:33 +08:00
content: getContent(sharedObjectName, sharedObjectType, doc).toJSON(),
2024-12-30 08:26:40 +08:00
};
});
// 如果配置了回调URL,则发送HTTP请求
if (CALLBACK_URL) {
callbackRequest(CALLBACK_URL, CALLBACK_TIMEOUT, dataToSend);
}
};
/**
* HTTP回调请求
* @param url - URL
* @param timeout -
* @param data -
*/
const callbackRequest = (url: URL, timeout: number, data: DataToSend): void => {
// 将数据转换为JSON字符串
const dataString = JSON.stringify(data);
// 配置HTTP请求选项
const options = {
hostname: url.hostname,
port: url.port,
path: url.pathname,
timeout,
method: 'POST',
headers: {
'Content-Type': 'application/json',
2025-03-31 20:44:33 +08:00
'Content-Length': Buffer.byteLength(dataString),
},
2024-12-30 08:26:40 +08:00
};
// 创建HTTP请求
const req = http.request(options);
// 处理超时事件
req.on('timeout', () => {
console.warn('Callback request timed out.');
req.abort();
});
// 处理错误事件
req.on('error', (e) => {
console.error('Callback request error.', e);
req.abort();
});
// 发送数据
req.write(dataString);
req.end();
};
/**
*
* @param objName -
* @param objType -
* @param doc -
* @returns
*/
2025-03-31 20:44:33 +08:00
const getContent = (
objName: string,
objType: string,
doc: WSSharedDoc,
): any => {
2024-12-30 08:26:40 +08:00
// 根据对象类型返回相应的共享对象
switch (objType) {
2025-03-31 20:44:33 +08:00
case 'Array':
return doc.getArray(objName);
case 'Map':
return doc.getMap(objName);
case 'Text':
return doc.getText(objName);
case 'XmlFragment':
return doc.getXmlFragment(objName);
case 'XmlElement':
return doc.getXmlElement(objName);
default:
return {};
2024-12-30 08:26:40 +08:00
}
};