From d46ff35dfb4f7ea756e75236393ea1350a2937cf Mon Sep 17 00:00:00 2001 From: softsimon Date: Mon, 2 Nov 2020 19:11:04 +0700 Subject: [PATCH] Fix: Split mempool disk cache into 50K txs per file --- backend/.gitignore | 1 + backend/src/api/blocks.ts | 2 +- backend/src/api/disk-cache.ts | 99 ++++++++++++++++------------------- backend/tsconfig.json | 3 +- 4 files changed, 48 insertions(+), 57 deletions(-) diff --git a/backend/.gitignore b/backend/.gitignore index ba8416a23..70c0d7e6c 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -43,3 +43,4 @@ testem.log Thumbs.db cache.json +cache2.json \ No newline at end of file diff --git a/backend/src/api/blocks.ts b/backend/src/api/blocks.ts index 0c6837cf5..29739ba6d 100644 --- a/backend/src/api/blocks.ts +++ b/backend/src/api/blocks.ts @@ -99,7 +99,7 @@ class Blocks { if (this.newBlockCallbacks.length) { this.newBlockCallbacks.forEach((cb) => cb(block, txIds, transactions)); } - diskCache.$saveCacheToDiskAsync(); + diskCache.$saveCacheToDisk(); } } diff --git a/backend/src/api/disk-cache.ts b/backend/src/api/disk-cache.ts index 58935e508..6cf7114ca 100644 --- a/backend/src/api/disk-cache.ts +++ b/backend/src/api/disk-cache.ts @@ -1,85 +1,74 @@ -import config from '../config'; import * as fs from 'fs'; +const fsPromises = fs.promises; import * as process from 'process'; +import * as cluster from 'cluster'; import memPool from './mempool'; import blocks from './blocks'; import logger from '../logger'; class DiskCache { private static FILE_NAME = './cache.json'; - private enabled = true; - + private static FILE_NAME_2 = './cache2.json'; constructor() { - if (process.env.workerId === '0' || !config.MEMPOOL.SPAWN_CLUSTER_PROCS) { - if (!fs.existsSync(DiskCache.FILE_NAME)) { - fs.closeSync(fs.openSync(DiskCache.FILE_NAME, 'w')); - logger.info('Disk cache file created'); - } - - process.on('SIGINT', () => { - this.saveCacheToDisk(); - process.exit(2); - }); - - process.on('SIGTERM', () => { - this.saveCacheToDisk(); - process.exit(2); - }); - } else { - this.enabled = false; + if (!cluster.isMaster) { + return; } + /* + if (!fs.existsSync(DiskCache.FILE_NAME)) { + fs.closeSync(fs.openSync(DiskCache.FILE_NAME, 'w')); + logger.info('Disk cache file created'); + } + */ + process.on('SIGINT', async () => { + await this.$saveCacheToDisk(); + process.exit(2); + }); + + process.on('SIGTERM', async () => { + await this.$saveCacheToDisk(); + process.exit(2); + }); } - async $saveCacheToDiskAsync(): Promise { - if (!this.enabled) { + async $saveCacheToDisk(): Promise { + if (!cluster.isMaster) { return; } try { - await this.$saveDataAsync(JSON.stringify({ - mempool: memPool.getMempool(), + logger.debug('Writing mempool and blocks data to disk cache...'); + const mempoolChunk_1 = Object.fromEntries(Object.entries(memPool.getMempool()).splice(0, 50000)); + const mempoolChunk_2 = Object.fromEntries(Object.entries(memPool.getMempool()).splice(50000)); + await fsPromises.writeFile(DiskCache.FILE_NAME, JSON.stringify({ blocks: blocks.getBlocks(), - })); + mempool: mempoolChunk_1 + }), {flag: 'w'}); + await fsPromises.writeFile(DiskCache.FILE_NAME_2, JSON.stringify({ + mempool: mempoolChunk_2 + }), {flag: 'w'}); logger.debug('Mempool and blocks data saved to disk cache'); } catch (e) { - logger.warn('Error writing to cache file asynchronously: ' + e.message || e); + logger.warn('Error writing to cache file: ' + e.message || e); } } loadMempoolCache() { - const cacheData = this.loadDataSync(); + if (!fs.existsSync(DiskCache.FILE_NAME)) { + return; + } + let data: any = {}; + const cacheData = fs.readFileSync(DiskCache.FILE_NAME, 'utf8'); if (cacheData) { logger.info('Restoring mempool and blocks data from disk cache'); - const data = JSON.parse(cacheData); - memPool.setMempool(data.mempool); - blocks.setBlocks(data.blocks); + data = JSON.parse(cacheData); } - } - private saveCacheToDisk() { - this.saveDataSync(JSON.stringify({ - mempool: memPool.getMempool(), - blocks: blocks.getBlocks(), - })); - logger.info('Mempool and blocks data saved to disk cache'); - } + if (fs.existsSync(DiskCache.FILE_NAME_2)) { + const cacheData2 = JSON.parse(fs.readFileSync(DiskCache.FILE_NAME_2, 'utf8')); + Object.assign(data.mempool, cacheData2.mempool); + } - private $saveDataAsync(dataBlob: string): Promise { - return new Promise((resolve, reject) => { - fs.writeFile(DiskCache.FILE_NAME, dataBlob, (err) => { - if (err) { - return reject(err); - } - resolve(); - }); - }); - } - - private saveDataSync(dataBlob: string) { - fs.writeFileSync(DiskCache.FILE_NAME, dataBlob, 'utf8'); - } - - private loadDataSync(): string { - return fs.readFileSync(DiskCache.FILE_NAME, 'utf8'); + memPool.setMempool(data.mempool); + blocks.setBlocks(data.blocks); } } diff --git a/backend/tsconfig.json b/backend/tsconfig.json index 9b3cb6248..5d0ff946a 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -1,7 +1,8 @@ { "compilerOptions": { "module": "commonjs", - "target": "es2015", + "target": "esnext", + "lib": ["es2019"], "strict": true, "noImplicitAny": false, "sourceMap": false,