achieve clean shutdown, no open handles
This commit is contained in:
parent
58c5f5dc4e
commit
b147378bf8
|
@ -69,6 +69,7 @@ export DEBUG="*,-express:*"
|
||||||
export RHIZOME_REQUEST_BIND_PORT=4000
|
export RHIZOME_REQUEST_BIND_PORT=4000
|
||||||
export RHIZOME_PUBLISH_BIND_PORT=4001
|
export RHIZOME_PUBLISH_BIND_PORT=4001
|
||||||
export RHIZOME_SEED_PEERS='localhost:4002, localhost:4004'
|
export RHIZOME_SEED_PEERS='localhost:4002, localhost:4004'
|
||||||
|
export RHIZOME_HTTP_API_ENABLE=true
|
||||||
export RHIZOME_HTTP_API_PORT=3000
|
export RHIZOME_HTTP_API_PORT=3000
|
||||||
export RHIZOME_PEER_ID=peer1
|
export RHIZOME_PEER_ID=peer1
|
||||||
export RHIZOME_PUB_SUB_TOPIC=rhizome-demo-1
|
export RHIZOME_PUB_SUB_TOPIC=rhizome-demo-1
|
||||||
|
@ -80,6 +81,7 @@ export DEBUG="*,-express:*"
|
||||||
export RHIZOME_REQUEST_BIND_PORT=4002
|
export RHIZOME_REQUEST_BIND_PORT=4002
|
||||||
export RHIZOME_PUBLISH_BIND_PORT=4003
|
export RHIZOME_PUBLISH_BIND_PORT=4003
|
||||||
export RHIZOME_SEED_PEERS='localhost:4000, localhost:4004'
|
export RHIZOME_SEED_PEERS='localhost:4000, localhost:4004'
|
||||||
|
export RHIZOME_HTTP_API_ENABLE=true
|
||||||
export RHIZOME_HTTP_API_PORT=3001
|
export RHIZOME_HTTP_API_PORT=3001
|
||||||
export RHIZOME_PEER_ID=peer2
|
export RHIZOME_PEER_ID=peer2
|
||||||
export RHIZOME_PUB_SUB_TOPIC=rhizome-demo-1
|
export RHIZOME_PUB_SUB_TOPIC=rhizome-demo-1
|
||||||
|
@ -91,6 +93,7 @@ export DEBUG="*,-express:*"
|
||||||
export RHIZOME_REQUEST_BIND_PORT=4004
|
export RHIZOME_REQUEST_BIND_PORT=4004
|
||||||
export RHIZOME_PUBLISH_BIND_PORT=4005
|
export RHIZOME_PUBLISH_BIND_PORT=4005
|
||||||
export RHIZOME_SEED_PEERS='localhost:4000, localhost:4002'
|
export RHIZOME_SEED_PEERS='localhost:4000, localhost:4002'
|
||||||
|
export RHIZOME_HTTP_API_ENABLE=true
|
||||||
export RHIZOME_HTTP_API_PORT=3002
|
export RHIZOME_HTTP_API_PORT=3002
|
||||||
export RHIZOME_PEER_ID=peer3
|
export RHIZOME_PEER_ID=peer3
|
||||||
export RHIZOME_PUB_SUB_TOPIC=rhizome-demo-1
|
export RHIZOME_PUB_SUB_TOPIC=rhizome-demo-1
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
"name": "rhizome-node",
|
"name": "rhizome-node",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "Rhizomatic database engine node",
|
"description": "Rhizomatic database engine node",
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"build:watch": "tsc --watch",
|
"build:watch": "tsc --watch",
|
||||||
|
|
|
@ -12,7 +12,6 @@ enum Decision {
|
||||||
};
|
};
|
||||||
|
|
||||||
export class DeltaStream {
|
export class DeltaStream {
|
||||||
rhizomeNode: RhizomeNode;
|
|
||||||
deltaStream = new EventEmitter();
|
deltaStream = new EventEmitter();
|
||||||
deltasProposed: Delta[] = [];
|
deltasProposed: Delta[] = [];
|
||||||
deltasAccepted: Delta[] = [];
|
deltasAccepted: Delta[] = [];
|
||||||
|
@ -20,9 +19,7 @@ export class DeltaStream {
|
||||||
deltasDeferred: Delta[] = [];
|
deltasDeferred: Delta[] = [];
|
||||||
hashesReceived = new Set<string>();
|
hashesReceived = new Set<string>();
|
||||||
|
|
||||||
constructor(rhizomeNode: RhizomeNode) {
|
constructor(readonly rhizomeNode: RhizomeNode) {}
|
||||||
this.rhizomeNode = rhizomeNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
applyPolicy(delta: Delta): Decision {
|
applyPolicy(delta: Delta): Decision {
|
||||||
return !!delta && Decision.Accept;
|
return !!delta && Decision.Accept;
|
|
@ -9,12 +9,6 @@ export class HttpHtml {
|
||||||
constructor(readonly rhizomeNode: RhizomeNode) {
|
constructor(readonly rhizomeNode: RhizomeNode) {
|
||||||
this.mdFiles = new MDFiles(this.rhizomeNode);
|
this.mdFiles = new MDFiles(this.rhizomeNode);
|
||||||
|
|
||||||
// Scan and watch for markdown files
|
|
||||||
this.mdFiles.readDir();
|
|
||||||
this.mdFiles.readReadme();
|
|
||||||
this.mdFiles.watchDir();
|
|
||||||
this.mdFiles.watchReadme();
|
|
||||||
|
|
||||||
// Serve README
|
// Serve README
|
||||||
this.router.get('/README', (_req: express.Request, res: express.Response) => {
|
this.router.get('/README', (_req: express.Request, res: express.Response) => {
|
||||||
const html = this.mdFiles.getReadmeHTML();
|
const html = this.mdFiles.getReadmeHTML();
|
||||||
|
@ -39,7 +33,15 @@ export class HttpHtml {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
start() {
|
||||||
this.mdFiles.close();
|
// Scan and watch for markdown files
|
||||||
|
this.mdFiles.readDir();
|
||||||
|
this.mdFiles.readReadme();
|
||||||
|
this.mdFiles.watchDir();
|
||||||
|
this.mdFiles.watchReadme();
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
this.mdFiles.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ export class HttpServer {
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
const {httpAddr, httpPort} = this.rhizomeNode.config;
|
const {httpAddr, httpPort} = this.rhizomeNode.config;
|
||||||
|
this.httpHtml.start();
|
||||||
this.server = this.app.listen({
|
this.server = this.app.listen({
|
||||||
port: httpPort,
|
port: httpPort,
|
||||||
host: httpAddr,
|
host: httpAddr,
|
||||||
|
@ -34,6 +35,6 @@ export class HttpServer {
|
||||||
|
|
||||||
async stop() {
|
async stop() {
|
||||||
this.server?.close();
|
this.server?.close();
|
||||||
this.httpHtml.close();
|
this.httpHtml.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,9 +122,7 @@ export class Lossless {
|
||||||
}
|
}
|
||||||
|
|
||||||
viewSpecific(entityId: DomainEntityID, deltaIds: DeltaID[], deltaFilter?: DeltaFilter): LosslessViewOne | undefined {
|
viewSpecific(entityId: DomainEntityID, deltaIds: DeltaID[], deltaFilter?: DeltaFilter): LosslessViewOne | undefined {
|
||||||
debug(`[${this.rhizomeNode.config.peerId}]`, `viewSpecific, deltaIds:`, JSON.stringify(deltaIds));
|
|
||||||
const combinedFilter = (delta: Delta) => {
|
const combinedFilter = (delta: Delta) => {
|
||||||
debug(`[${this.rhizomeNode.config.peerId}]`, `combinedFilter, deltaIds:`, JSON.stringify(deltaIds));
|
|
||||||
if (!deltaIds.includes(delta.id)) {
|
if (!deltaIds.includes(delta.id)) {
|
||||||
debug(`[${this.rhizomeNode.config.peerId}]`, `Excluding delta ${delta.id} because it's not in the requested list of deltas`);
|
debug(`[${this.rhizomeNode.config.peerId}]`, `Excluding delta ${delta.id} because it's not in the requested list of deltas`);
|
||||||
return false;
|
return false;
|
||||||
|
@ -191,7 +189,6 @@ export class Lossless {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(`[${this.rhizomeNode.config.peerId}]`, `Returning view:`, JSON.stringify(view, null, 2));
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Debug from 'debug';
|
import Debug from 'debug';
|
||||||
import {CREATOR, HTTP_API_ADDR, HTTP_API_ENABLE, HTTP_API_PORT, PEER_ID, PUBLISH_BIND_ADDR, PUBLISH_BIND_HOST, PUBLISH_BIND_PORT, REQUEST_BIND_ADDR, REQUEST_BIND_HOST, REQUEST_BIND_PORT, SEED_PEERS} from './config';
|
import {CREATOR, HTTP_API_ADDR, HTTP_API_ENABLE, HTTP_API_PORT, PEER_ID, PUBLISH_BIND_ADDR, PUBLISH_BIND_HOST, PUBLISH_BIND_PORT, REQUEST_BIND_ADDR, REQUEST_BIND_HOST, REQUEST_BIND_PORT, SEED_PEERS} from './config';
|
||||||
import {DeltaStream} from './deltas';
|
import {DeltaStream} from './delta-stream';
|
||||||
import {HttpServer} from './http/index';
|
import {HttpServer} from './http/index';
|
||||||
import {Lossless} from './lossless';
|
import {Lossless} from './lossless';
|
||||||
import {parseAddressList, PeerAddress, Peers} from './peers';
|
import {parseAddressList, PeerAddress, Peers} from './peers';
|
||||||
|
|
|
@ -69,10 +69,12 @@ class Peer {
|
||||||
|
|
||||||
async subscribeDeltas() {
|
async subscribeDeltas() {
|
||||||
if (!this.publishAddr) {
|
if (!this.publishAddr) {
|
||||||
debug(`[${this.rhizomeNode.config.peerId}]`, `Requesting publish addr from peer ${this.reqAddr.toAddrString()}`);
|
debug(`[${this.rhizomeNode.config.peerId}]`,
|
||||||
|
`Requesting publish addr from peer ${this.reqAddr.toAddrString()}`);
|
||||||
const res = await this.request(RequestMethods.GetPublishAddress);
|
const res = await this.request(RequestMethods.GetPublishAddress);
|
||||||
this.publishAddr = PeerAddress.fromString(res.toString());
|
this.publishAddr = PeerAddress.fromString(res.toString());
|
||||||
debug(`[${this.rhizomeNode.config.peerId}]`, `Received publish addr ${this.publishAddr.toAddrString()} from peer ${this.reqAddr.toAddrString()}`);
|
debug(`[${this.rhizomeNode.config.peerId}]`,
|
||||||
|
`Received publish addr ${this.publishAddr.toAddrString()} from peer ${this.reqAddr.toAddrString()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(`[${this.rhizomeNode.config.peerId}]`, `Subscribing to peer ${this.reqAddr.toAddrString()}`);
|
debug(`[${this.rhizomeNode.config.peerId}]`, `Subscribing to peer ${this.reqAddr.toAddrString()}`);
|
||||||
|
|
|
@ -12,15 +12,18 @@ export type PeerRequest = {
|
||||||
export type RequestHandler = (req: PeerRequest, res: ResponseSocket) => void;
|
export type RequestHandler = (req: PeerRequest, res: ResponseSocket) => void;
|
||||||
|
|
||||||
export class RequestSocket {
|
export class RequestSocket {
|
||||||
sock = new Request();
|
sock?: Request;
|
||||||
|
addrStr: string;
|
||||||
|
|
||||||
constructor(readonly requestReply: RequestReply, addr: PeerAddress) {
|
constructor(readonly requestReply: RequestReply, addr: PeerAddress) {
|
||||||
const addrStr = `tcp://${addr.addr}:${addr.port}`;
|
this.addrStr = `tcp://${addr.addr}:${addr.port}`;
|
||||||
this.sock.connect(addrStr);
|
this.sock = new Request();
|
||||||
debug(`[${this.requestReply.rhizomeNode.config.peerId}]`, `Request socket connecting to ${addrStr}`);
|
this.sock.connect(this.addrStr);
|
||||||
|
debug(`[${this.requestReply.rhizomeNode.config.peerId}]`, `Request socket connecting to ${this.addrStr}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async request(method: RequestMethods): Promise<Message> {
|
async request(method: RequestMethods): Promise<Message> {
|
||||||
|
if (!this.sock) throw new Error('Request socket is undefined');
|
||||||
const req: PeerRequest = {
|
const req: PeerRequest = {
|
||||||
method
|
method
|
||||||
};
|
};
|
||||||
|
@ -34,7 +37,9 @@ export class RequestSocket {
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.sock.close();
|
this.sock?.close();
|
||||||
|
// Make sure it goes out of scope
|
||||||
|
this.sock = undefined;
|
||||||
debug(`[${this.requestReply.rhizomeNode.config.peerId}]`, 'Request socket closed');
|
debug(`[${this.requestReply.rhizomeNode.config.peerId}]`, 'Request socket closed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +68,7 @@ function peerRequestFromMsg(msg: Message): PeerRequest | null {
|
||||||
|
|
||||||
export class RequestReply {
|
export class RequestReply {
|
||||||
rhizomeNode: RhizomeNode;
|
rhizomeNode: RhizomeNode;
|
||||||
replySock = new Reply();
|
replySock?: Reply;
|
||||||
requestStream = new EventEmitter();
|
requestStream = new EventEmitter();
|
||||||
requestBindAddrStr: string;
|
requestBindAddrStr: string;
|
||||||
|
|
||||||
|
@ -75,6 +80,7 @@ export class RequestReply {
|
||||||
|
|
||||||
// Listen for incoming requests
|
// Listen for incoming requests
|
||||||
async start() {
|
async start() {
|
||||||
|
this.replySock = new Reply();
|
||||||
|
|
||||||
await this.replySock.bind(this.requestBindAddrStr);
|
await this.replySock.bind(this.requestBindAddrStr);
|
||||||
debug(`[${this.rhizomeNode.config.peerId}]`, `Reply socket bound to ${this.requestBindAddrStr}`);
|
debug(`[${this.rhizomeNode.config.peerId}]`, `Reply socket bound to ${this.requestBindAddrStr}`);
|
||||||
|
@ -90,8 +96,10 @@ export class RequestReply {
|
||||||
// Each handler will get a copy of every message.
|
// Each handler will get a copy of every message.
|
||||||
registerRequestHandler(handler: RequestHandler) {
|
registerRequestHandler(handler: RequestHandler) {
|
||||||
this.requestStream.on('request', (req) => {
|
this.requestStream.on('request', (req) => {
|
||||||
const res = new ResponseSocket(this.replySock);
|
if (this.replySock) {
|
||||||
handler(req, res);
|
const res = new ResponseSocket(this.replySock);
|
||||||
|
handler(req, res);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,9 +108,11 @@ export class RequestReply {
|
||||||
}
|
}
|
||||||
|
|
||||||
async stop() {
|
async stop() {
|
||||||
await this.replySock.unbind(this.requestBindAddrStr);
|
if (this.replySock) {
|
||||||
this.replySock.close();
|
await this.replySock.unbind(this.requestBindAddrStr);
|
||||||
this.replySock = new Reply();
|
this.replySock.close();
|
||||||
debug(`[${this.rhizomeNode.config.peerId}]`, 'Reply socket closed');
|
this.replySock = undefined;
|
||||||
|
debug(`[${this.rhizomeNode.config.peerId}]`, 'Reply socket closed');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,7 @@ export class MDFiles {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
stop() {
|
||||||
this.dirWatcher?.close();
|
this.dirWatcher?.close();
|
||||||
this.readmeWatcher?.close();
|
this.readmeWatcher?.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"module": "CommonJS",
|
"module": "CommonJS",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"moduleResolution": "Node",
|
"moduleResolution": "Node",
|
||||||
"sourceMap": false,
|
"sourceMap": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"importsNotUsedAsValues": "remove",
|
"importsNotUsedAsValues": "remove",
|
||||||
|
|
Loading…
Reference in New Issue