@things-factory/integration-base 9.2.27 → 9.2.29
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-server/engine/connector/echo-back-connector.js +19 -0
- package/dist-server/engine/connector/echo-back-connector.js.map +1 -1
- package/dist-server/engine/task/echo-receive.js +25 -3
- package/dist-server/engine/task/echo-receive.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
|
@@ -15,6 +15,25 @@ class EchoBack {
|
|
|
15
15
|
let [host, port = 8124] = connection.endpoint.split(':');
|
|
16
16
|
try {
|
|
17
17
|
await socket.connect(Number(port), host);
|
|
18
|
+
// 수신 메시지 큐 + idle-flush 버퍼링.
|
|
19
|
+
// TCP는 바이트 스트림이라 메시지가 여러 청크로 쪼개지거나 합쳐져 도착할 수 있으므로,
|
|
20
|
+
// 마지막 수신 후 IDLE_MS 동안 추가 데이터가 없으면 그때까지 모인 바이트를 응답 1건으로 간주한다.
|
|
21
|
+
// 종료문자/길이를 몰라도 동작하며(끝 문자가 매번 달라도 무관), Buffer로 누적하므로 끝의 바이너리(체크섬 등)도 보존된다.
|
|
22
|
+
const IDLE_MS = 80;
|
|
23
|
+
socket.__messages__ = [];
|
|
24
|
+
let chunks = [];
|
|
25
|
+
let timer = null;
|
|
26
|
+
socket.socket.on('data', (data) => {
|
|
27
|
+
chunks.push(data);
|
|
28
|
+
if (timer)
|
|
29
|
+
clearTimeout(timer);
|
|
30
|
+
timer = setTimeout(() => {
|
|
31
|
+
;
|
|
32
|
+
socket.__messages__.push(Buffer.concat(chunks));
|
|
33
|
+
chunks = [];
|
|
34
|
+
timer = null;
|
|
35
|
+
}, IDLE_MS);
|
|
36
|
+
});
|
|
18
37
|
connection_manager_1.ConnectionManager.addConnectionInstance(connection, socket);
|
|
19
38
|
connection_manager_1.ConnectionManager.logger.info(`echo-back-connector connection(${connection.name}:${connection.endpoint}) is connected`);
|
|
20
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"echo-back-connector.js","sourceRoot":"","sources":["../../../server/engine/connector/echo-back-connector.ts"],"names":[],"mappings":";;;;AAAA,sDAAqB;AACrB,4EAA0C;AAG1C,8DAAyD;AAGzD,MAAa,QAAQ;IACnB,KAAK,CAAC,KAAK,CAAC,iBAAiB;QAC3B,MAAM,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAEjE,sCAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAA;IAClE,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,UAA2B;QACvC,IAAI,MAAM,GAAG,IAAI,wBAAa,CAAC,IAAI,aAAG,CAAC,MAAM,EAAE,CAAC,CAAA;QAChD,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAExD,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"echo-back-connector.js","sourceRoot":"","sources":["../../../server/engine/connector/echo-back-connector.ts"],"names":[],"mappings":";;;;AAAA,sDAAqB;AACrB,4EAA0C;AAG1C,8DAAyD;AAGzD,MAAa,QAAQ;IACnB,KAAK,CAAC,KAAK,CAAC,iBAAiB;QAC3B,MAAM,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAEjE,sCAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAA;IAClE,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,UAA2B;QACvC,IAAI,MAAM,GAAG,IAAI,wBAAa,CAAC,IAAI,aAAG,CAAC,MAAM,EAAE,CAAC,CAAA;QAChD,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAExD,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAA;YAExC,6BAA6B;YAC7B,mDAAmD;YACnD,6DAA6D;YAC7D,0EAA0E;YAC1E,MAAM,OAAO,GAAG,EAAE,CACjB;YAAC,MAAc,CAAC,YAAY,GAAG,EAAE,CAAA;YAClC,IAAI,MAAM,GAAa,EAAE,CAAA;YACzB,IAAI,KAAK,GAA0B,IAAI,CAEtC;YAAC,MAAc,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;gBAClD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBACjB,IAAI,KAAK;oBAAE,YAAY,CAAC,KAAK,CAAC,CAAA;gBAC9B,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;oBACtB,CAAC;oBAAC,MAAc,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;oBACzD,MAAM,GAAG,EAAE,CAAA;oBACX,KAAK,GAAG,IAAI,CAAA;gBACd,CAAC,EAAE,OAAO,CAAC,CAAA;YACb,CAAC,CAAC,CAAA;YAEF,sCAAiB,CAAC,qBAAqB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;YAE3D,sCAAiB,CAAC,MAAM,CAAC,IAAI,CAC3B,kCAAkC,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,QAAQ,gBAAgB,CACzF,CAAA;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,sCAAiB,CAAC,MAAM,CAAC,KAAK,CAC5B,kCAAkC,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,QAAQ,qBAAqB,EAC7F,CAAC,CACF,CAAA;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,UAA2B;QAC1C,IAAI,MAAM,GAAG,sCAAiB,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAA;QAEnE,MAAM,MAAM,CAAC,OAAO,EAAE,CAAA;QAEtB,sCAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,kCAAkC,UAAU,CAAC,IAAI,mBAAmB,CAAC,CAAA;IACrG,CAAC;IAED,IAAI,aAAa;QACf,OAAO,EAAE,CAAA;IACX,CAAC;IAED,IAAI,YAAY;QACd,OAAO,CAAC,MAAM,CAAC,CAAA;IACjB,CAAC;CACF;AA7DD,4BA6DC;AAED,sCAAiB,CAAC,iBAAiB,CAAC,WAAW,EAAE,IAAI,QAAQ,EAAE,CAAC,CAAA","sourcesContent":["import net from 'net'\nimport PromiseSocket from 'promise-socket'\n\nimport { Connector } from '../types'\nimport { ConnectionManager } from '../connection-manager'\nimport { InputConnection } from '../../service/connection/connection-type'\n\nexport class EchoBack implements Connector {\n async ready(connectionConfigs) {\n await Promise.all(connectionConfigs.map(this.connect.bind(this)))\n\n ConnectionManager.logger.info('echo-back connections are ready')\n }\n\n async connect(connection: InputConnection) {\n let socket = new PromiseSocket(new net.Socket())\n let [host, port = 8124] = connection.endpoint.split(':')\n\n try {\n await socket.connect(Number(port), host)\n\n // 수신 메시지 큐 + idle-flush 버퍼링.\n // TCP는 바이트 스트림이라 메시지가 여러 청크로 쪼개지거나 합쳐져 도착할 수 있으므로,\n // 마지막 수신 후 IDLE_MS 동안 추가 데이터가 없으면 그때까지 모인 바이트를 응답 1건으로 간주한다.\n // 종료문자/길이를 몰라도 동작하며(끝 문자가 매번 달라도 무관), Buffer로 누적하므로 끝의 바이너리(체크섬 등)도 보존된다.\n const IDLE_MS = 80\n ;(socket as any).__messages__ = []\n let chunks: Buffer[] = []\n let timer: NodeJS.Timeout | null = null\n\n ;(socket as any).socket.on('data', (data: Buffer) => {\n chunks.push(data)\n if (timer) clearTimeout(timer)\n timer = setTimeout(() => {\n ;(socket as any).__messages__.push(Buffer.concat(chunks))\n chunks = []\n timer = null\n }, IDLE_MS)\n })\n\n ConnectionManager.addConnectionInstance(connection, socket)\n\n ConnectionManager.logger.info(\n `echo-back-connector connection(${connection.name}:${connection.endpoint}) is connected`\n )\n } catch (e) {\n ConnectionManager.logger.error(\n `echo-back-connector connection(${connection.name}:${connection.endpoint}) is not connected.`,\n e\n )\n }\n }\n\n async disconnect(connection: InputConnection) {\n let socket = ConnectionManager.removeConnectionInstance(connection)\n\n await socket.destroy()\n\n ConnectionManager.logger.info(`echo-back-connector connection(${connection.name}) is disconnected`)\n }\n\n get parameterSpec() {\n return []\n }\n\n get taskPrefixes() {\n return ['echo']\n }\n}\n\nConnectionManager.registerConnector('echo-back', new EchoBack())\n"]}
|
|
@@ -1,13 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("@things-factory/utils");
|
|
3
4
|
const task_registry_1 = require("../task-registry");
|
|
4
5
|
const connection_manager_1 = require("../connection-manager");
|
|
5
|
-
|
|
6
|
+
const RECEIVE_TIMEOUT_MS = 5000; // 응답 대기 최대 시간 (초과 시 에러)
|
|
7
|
+
const POLL_MS = 50;
|
|
8
|
+
// 커넥터가 idle-flush로 큐(__messages__)에 적재한 완성 응답 1건을 꺼내 hex로 반환한다.
|
|
9
|
+
// read()를 직접 호출하지 않으므로 이후 send가 막히지 않고, 끝의 바이너리(체크섬 등)도 손실 없이 보존된다.
|
|
10
|
+
async function EchoReceive(step, { domain }) {
|
|
6
11
|
var { connection: connectionName } = step;
|
|
7
12
|
var connection = await connection_manager_1.ConnectionManager.getConnectionInstanceByName(domain, connectionName);
|
|
8
|
-
|
|
13
|
+
if (!connection) {
|
|
14
|
+
throw Error(`connection is not found : ${connectionName}`);
|
|
15
|
+
}
|
|
16
|
+
const queue = connection.__messages__;
|
|
17
|
+
if (!queue) {
|
|
18
|
+
throw Error(`connection(${connectionName}) does not support buffered receive`);
|
|
19
|
+
}
|
|
20
|
+
// 완성된 응답 1건이 큐에 들어올 때까지 대기 (무한 대기 방지를 위한 타임아웃 포함)
|
|
21
|
+
let waited = 0;
|
|
22
|
+
while (queue.length === 0) {
|
|
23
|
+
if (waited >= RECEIVE_TIMEOUT_MS) {
|
|
24
|
+
throw Error(`echo-receive timeout: no response within ${RECEIVE_TIMEOUT_MS}ms`);
|
|
25
|
+
}
|
|
26
|
+
await (0, utils_1.sleep)(POLL_MS);
|
|
27
|
+
waited += POLL_MS;
|
|
28
|
+
}
|
|
29
|
+
const message = queue.shift();
|
|
9
30
|
return {
|
|
10
|
-
data: message.toString()
|
|
31
|
+
data: message.toString('hex'), // 무손실 hex (끝 바이너리/체크섬 보존)
|
|
32
|
+
ascii: message.toString('latin1') // 참고용 (1바이트=1문자, 손실 없음)
|
|
11
33
|
};
|
|
12
34
|
}
|
|
13
35
|
EchoReceive.parameterSpec = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"echo-receive.js","sourceRoot":"","sources":["../../../server/engine/task/echo-receive.ts"],"names":[],"mappings":";;AAAA,oDAA+C;AAC/C,8DAAyD;AAKzD,KAAK,UAAU,WAAW,CAAC,IAAe,EAAE,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"echo-receive.js","sourceRoot":"","sources":["../../../server/engine/task/echo-receive.ts"],"names":[],"mappings":";;AAAA,iDAA6C;AAE7C,oDAA+C;AAC/C,8DAAyD;AAKzD,MAAM,kBAAkB,GAAG,IAAI,CAAA,CAAC,wBAAwB;AACxD,MAAM,OAAO,GAAG,EAAE,CAAA;AAElB,gEAAgE;AAChE,oEAAoE;AACpE,KAAK,UAAU,WAAW,CAAC,IAAe,EAAE,EAAE,MAAM,EAAW;IAC7D,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,GAAG,IAAI,CAAA;IAEzC,IAAI,UAAU,GAAG,MAAM,sCAAiB,CAAC,2BAA2B,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IAC5F,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,KAAK,CAAC,6BAA6B,cAAc,EAAE,CAAC,CAAA;IAC5D,CAAC;IAED,MAAM,KAAK,GAAc,UAAkB,CAAC,YAAY,CAAA;IACxD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,KAAK,CAAC,cAAc,cAAc,qCAAqC,CAAC,CAAA;IAChF,CAAC;IAED,kDAAkD;IAClD,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,IAAI,MAAM,IAAI,kBAAkB,EAAE,CAAC;YACjC,MAAM,KAAK,CAAC,4CAA4C,kBAAkB,IAAI,CAAC,CAAA;QACjF,CAAC;QACD,MAAM,IAAA,aAAK,EAAC,OAAO,CAAC,CAAA;QACpB,MAAM,IAAI,OAAO,CAAA;IACnB,CAAC;IAED,MAAM,OAAO,GAAW,KAAK,CAAC,KAAK,EAAY,CAAA;IAE/C,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,0BAA0B;QACzD,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,wBAAwB;KAC3D,CAAA;AACH,CAAC;AAED,WAAW,CAAC,aAAa,GAAG,EAAE,CAAA;AAE9B,4BAAY,CAAC,mBAAmB,CAAC,cAAc,EAAE,WAAW,CAAC,CAAA","sourcesContent":["import { sleep } from '@things-factory/utils'\n\nimport { TaskRegistry } from '../task-registry'\nimport { ConnectionManager } from '../connection-manager'\n\nimport { InputStep } from '../../service/step/step-type'\nimport { Context } from '../types'\n\nconst RECEIVE_TIMEOUT_MS = 5000 // 응답 대기 최대 시간 (초과 시 에러)\nconst POLL_MS = 50\n\n// 커넥터가 idle-flush로 큐(__messages__)에 적재한 완성 응답 1건을 꺼내 hex로 반환한다.\n// read()를 직접 호출하지 않으므로 이후 send가 막히지 않고, 끝의 바이너리(체크섬 등)도 손실 없이 보존된다.\nasync function EchoReceive(step: InputStep, { domain }: Context) {\n var { connection: connectionName } = step\n\n var connection = await ConnectionManager.getConnectionInstanceByName(domain, connectionName)\n if (!connection) {\n throw Error(`connection is not found : ${connectionName}`)\n }\n\n const queue: Buffer[] = (connection as any).__messages__\n if (!queue) {\n throw Error(`connection(${connectionName}) does not support buffered receive`)\n }\n\n // 완성된 응답 1건이 큐에 들어올 때까지 대기 (무한 대기 방지를 위한 타임아웃 포함)\n let waited = 0\n while (queue.length === 0) {\n if (waited >= RECEIVE_TIMEOUT_MS) {\n throw Error(`echo-receive timeout: no response within ${RECEIVE_TIMEOUT_MS}ms`)\n }\n await sleep(POLL_MS)\n waited += POLL_MS\n }\n\n const message: Buffer = queue.shift() as Buffer\n\n return {\n data: message.toString('hex'), // 무손실 hex (끝 바이너리/체크섬 보존)\n ascii: message.toString('latin1') // 참고용 (1바이트=1문자, 손실 없음)\n }\n}\n\nEchoReceive.parameterSpec = []\n\nTaskRegistry.registerTaskHandler('echo-receive', EchoReceive)\n"]}
|