- Introduced a new utility function `readFileUtf8WithTimeout` to handle file reading with a specified timeout, improving robustness against long read operations. - Added size validation for various team-related files (e.g., config, inbox, processes) to prevent issues with oversized files. - Updated multiple services (TeamConfigReader, TeamDataService, TeamInboxReader, TeamKanbanManager, TeamMembersMetaStore, TeamProvisioningService, TeamSentMessagesStore, TeamTaskReader) to utilize the new file reading method and enforce size limits. - Enhanced error handling to gracefully manage read timeouts and invalid file states, improving overall system stability. Made-with: Cursor
40 lines
1 KiB
TypeScript
40 lines
1 KiB
TypeScript
import * as fs from 'fs';
|
|
|
|
function isAbortError(error: unknown): boolean {
|
|
return (
|
|
!!error &&
|
|
typeof error === 'object' &&
|
|
'name' in error &&
|
|
typeof (error as { name?: unknown }).name === 'string' &&
|
|
(error as { name: string }).name === 'AbortError'
|
|
);
|
|
}
|
|
|
|
export class FileReadTimeoutError extends Error {
|
|
constructor(
|
|
public readonly filePath: string,
|
|
public readonly timeoutMs: number
|
|
) {
|
|
super(`Timed out after ${timeoutMs}ms reading ${filePath}`);
|
|
this.name = 'FileReadTimeoutError';
|
|
}
|
|
}
|
|
|
|
export async function readFileUtf8WithTimeout(
|
|
filePath: string,
|
|
timeoutMs: number
|
|
): Promise<string> {
|
|
const controller = new AbortController();
|
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
|
|
try {
|
|
return await fs.promises.readFile(filePath, { encoding: 'utf8', signal: controller.signal });
|
|
} catch (error) {
|
|
if (isAbortError(error)) {
|
|
throw new FileReadTimeoutError(filePath, timeoutMs);
|
|
}
|
|
throw error;
|
|
} finally {
|
|
clearTimeout(timeoutId);
|
|
}
|
|
}
|