File tree Expand file tree Collapse file tree 3 files changed +35
-3
lines changed Expand file tree Collapse file tree 3 files changed +35
-3
lines changed Original file line number Diff line number Diff line change @@ -230,7 +230,25 @@ abstract class AbstractBeccaEntity<T extends AbstractBeccaEntity<T>> {
230230 const blobNeedsInsert = ! sql . getValue ( "SELECT 1 FROM blobs WHERE blobId = ?" , [ newBlobId ] ) ;
231231
232232 if ( ! blobNeedsInsert ) {
233- return newBlobId ;
233+ if ( ! blobStorageService . hasExternalContentColumns ( ) ) {
234+ // If no external storage support, safe to reuse blob
235+ return newBlobId ;
236+ }
237+
238+ // Self recover external blob if the file was deleted externally
239+ const existingBlob = sql . getRow < { contentLocation : BlobContentLocation } > ( /*sql*/
240+ `SELECT contentLocation FROM blobs WHERE blobId = ?` ,
241+ [ newBlobId ]
242+ ) ;
243+
244+ const isInternalBlob = existingBlob ?. contentLocation === 'internal' ;
245+ if ( isInternalBlob || blobStorageService . externalFileExists ( existingBlob . contentLocation ) ) {
246+ // If external blob is still present, safe to reuse
247+ return newBlobId ;
248+ }
249+
250+ // External file is missing, recreate it
251+ log . info ( `External file missing for blob ${ newBlobId } , recreating...` ) ;
234252 }
235253
236254 // Check if we should store this blob externally
Original file line number Diff line number Diff line change @@ -23,7 +23,7 @@ export class BlobStorageService {
2323 /**
2424 * Check if the external content columns (contentLocation, contentLength) exist in the blobs table.
2525 * This is cached for performance.
26- * Returns false before migration 234 has been applied (for example when applying older migrations).
26+ * Returns false before migration 234 has been applied (aka when applying older migrations).
2727 */
2828 hasExternalContentColumns ( ) : boolean {
2929 if ( ! this . _hasExternalContentColumns ) {
@@ -123,6 +123,19 @@ export class BlobStorageService {
123123
124124 return blob . getContentLength ( content ) > config . ExternalBlobStorage . thresholdBytes ;
125125 }
126+
127+ /**
128+ * Check if an external blob file exists
129+ */
130+ externalFileExists ( contentLocation : BlobContentLocation ) : boolean {
131+ if ( contentLocation === "internal" || ! contentLocation . startsWith ( "file://" ) ) {
132+ return false ;
133+ }
134+
135+ const relativePath = contentLocation . replace ( "file://" , "" ) ;
136+ const filePath = path . join ( this . externalBlobPath , relativePath ) ;
137+ return fs . existsSync ( filePath ) ;
138+ }
126139}
127140
128141export default new BlobStorageService ( ) ;
Original file line number Diff line number Diff line change @@ -524,7 +524,8 @@ class ConsistencyChecks {
524524 JOIN blobs USING (blobId)
525525 WHERE isDeleted = 0
526526 AND isProtected = 0
527- AND content IS NULL` ,
527+ AND content IS NULL
528+ AND (contentLocation IS NULL OR contentLocation = 'internal')` ,
528529 ( { noteId, type, mime } ) => {
529530 if ( this . autoFix ) {
530531 const note = becca . getNote ( noteId ) ;
You can’t perform that action at this time.
0 commit comments