@remotion/serverless 4.0.516 → 4.0.517

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,23 @@
1
+ import type { EmittedArtifact } from '@remotion/renderer';
2
+ type ArtifactRegistration = {
3
+ chunk: number;
4
+ frame: number;
5
+ attempt: number;
6
+ filename: string;
7
+ };
8
+ export type ArtifactRegistrationResult = {
9
+ type: 'accepted';
10
+ } | {
11
+ type: 'retry-replay';
12
+ } | {
13
+ type: 'conflict';
14
+ };
15
+ export type OnArtifactFromRenderer = (params: {
16
+ artifact: EmittedArtifact;
17
+ chunk: number;
18
+ attempt: number;
19
+ }) => ArtifactRegistrationResult;
20
+ export declare const makeArtifactRegistry: () => {
21
+ registerArtifact: (artifact: ArtifactRegistration) => ArtifactRegistrationResult;
22
+ };
23
+ export {};
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeArtifactRegistry = void 0;
4
+ const makeArtifactRegistry = () => {
5
+ const artifactsByFilename = new Map();
6
+ const artifactsByAttempt = new Set();
7
+ const registerArtifact = (artifact) => {
8
+ const attemptKey = JSON.stringify([
9
+ artifact.chunk,
10
+ artifact.attempt,
11
+ artifact.filename,
12
+ ]);
13
+ if (artifactsByAttempt.has(attemptKey)) {
14
+ return { type: 'conflict' };
15
+ }
16
+ artifactsByAttempt.add(attemptKey);
17
+ const existingArtifact = artifactsByFilename.get(artifact.filename);
18
+ if (!existingArtifact) {
19
+ artifactsByFilename.set(artifact.filename, artifact);
20
+ return { type: 'accepted' };
21
+ }
22
+ if (existingArtifact.chunk === artifact.chunk &&
23
+ existingArtifact.frame === artifact.frame &&
24
+ artifact.attempt > existingArtifact.attempt) {
25
+ return { type: 'retry-replay' };
26
+ }
27
+ return { type: 'conflict' };
28
+ };
29
+ return { registerArtifact };
30
+ };
31
+ exports.makeArtifactRegistry = makeArtifactRegistry;
@@ -6,6 +6,7 @@ const path_1 = require("path");
6
6
  const renderer_1 = require("@remotion/renderer");
7
7
  const serverless_client_1 = require("@remotion/serverless-client");
8
8
  const serverless_client_2 = require("@remotion/serverless-client");
9
+ const artifact_registry_1 = require("../artifact-registry");
9
10
  const cleanup_props_1 = require("../cleanup-props");
10
11
  const find_output_file_in_bucket_1 = require("../find-output-file-in-bucket");
11
12
  const get_tmp_dir_1 = require("../get-tmp-dir");
