Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deleteRender() API #1337

Merged
merged 7 commits into from
Sep 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
55 changes: 55 additions & 0 deletions packages/docs/docs/lambda/deleterender.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
id: deleterender
title: deleteRender()
slug: /lambda/deleterender
---

Deletes a rendered video, audio or still and it's associated metada.

```ts twoslash
// @module: ESNext
// @target: ESNext
import { deleteRender } from "@remotion/lambda";

const { freedBytes } = await deleteRender({
bucketName: "remotionlambda-r42fs9fk",
region: "us-east-1",
renderId: "8hfxlw",
});

console.log(freedBytes); // 21249541
```

## Arguments

An object with the following properties:

### `region`

The [AWS region](/docs/lambda/region-selection) in which the render has performed.

### `bucketName`

The bucket name in which the render was stored. This should be the same variable you used for [`renderMediaOnLambda()`](/docs/lambda/rendermediaonlambda) or [`renderStillOnLambda()`](/docs/lambda/renderstillonlambda).

### `renderId`

The ID of the render. You can retrieve this ID by calling [`renderMediaOnLambda()`](/docs/lambda/rendermediaonlambda) or [`renderStillOnLambda()`](/docs/lambda/renderstillonlambda).

### `customCredentials`

_optional, available from v3.2.23_

