fix: Fix multiple bugs with new authentication flow
This commit is contained in:
108
electron/diagnostics/diagnostics.writer.ts
Normal file
108
electron/diagnostics/diagnostics.writer.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
import * as fsp from 'fs/promises';
|
||||
import * as path from 'path';
|
||||
import type { PerfDiagEntry } from './diagnostics.models';
|
||||
import {
|
||||
formatPerfDiagLine,
|
||||
pushRingBuffer,
|
||||
resolveDiagnosticsFilePath
|
||||
} from './diagnostics.rules';
|
||||
|
||||
const DEFAULT_RING_CAPACITY = 120;
|
||||
const FLUSH_DEBOUNCE_MS = 250;
|
||||
|
||||
export interface PerfDiagWriterOptions {
|
||||
userDataPath: string;
|
||||
sessionId: string;
|
||||
ringCapacity?: number;
|
||||
}
|
||||
|
||||
export class PerfDiagWriter {
|
||||
private readonly filePath: string;
|
||||
private readonly ringCapacity: number;
|
||||
private readonly pendingLines: string[] = [];
|
||||
private ring: PerfDiagEntry[] = [];
|
||||
private flushTimer: NodeJS.Timeout | null = null;
|
||||
private flushInFlight: Promise<void> | null = null;
|
||||
private disabled = false;
|
||||
|
||||
constructor(options: PerfDiagWriterOptions) {
|
||||
this.filePath = resolveDiagnosticsFilePath(options.userDataPath, options.sessionId);
|
||||
this.ringCapacity = options.ringCapacity ?? DEFAULT_RING_CAPACITY;
|
||||
}
|
||||
|
||||
get snapshotFilePath(): string {
|
||||
return this.filePath;
|
||||
}
|
||||
|
||||
get bufferedEntries(): readonly PerfDiagEntry[] {
|
||||
return this.ring;
|
||||
}
|
||||
|
||||
append(entry: PerfDiagEntry): void {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.ring = pushRingBuffer(this.ring, entry, this.ringCapacity);
|
||||
this.pendingLines.push(`${formatPerfDiagLine(entry)}\n`);
|
||||
this.scheduleFlush();
|
||||
} catch {
|
||||
this.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
async flush(): Promise<void> {
|
||||
if (this.disabled || this.pendingLines.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.flushInFlight) {
|
||||
await this.flushInFlight;
|
||||
return;
|
||||
}
|
||||
|
||||
const lines = this.pendingLines.splice(0, this.pendingLines.length);
|
||||
|
||||
this.flushInFlight = this.writeLines(lines)
|
||||
.catch(() => {
|
||||
this.disabled = true;
|
||||
})
|
||||
.finally(() => {
|
||||
this.flushInFlight = null;
|
||||
});
|
||||
|
||||
await this.flushInFlight;
|
||||
}
|
||||
|
||||
async flushSnapshot(label: string): Promise<void> {
|
||||
this.append({
|
||||
collectedAt: Date.now(),
|
||||
source: 'main',
|
||||
type: 'session',
|
||||
payload: {
|
||||
event: label,
|
||||
filePath: this.filePath,
|
||||
entries: this.ring
|
||||
}
|
||||
});
|
||||
|
||||
await this.flush();
|
||||
}
|
||||
|
||||
private scheduleFlush(): void {
|
||||
if (this.flushTimer) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.flushTimer = setTimeout(() => {
|
||||
this.flushTimer = null;
|
||||
void this.flush();
|
||||
}, FLUSH_DEBOUNCE_MS);
|
||||
}
|
||||
|
||||
private async writeLines(lines: string[]): Promise<void> {
|
||||
await fsp.mkdir(path.dirname(this.filePath), { recursive: true });
|
||||
await fsp.appendFile(this.filePath, lines.join(''), 'utf8');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user