




















1-import fs from "node:fs";
1+import {
2+createIncrementalLineReader,
3+resolvePositiveInteger,
4+} from "../incremental-line-reader.mjs";
2536const DEFAULT_MAX_READ_BYTES = 256 * 1024;
47const DEFAULT_TAIL_LINE_LIMIT = 160;
58const RELOAD_NEEDLE = "config change detected; evaluating reload";
69const RESTART_NEEDLE = "config change requires gateway restart";
7108-function positiveInteger(value, fallback) {
9-return Number.isSafeInteger(value) && value > 0 ? value : fallback;
10-}
11-12-function readSlice(filePath, start, length) {
13-if (length <= 0) {
14-return "";
15-}
16-const fd = fs.openSync(filePath, "r");
17-try {
18-const buffer = Buffer.alloc(length);
19-const bytesRead = fs.readSync(fd, buffer, 0, length, start);
20-return buffer.subarray(0, bytesRead).toString("utf8");
21-} finally {
22-fs.closeSync(fd);
23-}
24-}
25-2611export function inspectConfigReloadLogLine(line) {
2712return {
2813reload: line.includes(RELOAD_NEEDLE),
@@ -31,65 +16,21 @@ export function inspectConfigReloadLogLine(line) {
3116}
32173318export function createConfigReloadLogScanner(logPath, options = {}) {
34-const maxReadBytes = positiveInteger(options.maxReadBytes, DEFAULT_MAX_READ_BYTES);
35-const tailLineLimit = positiveInteger(options.tailLineLimit, DEFAULT_TAIL_LINE_LIMIT);
36-let offset = 0;
37-let pending = "";
19+const maxReadBytes = resolvePositiveInteger(options.maxReadBytes, DEFAULT_MAX_READ_BYTES);
20+const tailLineLimit = resolvePositiveInteger(options.tailLineLimit, DEFAULT_TAIL_LINE_LIMIT);
21+const reader = createIncrementalLineReader(logPath, { maxReadBytes });
3822let tailLines = [];
3923const reloadLines = [];
4024const restartLines = [];
41254226return {
4327scan() {
44-if (!fs.existsSync(logPath)) {
45-return { reloadLines, restartLines, tailLines };
46-}
47-48-const stats = fs.statSync(logPath);
49-if (!stats.isFile()) {
50-return { reloadLines, restartLines, tailLines };
51-}
52-if (stats.size < offset) {
53-offset = 0;
54-pending = "";
28+const { lines, reset } = reader.readLines();
29+if (reset) {
5530tailLines = [];
5631reloadLines.length = 0;
5732restartLines.length = 0;
5833}
59-if (stats.size === offset) {
60-return { reloadLines, restartLines, tailLines };
61-}
62-63-let start = offset;
64-let discardFirstLine = false;
65-let clamped = false;
66-if (start === 0 && stats.size > maxReadBytes) {
67-start = stats.size - maxReadBytes;
68-pending = "";
69-clamped = true;
70-} else if (stats.size - start > maxReadBytes) {
71-start = stats.size - maxReadBytes;
72-pending = "";
73-clamped = true;
74-}
75-if (clamped && start > 0) {
76-discardFirstLine = readSlice(logPath, start - 1, 1) !== "\n";
77-}
78-79-const text = readSlice(logPath, start, stats.size - start);
80-offset = stats.size;
81-let chunk = pending + text;
82-if (discardFirstLine) {
83-const newlineIndex = chunk.indexOf("\n");
84-if (newlineIndex === -1) {
85-pending = "";
86-return { reloadLines, restartLines, tailLines };
87-}
88-chunk = chunk.slice(newlineIndex + 1);
89-}
90-91-const lines = chunk.split("\n");
92-pending = lines.pop() ?? "";
9334for (const line of lines) {
9435const trimmed = line.replace(/\r$/u, "");
9536tailLines.push(trimmed);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。