@litert/televoke
Version:
A simple RPC service framework.
140 lines • 4.69 kB
JavaScript
"use strict";
/**
* Copyright 2025 Angus.Fenying <fenying@litert.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.WorkerThreadTransporter = exports.MainThreadTransporter = void 0;
const NodeWorker = require("node:worker_threads");
const Shared = require("../../shared");
const eWT = require("./WorkerThread.Errors");
const node_events_1 = require("node:events");
const PROPERTY_NAMES = ['remoteAddress', 'remotePort', 'localAddress', 'localPort', 'threadId'];
const MSG_PREFIX = 'televoke2://';
class AbstractThreadTransporter extends node_events_1.EventEmitter {
constructor(protocol) {
super();
this.protocol = protocol;
this._onMessage = (frame) => {
if (typeof frame !== 'string' || !frame.startsWith(MSG_PREFIX)) {
return;
}
this.emit('frame', [Buffer.from(frame.slice(MSG_PREFIX.length), 'base64')]);
};
}
getPropertyNames() {
return PROPERTY_NAMES;
}
getAllProperties() {
return {
'remoteAddress': '127.0.0.1',
'remotePort': 0,
'localAddress': '127.0.0.1',
'localPort': 0,
'threadId': NodeWorker.threadId,
};
}
getProperty(name) {
switch (name) {
case 'localPort':
return 0;
case 'localAddress':
return '127.0.0.1';
case 'remotePort':
return 0;
case 'remoteAddress':
return '127.0.0.1';
case 'threadId':
return NodeWorker.threadId;
default:
return undefined;
}
}
end() {
this.destroy();
}
_write(worker, frame) {
for (let i = 0; i < frame.length; i++) {
const f = frame[i];
if (!(f instanceof Buffer)) {
frame[i] = Buffer.from(f);
}
}
try {
worker.postMessage(MSG_PREFIX + Buffer.concat(frame).toString('base64'));
}
catch (e) {
throw new Shared.errors.network_error({ reason: 'conn_lost', cause: e });
}
}
}
class MainThreadTransporter extends AbstractThreadTransporter {
constructor(protocol, _worker) {
super(protocol);
this._worker = _worker;
this._closed = false;
this._onError = (e) => { this.emit('error', e); };
this._onExit = () => { this.destroy(); };
this._worker
.on('message', this._onMessage)
.on('error', this._onError)
.on('exit', this._onExit);
}
destroy() {
this._closed = true;
this._worker.removeListener('message', this._onMessage);
this._worker.removeListener('error', this._onError);
this._worker.removeListener('exit', this._onExit);
this.emit('close');
}
get writable() {
return !this._closed;
}
write(frame) {
if (this._closed) {
throw new Shared.errors.network_error({ reason: 'conn_lost' });
}
this._write(this._worker, frame);
}
}
exports.MainThreadTransporter = MainThreadTransporter;
class WorkerThreadTransporter extends AbstractThreadTransporter {
constructor(protocol) {
super(protocol);
this._hold = setInterval(() => { return; }, 3600000);
if (NodeWorker.isMainThread) {
throw new eWT.E_WORKER_THREAD_ONLY();
}
NodeWorker.parentPort.on('message', this._onMessage);
}
destroy() {
if (this._hold) {
clearInterval(this._hold);
this._hold = null;
NodeWorker.parentPort.removeListener('message', this._onMessage);
this.emit('close');
}
}
get writable() {
return !!this._hold;
}
write(frame) {
if (!this._hold) {
throw new Shared.errors.network_error({ reason: 'conn_lost' });
}
super._write(NodeWorker.parentPort, frame);
}
}
exports.WorkerThreadTransporter = WorkerThreadTransporter;
//# sourceMappingURL=WorkerThread.Transporter.js.map