Skip to content

Commit 0cfd738

Browse files
committed
Remove CloudFront invalidations; simplify S3 handling
1 parent 1c24b2f commit 0cfd738

3 files changed

Lines changed: 21 additions & 157 deletions

File tree

apps/web/actions/video/upload.ts

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
"use server";
22

3-
import {
4-
CloudFrontClient,
5-
CreateInvalidationCommand,
6-
} from "@aws-sdk/client-cloudfront";
73
import { db } from "@cap/database";
84
import { getCurrentUser } from "@cap/database/auth/session";
95
import { nanoId } from "@cap/database/helpers";
106
import { s3Buckets, videos, videoUploads } from "@cap/database/schema";
117
import { buildEnv, NODE_ENV, serverEnv } from "@cap/env";
128
import { dub, userIsPro } from "@cap/utils";
13-
import { AwsCredentials, S3Buckets } from "@cap/web-backend";
9+
import { S3Buckets } from "@cap/web-backend";
1410
import {
1511
type Folder,
1612
type Organisation,
@@ -47,37 +43,6 @@ async function getVideoUploadPresignedUrl({
4743
Option.map((id) => S3Bucket.S3BucketId.make(id)),
4844
);
4945

50-
if (Option.isNone(bucketIdOption)) {
51-
const distributionId = serverEnv().CAP_CLOUDFRONT_DISTRIBUTION_ID;
52-
if (distributionId) {
53-
const cloudfront = new CloudFrontClient({
54-
region: serverEnv().CAP_AWS_REGION || "us-east-1",
55-
credentials: await runPromise(
56-
Effect.map(AwsCredentials, (c) => c.credentials),
57-
),
58-
});
59-
60-
const pathToInvalidate = `/${fileKey}`;
61-
62-
try {
63-
await cloudfront.send(
64-
new CreateInvalidationCommand({
65-
DistributionId: distributionId,
66-
InvalidationBatch: {
67-
CallerReference: `${Date.now()}`,
68-
Paths: {
69-
Quantity: 1,
70-
Items: [pathToInvalidate],
71-
},
72-
},
73-
}),
74-
);
75-
} catch (error) {
76-
console.error("Failed to create CloudFront invalidation:", error);
77-
}
78-
}
79-
}
80-
8146
const contentType = fileKey.endsWith(".aac")
8247
? "audio/aac"
8348
: fileKey.endsWith(".webm")

apps/web/app/api/upload/[...route]/multipart.ts

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
1-
import {
2-
CloudFrontClient,
3-
CreateInvalidationCommand,
4-
} from "@aws-sdk/client-cloudfront";
51
import { updateIfDefined } from "@cap/database";
62
import * as Db from "@cap/database/schema";
73
import { serverEnv } from "@cap/env";
84
import {
9-
AwsCredentials,
105
Database,
116
makeCurrentUserLayer,
127
provideOptionalAuth,
@@ -299,9 +294,7 @@ app.post(
299294
const [video] = maybeVideo.value;
300295

301296
return yield* Effect.gen(function* () {
302-
const [bucket, customBucket] = yield* S3Buckets.getBucketAccess(
303-
video.bucketId,
304-
);
297+
const [bucket] = yield* S3Buckets.getBucketAccess(video.bucketId);
305298

306299
const { result, formattedParts } = yield* Effect.gen(function* () {
307300
console.log(
@@ -529,44 +522,6 @@ app.post(
529522
);
530523
}
531524

532-
if (Option.isNone(customBucket)) {
533-
const distributionId = serverEnv().CAP_CLOUDFRONT_DISTRIBUTION_ID;
534-
if (distributionId) {
535-
const cloudfront = new CloudFrontClient({
536-
region: serverEnv().CAP_AWS_REGION || "us-east-1",
537-
credentials: yield* Effect.map(
538-
AwsCredentials,
539-
(c) => c.credentials,
540-
),
541-
});
542-
543-
const pathToInvalidate = `/${fileKey}`;
544-
545-
yield* Effect.promise(() =>
546-
cloudfront.send(
547-
new CreateInvalidationCommand({
548-
DistributionId: distributionId,
549-
InvalidationBatch: {
550-
CallerReference: `${Date.now()}`,
551-
Paths: {
552-
Quantity: 1,
553-
Items: [pathToInvalidate],
554-
},
555-
},
556-
}),
557-
),
558-
).pipe(
559-
Effect.catchAll((e) =>
560-
Effect.logError(
561-
"Failed to create CloudFront invalidation:",
562-
e,
563-
),
564-
),
565-
Effect.withSpan("CloudFrontInvalidation"),
566-
);
567-
}
568-
}
569-
570525
return c.json({
571526
location: result.Location,
572527
success: true,

apps/web/app/api/upload/[...route]/signed.ts

Lines changed: 19 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
1-
import {
2-
CloudFrontClient,
3-
CreateInvalidationCommand,
4-
} from "@aws-sdk/client-cloudfront";
51
import type { PresignedPost } from "@aws-sdk/s3-presigned-post";
62
import { db, updateIfDefined } from "@cap/database";
73
import * as Db from "@cap/database/schema";
8-
import { serverEnv } from "@cap/env";
9-
import { AwsCredentials, S3Buckets } from "@cap/web-backend";
4+
import { S3Buckets } from "@cap/web-backend";
105
import { Video } from "@cap/web-domain";
116
import { zValidator } from "@hono/zod-validator";
127
import { and, eq } from "drizzle-orm";
@@ -125,53 +120,6 @@ app.post(
125120
.from(Db.s3Buckets)
126121
.where(eq(Db.s3Buckets.ownerId, user.id));
127122

128-
const s3Config = customBucket
129-
? {
130-
endpoint: customBucket.endpoint || undefined,
131-
region: customBucket.region,
132-
accessKeyId: customBucket.accessKeyId,
133-
secretAccessKey: customBucket.secretAccessKey,
134-
}
135-
: null;
136-
137-
if (
138-
!customBucket ||
139-
!s3Config ||
140-
customBucket.bucketName !== serverEnv().CAP_AWS_BUCKET
141-
) {
142-
const distributionId = serverEnv().CAP_CLOUDFRONT_DISTRIBUTION_ID;
143-
if (distributionId) {
144-
console.log("Creating CloudFront invalidation for", fileKey);
145-
146-
const cloudfront = new CloudFrontClient({
147-
region: serverEnv().CAP_AWS_REGION || "us-east-1",
148-
credentials: await runPromise(
149-
Effect.map(AwsCredentials, (c) => c.credentials),
150-
),
151-
});
152-
153-
const pathToInvalidate = `/${fileKey}`;
154-
155-
try {
156-
const invalidation = await cloudfront.send(
157-
new CreateInvalidationCommand({
158-
DistributionId: distributionId,
159-
InvalidationBatch: {
160-
CallerReference: `${Date.now()}`,
161-
Paths: {
162-
Quantity: 1,
163-
Items: [pathToInvalidate],
164-
},
165-
},
166-
}),
167-
);
168-
console.log("CloudFront invalidation created:", invalidation);
169-
} catch (error) {
170-
console.error("Failed to create CloudFront invalidation:", error);
171-
}
172-
}
173-
}
174-
175123
const contentType = fileKey.endsWith(".aac")
176124
? "audio/aac"
177125
: fileKey.endsWith(".webm")
@@ -184,9 +132,7 @@ app.post(
184132
? "application/x-mpegURL"
185133
: "video/mp2t";
186134

187-
let data: PresignedPost;
188-
189-
await Effect.gen(function* () {
135+
const data = await Effect.gen(function* () {
190136
const [bucket] = yield* S3Buckets.getBucketAccess(
191137
Option.fromNullable(customBucket?.id),
192138
);
@@ -200,31 +146,30 @@ app.post(
200146
: "",
201147
};
202148

203-
data = yield* bucket.getPresignedPostUrl(fileKey, {
149+
return yield* bucket.getPresignedPostUrl(fileKey, {
204150
Fields,
205151
Expires: 1800,
206152
});
207-
} else if (method === "put") {
208-
const presignedUrl = yield* bucket.getPresignedPutUrl(
209-
fileKey,
210-
{
211-
ContentType: contentType,
212-
Metadata: {
213-
userid: user.id,
214-
duration: durationInSecs ? durationInSecs.toString() : "",
215-
},
153+
}
154+
155+
const presignedUrl = yield* bucket.getPresignedPutUrl(
156+
fileKey,
157+
{
158+
ContentType: contentType,
159+
Metadata: {
160+
userid: user.id,
161+
duration: durationInSecs ? durationInSecs.toString() : "",
216162
},
217-
{ expiresIn: 1800 },
218-
);
163+
},
164+
{ expiresIn: 1800 },
165+
);
219166

220-
data = { url: presignedUrl, fields: {} };
221-
}
167+
return { url: presignedUrl, fields: {} } satisfies PresignedPost;
222168
}).pipe(runPromise);
223169

224170
console.log("Presigned URL created successfully");
225171

226-
// After successful presigned URL creation, trigger revalidation
227-
const videoIdFromKey = fileKey.split("/")[1]; // Assuming fileKey format is userId/videoId/...
172+
const videoIdFromKey = fileKey.split("/")[1];
228173

229174
const videoIdToUse = "videoId" in body ? body.videoId : videoIdFromKey;
230175
if (videoIdToUse) {
@@ -241,7 +186,6 @@ app.post(
241186
and(eq(Db.videos.id, videoId), eq(Db.videos.ownerId, user.id)),
242187
);
243188

244-
// i hate this but it'll have to do
245189
const clientSupportsUploadProgress = isFromDesktopSemver(
246190
c.req,
247191
UPLOAD_PROGRESS_VERSION,
@@ -253,8 +197,8 @@ app.post(
253197
.where(eq(Db.videoUploads.videoId, videoId));
254198
}
255199

256-
if (method === "post") return c.json({ presignedPostData: data! });
257-
else return c.json({ presignedPutData: data! });
200+
if (method === "post") return c.json({ presignedPostData: data });
201+
else return c.json({ presignedPutData: data });
258202
} catch (s3Error) {
259203
console.error("S3 operation failed:", s3Error);
260204
throw new Error(

0 commit comments

Comments
 (0)