From b80210f6b34437bbebc9bcc414555acee46dc823 Mon Sep 17 00:00:00 2001 From: Ayush Mishra Date: Sun, 17 Sep 2023 19:47:49 +0530 Subject: [PATCH 01/12] script to backup logs --- .../functions/_script/backup_and_cleanup.ts | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 supabase/functions/_script/backup_and_cleanup.ts diff --git a/supabase/functions/_script/backup_and_cleanup.ts b/supabase/functions/_script/backup_and_cleanup.ts new file mode 100644 index 0000000000..d07e76b5f1 --- /dev/null +++ b/supabase/functions/_script/backup_and_cleanup.ts @@ -0,0 +1,64 @@ +import { createClient } from 'https://esm.sh/@supabase/supabase-js@^2.2.3'; +import 'https://deno.land/x/dotenv/load.ts'; +import { r2 } from '../_utils/r2.js'; +import type { Database } from '../_utils/supabase.types.ts'; + +const supabaseUrl = Deno.env.get('SUPABASE_URL') || '***'; +const supabaseServiceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') || '***'; +const backupFolder = 'backup'; + +function useSupabase() { + const options = { + auth: { + autoRefreshToken: true, + persistSession: true, + detectSessionInUrl: false, + }, + }; + return createClient(supabaseUrl, supabaseServiceRoleKey, options); +} + +async function backupAndDeleteOldEntries() { + const supabase = useSupabase(); + const daysToKeep = 30; + + const currentDate = new Date(); + const cutoffDate = new Date(currentDate.getTime() - daysToKeep * 24 * 60 * 60 * 1000); + + const { data: oldEntries, error: queryError } = await supabase + .from('app_versions') + .select() + .lt('updated_at', cutoffDate.toISOString()); + + if (queryError) { + console.error('Error querying the Supabase table:', queryError.message); + return; + } + + const backupData = JSON.stringify(oldEntries); + const backupFilename = `backup-${currentDate.toISOString()}.json`; + const backupPath = `${backupFolder}/${backupFilename}`; + + try { + await r2.upload(backupPath, new TextEncoder().encode(backupData)); + console.log(`Backup saved to R2: ${backupPath}`); + } catch (backupError) { + console.error('Error saving backup to R2:', backupError); + } + + const { error: deleteError } = await supabase + .from('app_versions') + .delete() + .lt('updated_at', cutoffDate.toISOString()); + + if (deleteError) { + console.error('Error deleting entries from the Supabase table:', deleteError.message); + } else { + console.log('Deletion completed successfully.'); + } +} + +backupAndDeleteOldEntries().catch((error) => { + console.error('An error occurred:', error.message); + Deno.exit(1); +}); From 2bd5f417bf23a83ae3271ddc2403e93924e8bcc2 Mon Sep 17 00:00:00 2001 From: Ayush Mishra Date: Sun, 17 Sep 2023 22:25:47 +0530 Subject: [PATCH 02/12] fix --- .github/workflows/backup.yml | 40 +++++++++++ .../functions/_script/backup_and_cleanup.ts | 66 +++++++++++-------- 2 files changed, 80 insertions(+), 26 deletions(-) create mode 100644 .github/workflows/backup.yml diff --git a/.github/workflows/backup.yml b/.github/workflows/backup.yml new file mode 100644 index 0000000000..a39cdeed10 --- /dev/null +++ b/.github/workflows/backup.yml @@ -0,0 +1,40 @@ +name: Backup and Delete Old Entries + +on: + schedule: + - cron: '0 0 * * *' + +jobs: + backup_and_delete: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Deno + uses: denolib/setup-deno@v2 + with: + deno-version: '1.16.2' + + - name: Install dependencies + run: deno cache --unstable --lock=import_map.json --import-map=import_map.json script.ts + + - name: Execute backup script + run: deno run --unstable -A script.ts + env: + SUPABASE_URL: ${{ secrets.SUPABASE_URL }} + SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }} + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + S3_ENDPOINT: ${{ secrets.S3_ENDPOINT }} + S3_REGION: ${{ secrets.S3_REGION }} + S3_PORT: ${{ secrets.S3_PORT }} + S3_SSL: ${{ secrets.S3_SSL }} + + - name: Upload backup to GitHub Artifacts + uses: actions/upload-artifact@v2 + with: + name: backup + path: backup diff --git a/supabase/functions/_script/backup_and_cleanup.ts b/supabase/functions/_script/backup_and_cleanup.ts index d07e76b5f1..1337b4615b 100644 --- a/supabase/functions/_script/backup_and_cleanup.ts +++ b/supabase/functions/_script/backup_and_cleanup.ts @@ -1,6 +1,6 @@ import { createClient } from 'https://esm.sh/@supabase/supabase-js@^2.2.3'; import 'https://deno.land/x/dotenv/load.ts'; -import { r2 } from '../_utils/r2.js'; +import { r2 } from '../_utils/r2'; import type { Database } from '../_utils/supabase.types.ts'; const supabaseUrl = Deno.env.get('SUPABASE_URL') || '***'; @@ -21,40 +21,54 @@ function useSupabase() { async function backupAndDeleteOldEntries() { const supabase = useSupabase(); const daysToKeep = 30; + const pageSize = 1000; const currentDate = new Date(); const cutoffDate = new Date(currentDate.getTime() - daysToKeep * 24 * 60 * 60 * 1000); - const { data: oldEntries, error: queryError } = await supabase - .from('app_versions') - .select() - .lt('updated_at', cutoffDate.toISOString()); + let offset = 0; + let hasMoreData = true; - if (queryError) { - console.error('Error querying the Supabase table:', queryError.message); - return; - } + while (hasMoreData) { + const { data: oldEntries, error: queryError } = await supabase + .from('app_versions') + .select() + .lt('updated_at', cutoffDate.toISOString()) + .range(offset, offset + pageSize - 1); - const backupData = JSON.stringify(oldEntries); - const backupFilename = `backup-${currentDate.toISOString()}.json`; - const backupPath = `${backupFolder}/${backupFilename}`; + if (queryError) { + console.error('Error querying the Supabase table:', queryError.message); + return; + } - try { - await r2.upload(backupPath, new TextEncoder().encode(backupData)); - console.log(`Backup saved to R2: ${backupPath}`); - } catch (backupError) { - console.error('Error saving backup to R2:', backupError); - } + if (!oldEntries || oldEntries.length === 0) { + hasMoreData = false; + break; + } + + const backupData = JSON.stringify(oldEntries); + const backupFilename = `backup-${currentDate.toISOString()}-page-${offset / pageSize}.json`; + const backupPath = `${backupFolder}/${backupFilename}`; + + try { + await r2.upload(backupPath, new TextEncoder().encode(backupData)); + console.log(`Backup saved to R2: ${backupPath}`); + } catch (backupError) { + console.error('Error saving backup to R2:', backupError); + } + + const { error: deleteError } = await supabase + .from('app_versions') + .delete() + .lt('updated_at', cutoffDate.toISOString()); - const { error: deleteError } = await supabase - .from('app_versions') - .delete() - .lt('updated_at', cutoffDate.toISOString()); + if (deleteError) { + console.error('Error deleting entries from the Supabase table:', deleteError.message); + } else { + console.log('Deletion completed successfully.'); + } - if (deleteError) { - console.error('Error deleting entries from the Supabase table:', deleteError.message); - } else { - console.log('Deletion completed successfully.'); + offset += pageSize; } } From e35b9b683226b3f2c77b65f714be463eb181ef44 Mon Sep 17 00:00:00 2001 From: Ayush Mishra Date: Sun, 17 Sep 2023 22:32:04 +0530 Subject: [PATCH 03/12] bug risk fix --- .../functions/_script/backup_and_cleanup.ts | 93 +++++++++++-------- 1 file changed, 52 insertions(+), 41 deletions(-) diff --git a/supabase/functions/_script/backup_and_cleanup.ts b/supabase/functions/_script/backup_and_cleanup.ts index 1337b4615b..18de6fa37a 100644 --- a/supabase/functions/_script/backup_and_cleanup.ts +++ b/supabase/functions/_script/backup_and_cleanup.ts @@ -2,10 +2,11 @@ import { createClient } from 'https://esm.sh/@supabase/supabase-js@^2.2.3'; import 'https://deno.land/x/dotenv/load.ts'; import { r2 } from '../_utils/r2'; import type { Database } from '../_utils/supabase.types.ts'; +import * as fs from 'https://deno.land/std/fs/mod.ts'; const supabaseUrl = Deno.env.get('SUPABASE_URL') || '***'; const supabaseServiceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') || '***'; -const backupFolder = 'backup'; +const backupFolder = 'backup'; function useSupabase() { const options = { @@ -19,56 +20,66 @@ function useSupabase() { } async function backupAndDeleteOldEntries() { - const supabase = useSupabase(); - const daysToKeep = 30; - const pageSize = 1000; + try { + if (!await fs.exists(backupFolder)) { + await fs.ensureDir(backupFolder); + } - const currentDate = new Date(); - const cutoffDate = new Date(currentDate.getTime() - daysToKeep * 24 * 60 * 60 * 1000); + const supabase = useSupabase(); + const daysToKeep = 30; + const pageSize = 1000; - let offset = 0; - let hasMoreData = true; + const currentDate = new Date(); + const cutoffDate = new Date(currentDate.getTime() - daysToKeep * 24 * 60 * 60 * 1000); - while (hasMoreData) { - const { data: oldEntries, error: queryError } = await supabase - .from('app_versions') - .select() - .lt('updated_at', cutoffDate.toISOString()) - .range(offset, offset + pageSize - 1); + let offset = 0; + let hasMoreData = true; - if (queryError) { - console.error('Error querying the Supabase table:', queryError.message); - return; - } + while (hasMoreData) { + const { data: oldEntries, error: queryError } = await supabase + .from('app_versions') + .select() + .lt('updated_at', cutoffDate.toISOString()) + .range(offset, offset + pageSize - 1); - if (!oldEntries || oldEntries.length === 0) { - hasMoreData = false; - break; - } + if (queryError) { + console.error('Error querying the Supabase table:', queryError.message); + break; + } - const backupData = JSON.stringify(oldEntries); - const backupFilename = `backup-${currentDate.toISOString()}-page-${offset / pageSize}.json`; - const backupPath = `${backupFolder}/${backupFilename}`; + if (!oldEntries || oldEntries.length === 0) { + hasMoreData = false; + break; + } - try { - await r2.upload(backupPath, new TextEncoder().encode(backupData)); - console.log(`Backup saved to R2: ${backupPath}`); - } catch (backupError) { - console.error('Error saving backup to R2:', backupError); - } + const backupData = JSON.stringify(oldEntries); + const backupFilename = `backup-${currentDate.toISOString()}-page-${offset / pageSize}.json`; + const backupPath = `${backupFolder}/${backupFilename}`; - const { error: deleteError } = await supabase - .from('app_versions') - .delete() - .lt('updated_at', cutoffDate.toISOString()); + try { + await r2.upload(backupPath, new TextEncoder().encode(backupData)); + console.log(`Backup saved to R2: ${backupPath}`); + } catch (backupError) { + console.error('Error saving backup to R2:', backupError); + break; + } - if (deleteError) { - console.error('Error deleting entries from the Supabase table:', deleteError.message); - } else { - console.log('Deletion completed successfully.'); - } + const { error: deleteError } = await supabase + .from('app_versions') + .delete() + .lt('updated_at', cutoffDate.toISOString()); + + if (deleteError) { + console.error('Error deleting entries from the Supabase table:', deleteError.message); + break; + } else { + console.log('Deletion completed successfully.'); + } - offset += pageSize; + offset += pageSize; + } + } catch (e) { + console.error('An error occurred:', e.message); } } From 9d395a9ece79299f6bd65ca1c8eb064cdf96eb5d Mon Sep 17 00:00:00 2001 From: Ayush Mishra Date: Sun, 17 Sep 2023 22:34:26 +0530 Subject: [PATCH 04/12] fixes --- supabase/functions/_script/backup_and_cleanup.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/supabase/functions/_script/backup_and_cleanup.ts b/supabase/functions/_script/backup_and_cleanup.ts index 18de6fa37a..190543d752 100644 --- a/supabase/functions/_script/backup_and_cleanup.ts +++ b/supabase/functions/_script/backup_and_cleanup.ts @@ -61,7 +61,7 @@ async function backupAndDeleteOldEntries() { console.log(`Backup saved to R2: ${backupPath}`); } catch (backupError) { console.error('Error saving backup to R2:', backupError); - break; + throw new Error('Backup to R2 failed. Stopping execution to prevent data loss.'); } const { error: deleteError } = await supabase @@ -71,7 +71,7 @@ async function backupAndDeleteOldEntries() { if (deleteError) { console.error('Error deleting entries from the Supabase table:', deleteError.message); - break; + throw new Error('Deletion from the Supabase table failed. Stopping execution.'); } else { console.log('Deletion completed successfully.'); } From 0e58f9dc607abd4df1d97e4d197ed657c8efb334 Mon Sep 17 00:00:00 2001 From: Ayush Mishra <92002533+ayusham001@users.noreply.github.com> Date: Mon, 18 Sep 2023 15:17:59 +0530 Subject: [PATCH 05/12] Update supabase/functions/_script/backup_and_cleanup.ts Co-authored-by: Akhil --- supabase/functions/_script/backup_and_cleanup.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/supabase/functions/_script/backup_and_cleanup.ts b/supabase/functions/_script/backup_and_cleanup.ts index 190543d752..cdb99611df 100644 --- a/supabase/functions/_script/backup_and_cleanup.ts +++ b/supabase/functions/_script/backup_and_cleanup.ts @@ -78,12 +78,9 @@ async function backupAndDeleteOldEntries() { offset += pageSize; } - } catch (e) { - console.error('An error occurred:', e.message); - } } -backupAndDeleteOldEntries().catch((error) => { +backupAndDeleteOldEntries().then(() => 'Backup logs executed successfully').catch((error) => { console.error('An error occurred:', error.message); Deno.exit(1); }); From 919a6ad9789050a6ee36ad97c543522bcf82c316 Mon Sep 17 00:00:00 2001 From: Ayush Mishra Date: Mon, 18 Sep 2023 15:39:11 +0530 Subject: [PATCH 06/12] review fixes --- .../functions/_script/backup_and_cleanup.ts | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/supabase/functions/_script/backup_and_cleanup.ts b/supabase/functions/_script/backup_and_cleanup.ts index cdb99611df..4624e0e2f0 100644 --- a/supabase/functions/_script/backup_and_cleanup.ts +++ b/supabase/functions/_script/backup_and_cleanup.ts @@ -3,11 +3,17 @@ import 'https://deno.land/x/dotenv/load.ts'; import { r2 } from '../_utils/r2'; import type { Database } from '../_utils/supabase.types.ts'; import * as fs from 'https://deno.land/std/fs/mod.ts'; +import * as path from 'https://deno.land/std/path/mod.ts'; -const supabaseUrl = Deno.env.get('SUPABASE_URL') || '***'; -const supabaseServiceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') || '***'; +const supabaseUrl = Deno.env.get('SUPABASE_URL'); +const supabaseServiceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY'); const backupFolder = 'backup'; +if (!supabaseUrl || !supabaseServiceRoleKey) { + console.error('Error: SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY environment variables are required.'); + Deno.exit(1); +} + function useSupabase() { const options = { auth: { @@ -34,6 +40,8 @@ async function backupAndDeleteOldEntries() { let offset = 0; let hasMoreData = true; + let fileNumber = 0; + let recordsToDelete: Database['public']['Tables']['app_versions']['Row'][] = []; while (hasMoreData) { const { data: oldEntries, error: queryError } = await supabase @@ -53,21 +61,27 @@ async function backupAndDeleteOldEntries() { } const backupData = JSON.stringify(oldEntries); - const backupFilename = `backup-${currentDate.toISOString()}-page-${offset / pageSize}.json`; - const backupPath = `${backupFolder}/${backupFilename}`; + const backupFilename = `backup-${currentDate.toISOString()}-page-${offset}-${offset + pageSize - 1}.json`; + const backupPath = path.join(backupFolder, backupFilename); try { await r2.upload(backupPath, new TextEncoder().encode(backupData)); console.log(`Backup saved to R2: ${backupPath}`); + recordsToDelete = recordsToDelete.concat(oldEntries); } catch (backupError) { console.error('Error saving backup to R2:', backupError); throw new Error('Backup to R2 failed. Stopping execution to prevent data loss.'); } + offset += pageSize; + fileNumber++; + } + + if (recordsToDelete.length > 0) { const { error: deleteError } = await supabase .from('app_versions') .delete() - .lt('updated_at', cutoffDate.toISOString()); + .in('id', recordsToDelete.map(record => record.id)); if (deleteError) { console.error('Error deleting entries from the Supabase table:', deleteError.message); @@ -75,12 +89,10 @@ async function backupAndDeleteOldEntries() { } else { console.log('Deletion completed successfully.'); } - - offset += pageSize; } + } catch (e) { + console.error('An error occurred:', e.message); + } } -backupAndDeleteOldEntries().then(() => 'Backup logs executed successfully').catch((error) => { - console.error('An error occurred:', error.message); - Deno.exit(1); -}); +backupAndDeleteOldEntries(); From 16142401494923669e3a01ad36eb0970adefbd9a Mon Sep 17 00:00:00 2001 From: Ayush Mishra Date: Tue, 19 Sep 2023 12:26:31 +0530 Subject: [PATCH 07/12] Enhance Error Handling and Record Deletion Logic --- .../functions/_script/backup_and_cleanup.ts | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/supabase/functions/_script/backup_and_cleanup.ts b/supabase/functions/_script/backup_and_cleanup.ts index 4624e0e2f0..952b4f5802 100644 --- a/supabase/functions/_script/backup_and_cleanup.ts +++ b/supabase/functions/_script/backup_and_cleanup.ts @@ -26,6 +26,10 @@ function useSupabase() { } async function backupAndDeleteOldEntries() { + const currentDate = new Date(); + const backupFilenames: string[] = []; + const recordsToDelete: Database['public']['Tables']['app_versions']['Row'][] = []; + try { if (!await fs.exists(backupFolder)) { await fs.ensureDir(backupFolder); @@ -34,16 +38,12 @@ async function backupAndDeleteOldEntries() { const supabase = useSupabase(); const daysToKeep = 30; const pageSize = 1000; - - const currentDate = new Date(); - const cutoffDate = new Date(currentDate.getTime() - daysToKeep * 24 * 60 * 60 * 1000); - let offset = 0; let hasMoreData = true; - let fileNumber = 0; - let recordsToDelete: Database['public']['Tables']['app_versions']['Row'][] = []; while (hasMoreData) { + const cutoffDate = new Date(currentDate.getTime() - daysToKeep * 24 * 60 * 60 * 1000); + const { data: oldEntries, error: queryError } = await supabase .from('app_versions') .select() @@ -61,20 +61,20 @@ async function backupAndDeleteOldEntries() { } const backupData = JSON.stringify(oldEntries); - const backupFilename = `backup-${currentDate.toISOString()}-page-${offset}-${offset + pageSize - 1}.json`; + const backupFilename = `backup-${currentDate.toISOString()}-page-${offset / pageSize}.json`; const backupPath = path.join(backupFolder, backupFilename); try { await r2.upload(backupPath, new TextEncoder().encode(backupData)); console.log(`Backup saved to R2: ${backupPath}`); - recordsToDelete = recordsToDelete.concat(oldEntries); + backupFilenames.push(backupFilename); + + recordsToDelete.push(...oldEntries); } catch (backupError) { console.error('Error saving backup to R2:', backupError); - throw new Error('Backup to R2 failed. Stopping execution to prevent data loss.'); } offset += pageSize; - fileNumber++; } if (recordsToDelete.length > 0) { @@ -85,7 +85,6 @@ async function backupAndDeleteOldEntries() { if (deleteError) { console.error('Error deleting entries from the Supabase table:', deleteError.message); - throw new Error('Deletion from the Supabase table failed. Stopping execution.'); } else { console.log('Deletion completed successfully.'); } @@ -95,4 +94,4 @@ async function backupAndDeleteOldEntries() { } } -backupAndDeleteOldEntries(); +backupAndDeleteOldEntries(); \ No newline at end of file From db8ab70b4b1c27a9b3ec17f150531cbb04ec1245 Mon Sep 17 00:00:00 2001 From: Ayush Mishra Date: Tue, 19 Sep 2023 14:14:30 +0530 Subject: [PATCH 08/12] feat: sql query --- .../functions/_script/backup_and_cleanup.ts | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/supabase/functions/_script/backup_and_cleanup.ts b/supabase/functions/_script/backup_and_cleanup.ts index 952b4f5802..72164925ed 100644 --- a/supabase/functions/_script/backup_and_cleanup.ts +++ b/supabase/functions/_script/backup_and_cleanup.ts @@ -28,7 +28,6 @@ function useSupabase() { async function backupAndDeleteOldEntries() { const currentDate = new Date(); const backupFilenames: string[] = []; - const recordsToDelete: Database['public']['Tables']['app_versions']['Row'][] = []; try { if (!await fs.exists(backupFolder)) { @@ -43,12 +42,15 @@ async function backupAndDeleteOldEntries() { while (hasMoreData) { const cutoffDate = new Date(currentDate.getTime() - daysToKeep * 24 * 60 * 60 * 1000); + const query = ` + SELECT * FROM app_versions + WHERE updated_at < '${cutoffDate.toISOString()}' + OFFSET ${offset} + LIMIT ${pageSize} + `; const { data: oldEntries, error: queryError } = await supabase - .from('app_versions') - .select() - .lt('updated_at', cutoffDate.toISOString()) - .range(offset, offset + pageSize - 1); + .rpc('exec', { sql: query }); if (queryError) { console.error('Error querying the Supabase table:', queryError.message); @@ -68,8 +70,6 @@ async function backupAndDeleteOldEntries() { await r2.upload(backupPath, new TextEncoder().encode(backupData)); console.log(`Backup saved to R2: ${backupPath}`); backupFilenames.push(backupFilename); - - recordsToDelete.push(...oldEntries); } catch (backupError) { console.error('Error saving backup to R2:', backupError); } @@ -77,17 +77,16 @@ async function backupAndDeleteOldEntries() { offset += pageSize; } - if (recordsToDelete.length > 0) { - const { error: deleteError } = await supabase - .from('app_versions') - .delete() - .in('id', recordsToDelete.map(record => record.id)); + const deleteQuery = ` + DELETE FROM app_versions + WHERE updated_at < '${cutoffDate.toISOString()}' + `; + const { error: deleteError } = await supabase.rpc('exec', { sql: deleteQuery }); - if (deleteError) { - console.error('Error deleting entries from the Supabase table:', deleteError.message); - } else { - console.log('Deletion completed successfully.'); - } + if (deleteError) { + console.error('Error deleting entries from the Supabase table:', deleteError.message); + } else { + console.log('Deletion completed successfully.'); } } catch (e) { console.error('An error occurred:', e.message); From dbc09258d6f05891959ab68a9abe18ceb633480c Mon Sep 17 00:00:00 2001 From: Ayush Mishra Date: Tue, 19 Sep 2023 14:36:26 +0530 Subject: [PATCH 09/12] fixes --- .../functions/_script/backup_and_cleanup.ts | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/supabase/functions/_script/backup_and_cleanup.ts b/supabase/functions/_script/backup_and_cleanup.ts index 72164925ed..5dcd855908 100644 --- a/supabase/functions/_script/backup_and_cleanup.ts +++ b/supabase/functions/_script/backup_and_cleanup.ts @@ -1,6 +1,6 @@ import { createClient } from 'https://esm.sh/@supabase/supabase-js@^2.2.3'; import 'https://deno.land/x/dotenv/load.ts'; -import { r2 } from '../_utils/r2'; +import { r2 } from '../_utils/r2.ts'; import type { Database } from '../_utils/supabase.types.ts'; import * as fs from 'https://deno.land/std/fs/mod.ts'; import * as path from 'https://deno.land/std/path/mod.ts'; @@ -28,6 +28,7 @@ function useSupabase() { async function backupAndDeleteOldEntries() { const currentDate = new Date(); const backupFilenames: string[] = []; + const pageSize = 1000; try { if (!await fs.exists(backupFolder)) { @@ -36,12 +37,12 @@ async function backupAndDeleteOldEntries() { const supabase = useSupabase(); const daysToKeep = 30; - const pageSize = 1000; let offset = 0; let hasMoreData = true; + + const cutoffDate = new Date(currentDate.getTime() - daysToKeep * 24 * 60 * 60 * 1000); // Declare cutoffDate outside the loop while (hasMoreData) { - const cutoffDate = new Date(currentDate.getTime() - daysToKeep * 24 * 60 * 60 * 1000); const query = ` SELECT * FROM app_versions WHERE updated_at < '${cutoffDate.toISOString()}' @@ -72,21 +73,27 @@ async function backupAndDeleteOldEntries() { backupFilenames.push(backupFilename); } catch (backupError) { console.error('Error saving backup to R2:', backupError); + break; } offset += pageSize; } - const deleteQuery = ` - DELETE FROM app_versions - WHERE updated_at < '${cutoffDate.toISOString()}' - `; - const { error: deleteError } = await supabase.rpc('exec', { sql: deleteQuery }); + if (backupFilenames.length > 0) { + const deleteQuery = ` + DELETE FROM app_versions + WHERE updated_at < '${cutoffDate.toISOString()}' + OFFSET ${offset - pageSize} + LIMIT ${pageSize} + `; + + const { error: deleteError } = await supabase.rpc('exec', { sql: deleteQuery }); - if (deleteError) { - console.error('Error deleting entries from the Supabase table:', deleteError.message); - } else { - console.log('Deletion completed successfully.'); + if (deleteError) { + console.error('Error deleting entries from the Supabase table:', deleteError.message); + } else { + console.log('Deletion completed successfully.'); + } } } catch (e) { console.error('An error occurred:', e.message); From de7bf28915cf40f5e6ff0ad1edf318a1749fd888 Mon Sep 17 00:00:00 2001 From: Ayush Mishra Date: Tue, 19 Sep 2023 15:53:12 +0530 Subject: [PATCH 10/12] table change --- supabase/functions/_script/backup_and_cleanup.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/supabase/functions/_script/backup_and_cleanup.ts b/supabase/functions/_script/backup_and_cleanup.ts index 5dcd855908..1beefa6502 100644 --- a/supabase/functions/_script/backup_and_cleanup.ts +++ b/supabase/functions/_script/backup_and_cleanup.ts @@ -44,7 +44,7 @@ async function backupAndDeleteOldEntries() { while (hasMoreData) { const query = ` - SELECT * FROM app_versions + SELECT * FROM stats WHERE updated_at < '${cutoffDate.toISOString()}' OFFSET ${offset} LIMIT ${pageSize} @@ -81,7 +81,7 @@ async function backupAndDeleteOldEntries() { if (backupFilenames.length > 0) { const deleteQuery = ` - DELETE FROM app_versions + DELETE FROM stats WHERE updated_at < '${cutoffDate.toISOString()}' OFFSET ${offset - pageSize} LIMIT ${pageSize} From cdf067e9883067e9d5316ebc47deddad0487ff78 Mon Sep 17 00:00:00 2001 From: Ayush Mishra Date: Tue, 19 Sep 2023 18:57:53 +0530 Subject: [PATCH 11/12] tables update --- .../functions/_script/backup_and_cleanup.ts | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/supabase/functions/_script/backup_and_cleanup.ts b/supabase/functions/_script/backup_and_cleanup.ts index 1beefa6502..bc0ec6b407 100644 --- a/supabase/functions/_script/backup_and_cleanup.ts +++ b/supabase/functions/_script/backup_and_cleanup.ts @@ -25,7 +25,7 @@ function useSupabase() { return createClient(supabaseUrl, supabaseServiceRoleKey, options); } -async function backupAndDeleteOldEntries() { +async function backupAndDeleteTable(tableName: string) { const currentDate = new Date(); const backupFilenames: string[] = []; const pageSize = 1000; @@ -39,12 +39,12 @@ async function backupAndDeleteOldEntries() { const daysToKeep = 30; let offset = 0; let hasMoreData = true; - + const cutoffDate = new Date(currentDate.getTime() - daysToKeep * 24 * 60 * 60 * 1000); // Declare cutoffDate outside the loop while (hasMoreData) { const query = ` - SELECT * FROM stats + SELECT * FROM ${tableName} WHERE updated_at < '${cutoffDate.toISOString()}' OFFSET ${offset} LIMIT ${pageSize} @@ -54,7 +54,7 @@ async function backupAndDeleteOldEntries() { .rpc('exec', { sql: query }); if (queryError) { - console.error('Error querying the Supabase table:', queryError.message); + console.error(`Error querying the Supabase table "${tableName}":`, queryError.message); break; } @@ -64,7 +64,7 @@ async function backupAndDeleteOldEntries() { } const backupData = JSON.stringify(oldEntries); - const backupFilename = `backup-${currentDate.toISOString()}-page-${offset / pageSize}.json`; + const backupFilename = `backup-${currentDate.toISOString()}-${tableName}-page-${offset / pageSize}.json`; const backupPath = path.join(backupFolder, backupFilename); try { @@ -72,7 +72,7 @@ async function backupAndDeleteOldEntries() { console.log(`Backup saved to R2: ${backupPath}`); backupFilenames.push(backupFilename); } catch (backupError) { - console.error('Error saving backup to R2:', backupError); + console.error(`Error saving backup to R2 for table "${tableName}":`, backupError); break; } @@ -81,7 +81,7 @@ async function backupAndDeleteOldEntries() { if (backupFilenames.length > 0) { const deleteQuery = ` - DELETE FROM stats + DELETE FROM ${tableName} WHERE updated_at < '${cutoffDate.toISOString()}' OFFSET ${offset - pageSize} LIMIT ${pageSize} @@ -90,14 +90,22 @@ async function backupAndDeleteOldEntries() { const { error: deleteError } = await supabase.rpc('exec', { sql: deleteQuery }); if (deleteError) { - console.error('Error deleting entries from the Supabase table:', deleteError.message); + console.error(`Error deleting entries from the Supabase table "${tableName}":`, deleteError.message); } else { - console.log('Deletion completed successfully.'); + console.log(`Deletion completed successfully for table "${tableName}".`); } } } catch (e) { - console.error('An error occurred:', e.message); + console.error(`An error occurred for table "${tableName}":`, e.message); + } +} + +async function backupAndDeleteTables() { + const tablesToBackupAndDelete = ['stats', 'devices']; + + for (const tableName of tablesToBackupAndDelete) { + await backupAndDeleteTable(tableName); } } -backupAndDeleteOldEntries(); \ No newline at end of file +backupAndDeleteTables(); \ No newline at end of file From c278ec52cc7b2c3372b3fc9f3212cfc6ee976134 Mon Sep 17 00:00:00 2001 From: Ayush Mishra Date: Thu, 28 Sep 2023 10:45:07 +0530 Subject: [PATCH 12/12] setTimeout added --- supabase/functions/_script/backup_and_cleanup.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/supabase/functions/_script/backup_and_cleanup.ts b/supabase/functions/_script/backup_and_cleanup.ts index bc0ec6b407..f5e3a58705 100644 --- a/supabase/functions/_script/backup_and_cleanup.ts +++ b/supabase/functions/_script/backup_and_cleanup.ts @@ -43,6 +43,7 @@ async function backupAndDeleteTable(tableName: string) { const cutoffDate = new Date(currentDate.getTime() - daysToKeep * 24 * 60 * 60 * 1000); // Declare cutoffDate outside the loop while (hasMoreData) { + await new Promise(r => setTimeout(r, 3000)) const query = ` SELECT * FROM ${tableName} WHERE updated_at < '${cutoffDate.toISOString()}'