From f14d76c2eabe0d968826c93b3cc2ac8bcc8effa2 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 7 Jun 2026 22:53:15 -0400 Subject: [PATCH] Isolate API process from mining workers --- ecosystem.config.js | 17 ++++++++++++++ src/main.ts | 3 ++- src/services/bitcoin-rpc.service.ts | 35 ++++++++++++++++++++--------- src/services/stratum-v1.service.ts | 5 +++++ 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/ecosystem.config.js b/ecosystem.config.js index 502b20a..569b083 100644 --- a/ecosystem.config.js +++ b/ecosystem.config.js @@ -1,12 +1,28 @@ module.exports = { apps: [ + // API instance + { + name: 'api', + script: './dist/main.js', + instances: 1, + exec_mode: 'fork', + env: { + MASTER: 'false', + API_ONLY: 'true', + API_ENABLED: 'true', + NODE_CLUSTER_SCHED_POLICY: 'none', + }, + time: true + }, // Master instance { name: 'master', script: './dist/main.js', instances: 1, + exec_mode: 'fork', env: { MASTER: 'true', + API_ENABLED: 'false', NODE_CLUSTER_SCHED_POLICY: 'none', }, time: true @@ -19,6 +35,7 @@ module.exports = { exec_mode: "cluster", env: { MASTER: 'false', + API_ENABLED: 'false', NODE_CLUSTER_SCHED_POLICY: 'none', }, time: true diff --git a/src/main.ts b/src/main.ts index d3c93d6..048749c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -15,7 +15,8 @@ async function bootstrap() { return; } - const serveApi = process.env.MASTER !== 'false'; + const apiEnabled = process.env.API_ENABLED?.toLowerCase(); + const serveApi = apiEnabled == null ? process.env.MASTER !== 'false' : apiEnabled === 'true'; const secure = serveApi && process.env.API_SECURE?.toLowerCase() === 'true'; const currentDirectory = process.cwd(); const keyPath = path.join(currentDirectory, 'secrets', 'key.pem'); diff --git a/src/services/bitcoin-rpc.service.ts b/src/services/bitcoin-rpc.service.ts index 4cb36fc..d0d9171 100644 --- a/src/services/bitcoin-rpc.service.ts +++ b/src/services/bitcoin-rpc.service.ts @@ -47,22 +47,30 @@ export class BitcoinRpcService implements OnModuleInit { } }); - this.callRpc('getrpcinfo').then((res) => { - console.log('Bitcoin RPC connected'); - }, () => { - console.error('Could not reach RPC host'); - }); - - this.miningInfo = await this.getMiningInfo(); - console.log(`MASTER? ${process.env.MASTER}`) if (process.env.MASTER != 'true') { - await this.loadLatestTemplateForWorker(); + await this.loadLatestMiningInfoForReplayProcess(); + if (process.env.API_ONLY != 'true') { + await this.loadLatestTemplateForWorker(); + } await this.redisMessagingService.subscribeMiningInfoUpdates(async (miningInfo: IMiningInfo) => { this.miningInfo = miningInfo; - await this.loadTemplateForWorker(miningInfo.blocks); + if (process.env.API_ONLY != 'true') { + await this.loadTemplateForWorker(miningInfo.blocks); + } }); + if (process.env.API_ONLY == 'true') { + console.log('API-only process using Redis mining info replay'); + } + return; } else { + this.callRpc('getrpcinfo').then((res) => { + console.log('Bitcoin RPC connected'); + }, () => { + console.error('Could not reach RPC host'); + }); + + this.miningInfo = await this.getMiningInfo(); console.log('Using ZMQ'); const sock = new zmq.Subscriber; @@ -91,6 +99,13 @@ export class BitcoinRpcService implements OnModuleInit { } + private async loadLatestMiningInfoForReplayProcess() { + const latestMiningInfo = await this.redisMessagingService.getLatestMiningInfo(); + if (latestMiningInfo != null) { + this.miningInfo = latestMiningInfo; + } + } + private async listenForNewBlocks(sock: zmq.Subscriber) { for await (const [topic, msg] of sock) { console.log("New Block"); diff --git a/src/services/stratum-v1.service.ts b/src/services/stratum-v1.service.ts index 8875c7c..1465b83 100644 --- a/src/services/stratum-v1.service.ts +++ b/src/services/stratum-v1.service.ts @@ -68,6 +68,11 @@ export class StratumV1Service implements OnModuleInit { async onModuleInit(): Promise { + if (process.env.API_ONLY == 'true') { + console.log('API-only process skipping Stratum socket listeners'); + return; + } + if (process.env.MASTER == 'true') { await this.clientService.deleteAll(); await this.redisMessagingService?.clearClientPresence();