@@ -298,12 +299,17 @@ const innerLaunchHandler = async ({ params, options, overallProgress, registerCl
298
299
  }
299
300
  (0, fs_1.mkdirSync)(outdir);
300
301
  const files = [];
301
- const onArtifact = (artifact) => {
302
+ const artifactRegistry = (0, artifact_registry_1.makeArtifactRegistry)();
303
+ const onArtifact = ({ artifact, chunk, attempt }) => {
302
304
  var _a;
303
- if (overallProgress
304
- .getReceivedArtifacts()
305
- .find((a) => a.filename === artifact.filename)) {
306
- return { alreadyExisted: true };
305
+ const artifactRegistration = artifactRegistry.registerArtifact({
306
+ chunk,
307
+ frame: artifact.frame,
308
+ attempt,
309
+ filename: artifact.filename,
310
+ });
311
+ if (artifactRegistration.type !== 'accepted') {
312
+ return artifactRegistration;
307
313
  }
308
314
  const region = insideFunctionSpecifics.getCurrentRegionInFunction();
309
315
  const storageKey = (0, serverless_client_2.artifactName)(renderMetadata.renderId, artifact.filename);
@@ -340,16 +346,16 @@ const innerLaunchHandler = async ({ params, options, overallProgress, registerCl
340
346
  stack: err.stack,
341
347
  tmpDir: null,
342
348
  frame: artifact.frame,
343
- chunk: null,
349
+ chunk,
344
350
  isFatal: false,
345
- attempt: 1,
351
+ attempt,
346
352
  willRetry: false,
347
353
  totalAttempts: 1,
348
354
  });
349
355
  overallProgress.upload('artifactWriteError');
350
356
  renderer_1.RenderInternals.Log.error({ indent: false, logLevel: params.logLevel }, 'Failed to write artifact to S3', err);
351
357
  });
352
- return { alreadyExisted: false };
358
+ return artifactRegistration;
353
359
  };
354
360
  await Promise.all(lambdaPayloads.map(async (payload) => {
355
361
  await (0, stream_renderer_1.renderRendererFunctionWithRetry)({
@@ -1,5 +1,5 @@
1
- import type { EmittedArtifact } from '@remotion/renderer';
2
1
  import type { CloudProvider, ProviderSpecifics, ServerlessPayload } from '@remotion/serverless-client';
2
+ import type { OnArtifactFromRenderer } from './artifact-registry';
3
3
  import type { OverallProgressHelper } from './overall-render-progress';
4
4
  import type { InsideFunctionSpecifics } from './provider-implementation';
5
5
  export declare const renderRendererFunctionWithRetry: <Provider extends CloudProvider<string, Record<string, unknown>, Record<string, unknown>, string, object>>({ payload, files, functionName, outdir, overallProgress, logLevel, onArtifact, providerSpecifics, insideFunctionSpecifics, requestHandler, expectedBucketOwner, }: {
@@ -9,9 +9,7 @@ export declare const renderRendererFunctionWithRetry: <Provider extends CloudPro
9
9
  overallProgress: OverallProgressHelper<Provider>;
10
10
  files: string[];
11
11
  logLevel: "error" | "info" | "trace" | "verbose" | "warn";
12
- onArtifact: (asset: EmittedArtifact) => {
13
- alreadyExisted: boolean;
14
- };
12
+ onArtifact: OnArtifactFromRenderer;
15
13
  providerSpecifics: ProviderSpecifics<Provider>;
16
14
  insideFunctionSpecifics: InsideFunctionSpecifics<Provider>;
17
15
  requestHandler: Provider["requestHandler"] | null;
@@ -76,14 +76,21 @@ const streamRenderer = ({ payload, functionName, outdir, overallProgress, files,
76
76
  if (message.type === 'artifact-emitted') {
77
77
  const artifact = (0, serverless_client_1.deserializeArtifact)(message.payload.artifact);
78
78
  renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `Received artifact on frame ${message.payload.artifact.frame}:`, artifact.filename, artifact.content.length + 'bytes.');
79
- const { alreadyExisted } = onArtifact(artifact);
80
- if (alreadyExisted) {
79
+ const artifactRegistration = onArtifact({
80
+ artifact,
81
+ chunk: payload.chunk,
82
+ attempt: payload.attempt,
83
+ });
84
+ if (artifactRegistration.type === 'conflict') {
81
85
  return resolve({
82
86
  type: 'error',
83
87
  error: `Chunk ${payload.chunk} emitted an asset filename ${message.payload.artifact.filename} at frame ${message.payload.artifact.frame} but there is already another artifact with the same name. https://remotion.dev/docs/artifacts`,
84
88
  shouldRetry: false,
85
89
  });
86
90
  }
91
+ if (artifactRegistration.type === 'retry-replay') {
92
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `Ignoring artifact ${artifact.filename} replayed by attempt ${payload.attempt} of chunk ${payload.chunk}`);
93
+ }
87
94
  return;
88
95
  }
89
96
  if (message.type === 'error-occurred') {
@@ -309,14 +316,21 @@ const s3Renderer = async ({ payload, functionName, outdir, overallProgress, file
309
316
  downloadedKeys.push(key);
310
317
  }
311
318
  for (const emittedArtifact of emittedArtifacts) {
312
- const { alreadyExisted } = onArtifact(emittedArtifact);
313
- if (alreadyExisted) {
319
+ const artifactRegistration = onArtifact({
320
+ artifact: emittedArtifact,
321
+ chunk: payload.chunk,
322
+ attempt: payload.attempt,
323
+ });
324
+ if (artifactRegistration.type === 'conflict') {
314
325
  return {
315
326
  type: 'error',
316
327
  error: `Chunk ${payload.chunk} emitted an asset filename ${emittedArtifact.filename} at frame ${emittedArtifact.frame} but there is already another artifact with the same name. https://remotion.dev/docs/artifacts`,
317
328
  shouldRetry: false,
318
329
  };
319
330
  }
331
+ if (artifactRegistration.type === 'retry-replay') {
332
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `Ignoring artifact ${emittedArtifact.filename} replayed by attempt ${payload.attempt} of chunk ${payload.chunk}`);
333
+ }
320
334
  }
321
335
  files.push(...downloadedFiles);
322
336
  overallProgress.addChunkCompleted(payload.chunk, status.startedAt, status.completedAt);
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/serverless"
4
4
  },
5
5
  "name": "@remotion/serverless",
6
- "version": "4.0.516",
6
+ "version": "4.0.517",
7
7
  "description": "A runtime for distributed rendering",
8
8
  "main": "dist",
9
9
  "scripts": {
@@ -23,13 +23,13 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@remotion/renderer": "4.0.516",
27
- "@remotion/bundler": "4.0.516",
28
- "@remotion/licensing": "4.0.516",
29
- "@remotion/serverless-client": "4.0.516"
26
+ "@remotion/renderer": "4.0.517",
27
+ "@remotion/bundler": "4.0.517",
28
+ "@remotion/licensing": "4.0.517",
29
+ "@remotion/serverless-client": "4.0.517"
30
30
  },
31
31
  "devDependencies": {
32
- "@remotion/eslint-config-internal": "4.0.516",
32
+ "@remotion/eslint-config-internal": "4.0.517",
33
33
  "eslint": "9.19.0",
34
34
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
35
35
  },