MCPcopy Index your code
hub / github.com/heygen-com/hyperframes / handlePlan

Function handlePlan

packages/aws-lambda/src/handler.ts:228–298  ·  view source on GitHub ↗
(event: PlanEvent, deps?: HandlerDeps)

Source from the content-addressed store, hash-verified

226// ── Plan ────────────────────────────────────────────────────────────────────
227
228async function handlePlan(event: PlanEvent, deps?: HandlerDeps): Promise<PlanLambdaResult> {
229 const started = Date.now();
230 const s3 = deps?.s3 ?? getS3Client();
231 const primitive = deps?.primitives?.plan ?? plan;
232
233 // The producer's probe stage launches Chromium whenever the composition
234 // needs a runtime duration probe or has unresolved sub-compositions, so
235 // plan has to resolve Chrome the same way renderChunk does. Without this
236 // the probe throws "An `executablePath` or `channel` must be specified
237 // for `puppeteer-core`" the moment runProbeStage calls puppeteer.launch.
238 if (!deps?.skipChromeResolution && !process.env.PRODUCER_HEADLESS_SHELL_PATH) {
239 const chromePath = await resolveChromeExecutablePath();
240 process.env.PRODUCER_HEADLESS_SHELL_PATH = chromePath;
241 }
242
243 const work = mkdtempSync(join(deps?.tmpRoot ?? tmpdir(), "hf-lambda-plan-"));
244 // We use `.tar.gz` (not `.zip`) as the project archive's on-the-wire
245 // format because Lambda's Amazon Linux base image ships GNU `tar` but
246 // not `unzip` in `/usr/bin`. The smoke script + future CLI both
247 // produce tar.gz uploads.
248 const projectArchive = join(work, "project.tar.gz");
249 const projectDir = join(work, "project");
250 const planDir = join(work, "plan");
251
252 try {
253 await downloadS3ObjectToFile(s3, event.ProjectS3Uri, projectArchive);
254 await untarDirectory(projectArchive, projectDir);
255
256 const config: DistributedRenderConfig = {
257 ...event.Config,
258 };
259 const result: PlanResult = await primitive(projectDir, config, planDir);
260
261 // Upload the planDir as a single tarball. Step Functions cannot pass
262 // a directory-shaped artifact between states; we serialize and rely on
263 // the consumer (renderChunk / assemble) to untar. Audio is co-located
264 // alongside the plan so RenderChunk doesn't have to pull the whole
265 // plan tarball when audio isn't relevant to the chunk.
266 const planTar = join(work, "plan.tar.gz");
267 await tarDirectory(planDir, planTar);
268 const planTarUri = `${trimTrailingSlash(event.PlanOutputS3Prefix)}/plan.tar.gz`;
269 const audioPath = join(planDir, "audio.aac");
270 const hasAudio = existsSync(audioPath) && statSync(audioPath).size > 0;
271 const audioUri = hasAudio ? `${trimTrailingSlash(event.PlanOutputS3Prefix)}/audio.aac` : null;
272 // Plan and audio are independent S3 PUTs; run them in parallel so
273 // the response returns as soon as the slower of the two completes.
274 await Promise.all([
275 uploadFileToS3(s3, planTar, planTarUri, "application/gzip"),
276 hasAudio && audioUri ? uploadFileToS3(s3, audioPath, audioUri, "audio/aac") : null,
277 ]);
278
279 return {
280 Action: "plan",
281 PlanS3Uri: planTarUri,
282 PlanHash: result.planHash,
283 ChunkCount: result.chunkCount,
284 TotalFrames: result.totalFrames,
285 Fps: result.fps,

Callers 1

handlerFunction · 0.70

Calls 9

getS3ClientFunction · 0.85
downloadS3ObjectToFileFunction · 0.85
uploadFileToS3Function · 0.85
nowMethod · 0.80
untarDirectoryFunction · 0.70
tarDirectoryFunction · 0.70
trimTrailingSlashFunction · 0.70
cleanupDirFunction · 0.70

Tested by

no test coverage detected