@remotion/lambda 4.0.16 → 4.0.17

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.
@@ -47,6 +47,7 @@ const getCompositionsOnLambda = async ({ chromiumOptions, serveUrl, region, inpu
47
47
  region,
48
48
  receivedStreamingPayload: () => undefined,
49
49
  timeoutInTest: 120000,
50
+ retriesRemaining: 0,
50
51
  });
51
52
  return res.compositions;
52
53
  }
@@ -22,6 +22,7 @@ const getRenderProgress = async (input) => {
22
22
  region: input.region,
23
23
  receivedStreamingPayload: () => undefined,
24
24
  timeoutInTest: 120000,
25
+ retriesRemaining: 2,
25
26
  });
26
27
  return result;
27
28
  };
@@ -35,6 +35,7 @@ const renderMediaOnLambda = async (input) => {
35
35
  region,
36
36
  receivedStreamingPayload: () => undefined,
37
37
  timeoutInTest: 120000,
38
+ retriesRemaining: 0,
38
39
  });
39
40
  return {
40
41
  renderId: res.renderId,
@@ -77,6 +77,7 @@ const renderStillOnLambda = async ({ functionName, serveUrl, inputProps, imageFo
77
77
  }
78
78
  },
79
79
  timeoutInTest: 120000,
80
+ retriesRemaining: 0,
80
81
  });
81
82
  return {
82
83
  estimatedPrice: res.estimatedPrice,
@@ -462,6 +462,11 @@ const innerLaunchHandler = async (params, options) => {
462
462
  region: (0, get_current_region_1.getCurrentRegionInFunction)(),
463
463
  serialized: params.inputProps,
464
464
  });
465
+ const cleanupResolvedInputPropsProm = (0, cleanup_serialized_input_props_1.cleanupSerializedResolvedProps)({
466
+ bucketName: params.bucketName,
467
+ region: (0, get_current_region_1.getCurrentRegionInFunction)(),
468
+ serialized: serializedResolvedProps,
469
+ });
465
470
  const outputUrl = (0, get_output_url_from_metadata_1.getOutputUrlFromMetadata)(renderMetadata, params.bucketName, customCredentials);
