From 37de64083017570096c3c551449f7e39983d74c1 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Sat, 2 Nov 2024 10:49:52 +0800 Subject: [PATCH 1/4] Prevent infinite loop in exporter --- packages/api/src/jobs/export.ts | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/api/src/jobs/export.ts b/packages/api/src/jobs/export.ts index e5deb2ce0..82c12a488 100644 --- a/packages/api/src/jobs/export.ts +++ b/packages/api/src/jobs/export.ts @@ -5,6 +5,7 @@ import { TaskState } from '../generated/graphql' import { findExportById, saveExport } from '../services/export' import { findHighlightsByLibraryItemId } from '../services/highlights' import { + countLibraryItems, findLibraryItemById, searchLibraryItems, } from '../services/library_item' @@ -163,7 +164,17 @@ export const exportJob = async (jobData: ExportJobData) => { return } - logger.info('exporting all items...', { + const itemCount = await countLibraryItems( + { + query: 'in:all', + includeContent: false, + includeDeleted: false, + includePending: false, + }, + userId + ) + + logger.info(`exporting ${itemCount} items...`, { userId, }) @@ -230,8 +241,17 @@ export const exportJob = async (jobData: ExportJobData) => { const size = items.length // write data to the csv file if (size > 0) { - cursor = await uploadToBucket(userId, items, cursor, size, archive) - + let nextCursor = await uploadToBucket( + userId, + items, + cursor, + size, + archive + ) + if (nextCursor == cursor) { + break + } + cursor = nextCursor hasNext = size === batchSize } } while (hasNext) From 7599bbaded5181e1362c5a4b324d9dd28ae5e496 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Sat, 2 Nov 2024 11:05:40 +0800 Subject: [PATCH 2/4] Add cursor to logs --- packages/api/src/jobs/export.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/api/src/jobs/export.ts b/packages/api/src/jobs/export.ts index 82c12a488..64f933bfb 100644 --- a/packages/api/src/jobs/export.ts +++ b/packages/api/src/jobs/export.ts @@ -220,10 +220,10 @@ export const exportJob = async (jobData: ExportJobData) => { // Pipe the archiver output to the write stream archive.pipe(writeStream) + let cursor = 0 try { // fetch data from the database const batchSize = 20 - let cursor = 0 let hasNext = false do { const items = await searchLibraryItems( @@ -266,7 +266,7 @@ export const exportJob = async (jobData: ExportJobData) => { writeStream.on('error', reject) }) - logger.info('export completed', { + logger.info(`export completed, exported ${cursor} items`, { userId, }) From b74b1d40febdc28053a3ba1c37d7f4e7a6ebadde Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Sat, 2 Nov 2024 11:19:25 +0800 Subject: [PATCH 3/4] Use a const for nextCursor --- packages/api/src/jobs/export.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api/src/jobs/export.ts b/packages/api/src/jobs/export.ts index 64f933bfb..d367fc61f 100644 --- a/packages/api/src/jobs/export.ts +++ b/packages/api/src/jobs/export.ts @@ -241,7 +241,7 @@ export const exportJob = async (jobData: ExportJobData) => { const size = items.length // write data to the csv file if (size > 0) { - let nextCursor = await uploadToBucket( + const nextCursor = await uploadToBucket( userId, items, cursor, From 159b8276e0cf82bbf06b75a3b7eaf0a2afc6f864 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Sat, 2 Nov 2024 11:22:24 +0800 Subject: [PATCH 4/4] Fix comment --- packages/api/src/jobs/export.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api/src/jobs/export.ts b/packages/api/src/jobs/export.ts index d367fc61f..01f8ad2fe 100644 --- a/packages/api/src/jobs/export.ts +++ b/packages/api/src/jobs/export.ts @@ -273,7 +273,7 @@ export const exportJob = async (jobData: ExportJobData) => { // generate a temporary signed url for the zip file const [signedUrl] = await file.getSignedUrl({ action: 'read', - expires: Date.now() + 48 * 60 * 60 * 1000, // 24 hours + expires: Date.now() + 48 * 60 * 60 * 1000, // 48 hours }) logger.info('signed url for export:', {