镜像自地址
https://github.com/lhly/cloud-drive-renamer.git
已同步 2026-10-20 13:47:47 +08:00
fix: serialize diagnostic log appends
这个提交包含在:
父节点
c187bed711
当前提交
46e14ae2f5
@ -6,17 +6,25 @@ const MAX_RECENT_LOGS = 300;
|
|||||||
type DiagnosticStoreStorage = Pick<StorageManager, 'get' | 'set' | 'remove'>;
|
type DiagnosticStoreStorage = Pick<StorageManager, 'get' | 'set' | 'remove'>;
|
||||||
|
|
||||||
export class DiagnosticLogStore {
|
export class DiagnosticLogStore {
|
||||||
|
private appendChain: Promise<void> = Promise.resolve();
|
||||||
|
|
||||||
constructor(private readonly storageManager: DiagnosticStoreStorage = storage) {}
|
constructor(private readonly storageManager: DiagnosticStoreStorage = storage) {}
|
||||||
|
|
||||||
async append(entry: DiagnosticLogEntry): Promise<void> {
|
async append(entry: DiagnosticLogEntry): Promise<void> {
|
||||||
const recent = await this.getRecent();
|
const runAppend = async () => {
|
||||||
const next = [...recent, entry];
|
const recent = await this.getRecent();
|
||||||
|
const next = [...recent, entry];
|
||||||
|
|
||||||
if (next.length > MAX_RECENT_LOGS) {
|
if (next.length > MAX_RECENT_LOGS) {
|
||||||
next.splice(0, next.length - MAX_RECENT_LOGS);
|
next.splice(0, next.length - MAX_RECENT_LOGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.storageManager.set(DIAGNOSTIC_STORAGE_KEYS.RECENT_LOGS, next);
|
await this.storageManager.set(DIAGNOSTIC_STORAGE_KEYS.RECENT_LOGS, next);
|
||||||
|
};
|
||||||
|
|
||||||
|
const appendPromise = this.appendChain.then(runAppend, runAppend);
|
||||||
|
this.appendChain = appendPromise.catch(() => undefined);
|
||||||
|
return appendPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRecent(): Promise<DiagnosticLogEntry[]> {
|
async getRecent(): Promise<DiagnosticLogEntry[]> {
|
||||||
|
|||||||
@ -54,6 +54,33 @@ describe('DiagnosticLogStore', () => {
|
|||||||
expect(logs.at(-1)?.id).toBe('log-304');
|
expect(logs.at(-1)?.id).toBe('log-304');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not lose logs when append is called concurrently', async () => {
|
||||||
|
let currentLogs: DiagnosticLogEntry[] = [];
|
||||||
|
|
||||||
|
const concurrentStorage = {
|
||||||
|
get: vi.fn(async () => {
|
||||||
|
const snapshot = [...currentLogs];
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
|
return snapshot;
|
||||||
|
}),
|
||||||
|
set: vi.fn(async (_key: string, value: DiagnosticLogEntry[]) => {
|
||||||
|
currentLogs = value;
|
||||||
|
}),
|
||||||
|
remove: vi.fn(async () => {}),
|
||||||
|
};
|
||||||
|
|
||||||
|
const store = new DiagnosticLogStore(concurrentStorage as any);
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
store.append({ id: 'log-a', level: 'INFO', message: 'A' }),
|
||||||
|
store.append({ id: 'log-b', level: 'INFO', message: 'B' }),
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(currentLogs).toHaveLength(2);
|
||||||
|
expect(currentLogs.map((item) => item.id)).toEqual(['log-a', 'log-b']);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
it('clears the buffer without touching unrelated keys', async () => {
|
it('clears the buffer without touching unrelated keys', async () => {
|
||||||
const store = new DiagnosticLogStore(new StorageManager());
|
const store = new DiagnosticLogStore(new StorageManager());
|
||||||
|
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户