466
471
  const postRenderData = (0, create_post_render_data_1.createPostRenderData)({
467
472
  expectedBucketOwner: options.expectedBucketOwner,
@@ -472,7 +477,11 @@ const innerLaunchHandler = async (params, options) => {
472
477
  contents,
473
478
  errorExplanations: await errorExplanationsProm,
474
479
  timeToEncode: encodingStop - encodingStart,
475
- timeToDelete: (await Promise.all([deletProm, cleanupSerializedInputPropsProm])).reduce((a, b) => a + b, 0),
480
+ timeToDelete: (await Promise.all([
481
+ deletProm,
482
+ cleanupSerializedInputPropsProm,
483
+ cleanupResolvedInputPropsProm,
484
+ ])).reduce((a, b) => a + b, 0),
476
485
  outputFile: {
477
486
  lastModified: Date.now(),
478
487
  size: outputSize.size,
@@ -12,6 +12,7 @@ const call_lambda_1 = require("../shared/call-lambda");
12
12
  const chunk_progress_1 = require("../shared/chunk-progress");
13
13
  const compress_props_1 = require("../shared/compress-props");
14
14
  const constants_1 = require("../shared/constants");
15
+ const is_flaky_error_1 = require("../shared/is-flaky-error");
15
16
  const get_browser_instance_1 = require("./helpers/get-browser-instance");
16
17
  const get_chromium_executable_path_1 = require("./helpers/get-chromium-executable-path");
17
18
  const get_current_region_1 = require("./helpers/get-current-region");
@@ -223,15 +224,9 @@ const rendererHandler = async (params, options) => {
223
224
  console.log({ err });
224
225
  throw err;
225
226
  }
226
- const { message } = err;
227
227
  // If this error is encountered, we can just retry as it
228
228
  // is a very rare error to occur
229
- const isRetryableError = message.includes('FATAL:zygote_communication_linux.cc') ||
230
- message.includes('error while loading shared libraries: libnss3.so') ||
231
- message.includes('but the server sent no data') ||
232
- message.includes('Compositor panicked') ||
233
- (message.includes('Compositor exited') && !message.includes('SIGSEGV')) ||
234
- message.includes('Timed out while setting up the headless browser');
229
+ const isRetryableError = (0, is_flaky_error_1.isFlakyError)(err);
235
230
  const shouldNotRetry = err.name === 'CancelledError';
236
231
  const isFatal = !isRetryableError;
237
232
  const willRetry = isRetryableError && params.retriesLeft > 0 && !shouldNotRetry;
@@ -268,6 +263,7 @@ const rendererHandler = async (params, options) => {
268
263
  region: (0, get_current_region_1.getCurrentRegionInFunction)(),
269
264
  receivedStreamingPayload: () => undefined,
270
265
  timeoutInTest: 120000,
266
+ retriesRemaining: 0,
271
267
  });
272
268
  return res;
273
269
  }
@@ -16,6 +16,7 @@ const cleanup_serialized_input_props_1 = require("../shared/cleanup-serialized-i
16
16
  const compress_props_1 = require("../shared/compress-props");
17
17
  const constants_1 = require("../shared/constants");
18
18
  const convert_to_serve_url_1 = require("../shared/convert-to-serve-url");
19
+ const is_flaky_error_1 = require("../shared/is-flaky-error");
19
20
  const make_s3_url_1 = require("../shared/make-s3-url");
20
21
  const validate_download_behavior_1 = require("../shared/validate-download-behavior");
21
22
  const validate_outname_1 = require("../shared/validate-outname");
@@ -203,8 +204,7 @@ const stillHandler = async (options) => {
203
204
  catch (err) {
204
205
  // If this error is encountered, we can just retry as it
205
206
  // is a very rare error to occur
206
- const isBrowserError = err.message.includes('FATAL:zygote_communication_linux.cc') ||
207
- err.message.includes('error while loading shared libraries: libnss3.so');
207
+ const isBrowserError = (0, is_flaky_error_1.isFlakyError)(err);
208
208
  const willRetry = isBrowserError || params.maxRetries > 0;
209
209
  if (!willRetry) {
210
210
  throw err;
@@ -221,6 +221,7 @@ const stillHandler = async (options) => {
221
221
  type: constants_1.LambdaRoutines.still,
222
222
  receivedStreamingPayload: () => undefined,
223
223
  timeoutInTest: 120000,
224
+ retriesRemaining: 0,
224
225
  });
225
226
  const bucketName = (_a = params.bucketName) !== null && _a !== void 0 ? _a : (await (0, get_or_create_bucket_1.getOrCreateBucket)({
226
227
  region: (0, get_current_region_1.getCurrentRegionInFunction)(),
@@ -2,11 +2,15 @@ import type { StreamingPayloads } from '../functions/helpers/streaming-payloads'
2
2
  import type { AwsRegion } from '../pricing/aws-regions';
3
3
  import type { LambdaPayloads, LambdaRoutines } from './constants';
4
4
  import type { LambdaReturnValues } from './return-values';
5
- export declare const callLambda: <T extends LambdaRoutines>({ functionName, type, payload, region, receivedStreamingPayload, timeoutInTest, }: {
5
+ type Options<T extends LambdaRoutines> = {
6
6
  functionName: string;
7
7
  type: T;
8
- payload: Omit<LambdaPayloads[T], "type">;
8
+ payload: Omit<LambdaPayloads[T], 'type'>;
9
9
  region: AwsRegion;
10
10
  receivedStreamingPayload: (streamPayload: StreamingPayloads) => void;
11
11
  timeoutInTest: number;
12
+ };
13
+ export declare const callLambda: <T extends LambdaRoutines>(options: Options<T> & {
14
+ retriesRemaining: number;
12
15
  }) => Promise<LambdaReturnValues[T]>;
16
+ export {};
@@ -4,7 +4,30 @@ exports.callLambda = void 0;
4
4
  const client_lambda_1 = require("@aws-sdk/client-lambda");
5
5
  const streaming_payloads_1 = require("../functions/helpers/streaming-payloads");
6
6
  const aws_clients_1 = require("./aws-clients");
7
- const callLambda = async ({ functionName, type, payload, region, receivedStreamingPayload, timeoutInTest, }) => {
7
+ const INVALID_JSON_MESSAGE = 'Cannot parse Lambda response as JSON';
8
+ const callLambda = async (options) => {
9
+ // As of August 2023, Lambda streaming sometimes misses parts of the JSON response.
10
+ // Handling this for now by applying a retry mechanism.
11
+ try {
12
+ // Do not remove this await
13
+ const res = await callLambdaWithoutRetry(options);
14
+ return res;
15
+ }
16
+ catch (err) {
17
+ if (options.retriesRemaining === 0) {
18
+ throw err;
19
+ }
20
+ if (!err.message.includes(INVALID_JSON_MESSAGE)) {
21
+ throw err;
22
+ }
23
+ return (0, exports.callLambda)({
24
+ ...options,
25
+ retriesRemaining: options.retriesRemaining - 1,
26
+ });
27
+ }
28
+ };
29
+ exports.callLambda = callLambda;
30
+ const callLambdaWithoutRetry = async ({ functionName, type, payload, region, receivedStreamingPayload, timeoutInTest, }) => {
8
31
  const res = await (0, aws_clients_1.getLambdaClient)(region, timeoutInTest).send(new client_lambda_1.InvokeWithResponseStreamCommand({
9
32
  FunctionName: functionName,
10
33
  Payload: JSON.stringify({ type, ...payload }),
@@ -38,13 +61,12 @@ const callLambda = async ({ functionName, type, payload, region, receivedStreami
38
61
  const json = parseJson(responsePayload.trim());
39
62
  return json;
40
63
  };
41
- exports.callLambda = callLambda;
42
64
  const parseJsonWithErrorSurfacing = (input) => {
43
65
  try {
44
66
  return JSON.parse(input);
45
67
  }
46
68
  catch (_a) {
47
- throw new Error(`Cannot parse Lambda response as JSON. Response: ${input}`);
69
+ throw new Error(`${INVALID_JSON_MESSAGE}. Response: ${input}`);
48
70
  }
49
71
  };
50
72
  const parseJson = (input) => {
@@ -5,3 +5,8 @@ export declare const cleanupSerializedInputProps: ({ serialized, region, bucketN
5
5
  region: AwsRegion;
6
6
  bucketName: string;
7
7
  }) => Promise<number>;
8
+ export declare const cleanupSerializedResolvedProps: ({ serialized, region, bucketName, }: {
9
+ serialized: SerializedInputProps;
10
+ region: AwsRegion;
11
+ bucketName: string;
12
+ }) => Promise<number>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.cleanupSerializedInputProps = void 0;
3
+ exports.cleanupSerializedResolvedProps = exports.cleanupSerializedInputProps = void 0;
4
4
  const io_1 = require("../functions/helpers/io");
5
5
  const constants_1 = require("./constants");
6
6
  const cleanupSerializedInputProps = async ({ serialized, region, bucketName, }) => {
@@ -17,3 +17,17 @@ const cleanupSerializedInputProps = async ({ serialized, region, bucketName, })
17
17
  return Date.now() - time;
18
18
  };
19
19
  exports.cleanupSerializedInputProps = cleanupSerializedInputProps;
20
+ const cleanupSerializedResolvedProps = async ({ serialized, region, bucketName, }) => {
21
+ if (serialized.type === 'payload') {
22
+ return 0;
23
+ }
24
+ const time = Date.now();
25
+ await (0, io_1.lambdaDeleteFile)({
26
+ bucketName,
27
+ key: (0, constants_1.resolvedPropsKey)(serialized.hash),
28
+ region,
29
+ customCredentials: null,
30
+ });
31
+ return Date.now() - time;
32
+ };
33
+ exports.cleanupSerializedResolvedProps = cleanupSerializedResolvedProps;
@@ -14,6 +14,7 @@ const getFunctionVersion = async ({ functionName, region, }) => {
14
14
  type: constants_1.LambdaRoutines.info,
15
15
  receivedStreamingPayload: () => undefined,
16
16
  timeoutInTest: 120000,
17
+ retriesRemaining: 0,
17
18
  });
18
19
  return result.version;
19
20
  }
@@ -0,0 +1 @@
1
+ export declare const isFlakyError: (err: Error) => boolean;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isFlakyError = void 0;
4
+ const isFlakyError = (err) => {
5
+ const { message } = err;
6
+ // storage.googleapis.com sometimes returns 500s, and Video does not have retry on its own
7
+ if ((message.includes('Format error') || message.includes('audio metadata')) &&
8
+ message.includes('storage.googleapis.com')) {
9
+ return true;
10
+ }
11
+ if (message.includes('FATAL:zygote_communication_linux.cc')) {
12
+ return true;
13
+ }
14
+ if (message.includes('error while loading shared libraries: libnss3.so')) {
15
+ return true;
16
+ }
17
+ if (message.includes('but the server sent no data')) {
18
+ return true;
19
+ }
20
+ if (message.includes('Compositor panicked')) {
21
+ return true;
22
+ }
23
+ if (message.includes('Compositor exited') && !message.includes('SIGSEGV')) {
24
+ return true;
25
+ }
26
+ if (message.includes('Timed out while setting up the headless browser')) {
27
+ return true;
28
+ }
29
+ return false;
30
+ };
31
+ exports.isFlakyError = isFlakyError;
@@ -0,0 +1 @@
1
+ export declare const isFlakyError: (err: Error) => boolean;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isFlakyError = void 0;
4
+ const isFlakyError = (err) => {
5
+ const { message } = err;
6
+ return (message.includes('FATAL:zygote_communication_linux.cc') ||
7
+ message.includes('error while loading shared libraries: libnss3.so') ||
8
+ message.includes('but the server sent no data') ||
9
+ message.includes('Compositor panicked') ||
10
+ (message.includes('Compositor exited') && !message.includes('SIGSEGV')) ||
11
+ message.includes('Timed out while setting up the headless browser'));
12
+ };
13
+ exports.isFlakyError = isFlakyError;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/lambda",
3
- "version": "4.0.16",
3
+ "version": "4.0.17",
4
4
  "description": "Distributed renderer for Remotion based on AWS Lambda",
5
5
  "main": "dist/index.js",
6
6
  "sideEffects": false,
@@ -26,10 +26,10 @@
26
26
  "aws-policies": "^1.0.1",
27
27
  "mime-types": "2.1.34",
28
28
  "zod": "3.21.4",
29
- "@remotion/bundler": "4.0.16",
30
- "@remotion/cli": "4.0.16",
31
- "@remotion/renderer": "4.0.16",
32
- "remotion": "4.0.16"
29
+ "@remotion/bundler": "4.0.17",
30
+ "remotion": "4.0.17",
31
+ "@remotion/renderer": "4.0.17",
32
+ "@remotion/cli": "4.0.17"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@jonny/eslint-config": "3.0.266",
@@ -44,11 +44,11 @@
44
44
  "typescript": "4.9.5",
45
45
  "vitest": "0.31.1",
46
46
  "zip-lib": "^0.7.2",
47
- "@remotion/bundler": "4.0.16",
48
- "@remotion/compositor-linux-arm64-gnu": "4.0.16"
47
+ "@remotion/bundler": "4.0.17",
48
+ "@remotion/compositor-linux-arm64-gnu": "4.0.17"
49
49
  },
50
50
  "peerDependencies": {
51
- "@remotion/bundler": "4.0.16"
51
+ "@remotion/bundler": "4.0.17"
52
52
  },
53
53
  "publishConfig": {
54
54
  "access": "public"
Binary file