diff --git a/supabase/functions/_backend/triggers/on_version_update.ts b/supabase/functions/_backend/triggers/on_version_update.ts index 6645fe246..7d6f46a7b 100644 --- a/supabase/functions/_backend/triggers/on_version_update.ts +++ b/supabase/functions/_backend/triggers/on_version_update.ts @@ -1,9 +1,12 @@ import type { Context } from 'hono' import type { MiddlewareKeyVariables } from '../utils/hono.ts' import type { Database } from '../utils/supabase.types.ts' +import { eq } from 'drizzle-orm' import { Hono } from 'hono/tiny' import { BRES, middlewareAPISecret, triggerValidator } from '../utils/hono.ts' import { cloudlog } from '../utils/loggin.ts' +import { closeClient, getDrizzleClient, getPgClient } from '../utils/pg.ts' +import { manifest } from '../utils/postgress_schema.ts' import { getPath, s3 } from '../utils/s3.ts' import { createStatsMeta } from '../utils/stats.ts' import { supabaseAdmin } from '../utils/supabase.ts' @@ -112,45 +115,53 @@ async function updateIt(c: Context, record: Database['public']['Tables']['app_ve async function deleteManifest(c: Context, record: Database['public']['Tables']['app_versions']['Row']) { // Delete manifest entries - first get them to delete from S3 - const { data: manifestEntries, error: fetchError } = await supabaseAdmin(c) - .from('manifest') - .select() - .eq('app_version_id', record.id) + const pgClient = getPgClient(c) + const drizzleClient = getDrizzleClient(pgClient) - if (fetchError) { - cloudlog({ requestId: c.get('requestId'), message: 'error fetch manifest entries', error: fetchError }) - } - else if (manifestEntries && manifestEntries.length > 0) { - // Delete each file from S3 - const promisesDeleteS3 = [] - for (const entry of manifestEntries) { - if (entry.s3_path) { - promisesDeleteS3.push(supabaseAdmin(c) - .from('manifest') - .select('*', { count: 'exact', head: true }) - .eq('file_name', entry.file_name) - .eq('file_hash', entry.file_hash) - .neq('app_version_id', record.id) - .then((v) => { - const count = v.count ?? 0 - if (!count) { - return supabaseAdmin(c) - .from('manifest') - .delete() - .eq('id', entry.id) - } - cloudlog({ requestId: c.get('requestId'), message: 'deleted manifest file from S3', s3_path: entry.s3_path }) - return Promise.all([ - s3.deleteObject(c, entry.s3_path), - supabaseAdmin(c) - .from('manifest') - .delete() - .eq('id', entry.id), - ]) as any - })) + try { + const manifestEntries = await drizzleClient + .select() + .from(manifest) + .where(eq(manifest.app_version_id, record.id)) + + if (manifestEntries && manifestEntries.length > 0) { + // Delete each file from S3 + const promisesDeleteS3 = [] + for (const entry of manifestEntries) { + if (entry.s3_path) { + promisesDeleteS3.push(supabaseAdmin(c) + .from('manifest') + .select('*', { count: 'exact', head: true }) + .eq('file_name', entry.file_name) + .eq('file_hash', entry.file_hash) + .neq('app_version_id', record.id) + .then((v) => { + const count = v.count ?? 0 + if (!count) { + return supabaseAdmin(c) + .from('manifest') + .delete() + .eq('id', entry.id) + } + cloudlog({ requestId: c.get('requestId'), message: 'deleted manifest file from S3', s3_path: entry.s3_path }) + return Promise.all([ + s3.deleteObject(c, entry.s3_path), + supabaseAdmin(c) + .from('manifest') + .delete() + .eq('id', entry.id), + ]) as any + })) + } } + await backgroundTask(c, Promise.all(promisesDeleteS3)) } - await backgroundTask(c, Promise.all(promisesDeleteS3)) + } + catch (error) { + cloudlog({ requestId: c.get('requestId'), message: 'error fetch manifest entries', error }) + } + finally { + await closeClient(c, pgClient) } } diff --git a/supabase/functions/_backend/utils/s3.ts b/supabase/functions/_backend/utils/s3.ts index 3d0218c98..12e8370a3 100644 --- a/supabase/functions/_backend/utils/s3.ts +++ b/supabase/functions/_backend/utils/s3.ts @@ -66,19 +66,25 @@ async function getUploadUrl(c: Context, fileId: string, expirySeconds = 1200) { async function deleteObject(c: Context, fileId: string) { const client = initS3(c) - await client.deleteObject(fileId) - return true + const url = await client.getPresignedUrl('DELETE', fileId) + const response = await fetch(url, { + method: 'DELETE', + }) + return response.status >= 200 && response.status < 300 } async function checkIfExist(c: Context, fileId: string | null) { if (!fileId) { return false } - const client = initS3(c) - try { - const file = await client.statObject(fileId) - return file.size > 0 + const client = initS3(c) + const url = await client.getPresignedUrl('HEAD', fileId) + const response = await fetch(url, { + method: 'HEAD', + }) + const contentLength = Number.parseInt(response.headers.get('content-length') || '0') + return response.status === 200 && contentLength > 0 } catch { // cloudlog({ requestId: c.get('requestId'), message: 'checkIfExist', fileId, error })