Skip to content

Commit c186797

Browse files
author
Lucas Araujo
committed
[DDW-812] Remove tail dependency and copy only the necessary code from it
1 parent bf5d7be commit c186797

File tree

4 files changed

+184
-6
lines changed

4 files changed

+184
-6
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,6 @@
271271
"shasum": "1.0.2",
272272
"source-map-support": "0.5.19",
273273
"spectron-fake-dialog": "0.0.1",
274-
"tail": "2.2.4",
275274
"tcp-port-used": "1.0.1",
276275
"trezor-connect": "8.2.4-extended",
277276
"unorm": "1.6.0",

source/main/utils/handleCheckBlockReplayProgress.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { BrowserWindow } from 'electron';
22
import fs from 'fs';
33
import moment from 'moment';
44
import path from 'path';
5-
import { Tail } from 'tail';
5+
import { Tail } from './tail';
66
import { getBlockSyncProgressChannel } from '../ipc/get-block-sync-progress';
77
import type { GetBlockSyncProgressType } from '../../common/ipc/api';
88
import { BlockSyncType } from '../../common/types/cardano-node.types';

source/main/utils/tail.ts

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import events from 'events';
2+
import fs from 'fs';
3+
import path from 'path';
4+
import { logger as defaultLogger } from './logging';
5+
import type { Logger } from '../../common/types/logging.types';
6+
7+
const ENCODING = 'utf-8';
8+
9+
export class Tail extends events.EventEmitter {
10+
filename: string;
11+
buffer: string;
12+
internalDispatcher: events.EventEmitter;
13+
queue: { start: number; end: number }[];
14+
isWatching: boolean;
15+
currentCursorPos: number;
16+
watcher: fs.FSWatcher;
17+
rewatchId: NodeJS.Timeout;
18+
logger: Logger;
19+
20+
constructor(filename: string, logger: Logger = defaultLogger) {
21+
super();
22+
this.filename = filename;
23+
this.logger = logger;
24+
25+
this.logger.info(`Tail starting...`);
26+
this.logger.info(`filename: ${this.filename}`);
27+
28+
try {
29+
fs.accessSync(this.filename, fs.constants.F_OK);
30+
} catch (err) {
31+
if (err.code === 'ENOENT') {
32+
throw err;
33+
}
34+
}
35+
36+
this.buffer = '';
37+
this.internalDispatcher = new events.EventEmitter();
38+
this.queue = [];
39+
this.isWatching = false;
40+
41+
this.internalDispatcher.on('next', () => {
42+
this.readBlock();
43+
});
44+
45+
try {
46+
this.watch(this.latestPosition());
47+
} catch (err) {
48+
this.logger.error(`watch for ${this.filename} failed: ${err}`);
49+
this.emit('error', `watch for ${this.filename} failed: ${err}`);
50+
}
51+
}
52+
53+
latestPosition() {
54+
try {
55+
return fs.statSync(this.filename).size;
56+
} catch (err) {
57+
this.logger.error(`size check for ${this.filename} failed: ${err}`);
58+
this.emit('error', `size check for ${this.filename} failed: ${err}`);
59+
throw err;
60+
}
61+
}
62+
63+
readBlock() {
64+
if (this.queue.length >= 1) {
65+
const block = this.queue[0];
66+
if (block.end > block.start) {
67+
const stream = fs.createReadStream(this.filename, {
68+
start: block.start,
69+
end: block.end - 1,
70+
encoding: ENCODING,
71+
});
72+
stream.on('error', (error) => {
73+
this.logger.error(`Tail error: ${error}`);
74+
this.emit('error', error);
75+
});
76+
stream.on('end', () => {
77+
this.queue.shift();
78+
if (this.queue.length > 0) {
79+
this.internalDispatcher.emit('next');
80+
}
81+
});
82+
stream.on('data', (d) => {
83+
this.buffer += d;
84+
const parts = this.buffer.split(/[\r]{0,1}\n/);
85+
this.buffer = parts.pop();
86+
for (const chunk of parts) {
87+
this.emit('line', chunk);
88+
}
89+
});
90+
}
91+
}
92+
}
93+
94+
change() {
95+
const p = this.latestPosition();
96+
if (p < this.currentCursorPos) {
97+
this.currentCursorPos = p;
98+
} else if (p > this.currentCursorPos) {
99+
this.queue.push({ start: this.currentCursorPos, end: p });
100+
this.currentCursorPos = p;
101+
if (this.queue.length === 1) {
102+
this.internalDispatcher.emit('next');
103+
}
104+
}
105+
}
106+
107+
watch(startingCursor) {
108+
if (this.isWatching) return;
109+
this.logger.info(`filesystem.watch present? ${fs.watch !== undefined}`);
110+
111+
this.isWatching = true;
112+
this.currentCursorPos = startingCursor;
113+
114+
if (fs.watch) {
115+
this.logger.info(`watch strategy: watch`);
116+
this.watcher = fs.watch(this.filename, {}, (e, filename) => {
117+
this.watchEvent(e, filename);
118+
});
119+
} else {
120+
this.logger.info(`watch strategy: watchFile`);
121+
fs.watchFile(this.filename, {}, (curr, prev) => {
122+
this.watchFileEvent(curr, prev);
123+
});
124+
}
125+
}
126+
127+
rename(filename) {
128+
if (filename === undefined || filename !== this.filename) {
129+
this.unwatch();
130+
this.filename = path.join(path.dirname(this.filename), filename);
131+
this.rewatchId = setTimeout(() => {
132+
try {
133+
this.watch(this.currentCursorPos);
134+
} catch (ex) {
135+
this.logger.error(
136+
`'rename' event for ${this.filename}. File not available anymore.`
137+
);
138+
this.emit('error', ex);
139+
}
140+
}, 1000);
141+
} else {
142+
this.logger.info('rename event but same filename');
143+
}
144+
}
145+
146+
watchEvent(e, evtFilename) {
147+
try {
148+
if (e === 'change') {
149+
this.change();
150+
} else if (e === 'rename') {
151+
this.rename(evtFilename);
152+
}
153+
} catch (err) {
154+
this.logger.error(`watchEvent for ${this.filename} failed: ${err}`);
155+
this.emit('error', `watchEvent for ${this.filename} failed: ${err}`);
156+
}
157+
}
158+
159+
watchFileEvent(curr, prev) {
160+
if (curr.size > prev.size) {
161+
this.currentCursorPos = curr.size;
162+
this.queue.push({ start: prev.size, end: curr.size });
163+
if (this.queue.length === 1) {
164+
this.internalDispatcher.emit('next');
165+
}
166+
}
167+
}
168+
169+
unwatch() {
170+
if (this.watcher) {
171+
this.watcher.close();
172+
} else {
173+
fs.unwatchFile(this.filename);
174+
}
175+
if (this.rewatchId) {
176+
clearTimeout(this.rewatchId);
177+
this.rewatchId = undefined;
178+
}
179+
this.isWatching = false;
180+
this.queue = [];
181+
this.logger.info(`Unwatch ${this.filename}`);
182+
}
183+
}

yarn.lock

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16456,10 +16456,6 @@ table@^6.0.1:
1645616456
slice-ansi "^4.0.0"
1645716457
string-width "^4.2.0"
1645816458

16459-
16460-
version "2.2.4"
16461-
resolved "https://registry.yarnpkg.com/tail/-/tail-2.2.4.tgz#90dd4c5a174a3fa39dcb65a1df1950a4a0093a41"
16462-
1646316459
tapable@^0.1.8:
1646416460
version "0.1.10"
1646516461
resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4"

0 commit comments

Comments
 (0)