
























@@ -59,6 +59,10 @@ type TelegramMessageCacheBucket = {
5959persistedEntryCount: number;
6060};
616162+type PersistedMessageReadResult = TelegramMessageCacheBucket & {
63+needsRewrite: boolean;
64+};
65+6266const DEFAULT_MAX_MESSAGES = 5000;
6367const COMPACT_THRESHOLD_RATIO = 2;
6468const persistedMessageCacheBuckets = new Map<string, TelegramMessageCacheBucket>();
@@ -173,6 +177,85 @@ function parsePersistedEntry(value: unknown): {
173177return node ? { key: value.key, node } : null;
174178}
175179180+function findJsonArrayEnd(text: string): number {
181+let depth = 0;
182+let inString = false;
183+let escaped = false;
184+let started = false;
185+for (let index = 0; index < text.length; index++) {
186+const char = text[index];
187+if (!started) {
188+if (char.trim() === "") {
189+continue;
190+}
191+if (char !== "[") {
192+return -1;
193+}
194+started = true;
195+depth = 1;
196+continue;
197+}
198+if (inString) {
199+if (escaped) {
200+escaped = false;
201+} else if (char === "\\") {
202+escaped = true;
203+} else if (char === '"') {
204+inString = false;
205+}
206+continue;
207+}
208+if (char === '"') {
209+inString = true;
210+} else if (char === "[") {
211+depth++;
212+} else if (char === "]") {
213+depth--;
214+if (depth === 0) {
215+return index + 1;
216+}
217+}
218+}
219+return -1;
220+}
221+222+function readPersistedEntryValues(raw: string): { values: unknown[]; needsRewrite: boolean } {
223+const values: unknown[] = [];
224+let needsRewrite = false;
225+const readLines = (text: string) => {
226+for (const line of text.split("\n")) {
227+if (!line.trim()) {
228+continue;
229+}
230+try {
231+const value: unknown = JSON.parse(line);
232+values.push(value);
233+} catch {
234+needsRewrite = true;
235+}
236+}
237+};
238+const trimmedStart = raw.trimStart();
239+if (trimmedStart.startsWith("[")) {
240+const startOffset = raw.length - trimmedStart.length;
241+const arrayEnd = findJsonArrayEnd(raw.slice(startOffset));
242+if (arrayEnd === -1) {
243+needsRewrite = true;
244+readLines(raw);
245+return { values, needsRewrite };
246+}
247+const legacyValue: unknown = JSON.parse(raw.slice(startOffset, startOffset + arrayEnd));
248+if (Array.isArray(legacyValue)) {
249+values.push(...legacyValue);
250+}
251+needsRewrite = true;
252+readLines(raw.slice(startOffset + arrayEnd));
253+return { values, needsRewrite };
254+}
255+readLines(raw);
256+return { values, needsRewrite };
257+}
258+176259function trimMessages(messages: Map<string, TelegramCachedMessageNode>, maxMessages: number): void {
177260while (messages.size > maxMessages) {
178261const oldest = messages.keys().next().value;
@@ -183,18 +266,18 @@ function trimMessages(messages: Map<string, TelegramCachedMessageNode>, maxMessa
183266}
184267}
185268186-function readPersistedMessages(filePath: string, maxMessages: number) {
269+function readPersistedMessages(filePath: string, maxMessages: number): PersistedMessageReadResult {
187270const messages = new Map<string, TelegramCachedMessageNode>();
188271let persistedEntryCount = 0;
272+let needsRewrite = false;
189273if (!fs.existsSync(filePath)) {
190-return { messages, persistedEntryCount };
274+return { messages, persistedEntryCount, needsRewrite };
191275}
192276try {
193-for (const line of fs.readFileSync(filePath, "utf-8").split("\n")) {
194-if (!line.trim()) {
195-continue;
196-}
197-const entry = parsePersistedEntry(JSON.parse(line));
277+const persisted = readPersistedEntryValues(fs.readFileSync(filePath, "utf-8"));
278+needsRewrite = persisted.needsRewrite;
279+for (const value of persisted.values) {
280+const entry = parsePersistedEntry(value);
198281if (!entry) {
199282continue;
200283}
@@ -205,8 +288,9 @@ function readPersistedMessages(filePath: string, maxMessages: number) {
205288}
206289} catch (error) {
207290logVerbose(`telegram: failed to read message cache: ${String(error)}`);
291+needsRewrite = true;
208292}
209-return { messages, persistedEntryCount };
293+return { messages, persistedEntryCount, needsRewrite };
210294}
211295212296function serializePersistedEntry(key: string, node: TelegramCachedMessageNode): string {
@@ -279,6 +363,16 @@ function resolveMessageCacheBucket(params: {
279363messages: persisted.messages,
280364persistedEntryCount: persisted.persistedEntryCount,
281365};
366+if (persisted.needsRewrite) {
367+try {
368+bucket.persistedEntryCount = replacePersistedMessages({
369+messages: bucket.messages,
370+ persistedPath,
371+});
372+} catch (error) {
373+logVerbose(`telegram: failed to compact message cache: ${String(error)}`);
374+}
375+}
282376persistedMessageCacheBuckets.set(persistedPath, bucket);
283377return bucket;
284378}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。