Skip to content

Commit 2f8cb21

Browse files
committed
chore: log v2 payloads on failure
1 parent b37d40d commit 2f8cb21

File tree

1 file changed

+70
-56
lines changed

1 file changed

+70
-56
lines changed

src/controllers/settingsController.ts

Lines changed: 70 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -71,76 +71,81 @@ export async function handleBuildSettingsV2(payload: BuildRequestV2) {
7171
throw new ValidationError('Request body is required');
7272
}
7373

74-
console.log('[COMAPEO-API] Received request for /v2 build.');
74+
try {
75+
console.log('[COMAPEO-API] Received request for /v2 build.');
7576

76-
const result = await buildComapeoCatV2(payload);
77-
const tmpDir = path.dirname(result.outputPath);
77+
const result = await buildComapeoCatV2(payload);
78+
const tmpDir = path.dirname(result.outputPath);
7879

79-
if (result.warnings.length > 0) {
80-
for (const warning of result.warnings) {
81-
console.warn(`[COMAPEO-API][WARN] ${warning}`);
80+
if (result.warnings.length > 0) {
81+
for (const warning of result.warnings) {
82+
console.warn(`[COMAPEO-API][WARN] ${warning}`);
83+
}
8284
}
83-
}
8485

85-
console.log(`[COMAPEO-API] Generated .comapeocat file: ${result.outputPath}. Starting validation.`);
86-
87-
try {
88-
const reader = new Reader(result.outputPath);
89-
const validationResult = await validateComapeocatWithTimeout(reader, result.outputPath);
90-
if (Array.isArray(validationResult) && validationResult.length > 0) {
91-
// Validation failed
92-
const errors = validationResult.map(e => `${e.message} at ${e.filePath || 'unknown file'}`).join('\n');
93-
console.error(`[COMAPEO-API] .comapeocat validation failed for ${result.outputPath}:\n${errors}`);
94-
// Clean up temp directory before throwing error
86+
console.log(`[COMAPEO-API] Generated .comapeocat file: ${result.outputPath}. Starting validation.`);
87+
88+
try {
89+
const reader = new Reader(result.outputPath);
90+
const validationResult = await validateComapeocatWithTimeout(reader, result.outputPath);
91+
if (Array.isArray(validationResult) && validationResult.length > 0) {
92+
// Validation failed
93+
const errors = validationResult.map(e => `${e.message} at ${e.filePath || 'unknown file'}`).join('\n');
94+
console.error(`[COMAPEO-API] .comapeocat validation failed for ${result.outputPath}:\n${errors}`);
95+
// Clean up temp directory before throwing error
96+
await fs.rm(tmpDir, { recursive: true, force: true }).catch(console.error);
97+
throw new ValidationError(`Generated .comapeocat file is invalid:\n${errors}`);
98+
}
99+
console.log(`[COMAPEO-API] .comapeocat validation successful for ${result.outputPath}.`);
100+
} catch (validationError: any) { // Explicitly type validationError as 'any' for broader compatibility
101+
// Handle errors during validation itself (e.g., file not found, reader issues)
102+
console.error(`[COMAPEO-API] Error during .comapeocat validation for ${result.outputPath}:`, validationError);
103+
// Clean up temp directory before re-throwing error
95104
await fs.rm(tmpDir, { recursive: true, force: true }).catch(console.error);
96-
throw new ValidationError(`Generated .comapeocat file is invalid:\n${errors}`);
105+
throw new ProcessingError(`Failed to validate generated .comapeocat file: ${validationError.message}`);
97106
}
98-
console.log(`[COMAPEO-API] .comapeocat validation successful for ${result.outputPath}.`);
99-
} catch (validationError: any) { // Explicitly type validationError as 'any' for broader compatibility
100-
// Handle errors during validation itself (e.g., file not found, reader issues)
101-
console.error(`[COMAPEO-API] Error during .comapeocat validation for ${result.outputPath}:`, validationError);
102-
// Clean up temp directory before re-throwing error
103-
await fs.rm(tmpDir, { recursive: true, force: true }).catch(console.error);
104-
throw new ProcessingError(`Failed to validate generated .comapeocat file: ${validationError.message}`);
105-
}
106107

107-
// Create a streaming response that cleans up after the file is sent
108-
const bunFile = Bun.file(result.outputPath);
109-
const originalStream = bunFile.stream();
108+
// Create a streaming response that cleans up after the file is sent
109+
const bunFile = Bun.file(result.outputPath);
110+
const originalStream = bunFile.stream();
110111

111-
console.log(`[COMAPEO-API] Sending .comapeocat file: ${result.fileName}`);
112+
console.log(`[COMAPEO-API] Sending .comapeocat file: ${result.fileName}`);
112113

113-
// Wrap the stream to ensure cleanup happens after streaming completes
114-
const reader = originalStream.getReader();
115-
const cleanupStream = new ReadableStream({
116-
async pull(controller) {
117-
const { done, value } = await reader.read();
118-
if (done) {
119-
controller.close();
120-
// Clean up temp directory after streaming is complete
114+
// Wrap the stream to ensure cleanup happens after streaming completes
115+
const reader = originalStream.getReader();
116+
const cleanupStream = new ReadableStream({
117+
async pull(controller) {
118+
const { done, value } = await reader.read();
119+
if (done) {
120+
controller.close();
121+
// Clean up temp directory after streaming is complete
122+
fs.rm(tmpDir, { recursive: true, force: true }).catch(console.error);
123+
} else {
124+
controller.enqueue(value);
125+
}
126+
},
127+
cancel() {
128+
// Clean up if the stream is cancelled/aborted
121129
fs.rm(tmpDir, { recursive: true, force: true }).catch(console.error);
122-
} else {
123-
controller.enqueue(value);
124130
}
125-
},
126-
cancel() {
127-
// Clean up if the stream is cancelled/aborted
128-
fs.rm(tmpDir, { recursive: true, force: true }).catch(console.error);
129-
}
130-
});
131+
});
131132

132-
const headers: Record<string, string> = {
133-
'Content-Type': 'application/octet-stream',
134-
'Content-Disposition': `attachment; filename="${path.basename(result.outputPath)}"`,
135-
'Content-Length': bunFile.size.toString(),
136-
};
133+
const headers: Record<string, string> = {
134+
'Content-Type': 'application/octet-stream',
135+
'Content-Disposition': `attachment; filename="${path.basename(result.outputPath)}"`,
136+
'Content-Length': bunFile.size.toString(),
137+
};
137138

138-
const warningsHeader = formatWarningsHeader(result.warnings);
139-
if (warningsHeader) {
140-
headers['X-Comapeo-Warnings'] = warningsHeader;
141-
}
139+
const warningsHeader = formatWarningsHeader(result.warnings);
140+
if (warningsHeader) {
141+
headers['X-Comapeo-Warnings'] = warningsHeader;
142+
}
142143

143-
return new Response(cleanupStream, { headers });
144+
return new Response(cleanupStream, { headers });
145+
} catch (error) {
146+
logV2PayloadForFailure(payload, error);
147+
throw error;
148+
}
144149
}
145150

146151
async function validateComapeocatWithTimeout(reader: Reader, outputPath: string) {
@@ -177,3 +182,12 @@ function formatWarningsHeader(warnings: string[]) {
177182
// Limit header size to a reasonable length to avoid header bloat
178183
return joined.length > 1024 ? `${joined.slice(0, 1021)}...` : joined;
179184
}
185+
186+
function logV2PayloadForFailure(payload: BuildRequestV2, error: unknown) {
187+
try {
188+
const serializedPayload = JSON.stringify(payload, null, 2);
189+
console.error('[COMAPEO-API][ERROR] /v2 build failed. Payload dump follows:', serializedPayload, error);
190+
} catch (serializationError) {
191+
console.error('[COMAPEO-API][ERROR] /v2 build failed and payload serialization threw an error:', serializationError, error);
192+
}
193+
}

0 commit comments

Comments
 (0)