If the render was saved to a [different cloud](/docs/lambda/custom-destination#saving-to-another-cloud), pass an object with the same `endpoint`, `accessKeyId` and `secretAccessKey` as you passed to [`renderMediaOnLambda()`](/docs/lambda/rendermediaonlambda#outname) or [`renderStillOnLambda()`](/docs/lambda/renderstillonlambda#outname).

## Return value

Returns a promise resolving to an object with the following properties:

### `freedBytes`

The amount of bytes that were removed from the S3 bucket.

## See also

- [Source code for this function](https://github.com/remotion-dev/remotion/blob/main/packages/lambda/src/api/delete-render.ts)
2 changes: 1 addition & 1 deletion packages/docs/docs/lambda/downloadmedia.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ The [AWS region](/docs/lambda/region-selection) in which the render has performe

### `bucketName`

The bucket name in which you the render was stored. This should be the same variable you used for `renderMediaOnLambda()`.
The bucket name in which the render was stored. This should be the same variable you used for [`renderMediaOnLambda()`](/docs/lambda/rendermediaonlambda) or [`renderStillOnLambda()`](/docs/lambda/renderstillonlambda).

### `renderId`

Expand Down
1 change: 1 addition & 0 deletions packages/docs/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ module.exports = {
"lambda/getregions",
"lambda/getsites",
"lambda/downloadmedia",
"lambda/deleterender",
"lambda/getuserpolicy",
"lambda/getrolepolicy",
"lambda/getorcreatebucket",
Expand Down
80 changes: 80 additions & 0 deletions packages/lambda/src/api/delete-render.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import type {AwsRegion} from '../client';
import {rendersPrefix} from '../defaults';
import {getExpectedOutName} from '../functions/helpers/expected-out-name';
import {getRenderMetadata} from '../functions/helpers/get-render-metadata';
import {lambdaDeleteFile, lambdaLs} from '../functions/helpers/io';
import type {CustomCredentials} from '../shared/aws-clients';
import {getAccountId} from '../shared/get-account-id';
import {cleanItems} from './clean-items';

export type DeleteRenderInput = {
region: AwsRegion;
bucketName: string;
renderId: string;
customCredentials?: CustomCredentials;
};

/**
* @description Deletes a render artifact and it's metadata given it's renderId.
* @link https://remotion.dev/docs/lambda/deleterender
* @param params.region The AWS region in which the media resides.
* @param params.bucketName The `bucketName` that was specified during the render
* @param params.renderId The `renderId` that was obtained after triggering the render.
* @param params.customCredentials If the file was saved to a foreign cloud, pass credentials for reading from it.
*/
export const deleteRender = async (input: DeleteRenderInput) => {
const expectedBucketOwner = await getAccountId({
region: input.region,
});
const renderMetadata = await getRenderMetadata({
bucketName: input.bucketName,
expectedBucketOwner,
region: input.region,
renderId: input.renderId,
});

const {key, renderBucketName, customCredentials} = getExpectedOutName(
renderMetadata,
input.bucketName,
input.customCredentials ?? null
);

await lambdaDeleteFile({
bucketName: renderBucketName,
customCredentials,
key,
region: input.region,
});

let files = await lambdaLs({
bucketName: input.bucketName,
prefix: rendersPrefix(input.renderId),
region: input.region,
expectedBucketOwner,
});

let totalSize = 0;

while (files.length > 0) {
totalSize += files.reduce((a, b) => {
return a + (b.Size ?? 0);
}, 0);
await cleanItems({
list: files.map((f) => f.Key as string),
bucket: input.bucketName,
onAfterItemDeleted: () => undefined,
onBeforeItemDeleted: () => undefined,
region: input.region,
});
files = await lambdaLs({
bucketName: input.bucketName,
prefix: rendersPrefix(input.renderId),
region: input.region,
expectedBucketOwner,
});
}

return {
freedBytes: totalSize,
};
};
6 changes: 0 additions & 6 deletions packages/lambda/src/api/delete-site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,6 @@ export const deleteSite = async ({
expectedBucketOwner: accountId,
});

if (files.length === 0) {
return {
totalSizeInBytes: 0,
};
}

let totalSize = 0;

while (files.length > 0) {
Expand Down
2 changes: 1 addition & 1 deletion packages/lambda/src/api/download-media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export type DownloadMediaOutput = {
* @link https://remotion.dev/docs/lambda/downloadmedia
* @param params.region The AWS region in which the media resides.
* @param params.bucketName The `bucketName` that was specified during the render.
* @param params.renderId The `renderId` that was obtainer after triggering the render.
* @param params.renderId The `renderId` that was obtained after triggering the render.
* @param params.outPath Where to save the media.
* @param params.onProgress Progress callback function - see docs for details.
* @param params.customCredentials If the file was saved to a foreign cloud, pass credentials for reading from it.
Expand Down
4 changes: 3 additions & 1 deletion packages/lambda/src/functions/helpers/io.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,14 @@ export const lambdaDeleteFile = async ({
bucketName,
key,
region,
customCredentials,
}: {
region: AwsRegion;
bucketName: string;
key: string;
customCredentials: CustomCredentials | null;
}) => {
await getS3Client(region, null).send(
await getS3Client(region, customCredentials).send(
new DeleteObjectCommand({
Bucket: bucketName,
Key: key,
Expand Down
1 change: 1 addition & 0 deletions packages/lambda/src/functions/launch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ const innerLaunchHandler = async (params: LambdaPayload, options: Options) => {
bucketName: params.bucketName,
key: initalizedMetadataKey(params.renderId),
region: getCurrentRegionInFunction(),
customCredentials: null,
});

await Promise.all([cleanupChunksProm, fs.promises.rm(outfile)]);
Expand Down
2 changes: 2 additions & 0 deletions packages/lambda/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {DeleteFunctionInput} from './api/delete-function';
import {deleteFunction} from './api/delete-function';
import {deleteRender} from './api/delete-render';
import type {DeleteSiteInput, DeleteSiteOutput} from './api/delete-site';
import {deleteSite} from './api/delete-site';
import type {
Expand Down Expand Up @@ -85,6 +86,7 @@ export {
getRegions,
getAwsClient,
presignUrl,
deleteRender,
};
export type {
AwsRegion,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import fs, {createWriteStream} from 'fs';
import os from 'os';
import path from 'path';
import {VERSION} from 'remotion/version';
import {LambdaRoutines} from '../../../defaults';
import {deleteRender} from '../../../api/delete-render';
import {LambdaRoutines, rendersPrefix} from '../../../defaults';
import {handler} from '../../../functions';
import {lambdaReadFile} from '../../../functions/helpers/io';
import {lambdaLs, lambdaReadFile} from '../../../functions/helpers/io';
import type {LambdaReturnValues} from '../../../shared/return-values';
import {disableLogs, enableLogs} from '../../disable-logs';

Expand Down Expand Up @@ -97,4 +98,28 @@ test('Should make a transparent video', async () => {
expect(probe.stderr).toMatch(/Video: vp8, yuv420p/);
expect(probe.stderr).toMatch(/Audio: opus, 48000 Hz/);
fs.unlinkSync(out);

const files = await lambdaLs({
bucketName: progress.outBucket as string,
region: 'eu-central-1',
expectedBucketOwner: 'abc',
prefix: rendersPrefix(startRes.renderId),
});

expect(files.length).toBe(4);

await deleteRender({
bucketName: progress.outBucket as string,
region: 'eu-central-1',
renderId: startRes.renderId,
});

const expectFiles = await lambdaLs({
bucketName: progress.outBucket as string,
region: 'eu-central-1',
expectedBucketOwner: 'abc',
prefix: rendersPrefix(startRes.renderId),
});

expect(expectFiles.length).toBe(0);
});