@@ -4,9 +4,13 @@ import moment from 'moment';
44import path from 'path' ;
55import { Tail } from 'tail' ;
66import { getBlockSyncProgressChannel } from '../ipc/get-block-sync-progress' ;
7- import type { GetBlockSyncProgressType } from '../../common/ipc/api' ;
8- import { BlockSyncType } from '../../common/types/cardano-node.types' ;
7+ import {
8+ BlockSyncProgress ,
9+ BlockSyncType ,
10+ } from '../../common/types/cardano-node.types' ;
911import { isItFreshLog } from './blockSyncProgressHelpers' ;
12+ import { environment } from '../environment' ;
13+ import { logger } from './logging' ;
1014
1115const blockKeyword = 'Replayed block' ;
1216const validatingChunkKeyword = 'Validating chunk' ;
@@ -20,7 +24,7 @@ const progressKeywords = [
2024 ledgerKeyword ,
2125] ;
2226
23- const keywordTypeMap : Record < string , GetBlockSyncProgressType > = {
27+ const keywordTypeMap : Record < string , BlockSyncType > = {
2428 [ blockKeyword ] : BlockSyncType . replayedBlock ,
2529 [ validatingChunkKeyword ] : BlockSyncType . validatingChunk ,
2630 [ validatedChunkKeyword ] : BlockSyncType . validatingChunk ,
@@ -31,7 +35,7 @@ function containProgressKeywords(line: string) {
3135 return progressKeywords . some ( ( keyword ) => line . includes ( keyword ) ) ;
3236}
3337
34- function getProgressType ( line : string ) : GetBlockSyncProgressType | null {
38+ function getProgressType ( line : string ) : BlockSyncType | null {
3539 const key = progressKeywords . find ( ( k ) => line . includes ( k ) ) ;
3640
3741 if ( ! key ) {
@@ -43,35 +47,94 @@ function getProgressType(line: string): GetBlockSyncProgressType | null {
4347
4448const applicationStartDate = moment . utc ( ) ;
4549
46- export const handleCheckBlockReplayProgress = (
47- mainWindow : BrowserWindow ,
48- logsDirectoryPath : string
49- ) => {
50- const filename = 'node.log' ;
51- const logFilePath = `${ logsDirectoryPath } /pub/` ;
52- const filePath = path . join ( logFilePath , filename ) ;
53- if ( ! fs . existsSync ( filePath ) ) return ;
54-
55- const tail = new Tail ( filePath ) ;
50+ const createHandleNewLogLine = ( mainWindow : BrowserWindow ) => {
51+ const progressReport : BlockSyncProgress = {
52+ [ BlockSyncType . validatingChunk ] : 0 ,
53+ [ BlockSyncType . replayedBlock ] : 0 ,
54+ [ BlockSyncType . pushingLedger ] : 0 ,
55+ } ;
5656
57- tail . on ( 'line' , ( line ) => {
57+ return ( line : string ) => {
5858 if (
5959 ! isItFreshLog ( applicationStartDate , line ) ||
6060 ! containProgressKeywords ( line )
6161 ) {
6262 return ;
6363 }
6464
65- const percentage = line . match ( / P r o g r e s s : ( [ \s \d . , ] + ) % / ) ?. [ 1 ] ;
66- const progressType = getProgressType ( line ) ;
67- if ( ! percentage || ! progressType ) {
65+ const unparsedProgress = line . match ( / P r o g r e s s : ( [ \s \d . , ] + ) % / ) ?. [ 1 ] ;
66+ const type = getProgressType ( line ) ;
67+ if ( ! unparsedProgress || ! type ) {
6868 return ;
6969 }
70- const finalProgressPercentage = parseFloat ( percentage ) ;
71- // Send result to renderer process (NetworkStatusStore)
72- getBlockSyncProgressChannel . send (
73- { progress : finalProgressPercentage , type : progressType } ,
74- mainWindow . webContents
75- ) ;
70+
71+ const progress = Math . floor ( parseFloat ( unparsedProgress ) ) ;
72+
73+ if ( progressReport [ type ] !== progress ) {
74+ progressReport [ type ] = progress ;
75+ getBlockSyncProgressChannel . send ( progressReport , mainWindow . webContents ) ;
76+ }
77+ } ;
78+ } ;
79+
80+ const watchLogFile = ( {
81+ logFilePath,
82+ mainWindow,
83+ } : {
84+ logFilePath : string ;
85+ mainWindow : BrowserWindow ;
86+ } ) => {
87+ const tail = new Tail ( logFilePath , {
88+ // using fs.watchFile instead of fs.watch on Windows because of Node API issues:
89+ // https://github.com/nodejs/node/issues/36888
90+ // https://github.com/lucagrulla/node-tail/issues/137
91+ // https://nodejs.org/dist/latest-v14.x/docs/api/fs.html#fs_caveats
92+ useWatchFile : environment . isWindows ,
93+ fromBeginning : true ,
7694 } ) ;
95+
96+ const handleNewLogLine = createHandleNewLogLine ( mainWindow ) ;
97+ tail . on ( 'line' , handleNewLogLine ) ;
98+ } ;
99+
100+ const waitForLogFileToBeCreatedAndWatchIt = ( {
101+ logFileName,
102+ logFileDirPath,
103+ mainWindow,
104+ } : {
105+ logFileName : string ;
106+ logFileDirPath : string ;
107+ mainWindow : BrowserWindow ;
108+ } ) => {
109+ const watcher = fs . watch ( logFileDirPath , { } , ( eventName , file ) => {
110+ if ( eventName === 'rename' && logFileName === file ) {
111+ watchLogFile ( {
112+ logFilePath : path . join ( logFileDirPath , logFileName ) ,
113+ mainWindow,
114+ } ) ;
115+ watcher . close ( ) ;
116+ }
117+ } ) ;
118+ } ;
119+
120+ export const handleCheckBlockReplayProgress = (
121+ mainWindow : BrowserWindow ,
122+ logsDirectoryPath : string
123+ ) => {
124+ const logFileName = 'node.log' ;
125+ const logFileDirPath = `${ logsDirectoryPath } /pub/` ;
126+ const logFilePath = path . join ( logFileDirPath , logFileName ) ;
127+
128+ if ( ! fs . existsSync ( logFilePath ) ) {
129+ waitForLogFileToBeCreatedAndWatchIt ( {
130+ logFileDirPath,
131+ logFileName,
132+ mainWindow,
133+ } ) ;
134+ } else {
135+ watchLogFile ( {
136+ logFilePath,
137+ mainWindow,
138+ } ) ;
139+ }
77140} ;
0 commit comments