Skip to content

Commit 3331d7e

Browse files
committed
prepare and request labeling after generating manifest
1 parent 54e2d1c commit 3331d7e

File tree

2 files changed

+158
-1
lines changed

2 files changed

+158
-1
lines changed

src/apiService/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,14 @@ export class ApiService {
2929
path: string,
3030
body?: object,
3131
) {
32+
const headers = this.getHeaders();
33+
if (body) {
34+
headers.set("Content-Type", "application/json");
35+
}
36+
3237
const response = await fetch(`${this.apiHost}${path}`, {
3338
method,
34-
headers: this.getHeaders(),
39+
headers,
3540
body: body ? JSON.stringify(body) : undefined,
3641
});
3742
return response;

src/cli/handlers/manifest/generate.ts

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ function builder(
4545
}
4646
return value;
4747
},
48+
}).option("upload-batch", {
49+
type: "number",
50+
description: "Number of files to process in parallel batches",
51+
default: 20,
4852
});
4953
}
5054

@@ -128,6 +132,7 @@ async function handler(
128132
branch?: string;
129133
commitSha?: string;
130134
commitShaDate?: string;
135+
"upload-batch": number;
131136
},
132137
) {
133138
const napiConfig = argv.napiConfig as z.infer<typeof localConfigSchema>;
@@ -274,6 +279,15 @@ async function handler(
274279
`\nView it here: https://app.nanoapi.io/projects/${projectId}/manifests/${responseBody.id}`,
275280
);
276281
}
282+
283+
console.info("🔍 Requesting labeling...");
284+
await requestLabeling(
285+
files,
286+
responseBody.id,
287+
apiService,
288+
argv["upload-batch"],
289+
);
290+
console.info("✅ Labeling requested successfully");
277291
} catch (error) {
278292
console.error(
279293
`❌ Failed to upload manifest to API for project id: ${projectId}`,
@@ -305,3 +319,141 @@ export default {
305319
builder,
306320
handler,
307321
};
322+
323+
async function requestLabeling(
324+
files: Map<string, { path: string; content: string }>,
325+
manifestId: number,
326+
apiService: ApiService,
327+
batchSize: number,
328+
) {
329+
// Prepare for labeling
330+
console.info("🔍 Preparing for labeling...");
331+
const filesArray = Array.from(files.values());
332+
333+
// Upload files in configurable batches
334+
const allUploadResults: { path: string; bucketName: string | null }[] = [];
335+
336+
for (let i = 0; i < filesArray.length; i += batchSize) {
337+
const batch = filesArray.slice(i, i + batchSize);
338+
const batchNumber = Math.floor(i / batchSize) + 1;
339+
const totalBatches = Math.ceil(filesArray.length / batchSize);
340+
341+
console.info(
342+
`📝 Processing batch ${batchNumber}/${totalBatches} (${batch.length} files)...`,
343+
);
344+
345+
// Separate empty files from files that need uploading
346+
const filesToUpload = batch.filter((file) =>
347+
file.content && file.content.trim() !== ""
348+
);
349+
const emptyFiles = batch.filter((file) =>
350+
!file.content || file.content.trim() === ""
351+
);
352+
353+
// Add empty files to results with null bucket names
354+
emptyFiles.forEach((file) => {
355+
allUploadResults.push({ path: file.path, bucketName: null });
356+
});
357+
358+
// Upload non-empty files in parallel
359+
if (filesToUpload.length > 0) {
360+
const batchPromises = filesToUpload.map(async (file) => {
361+
try {
362+
const response = await apiService.performRequest(
363+
"POST",
364+
"/labeling/temp",
365+
{ path: file.path, content: file.content },
366+
);
367+
368+
if (response.status !== 200) {
369+
const errorText = await response.text();
370+
throw new Error(
371+
`Failed to upload file ${file.path}: ${errorText} ${response.status}`,
372+
);
373+
}
374+
375+
const { bucketName } = await response.json() as {
376+
bucketName: string;
377+
};
378+
return { path: file.path, bucketName };
379+
} catch (error) {
380+
console.error(
381+
`❌ Failed to upload ${file.path}: ${
382+
error instanceof Error ? error.message : String(error)
383+
}`,
384+
);
385+
return null;
386+
}
387+
});
388+
389+
const batchResults = await Promise.all(batchPromises);
390+
const successfulResults = batchResults.filter((
391+
result,
392+
): result is { path: string; bucketName: string } => result !== null);
393+
allUploadResults.push(...successfulResults);
394+
395+
const skippedCount = emptyFiles.length;
396+
const failedCount = filesToUpload.length - successfulResults.length;
397+
398+
if (failedCount > 0) {
399+
console.warn(
400+
`⚠️ Batch ${batchNumber} completed (${successfulResults.length} uploaded, ${failedCount} failed, ${skippedCount} skipped)`,
401+
);
402+
} else {
403+
console.info(
404+
`✅ Batch ${batchNumber} completed (${successfulResults.length} files uploaded, ${skippedCount} skipped)`,
405+
);
406+
}
407+
} else {
408+
console.info(
409+
`✅ Batch ${batchNumber} completed (${emptyFiles.length} files skipped)`,
410+
);
411+
}
412+
}
413+
414+
const labelingMap = Object.fromEntries(
415+
allUploadResults.map(({ path, bucketName }) => [path, bucketName]),
416+
);
417+
418+
// Upload labeling payload as a temp file
419+
const labelingMapFile = await apiService.performRequest(
420+
"POST",
421+
"/labeling/temp",
422+
{
423+
path: "labelingMapFile.json",
424+
content: JSON.stringify(labelingMap, null, 2),
425+
},
426+
);
427+
428+
if (labelingMapFile.status !== 200) {
429+
console.error(`❌ Failed to upload labeling payload`);
430+
Deno.exit(1);
431+
}
432+
433+
const labelingFileMapFileResponse = await labelingMapFile.json() as {
434+
bucketName: string;
435+
};
436+
437+
console.info(`✅ Labeling preparation completed successfully`);
438+
439+
// request labeling to API with the temp file
440+
const labelingResponse = await apiService.performRequest(
441+
"POST",
442+
"/labeling/request",
443+
{
444+
manifestId,
445+
fileMapName: labelingFileMapFileResponse.bucketName,
446+
},
447+
);
448+
449+
if (labelingResponse.status !== 200) {
450+
console.error(`❌ Failed to request labeling`);
451+
console.error(
452+
` Error: ${labelingResponse.statusText} ${labelingResponse.status} ${await labelingResponse
453+
.text()}`,
454+
);
455+
Deno.exit(1);
456+
}
457+
458+
console.info(`✅ Labeling request completed successfully`);
459+
}

0 commit comments

Comments
 (0)