@@ -9,10 +9,8 @@ import {
99import { db } from "@/lib/db" ;
1010import { env } from "@/lib/env" ;
1111import { users , videos } from "@/lib/schema" ;
12- import type { initialUploadTask } from "@/trigger/initial-upload" ;
13- import type { thumbnailTrackTask } from "@/trigger/thumbnail-track" ;
14- import type { transcodingTask } from "@/trigger/transcoding" ;
1512import type { videoDeletionTask } from "@/trigger/video-deletion" ;
13+ import type { Step , videoProcessingTask } from "@/trigger/video-processing" ;
1614import {
1715 DeleteObjectCommand ,
1816 GetObjectCommand ,
@@ -76,9 +74,16 @@ export async function deleteVideo(videoId: string) {
7674 return { success : false , message : "Not authorized" } ;
7775 }
7876
79- // TODO: use realtime to inform the user better
80-
81- await tasks . trigger < typeof videoDeletionTask > ( "video-deletion" , { videoId } ) ;
77+ try {
78+ await tasks . trigger < typeof videoDeletionTask > ( "video-deletion" , {
79+ videoId,
80+ } ) ;
81+ } catch {
82+ return {
83+ success : false ,
84+ message : "Failed to delete video" ,
85+ } ;
86+ }
8287
8388 return {
8489 success : true ,
@@ -233,35 +238,36 @@ export async function uploadComplete(key: string, title: string, mimeType: strin
233238 videoId = nanoid ( 8 ) ;
234239 }
235240
236- await db
237- . update ( users )
238- . set ( {
239- totalStorageUsed : userData . totalStorageUsed + ( headResponse ?. ContentLength ?? 0 ) ,
240- } )
241- . where ( eq ( users . id , userId ) ) ;
242-
243- const [ videoData ] = await db
244- . insert ( videos )
245- . values ( {
246- id : videoId ,
247- authorId : userId ,
248- nativeFileKey : key ,
249- fileSizeBytes : headResponse ?. ContentLength ?? 0 ,
250- title : title . substring ( 0 , VIDEO_TITLE_MAX_LENGTH ) ,
251- isProcessing : userData . accountTier !== "free" ,
252- deletionDate :
253- userData . accountTier === "free"
254- ? sql . raw ( `now() + INTERVAL '${ FREE_PLAN_VIDEO_RETENION_DAYS } days'` )
255- : null ,
256- sources : [
257- {
258- isNative : true ,
259- key : key ,
260- type : mimeType === "video/quicktime" ? "video/mp4" : mimeType ,
261- } ,
262- ] ,
263- } )
264- . returning ( ) ;
241+ const [ [ videoData ] ] = await db . batch ( [
242+ db
243+ . insert ( videos )
244+ . values ( {
245+ id : videoId ,
246+ authorId : userId ,
247+ nativeFileKey : key ,
248+ fileSizeBytes : headResponse ?. ContentLength ?? 0 ,
249+ title : title . substring ( 0 , VIDEO_TITLE_MAX_LENGTH ) ,
250+ isProcessing : userData . accountTier !== "free" ,
251+ deletionDate :
252+ userData . accountTier === "free"
253+ ? sql . raw ( `now() + INTERVAL '${ FREE_PLAN_VIDEO_RETENION_DAYS } days'` )
254+ : null ,
255+ sources : [
256+ {
257+ isNative : true ,
258+ key : key ,
259+ type : mimeType === "video/quicktime" ? "video/mp4" : mimeType ,
260+ } ,
261+ ] ,
262+ } )
263+ . returning ( ) ,
264+ db
265+ . update ( users )
266+ . set ( {
267+ totalStorageUsed : userData . totalStorageUsed + ( headResponse ?. ContentLength ?? 0 ) ,
268+ } )
269+ . where ( eq ( users . id , userId ) ) ,
270+ ] ) ;
265271
266272 try {
267273 const cachedVideos = await redis . hget < ( typeof videoData ) [ ] > ( `videos:${ userId } ` , "videos" ) ;
@@ -276,37 +282,33 @@ export async function uploadComplete(key: string, title: string, mimeType: strin
276282 }
277283
278284 try {
279- const promises : Promise < unknown > [ ] = [
280- tasks . trigger < typeof initialUploadTask > (
281- "initial-upload" ,
282- { videoId : videoData . id } ,
283- {
284- tags : [ userId , `initial-upload-${ videoId } ` , `video_${ videoData . id } ` ] ,
285- } ,
286- ) ,
287- ] ;
285+ const videoProcessingSteps : Step [ ] = [ "video-duration" , "thumbnails" ] ;
288286
289287 if ( userData . accountTier !== "free" ) {
290- promises . push (
291- tasks . trigger < typeof transcodingTask > (
292- "transcoding" ,
293- { videoId : videoData . id } ,
294- { tags : [ userId , `video_${ videoData . id } ` ] } ,
295- ) ,
296- ) ;
288+ videoProcessingSteps . push ( "transcoding" ) ;
297289 }
298290
299291 if ( ! videoData . isPrivate ) {
300- promises . push (
301- tasks . trigger < typeof thumbnailTrackTask > (
302- "thumbnail-track" ,
303- { videoId } ,
304- { tags : [ userId , `video_${ videoId } ` ] } ,
305- ) ,
306- ) ;
292+ videoProcessingSteps . push ( "thumbnail-track" ) ;
307293 }
308294
309- await Promise . all ( promises ) ;
295+ for ( let i = 0 ; i < 3 ; i ++ ) {
296+ try {
297+ await tasks . trigger < typeof videoProcessingTask > (
298+ "video-processing" ,
299+ {
300+ videoId,
301+ steps : videoProcessingSteps ,
302+ } ,
303+ {
304+ tags : [ `video-processing-${ videoData . id } ` ] ,
305+ } ,
306+ ) ;
307+ break ;
308+ } catch ( err ) {
309+ if ( i === 2 ) throw err ;
310+ }
311+ }
310312 } catch ( e ) {
311313 console . error ( e ) ;
312314
@@ -336,7 +338,7 @@ export async function uploadComplete(key: string, title: string, mimeType: strin
336338 success : true ,
337339 triggerAccessToken : await triggerAuth . createPublicToken ( {
338340 scopes : {
339- read : { tags : `initial-upload -${ videoId } ` } ,
341+ read : { tags : `video-processing -${ videoId } ` } ,
340342 } ,
341343 } ) ,
342344 video : {
0 commit comments