Remove Tail

Summary: We no longer need to Tail the logs as we stream the logs over WebSockets (see D37459924 (dcbc7c40bb))

Reviewed By: lblasa

Differential Revision: D37550482

fbshipit-source-id: 92a87f2ba1ecec140bbbb9e71df107341765ad46
This commit is contained in:
Andrey Goncharov
2022-06-30 07:50:06 -07:00
committed by Facebook GitHub Bot
parent f8763f95fa
commit 8c2ef5738e
3 changed files with 0 additions and 164 deletions

View File

@@ -12,7 +12,6 @@ export {loadSettings} from './utils/settings';
export {loadLauncherSettings} from './utils/launcherSettings';
export {loadProcessConfig} from './utils/processConfig';
export {getEnvironmentInfo} from './utils/environmentInfo';
export * from './utils/tail';
export {getGatekeepers} from './gk';
export {setupPrefetcher} from './fb-stubs/Prefetcher';
export * from './server/attachSocketServer';

View File

@@ -1,144 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import EventEmitter from 'events';
import fs, {FSWatcher} from 'fs-extra';
import path from 'path';
export type TailOptions = {
separator: RegExp;
encoding: BufferEncoding;
fromBeginning: boolean;
};
type TailBlock = {
start: number;
end: number;
};
export class Tail extends EventEmitter {
absPath: string;
dispatcher = new EventEmitter();
buffer = '';
queue: TailBlock[] = [];
isWatching = false;
currentCursorPosition = 0;
watcher: FSWatcher | undefined = undefined;
constructor(
private readonly filename: string,
private readonly options: TailOptions = {
separator: /[\r]{0,1}\n/,
fromBeginning: true,
encoding: 'utf8',
},
) {
super();
this.absPath = path.dirname(this.filename);
this.dispatcher.on('next', () => {
this.read_();
});
}
async watch() {
if (this.isWatching) {
return;
}
this.isWatching = true;
let startingCursor = 0;
if (!this.options.fromBeginning) {
startingCursor = await this.latestPosition_();
}
this.watch_(startingCursor, this.options.fromBeginning);
}
unwatch() {
if (this.watcher) {
this.watcher.close();
}
this.isWatching = false;
}
private async latestPosition_(): Promise<number> {
return (await fs.stat(this.filename)).size;
}
private read_() {
if (this.queue.length >= 1) {
const block = this.queue[0];
if (block.end > block.start) {
const stream = fs.createReadStream(this.filename, {
start: block.start,
end: block.end - 1,
encoding: this.options.encoding,
});
stream.on('error', (error) => {
this.emit('error', error);
});
stream.on('end', () => {
this.queue.shift();
if (this.queue.length > 0) {
this.dispatcher.emit('next');
}
if (this.buffer.length > 0) {
this.emit('line', this.buffer);
this.buffer = '';
}
});
stream.on('data', (d) => {
this.buffer += d;
const parts = this.buffer.split(this.options.separator);
// The last part may be an incomplete chunk, so
// push that back into the buffer. Otherwise, reset buffer.
this.buffer = parts.pop() || '';
for (const chunk of parts) {
this.emit('line', chunk);
}
});
}
}
}
private async fileUpdated_() {
const latestPosition = await this.latestPosition_();
// Case where text is not appended but it's actually a w+
if (latestPosition < this.currentCursorPosition) {
this.currentCursorPosition = latestPosition;
} else if (latestPosition > this.currentCursorPosition) {
this.queue.push({start: this.currentCursorPosition, end: latestPosition});
this.currentCursorPosition = latestPosition;
// Only emit if the queue was empty and now is not.
if (this.queue.length == 1) {
this.dispatcher.emit('next');
}
}
}
private watch_(cursor: number, readPrevious: boolean) {
this.currentCursorPosition = cursor;
if (readPrevious) {
this.fileUpdated_();
}
this.watcher = fs.watch(this.filename, {}, (eventType, filename) => {
this.watchEvent_(eventType, filename);
});
}
private watchEvent_(eventType: string, _filename: string) {
try {
if (eventType === 'change') {
this.fileUpdated_();
}
} catch (err) {}
}
}