diff --git a/e2e/src/api/specs/integrity.e2e-spec.ts b/e2e/src/api/specs/integrity.e2e-spec.ts index 17a8585714..937dc71bfa 100644 --- a/e2e/src/api/specs/integrity.e2e-spec.ts +++ b/e2e/src/api/specs/integrity.e2e-spec.ts @@ -100,7 +100,7 @@ describe('/admin/integrity', () => { describe('POST /summary (& jobs)', async () => { it.sequential('reports no issues', async () => { await utils.createJob(admin.accessToken, { - name: ManualJobName.IntegrityOrphanFiles, + name: ManualJobName.IntegrityUntrackedFiles, }); await utils.createJob(admin.accessToken, { @@ -112,7 +112,7 @@ describe('/admin/integrity', () => { }); await utils.createJob(admin.accessToken, { - name: ManualJobName.IntegrityOrphanFilesDeleteAll, + name: ManualJobName.IntegrityUntrackedFilesDeleteAll, }); await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck); @@ -125,16 +125,16 @@ describe('/admin/integrity', () => { expect(status).toBe(200); expect(body).toEqual({ missing_file: 0, - orphan_file: 0, + untracked_file: 0, checksum_mismatch: 0, }); }); - it.sequential('should detect an orphan file (job: check orphan files)', async () => { - await utils.putTextFile('orphan', `/data/upload/${admin.userId}/orphan1.png`); + it.sequential('should detect an untracked file (job: check untracked files)', async () => { + await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked1.png`); await utils.createJob(admin.accessToken, { - name: ManualJobName.IntegrityOrphanFiles, + name: ManualJobName.IntegrityUntrackedFiles, }); await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck); @@ -147,18 +147,18 @@ describe('/admin/integrity', () => { expect(status).toBe(200); expect(body).toEqual( expect.objectContaining({ - orphan_file: 1, + untracked_file: 1, }), ); }); - it.sequential('should detect outdated orphan file reports (job: refresh orphan files)', async () => { + it.sequential('should detect outdated untracked file reports (job: refresh untracked files)', async () => { // these should not be detected: - await utils.putTextFile('orphan', `/data/upload/${admin.userId}/orphan2.png`); - await utils.putTextFile('orphan', `/data/upload/${admin.userId}/orphan3.png`); + await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked2.png`); + await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked3.png`); await utils.createJob(admin.accessToken, { - name: ManualJobName.IntegrityOrphanFilesRefresh, + name: ManualJobName.IntegrityUntrackedFilesRefresh, }); await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck); @@ -171,22 +171,22 @@ describe('/admin/integrity', () => { expect(status).toBe(200); expect(body).toEqual( expect.objectContaining({ - orphan_file: 0, + untracked_file: 0, }), ); }); - it.sequential('should delete orphan files (job: delete all orphan file reports)', async () => { - await utils.putTextFile('orphan', `/data/upload/${admin.userId}/orphan1.png`); + it.sequential('should delete untracked files (job: delete all untracked file reports)', async () => { + await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked1.png`); await utils.createJob(admin.accessToken, { - name: ManualJobName.IntegrityOrphanFiles, + name: ManualJobName.IntegrityUntrackedFiles, }); await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck); await utils.createJob(admin.accessToken, { - name: ManualJobName.IntegrityOrphanFilesDeleteAll, + name: ManualJobName.IntegrityUntrackedFilesDeleteAll, }); await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck); @@ -199,7 +199,7 @@ describe('/admin/integrity', () => { expect(status).toBe(200); expect(body).toEqual( expect.objectContaining({ - orphan_file: 0, + untracked_file: 0, }), ); }); @@ -387,11 +387,11 @@ describe('/admin/integrity', () => { }); describe('POST /report', async () => { - it.sequential('reports orphan files', async () => { - await utils.putTextFile('orphan', `/data/upload/${admin.userId}/orphan1.png`); + it.sequential('reports untracked files', async () => { + await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked1.png`); await utils.createJob(admin.accessToken, { - name: ManualJobName.IntegrityOrphanFiles, + name: ManualJobName.IntegrityUntrackedFiles, }); await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck); @@ -399,7 +399,7 @@ describe('/admin/integrity', () => { const { status, body } = await request(app) .post('/admin/integrity/report') .set('Authorization', `Bearer ${admin.accessToken}`) - .send({ type: 'orphan_file' }); + .send({ type: 'untracked_file' }); expect(status).toBe(200); expect(body).toEqual({ @@ -407,8 +407,8 @@ describe('/admin/integrity', () => { items: expect.arrayContaining([ { id: expect.any(String), - type: 'orphan_file', - path: `/data/upload/${admin.userId}/orphan1.png`, + type: 'untracked_file', + path: `/data/upload/${admin.userId}/untracked1.png`, assetId: null, fileAssetId: null, }, @@ -476,11 +476,11 @@ describe('/admin/integrity', () => { }); describe('DELETE /report/:id', async () => { - it.sequential('delete orphan files', async () => { - await utils.putTextFile('orphan', `/data/upload/${admin.userId}/orphan1.png`); + it.sequential('delete untracked files', async () => { + await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked1.png`); await utils.createJob(admin.accessToken, { - name: ManualJobName.IntegrityOrphanFiles, + name: ManualJobName.IntegrityUntrackedFiles, }); await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck); @@ -488,12 +488,12 @@ describe('/admin/integrity', () => { const { status: listStatus, body: listBody } = await request(app) .post('/admin/integrity/report') .set('Authorization', `Bearer ${admin.accessToken}`) - .send({ type: 'orphan_file' }); + .send({ type: 'untracked_file' }); expect(listStatus).toBe(200); const report = (listBody as IntegrityReportResponseDto).items.find( - (item) => item.path === `/data/upload/${admin.userId}/orphan1.png`, + (item) => item.path === `/data/upload/${admin.userId}/untracked1.png`, )!; const { status } = await request(app) @@ -504,7 +504,7 @@ describe('/admin/integrity', () => { expect(status).toBe(200); await utils.createJob(admin.accessToken, { - name: ManualJobName.IntegrityOrphanFiles, + name: ManualJobName.IntegrityUntrackedFiles, }); await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck); @@ -512,7 +512,7 @@ describe('/admin/integrity', () => { const { status: listStatus2, body: listBody2 } = await request(app) .post('/admin/integrity/report') .set('Authorization', `Bearer ${admin.accessToken}`) - .send({ type: 'orphan_file' }); + .send({ type: 'untracked_file' }); expect(listStatus2).toBe(200); expect(listBody2).not.toBe( @@ -610,17 +610,17 @@ describe('/admin/integrity', () => { }); describe('GET /report/:type/csv', () => { - it.sequential('exports orphan files as csv', async () => { - await utils.putTextFile('orphan', `/data/upload/${admin.userId}/orphan1.png`); + it.sequential('exports untracked files as csv', async () => { + await utils.putTextFile('untracked', `/data/upload/${admin.userId}/untracked1.png`); await utils.createJob(admin.accessToken, { - name: ManualJobName.IntegrityOrphanFiles, + name: ManualJobName.IntegrityUntrackedFiles, }); await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck); const { status, headers, text } = await request(app) - .get('/admin/integrity/report/orphan_file/csv') + .get('/admin/integrity/report/untracked_file/csv') .set('Authorization', `Bearer ${admin.accessToken}`) .send(); @@ -628,17 +628,17 @@ describe('/admin/integrity', () => { expect(headers['content-type']).toContain('text/csv'); expect(headers['content-disposition']).toContain('.csv'); expect(text).toContain('id,type,assetId,fileAssetId,path'); - expect(text).toContain(`orphan_file`); - expect(text).toContain(`/data/upload/${admin.userId}/orphan1.png`); + expect(text).toContain(`untracked_file`); + expect(text).toContain(`/data/upload/${admin.userId}/untracked1.png`); }); }); describe('GET /report/:id/file', () => { - it.sequential('downloads orphan file', async () => { - await utils.putTextFile('orphan-content', `/data/upload/${admin.userId}/orphan1.png`); + it.sequential('downloads untracked file', async () => { + await utils.putTextFile('untracked-content', `/data/upload/${admin.userId}/untracked1.png`); await utils.createJob(admin.accessToken, { - name: ManualJobName.IntegrityOrphanFiles, + name: ManualJobName.IntegrityUntrackedFiles, }); await utils.waitForQueueFinish(admin.accessToken, QueueName.IntegrityCheck); @@ -646,10 +646,10 @@ describe('/admin/integrity', () => { const { body: listBody } = await request(app) .post('/admin/integrity/report') .set('Authorization', `Bearer ${admin.accessToken}`) - .send({ type: 'orphan_file' }); + .send({ type: 'untracked_file' }); const report = (listBody as IntegrityReportResponseDto).items.find( - (item) => item.path === `/data/upload/${admin.userId}/orphan1.png`, + (item) => item.path === `/data/upload/${admin.userId}/untracked1.png`, )!; const { status, headers, body } = await request(app) @@ -660,7 +660,7 @@ describe('/admin/integrity', () => { expect(status).toBe(200); expect(headers['content-type']).toContain('application/octet-stream'); - expect(body.toString()).toBe('orphan-content'); + expect(body.toString()).toBe('untracked-content'); }); }); }); diff --git a/i18n/en.json b/i18n/en.json index 8d87981015..f3f74006f6 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -195,9 +195,9 @@ "maintenance_integrity_missing_file": "Missing Files", "maintenance_integrity_missing_file_job": "Check for missing files", "maintenance_integrity_missing_file_refresh_job": "Refresh missing file reports", - "maintenance_integrity_orphan_file": "Orphan Files", - "maintenance_integrity_orphan_file_job": "Check for orphaned files", - "maintenance_integrity_orphan_file_refresh_job": "Refresh orphan file reports", + "maintenance_integrity_untracked_file": "Untracked Files", + "maintenance_integrity_untracked_file_job": "Check for untracked files", + "maintenance_integrity_untracked_file_refresh_job": "Refresh untracked file reports", "maintenance_integrity_report": "Integrity Report", "maintenance_settings": "Maintenance", "maintenance_settings_description": "Put Immich into maintenance mode.", diff --git a/mobile/openapi/lib/api/maintenance_admin_api.dart b/mobile/openapi/lib/api/maintenance_admin_api.dart index 5e9289fd05..164f0c6661 100644 --- a/mobile/openapi/lib/api/maintenance_admin_api.dart +++ b/mobile/openapi/lib/api/maintenance_admin_api.dart @@ -180,7 +180,7 @@ class MaintenanceAdminApi { /// Download flagged file /// - /// Download the orphan/broken file if one exists + /// Download the untracked/broken file if one exists /// /// Note: This method returns the HTTP [Response]. /// @@ -215,7 +215,7 @@ class MaintenanceAdminApi { /// Download flagged file /// - /// Download the orphan/broken file if one exists + /// Download the untracked/broken file if one exists /// /// Parameters: /// diff --git a/mobile/openapi/lib/model/integrity_get_report_dto.dart b/mobile/openapi/lib/model/integrity_get_report_dto.dart index 57cf5c2c20..156647a1f2 100644 --- a/mobile/openapi/lib/model/integrity_get_report_dto.dart +++ b/mobile/openapi/lib/model/integrity_get_report_dto.dart @@ -24,7 +24,7 @@ class IntegrityGetReportDto { /// source code must fall back to having a nullable type. /// Consider adding a "default:" property in the specification file to hide this note. /// - DateTime? cursor; + String? cursor; /// Minimum value: 1 /// @@ -56,7 +56,7 @@ class IntegrityGetReportDto { Map toJson() { final json = {}; if (this.cursor != null) { - json[r'cursor'] = this.cursor!.toUtc().toIso8601String(); + json[r'cursor'] = this.cursor; } else { // json[r'cursor'] = null; } @@ -78,7 +78,7 @@ class IntegrityGetReportDto { final json = value.cast(); return IntegrityGetReportDto( - cursor: mapDateTime(json, r'cursor', r''), + cursor: mapValueOfType(json, r'cursor'), limit: num.parse('${json[r'limit']}'), type: IntegrityReportType.fromJson(json[r'type'])!, ); diff --git a/mobile/openapi/lib/model/integrity_report_response_dto.dart b/mobile/openapi/lib/model/integrity_report_response_dto.dart index ab72fb88bd..5b2dc68e6c 100644 --- a/mobile/openapi/lib/model/integrity_report_response_dto.dart +++ b/mobile/openapi/lib/model/integrity_report_response_dto.dart @@ -25,7 +25,7 @@ class IntegrityReportResponseDto { /// source code must fall back to having a nullable type. /// Consider adding a "default:" property in the specification file to hide this note. /// - DateTime? nextCursor; + String? nextCursor; @override bool operator ==(Object other) => identical(this, other) || other is IntegrityReportResponseDto && @@ -45,7 +45,7 @@ class IntegrityReportResponseDto { final json = {}; json[r'items'] = this.items; if (this.nextCursor != null) { - json[r'nextCursor'] = this.nextCursor!.toUtc().toIso8601String(); + json[r'nextCursor'] = this.nextCursor; } else { // json[r'nextCursor'] = null; } @@ -62,7 +62,7 @@ class IntegrityReportResponseDto { return IntegrityReportResponseDto( items: IntegrityReportDto.listFromJson(json[r'items']), - nextCursor: mapDateTime(json, r'nextCursor', r''), + nextCursor: mapValueOfType(json, r'nextCursor'), ); } return null; diff --git a/mobile/openapi/lib/model/integrity_report_summary_response_dto.dart b/mobile/openapi/lib/model/integrity_report_summary_response_dto.dart index 4b649b1328..0c6eeb6480 100644 --- a/mobile/openapi/lib/model/integrity_report_summary_response_dto.dart +++ b/mobile/openapi/lib/model/integrity_report_summary_response_dto.dart @@ -15,36 +15,36 @@ class IntegrityReportSummaryResponseDto { IntegrityReportSummaryResponseDto({ required this.checksumMismatch, required this.missingFile, - required this.orphanFile, + required this.untrackedFile, }); int checksumMismatch; int missingFile; - int orphanFile; + int untrackedFile; @override bool operator ==(Object other) => identical(this, other) || other is IntegrityReportSummaryResponseDto && other.checksumMismatch == checksumMismatch && other.missingFile == missingFile && - other.orphanFile == orphanFile; + other.untrackedFile == untrackedFile; @override int get hashCode => // ignore: unnecessary_parenthesis (checksumMismatch.hashCode) + (missingFile.hashCode) + - (orphanFile.hashCode); + (untrackedFile.hashCode); @override - String toString() => 'IntegrityReportSummaryResponseDto[checksumMismatch=$checksumMismatch, missingFile=$missingFile, orphanFile=$orphanFile]'; + String toString() => 'IntegrityReportSummaryResponseDto[checksumMismatch=$checksumMismatch, missingFile=$missingFile, untrackedFile=$untrackedFile]'; Map toJson() { final json = {}; json[r'checksum_mismatch'] = this.checksumMismatch; json[r'missing_file'] = this.missingFile; - json[r'orphan_file'] = this.orphanFile; + json[r'untracked_file'] = this.untrackedFile; return json; } @@ -59,7 +59,7 @@ class IntegrityReportSummaryResponseDto { return IntegrityReportSummaryResponseDto( checksumMismatch: mapValueOfType(json, r'checksum_mismatch')!, missingFile: mapValueOfType(json, r'missing_file')!, - orphanFile: mapValueOfType(json, r'orphan_file')!, + untrackedFile: mapValueOfType(json, r'untracked_file')!, ); } return null; @@ -109,7 +109,7 @@ class IntegrityReportSummaryResponseDto { static const requiredKeys = { 'checksum_mismatch', 'missing_file', - 'orphan_file', + 'untracked_file', }; } diff --git a/mobile/openapi/lib/model/integrity_report_type.dart b/mobile/openapi/lib/model/integrity_report_type.dart index f027cd6f5a..605d016c5c 100644 --- a/mobile/openapi/lib/model/integrity_report_type.dart +++ b/mobile/openapi/lib/model/integrity_report_type.dart @@ -23,13 +23,13 @@ class IntegrityReportType { String toJson() => value; - static const orphanFile = IntegrityReportType._(r'orphan_file'); + static const untrackedFile = IntegrityReportType._(r'untracked_file'); static const missingFile = IntegrityReportType._(r'missing_file'); static const checksumMismatch = IntegrityReportType._(r'checksum_mismatch'); /// List of all possible values in this [enum][IntegrityReportType]. static const values = [ - orphanFile, + untrackedFile, missingFile, checksumMismatch, ]; @@ -70,7 +70,7 @@ class IntegrityReportTypeTypeTransformer { IntegrityReportType? decode(dynamic data, {bool allowNull = true}) { if (data != null) { switch (data) { - case r'orphan_file': return IntegrityReportType.orphanFile; + case r'untracked_file': return IntegrityReportType.untrackedFile; case r'missing_file': return IntegrityReportType.missingFile; case r'checksum_mismatch': return IntegrityReportType.checksumMismatch; default: diff --git a/mobile/openapi/lib/model/job_name.dart b/mobile/openapi/lib/model/job_name.dart index 99959a0954..3c55d9b5d2 100644 --- a/mobile/openapi/lib/model/job_name.dart +++ b/mobile/openapi/lib/model/job_name.dart @@ -78,9 +78,9 @@ class JobName { static const ocrQueueAll = JobName._(r'OcrQueueAll'); static const ocr = JobName._(r'Ocr'); static const workflowRun = JobName._(r'WorkflowRun'); - static const integrityOrphanedFilesQueueAll = JobName._(r'IntegrityOrphanedFilesQueueAll'); - static const integrityOrphanedFiles = JobName._(r'IntegrityOrphanedFiles'); - static const integrityOrphanedRefresh = JobName._(r'IntegrityOrphanedRefresh'); + static const integrityUntrackedFilesQueueAll = JobName._(r'IntegrityUntrackedFilesQueueAll'); + static const integrityUntrackedFiles = JobName._(r'IntegrityUntrackedFiles'); + static const integrityUntrackedRefresh = JobName._(r'IntegrityUntrackedRefresh'); static const integrityMissingFilesQueueAll = JobName._(r'IntegrityMissingFilesQueueAll'); static const integrityMissingFiles = JobName._(r'IntegrityMissingFiles'); static const integrityMissingFilesRefresh = JobName._(r'IntegrityMissingFilesRefresh'); @@ -146,9 +146,9 @@ class JobName { ocrQueueAll, ocr, workflowRun, - integrityOrphanedFilesQueueAll, - integrityOrphanedFiles, - integrityOrphanedRefresh, + integrityUntrackedFilesQueueAll, + integrityUntrackedFiles, + integrityUntrackedRefresh, integrityMissingFilesQueueAll, integrityMissingFiles, integrityMissingFilesRefresh, @@ -249,9 +249,9 @@ class JobNameTypeTransformer { case r'OcrQueueAll': return JobName.ocrQueueAll; case r'Ocr': return JobName.ocr; case r'WorkflowRun': return JobName.workflowRun; - case r'IntegrityOrphanedFilesQueueAll': return JobName.integrityOrphanedFilesQueueAll; - case r'IntegrityOrphanedFiles': return JobName.integrityOrphanedFiles; - case r'IntegrityOrphanedRefresh': return JobName.integrityOrphanedRefresh; + case r'IntegrityUntrackedFilesQueueAll': return JobName.integrityUntrackedFilesQueueAll; + case r'IntegrityUntrackedFiles': return JobName.integrityUntrackedFiles; + case r'IntegrityUntrackedRefresh': return JobName.integrityUntrackedRefresh; case r'IntegrityMissingFilesQueueAll': return JobName.integrityMissingFilesQueueAll; case r'IntegrityMissingFiles': return JobName.integrityMissingFiles; case r'IntegrityMissingFilesRefresh': return JobName.integrityMissingFilesRefresh; diff --git a/mobile/openapi/lib/model/manual_job_name.dart b/mobile/openapi/lib/model/manual_job_name.dart index 60d14e6ef7..c32c0ffd0b 100644 --- a/mobile/openapi/lib/model/manual_job_name.dart +++ b/mobile/openapi/lib/model/manual_job_name.dart @@ -30,13 +30,13 @@ class ManualJobName { static const memoryCreate = ManualJobName._(r'memory-create'); static const backupDatabase = ManualJobName._(r'backup-database'); static const integrityMissingFiles = ManualJobName._(r'integrity-missing-files'); - static const integrityOrphanFiles = ManualJobName._(r'integrity-orphan-files'); + static const integrityUntrackedFiles = ManualJobName._(r'integrity-untracked-files'); static const integrityChecksumMismatch = ManualJobName._(r'integrity-checksum-mismatch'); static const integrityMissingFilesRefresh = ManualJobName._(r'integrity-missing-files-refresh'); - static const integrityOrphanFilesRefresh = ManualJobName._(r'integrity-orphan-files-refresh'); + static const integrityUntrackedFilesRefresh = ManualJobName._(r'integrity-untracked-files-refresh'); static const integrityChecksumMismatchRefresh = ManualJobName._(r'integrity-checksum-mismatch-refresh'); static const integrityMissingFilesDeleteAll = ManualJobName._(r'integrity-missing-files-delete-all'); - static const integrityOrphanFilesDeleteAll = ManualJobName._(r'integrity-orphan-files-delete-all'); + static const integrityUntrackedFilesDeleteAll = ManualJobName._(r'integrity-untracked-files-delete-all'); static const integrityChecksumMismatchDeleteAll = ManualJobName._(r'integrity-checksum-mismatch-delete-all'); /// List of all possible values in this [enum][ManualJobName]. @@ -48,13 +48,13 @@ class ManualJobName { memoryCreate, backupDatabase, integrityMissingFiles, - integrityOrphanFiles, + integrityUntrackedFiles, integrityChecksumMismatch, integrityMissingFilesRefresh, - integrityOrphanFilesRefresh, + integrityUntrackedFilesRefresh, integrityChecksumMismatchRefresh, integrityMissingFilesDeleteAll, - integrityOrphanFilesDeleteAll, + integrityUntrackedFilesDeleteAll, integrityChecksumMismatchDeleteAll, ]; @@ -101,13 +101,13 @@ class ManualJobNameTypeTransformer { case r'memory-create': return ManualJobName.memoryCreate; case r'backup-database': return ManualJobName.backupDatabase; case r'integrity-missing-files': return ManualJobName.integrityMissingFiles; - case r'integrity-orphan-files': return ManualJobName.integrityOrphanFiles; + case r'integrity-untracked-files': return ManualJobName.integrityUntrackedFiles; case r'integrity-checksum-mismatch': return ManualJobName.integrityChecksumMismatch; case r'integrity-missing-files-refresh': return ManualJobName.integrityMissingFilesRefresh; - case r'integrity-orphan-files-refresh': return ManualJobName.integrityOrphanFilesRefresh; + case r'integrity-untracked-files-refresh': return ManualJobName.integrityUntrackedFilesRefresh; case r'integrity-checksum-mismatch-refresh': return ManualJobName.integrityChecksumMismatchRefresh; case r'integrity-missing-files-delete-all': return ManualJobName.integrityMissingFilesDeleteAll; - case r'integrity-orphan-files-delete-all': return ManualJobName.integrityOrphanFilesDeleteAll; + case r'integrity-untracked-files-delete-all': return ManualJobName.integrityUntrackedFilesDeleteAll; case r'integrity-checksum-mismatch-delete-all': return ManualJobName.integrityChecksumMismatchDeleteAll; default: if (!allowNull) { diff --git a/mobile/openapi/lib/model/system_config_integrity_checks.dart b/mobile/openapi/lib/model/system_config_integrity_checks.dart index 37a75ed3d7..ef047e156a 100644 --- a/mobile/openapi/lib/model/system_config_integrity_checks.dart +++ b/mobile/openapi/lib/model/system_config_integrity_checks.dart @@ -15,36 +15,36 @@ class SystemConfigIntegrityChecks { SystemConfigIntegrityChecks({ required this.checksumFiles, required this.missingFiles, - required this.orphanedFiles, + required this.untrackedFiles, }); SystemConfigIntegrityChecksumJob checksumFiles; SystemConfigIntegrityJob missingFiles; - SystemConfigIntegrityJob orphanedFiles; + SystemConfigIntegrityJob untrackedFiles; @override bool operator ==(Object other) => identical(this, other) || other is SystemConfigIntegrityChecks && other.checksumFiles == checksumFiles && other.missingFiles == missingFiles && - other.orphanedFiles == orphanedFiles; + other.untrackedFiles == untrackedFiles; @override int get hashCode => // ignore: unnecessary_parenthesis (checksumFiles.hashCode) + (missingFiles.hashCode) + - (orphanedFiles.hashCode); + (untrackedFiles.hashCode); @override - String toString() => 'SystemConfigIntegrityChecks[checksumFiles=$checksumFiles, missingFiles=$missingFiles, orphanedFiles=$orphanedFiles]'; + String toString() => 'SystemConfigIntegrityChecks[checksumFiles=$checksumFiles, missingFiles=$missingFiles, untrackedFiles=$untrackedFiles]'; Map toJson() { final json = {}; json[r'checksumFiles'] = this.checksumFiles; json[r'missingFiles'] = this.missingFiles; - json[r'orphanedFiles'] = this.orphanedFiles; + json[r'untrackedFiles'] = this.untrackedFiles; return json; } @@ -59,7 +59,7 @@ class SystemConfigIntegrityChecks { return SystemConfigIntegrityChecks( checksumFiles: SystemConfigIntegrityChecksumJob.fromJson(json[r'checksumFiles'])!, missingFiles: SystemConfigIntegrityJob.fromJson(json[r'missingFiles'])!, - orphanedFiles: SystemConfigIntegrityJob.fromJson(json[r'orphanedFiles'])!, + untrackedFiles: SystemConfigIntegrityJob.fromJson(json[r'untrackedFiles'])!, ); } return null; @@ -109,7 +109,7 @@ class SystemConfigIntegrityChecks { static const requiredKeys = { 'checksumFiles', 'missingFiles', - 'orphanedFiles', + 'untrackedFiles', }; } diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 2a9ff2b2c4..cfba2f17a6 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -431,7 +431,7 @@ }, "/admin/integrity/report/{id}/file": { "get": { - "description": "Download the orphan/broken file if one exists", + "description": "Download the untracked/broken file if one exists", "operationId": "getIntegrityReportFile", "parameters": [ { @@ -16997,20 +16997,20 @@ "missing_file": { "type": "integer" }, - "orphan_file": { + "untracked_file": { "type": "integer" } }, "required": [ "checksum_mismatch", "missing_file", - "orphan_file" + "untracked_file" ], "type": "object" }, "IntegrityReportType": { "enum": [ - "orphan_file", + "untracked_file", "missing_file", "checksum_mismatch" ], @@ -17088,9 +17088,9 @@ "OcrQueueAll", "Ocr", "WorkflowRun", - "IntegrityOrphanedFilesQueueAll", - "IntegrityOrphanedFiles", - "IntegrityOrphanedRefresh", + "IntegrityUntrackedFilesQueueAll", + "IntegrityUntrackedFiles", + "IntegrityUntrackedRefresh", "IntegrityMissingFilesQueueAll", "IntegrityMissingFiles", "IntegrityMissingFilesRefresh", @@ -17368,13 +17368,13 @@ "memory-create", "backup-database", "integrity-missing-files", - "integrity-orphan-files", + "integrity-untracked-files", "integrity-checksum-mismatch", "integrity-missing-files-refresh", - "integrity-orphan-files-refresh", + "integrity-untracked-files-refresh", "integrity-checksum-mismatch-refresh", "integrity-missing-files-delete-all", - "integrity-orphan-files-delete-all", + "integrity-untracked-files-delete-all", "integrity-checksum-mismatch-delete-all" ], "type": "string" @@ -22022,14 +22022,14 @@ "missingFiles": { "$ref": "#/components/schemas/SystemConfigIntegrityJob" }, - "orphanedFiles": { + "untrackedFiles": { "$ref": "#/components/schemas/SystemConfigIntegrityJob" } }, "required": [ "checksumFiles", "missingFiles", - "orphanedFiles" + "untrackedFiles" ], "type": "object" }, diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index 2f51bfb397..389b733853 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -8,7 +8,7 @@ import * as Oazapfts from "@oazapfts/runtime"; import * as QS from "@oazapfts/runtime/query"; export const defaults: Oazapfts.Defaults = { headers: {}, - baseUrl: "/api", + baseUrl: "/api" }; const oazapfts = Oazapfts.runtime(defaults); export const servers = { @@ -57,7 +57,7 @@ export type IntegrityReportResponseDto = { export type IntegrityReportSummaryResponseDto = { checksum_mismatch: number; missing_file: number; - orphan_file: number; + untracked_file: number; }; export type SetMaintenanceModeDto = { action: MaintenanceAction; @@ -1491,7 +1491,7 @@ export type SystemConfigIntegrityJob = { export type SystemConfigIntegrityChecks = { checksumFiles: SystemConfigIntegrityChecksumJob; missingFiles: SystemConfigIntegrityJob; - orphanedFiles: SystemConfigIntegrityJob; + untrackedFiles: SystemConfigIntegrityJob; }; export type JobSettingsDto = { concurrency: number; @@ -5257,7 +5257,7 @@ export enum UserAvatarColor { Amber = "amber" } export enum IntegrityReportType { - OrphanFile = "orphan_file", + UntrackedFile = "untracked_file", MissingFile = "missing_file", ChecksumMismatch = "checksum_mismatch" } @@ -5503,13 +5503,13 @@ export enum ManualJobName { MemoryCreate = "memory-create", BackupDatabase = "backup-database", IntegrityMissingFiles = "integrity-missing-files", - IntegrityOrphanFiles = "integrity-orphan-files", + IntegrityUntrackedFiles = "integrity-untracked-files", IntegrityChecksumMismatch = "integrity-checksum-mismatch", IntegrityMissingFilesRefresh = "integrity-missing-files-refresh", - IntegrityOrphanFilesRefresh = "integrity-orphan-files-refresh", + IntegrityUntrackedFilesRefresh = "integrity-untracked-files-refresh", IntegrityChecksumMismatchRefresh = "integrity-checksum-mismatch-refresh", IntegrityMissingFilesDeleteAll = "integrity-missing-files-delete-all", - IntegrityOrphanFilesDeleteAll = "integrity-orphan-files-delete-all", + IntegrityUntrackedFilesDeleteAll = "integrity-untracked-files-delete-all", IntegrityChecksumMismatchDeleteAll = "integrity-checksum-mismatch-delete-all" } export enum QueueName { @@ -5624,9 +5624,9 @@ export enum JobName { OcrQueueAll = "OcrQueueAll", Ocr = "Ocr", WorkflowRun = "WorkflowRun", - IntegrityOrphanedFilesQueueAll = "IntegrityOrphanedFilesQueueAll", - IntegrityOrphanedFiles = "IntegrityOrphanedFiles", - IntegrityOrphanedRefresh = "IntegrityOrphanedRefresh", + IntegrityUntrackedFilesQueueAll = "IntegrityUntrackedFilesQueueAll", + IntegrityUntrackedFiles = "IntegrityUntrackedFiles", + IntegrityUntrackedRefresh = "IntegrityUntrackedRefresh", IntegrityMissingFilesQueueAll = "IntegrityMissingFilesQueueAll", IntegrityMissingFiles = "IntegrityMissingFiles", IntegrityMissingFilesRefresh = "IntegrityMissingFilesRefresh", diff --git a/server/src/config.ts b/server/src/config.ts index 4f366737bf..42d1279eed 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -51,7 +51,7 @@ export interface SystemConfig { enabled: boolean; cronExpression: string; }; - orphanedFiles: { + untrackedFiles: { enabled: boolean; cronExpression: string; }; @@ -243,7 +243,7 @@ export const defaults = Object.freeze({ enabled: true, cronExpression: CronExpression.EVERY_DAY_AT_3AM, }, - orphanedFiles: { + untrackedFiles: { enabled: true, cronExpression: CronExpression.EVERY_DAY_AT_3AM, }, diff --git a/server/src/controllers/integrity.controller.ts b/server/src/controllers/integrity.controller.ts index 083c8055bb..9d455e3c68 100644 --- a/server/src/controllers/integrity.controller.ts +++ b/server/src/controllers/integrity.controller.ts @@ -76,7 +76,7 @@ export class IntegrityController { @Get('report/:id/file') @Endpoint({ summary: 'Download flagged file', - description: 'Download the orphan/broken file if one exists', + description: 'Download the untracked/broken file if one exists', history: new HistoryBuilder().added('v9.9.9').alpha('v9.9.9'), }) @FileResponse() diff --git a/server/src/dtos/integrity.dto.ts b/server/src/dtos/integrity.dto.ts index 1264201147..7425a4d727 100644 --- a/server/src/dtos/integrity.dto.ts +++ b/server/src/dtos/integrity.dto.ts @@ -10,7 +10,7 @@ export class IntegrityReportSummaryResponseDto { @ApiProperty({ type: 'integer' }) [IntegrityReportType.MissingFile]!: number; @ApiProperty({ type: 'integer' }) - [IntegrityReportType.OrphanFile]!: number; + [IntegrityReportType.UntrackedFile]!: number; } export class IntegrityGetReportDto { diff --git a/server/src/dtos/system-config.dto.ts b/server/src/dtos/system-config.dto.ts index 2510c8768e..150e0adb3f 100644 --- a/server/src/dtos/system-config.dto.ts +++ b/server/src/dtos/system-config.dto.ts @@ -174,7 +174,7 @@ class SystemConfigIntegrityChecks { @Type(() => SystemConfigIntegrityJob) @ValidateNested() @IsObject() - orphanedFiles!: SystemConfigIntegrityJob; + untrackedFiles!: SystemConfigIntegrityJob; @Type(() => SystemConfigIntegrityChecksumJob) @ValidateNested() diff --git a/server/src/enum.ts b/server/src/enum.ts index c42ac36df1..74cc446e20 100644 --- a/server/src/enum.ts +++ b/server/src/enum.ts @@ -347,7 +347,7 @@ export enum SourceType { } export enum IntegrityReportType { - OrphanFile = 'orphan_file', + UntrackedFile = 'untracked_file', MissingFile = 'missing_file', ChecksumFail = 'checksum_mismatch', } @@ -360,13 +360,13 @@ export enum ManualJobName { MemoryCreate = 'memory-create', BackupDatabase = 'backup-database', IntegrityMissingFiles = `integrity-missing-files`, - IntegrityOrphanFiles = `integrity-orphan-files`, + IntegrityUntrackedFiles = `integrity-untracked-files`, IntegrityChecksumFiles = `integrity-checksum-mismatch`, IntegrityMissingFilesRefresh = `integrity-missing-files-refresh`, - IntegrityOrphanFilesRefresh = `integrity-orphan-files-refresh`, + IntegrityUntrackedFilesRefresh = `integrity-untracked-files-refresh`, IntegrityChecksumFilesRefresh = `integrity-checksum-mismatch-refresh`, IntegrityMissingFilesDeleteAll = `integrity-missing-files-delete-all`, - IntegrityOrphanFilesDeleteAll = `integrity-orphan-files-delete-all`, + IntegrityUntrackedFilesDeleteAll = `integrity-untracked-files-delete-all`, IntegrityChecksumFilesDeleteAll = `integrity-checksum-mismatch-delete-all`, } @@ -662,9 +662,9 @@ export enum JobName { WorkflowRun = 'WorkflowRun', // Integrity - IntegrityOrphanedFilesQueueAll = 'IntegrityOrphanedFilesQueueAll', - IntegrityOrphanedFiles = 'IntegrityOrphanedFiles', - IntegrityOrphanedFilesRefresh = 'IntegrityOrphanedRefresh', + IntegrityUntrackedFilesQueueAll = 'IntegrityUntrackedFilesQueueAll', + IntegrityUntrackedFiles = 'IntegrityUntrackedFiles', + IntegrityUntrackedFilesRefresh = 'IntegrityUntrackedRefresh', IntegrityMissingFilesQueueAll = 'IntegrityMissingFilesQueueAll', IntegrityMissingFiles = 'IntegrityMissingFiles', IntegrityMissingFilesRefresh = 'IntegrityMissingFilesRefresh', diff --git a/server/src/queries/integrity.repository.sql b/server/src/queries/integrity.repository.sql index a381a1abc6..ef7673dead 100644 --- a/server/src/queries/integrity.repository.sql +++ b/server/src/queries/integrity.repository.sql @@ -21,7 +21,7 @@ select count(*) filter ( where "type" = $3 - ) as "orphan_file" + ) as "untracked_file" from "integrity_report" diff --git a/server/src/repositories/integrity.repository.ts b/server/src/repositories/integrity.repository.ts index dde3f0fffa..c2bc5be236 100644 --- a/server/src/repositories/integrity.repository.ts +++ b/server/src/repositories/integrity.repository.ts @@ -57,8 +57,8 @@ export class IntegrityRepository { .select((eb) => eb.fn .countAll() - .filterWhere('type', '=', IntegrityReportType.OrphanFile) - .as(IntegrityReportType.OrphanFile), + .filterWhere('type', '=', IntegrityReportType.UntrackedFile) + .as(IntegrityReportType.UntrackedFile), ) .executeTakeFirstOrThrow(); } @@ -149,7 +149,7 @@ export class IntegrityRepository { ) .leftJoin('integrity_report', (join) => join - .on('integrity_report.type', '=', IntegrityReportType.OrphanFile) + .on('integrity_report.type', '=', IntegrityReportType.UntrackedFile) .on((eb) => eb.or([ eb('integrity_report.assetId', '=', eb.ref('allPaths.assetId')), diff --git a/server/src/services/integrity.service.spec.ts b/server/src/services/integrity.service.spec.ts index a350e6bd05..ed640f1273 100644 --- a/server/src/services/integrity.service.spec.ts +++ b/server/src/services/integrity.service.spec.ts @@ -145,7 +145,7 @@ describe(IntegrityService.name, () => { expect(mocks.asset.deleteFiles).toHaveBeenCalledWith([{ id: 'fileAssetId' }]); }); - it('deletes orphaned file', async () => { + it('deletes untracked file', async () => { mocks.integrityReport.getById.mockResolvedValue({ id: 'id', createdAt: new Date(0), @@ -169,7 +169,7 @@ describe(IntegrityService.name, () => { }); }); - describe('handleOrphanedFilesQueueAll', () => { + describe('handleUntrackedFilesQueueAll', () => { beforeEach(() => { mocks.integrityReport.streamIntegrityReportsWithAssetChecksum.mockReturnValue((function* () {})() as never); }); @@ -189,11 +189,11 @@ describe(IntegrityService.name, () => { })() as never, ); - await sut.handleOrphanedFilesQueueAll({ refreshOnly: false }); + await sut.handleUntrackedFilesQueueAll({ refreshOnly: false }); expect(mocks.job.queue).toBeCalledTimes(4); expect(mocks.job.queue).toBeCalledWith({ - name: JobName.IntegrityOrphanedFiles, + name: JobName.IntegrityUntrackedFiles, data: { type: 'asset', paths: expect.arrayContaining(['/path/to/file']), @@ -201,7 +201,7 @@ describe(IntegrityService.name, () => { }); expect(mocks.job.queue).toBeCalledWith({ - name: JobName.IntegrityOrphanedFiles, + name: JobName.IntegrityUntrackedFiles, data: { type: 'asset_file', paths: expect.arrayContaining(['/path/to/file3']), @@ -216,11 +216,11 @@ describe(IntegrityService.name, () => { })() as never, ); - await sut.handleOrphanedFilesQueueAll({ refreshOnly: false }); + await sut.handleUntrackedFilesQueueAll({ refreshOnly: false }); expect(mocks.job.queue).toBeCalledTimes(1); expect(mocks.job.queue).toBeCalledWith({ - name: JobName.IntegrityOrphanedFilesRefresh, + name: JobName.IntegrityUntrackedFilesRefresh, data: { items: expect.arrayContaining(['mockReport']), }, @@ -228,33 +228,33 @@ describe(IntegrityService.name, () => { }); it('should succeed', async () => { - await expect(sut.handleOrphanedFilesQueueAll({ refreshOnly: false })).resolves.toBe(JobStatus.Success); + await expect(sut.handleUntrackedFilesQueueAll({ refreshOnly: false })).resolves.toBe(JobStatus.Success); }); }); - describe('handleOrphanedFiles', () => { - it('should detect orphaned asset files', async () => { + describe('handleUntrackedFiles', () => { + it('should detect untracked asset files', async () => { mocks.integrityReport.getAssetPathsByPaths.mockResolvedValue([ { originalPath: '/path/to/file1', encodedVideoPath: null }, ]); - await sut.handleOrphanedFiles({ + await sut.handleUntrackedFiles({ type: 'asset', - paths: ['/path/to/file1', '/path/to/orphan'], + paths: ['/path/to/file1', '/path/to/untracked'], }); - expect(mocks.integrityReport.getAssetPathsByPaths).toHaveBeenCalledWith(['/path/to/file1', '/path/to/orphan']); + expect(mocks.integrityReport.getAssetPathsByPaths).toHaveBeenCalledWith(['/path/to/file1', '/path/to/untracked']); expect(mocks.integrityReport.create).toHaveBeenCalledWith([ - { type: IntegrityReportType.OrphanFile, path: '/path/to/orphan' }, + { type: IntegrityReportType.UntrackedFile, path: '/path/to/untracked' }, ]); }); - it('should not create reports when no orphans found for assets', async () => { + it('should not create reports when no untracked files found for assets', async () => { mocks.integrityReport.getAssetPathsByPaths.mockResolvedValue([ { originalPath: '/path/to/file1', encodedVideoPath: '/path/to/encoded' }, ]); - await sut.handleOrphanedFiles({ + await sut.handleUntrackedFiles({ type: 'asset', paths: ['/path/to/file1', '/path/to/encoded'], }); @@ -262,28 +262,28 @@ describe(IntegrityService.name, () => { expect(mocks.integrityReport.create).not.toHaveBeenCalled(); }); - it('should detect orphaned asset_file files', async () => { + it('should detect untracked asset_file files', async () => { mocks.integrityReport.getAssetFilePathsByPaths.mockResolvedValue([{ path: '/path/to/thumb1' }]); - await sut.handleOrphanedFiles({ + await sut.handleUntrackedFiles({ type: 'asset_file', - paths: ['/path/to/thumb1', '/path/to/orphan_thumb'], + paths: ['/path/to/thumb1', '/path/to/untracked_thumb'], }); expect(mocks.integrityReport.create).toHaveBeenCalledWith([ - { type: IntegrityReportType.OrphanFile, path: '/path/to/orphan_thumb' }, + { type: IntegrityReportType.UntrackedFile, path: '/path/to/untracked_thumb' }, ]); }); }); - describe('handleOrphanedRefresh', () => { + describe('handleUntrackedRefresh', () => { it('should delete reports for files that no longer exist', async () => { mocks.storage.stat .mockRejectedValueOnce(new Error('ENOENT')) .mockResolvedValueOnce({} as never) .mockRejectedValueOnce(new Error('ENOENT')); - await sut.handleOrphanedRefresh({ + await sut.handleUntrackedRefresh({ items: [ { reportId: 'report1', path: '/path/to/missing1' }, { reportId: 'report2', path: '/path/to/existing' }, @@ -297,7 +297,7 @@ describe(IntegrityService.name, () => { it('should not delete reports for files that still exist', async () => { mocks.storage.stat.mockResolvedValue({} as never); - await sut.handleOrphanedRefresh({ + await sut.handleUntrackedRefresh({ items: [{ reportId: 'report1', path: '/path/to/existing' }], }); @@ -305,7 +305,7 @@ describe(IntegrityService.name, () => { }); it('should succeed', async () => { - await expect(sut.handleOrphanedRefresh({ items: [] })).resolves.toBe(JobStatus.Success); + await expect(sut.handleUntrackedRefresh({ items: [] })).resolves.toBe(JobStatus.Success); }); }); @@ -604,24 +604,24 @@ describe(IntegrityService.name, () => { expect(mocks.job.queue).toHaveBeenCalledTimes(2); }); - it('should queue delete jobs for orphan file reports', async () => { + it('should queue delete jobs for untracked file reports', async () => { mocks.integrityReport.streamIntegrityReportsByProperty.mockReturnValue( (function* () { - yield { id: 'report1', path: '/path/to/orphan' }; + yield { id: 'report1', path: '/path/to/untracked' }; })() as never, ); - await sut.handleDeleteAllIntegrityReports({ type: IntegrityReportType.OrphanFile }); + await sut.handleDeleteAllIntegrityReports({ type: IntegrityReportType.UntrackedFile }); expect(mocks.integrityReport.streamIntegrityReportsByProperty).toHaveBeenCalledWith( undefined, - IntegrityReportType.OrphanFile, + IntegrityReportType.UntrackedFile, ); expect(mocks.job.queue).toHaveBeenCalledWith({ name: JobName.IntegrityDeleteReports, data: { - reports: [{ id: 'report1', path: '/path/to/orphan' }], + reports: [{ id: 'report1', path: '/path/to/untracked' }], }, }); }); @@ -648,7 +648,7 @@ describe(IntegrityService.name, () => { { id: 'report1', assetId: 'asset1', fileAssetId: null, path: '/path/to/file1' }, { id: 'report2', assetId: 'asset2', fileAssetId: null, path: '/path/to/file2' }, { id: 'report3', assetId: null, fileAssetId: 'fileAsset1', path: '/path/to/file3' }, - { id: 'report4', assetId: null, fileAssetId: null, path: '/path/to/orphan' }, + { id: 'report4', assetId: null, fileAssetId: null, path: '/path/to/untracked' }, ], }); @@ -666,7 +666,7 @@ describe(IntegrityService.name, () => { expect(mocks.asset.deleteFiles).toHaveBeenCalledWith([{ id: 'fileAsset1' }]); - expect(mocks.storage.unlink).toHaveBeenCalledWith('/path/to/orphan'); + expect(mocks.storage.unlink).toHaveBeenCalledWith('/path/to/untracked'); expect(mocks.integrityReport.deleteByIds).toHaveBeenCalledWith(['report4']); }); diff --git a/server/src/services/integrity.service.ts b/server/src/services/integrity.service.ts index 32493e3f39..13f06a4b32 100644 --- a/server/src/services/integrity.service.ts +++ b/server/src/services/integrity.service.ts @@ -31,15 +31,15 @@ import { IIntegrityDeleteReportTypeJob, IIntegrityJob, IIntegrityMissingFilesJob, - IIntegrityOrphanedFilesJob, IIntegrityPathWithChecksumJob, IIntegrityPathWithReportJob, + IIntegrityUntrackedFilesJob, } from 'src/types'; import { ImmichFileResponse } from 'src/utils/file'; import { handlePromiseError } from 'src/utils/misc'; /** - * Orphan Files: + * Untracked Files: * Files are detected in /data/encoded-video, /data/library, /data/upload * Checked against the asset table * Files are detected in /data/thumbs @@ -69,20 +69,20 @@ export class IntegrityService extends BaseService { @OnEvent({ name: 'ConfigInit', workers: [ImmichWorker.Microservices] }) async onConfigInit({ newConfig: { - integrityChecks: { orphanedFiles, missingFiles, checksumFiles }, + integrityChecks: { untrackedFiles, missingFiles, checksumFiles }, }, }: ArgOf<'ConfigInit'>) { this.integrityLock = await this.databaseRepository.tryLock(DatabaseLock.IntegrityCheck); if (this.integrityLock) { this.cronRepository.create({ - name: 'integrityOrphanedFiles', - expression: orphanedFiles.cronExpression, + name: 'integrityUntrackedFiles', + expression: untrackedFiles.cronExpression, onTick: () => handlePromiseError( - this.jobRepository.queue({ name: JobName.IntegrityOrphanedFilesQueueAll, data: {} }), + this.jobRepository.queue({ name: JobName.IntegrityUntrackedFilesQueueAll, data: {} }), this.logger, ), - start: orphanedFiles.enabled, + start: untrackedFiles.enabled, }); this.cronRepository.create({ @@ -109,7 +109,7 @@ export class IntegrityService extends BaseService { @OnEvent({ name: 'ConfigUpdate', server: true }) onConfigUpdate({ newConfig: { - integrityChecks: { orphanedFiles, missingFiles, checksumFiles }, + integrityChecks: { untrackedFiles, missingFiles, checksumFiles }, }, }: ArgOf<'ConfigUpdate'>) { if (!this.integrityLock) { @@ -117,9 +117,9 @@ export class IntegrityService extends BaseService { } this.cronRepository.update({ - name: 'integrityOrphanedFiles', - expression: orphanedFiles.cronExpression, - start: orphanedFiles.enabled, + name: 'integrityUntrackedFiles', + expression: untrackedFiles.cronExpression, + start: untrackedFiles.enabled, }); this.cronRepository.update({ @@ -194,16 +194,16 @@ export class IntegrityService extends BaseService { } } - @OnJob({ name: JobName.IntegrityOrphanedFilesQueueAll, queue: QueueName.IntegrityCheck }) - async handleOrphanedFilesQueueAll({ refreshOnly }: IIntegrityJob = {}): Promise { - this.logger.log(`Checking for out of date orphaned file reports...`); + @OnJob({ name: JobName.IntegrityUntrackedFilesQueueAll, queue: QueueName.IntegrityCheck }) + async handleUntrackedFilesQueueAll({ refreshOnly }: IIntegrityJob = {}): Promise { + this.logger.log(`Checking for out of date untracked file reports...`); - const reports = this.integrityRepository.streamIntegrityReportsWithAssetChecksum(IntegrityReportType.OrphanFile); + const reports = this.integrityRepository.streamIntegrityReportsWithAssetChecksum(IntegrityReportType.UntrackedFile); let total = 0; for await (const batchReports of chunk(reports, JOBS_LIBRARY_PAGINATION_SIZE)) { await this.jobRepository.queue({ - name: JobName.IntegrityOrphanedFilesRefresh, + name: JobName.IntegrityUntrackedFilesRefresh, data: { items: batchReports, }, @@ -218,7 +218,7 @@ export class IntegrityService extends BaseService { return JobStatus.Success; } - this.logger.log(`Scanning for orphaned files...`); + this.logger.log(`Scanning for untracked files...`); const assetPaths = this.storageRepository.walk({ pathsToCrawl: [StorageFolder.EncodedVideo, StorageFolder.Library, StorageFolder.Upload].map((folder) => @@ -247,7 +247,7 @@ export class IntegrityService extends BaseService { total = 0; for await (const [batchType, batchPaths] of paths()) { await this.jobRepository.queue({ - name: JobName.IntegrityOrphanedFiles, + name: JobName.IntegrityUntrackedFiles, data: { type: batchType, paths: batchPaths, @@ -257,48 +257,48 @@ export class IntegrityService extends BaseService { const count = batchPaths.length; total += count; - this.logger.log(`Queued orphan check of ${count} file(s) (${total} so far)`); + this.logger.log(`Queued untracked check of ${count} file(s) (${total} so far)`); } return JobStatus.Success; } - @OnJob({ name: JobName.IntegrityOrphanedFiles, queue: QueueName.IntegrityCheck }) - async handleOrphanedFiles({ type, paths }: IIntegrityOrphanedFilesJob): Promise { - this.logger.log(`Processing batch of ${paths.length} files to check if they are orphaned.`); + @OnJob({ name: JobName.IntegrityUntrackedFiles, queue: QueueName.IntegrityCheck }) + async handleUntrackedFiles({ type, paths }: IIntegrityUntrackedFilesJob): Promise { + this.logger.log(`Processing batch of ${paths.length} files to check if they are untracked.`); - const orphanedFiles = new Set(paths); + const untrackedFiles = new Set(paths); if (type === 'asset') { const assets = await this.integrityRepository.getAssetPathsByPaths(paths); for (const { originalPath, encodedVideoPath } of assets) { - orphanedFiles.delete(originalPath); + untrackedFiles.delete(originalPath); if (encodedVideoPath) { - orphanedFiles.delete(encodedVideoPath); + untrackedFiles.delete(encodedVideoPath); } } } else { const assets = await this.integrityRepository.getAssetFilePathsByPaths(paths); for (const { path } of assets) { - orphanedFiles.delete(path); + untrackedFiles.delete(path); } } - if (orphanedFiles.size > 0) { + if (untrackedFiles.size > 0) { await this.integrityRepository.create( - [...orphanedFiles].map((path) => ({ - type: IntegrityReportType.OrphanFile, + [...untrackedFiles].map((path) => ({ + type: IntegrityReportType.UntrackedFile, path, })), ); } - this.logger.log(`Processed ${paths.length} and found ${orphanedFiles.size} orphaned file(s).`); + this.logger.log(`Processed ${paths.length} and found ${untrackedFiles.size} untracked file(s).`); return JobStatus.Success; } - @OnJob({ name: JobName.IntegrityOrphanedFilesRefresh, queue: QueueName.IntegrityCheck }) - async handleOrphanedRefresh({ items }: IIntegrityPathWithReportJob): Promise { + @OnJob({ name: JobName.IntegrityUntrackedFilesRefresh, queue: QueueName.IntegrityCheck }) + async handleUntrackedRefresh({ items }: IIntegrityPathWithReportJob): Promise { this.logger.log(`Processing batch of ${items.length} reports to check if they are out of date.`); const results = await Promise.all( @@ -619,7 +619,7 @@ export class IntegrityService extends BaseService { properties = ['assetId', 'fileAssetId'] as const; break; } - case IntegrityReportType.OrphanFile: { + case IntegrityReportType.UntrackedFile: { properties = [void 0] as const; break; } diff --git a/server/src/services/job.service.ts b/server/src/services/job.service.ts index 1cd9ea2e1f..5516eeb826 100644 --- a/server/src/services/job.service.ts +++ b/server/src/services/job.service.ts @@ -38,8 +38,8 @@ const asJobItem = (dto: JobCreateDto): JobItem => { return { name: JobName.IntegrityMissingFilesQueueAll }; } - case ManualJobName.IntegrityOrphanFiles: { - return { name: JobName.IntegrityOrphanedFilesQueueAll }; + case ManualJobName.IntegrityUntrackedFiles: { + return { name: JobName.IntegrityUntrackedFilesQueueAll }; } case ManualJobName.IntegrityChecksumFiles: { @@ -50,8 +50,8 @@ const asJobItem = (dto: JobCreateDto): JobItem => { return { name: JobName.IntegrityMissingFilesQueueAll, data: { refreshOnly: true } }; } - case ManualJobName.IntegrityOrphanFilesRefresh: { - return { name: JobName.IntegrityOrphanedFilesQueueAll, data: { refreshOnly: true } }; + case ManualJobName.IntegrityUntrackedFilesRefresh: { + return { name: JobName.IntegrityUntrackedFilesQueueAll, data: { refreshOnly: true } }; } case ManualJobName.IntegrityChecksumFilesRefresh: { @@ -62,8 +62,8 @@ const asJobItem = (dto: JobCreateDto): JobItem => { return { name: JobName.IntegrityDeleteReportType, data: { type: IntegrityReportType.MissingFile } }; } - case ManualJobName.IntegrityOrphanFilesDeleteAll: { - return { name: JobName.IntegrityDeleteReportType, data: { type: IntegrityReportType.OrphanFile } }; + case ManualJobName.IntegrityUntrackedFilesDeleteAll: { + return { name: JobName.IntegrityDeleteReportType, data: { type: IntegrityReportType.UntrackedFile } }; } case ManualJobName.IntegrityChecksumFilesDeleteAll: { diff --git a/server/src/services/system-config.service.spec.ts b/server/src/services/system-config.service.spec.ts index f6ba209951..862e77aa19 100644 --- a/server/src/services/system-config.service.spec.ts +++ b/server/src/services/system-config.service.spec.ts @@ -74,7 +74,7 @@ const updatedConfig = Object.freeze({ tonemap: ToneMapping.Hable, }, integrityChecks: { - orphanedFiles: { + untrackedFiles: { enabled: true, cronExpression: '0 03 * * *', }, diff --git a/server/src/types.ts b/server/src/types.ts index 19480cdde1..16ce2909af 100644 --- a/server/src/types.ts +++ b/server/src/types.ts @@ -294,7 +294,7 @@ export interface IIntegrityDeleteReportsJob { }[]; } -export interface IIntegrityOrphanedFilesJob { +export interface IIntegrityUntrackedFilesJob { type: 'asset' | 'asset_file'; paths: string[]; } @@ -428,9 +428,9 @@ export type JobItem = | { name: JobName.WorkflowRun; data: IWorkflowJob } // Integrity - | { name: JobName.IntegrityOrphanedFilesQueueAll; data?: IIntegrityJob } - | { name: JobName.IntegrityOrphanedFiles; data: IIntegrityOrphanedFilesJob } - | { name: JobName.IntegrityOrphanedFilesRefresh; data: IIntegrityPathWithReportJob } + | { name: JobName.IntegrityUntrackedFilesQueueAll; data?: IIntegrityJob } + | { name: JobName.IntegrityUntrackedFiles; data: IIntegrityUntrackedFilesJob } + | { name: JobName.IntegrityUntrackedFilesRefresh; data: IIntegrityPathWithReportJob } | { name: JobName.IntegrityMissingFilesQueueAll; data?: IIntegrityJob } | { name: JobName.IntegrityMissingFiles; data: IIntegrityPathWithReportJob } | { name: JobName.IntegrityMissingFilesRefresh; data: IIntegrityPathWithReportJob } diff --git a/web/src/lib/modals/JobCreateModal.svelte b/web/src/lib/modals/JobCreateModal.svelte index ec050f87af..c1099d7537 100644 --- a/web/src/lib/modals/JobCreateModal.svelte +++ b/web/src/lib/modals/JobCreateModal.svelte @@ -21,8 +21,8 @@ value: ManualJobName.IntegrityMissingFiles, }, { - title: $t('admin.maintenance_integrity_orphan_file_job'), - value: ManualJobName.IntegrityOrphanFiles, + title: $t('admin.maintenance_integrity_untracked_file_job'), + value: ManualJobName.IntegrityUntrackedFiles, }, { title: $t('admin.maintenance_integrity_checksum_mismatch_job'), @@ -33,8 +33,8 @@ value: ManualJobName.IntegrityMissingFilesRefresh, }, { - title: $t('admin.maintenance_integrity_orphan_file_refresh_job'), - value: ManualJobName.IntegrityOrphanFilesRefresh, + title: $t('admin.maintenance_integrity_untracked_file_refresh_job'), + value: ManualJobName.IntegrityUntrackedFilesRefresh, }, { title: $t('admin.maintenance_integrity_checksum_mismatch_refresh_job'), diff --git a/web/src/routes/admin/maintenance/+page.svelte b/web/src/routes/admin/maintenance/+page.svelte index b94e7a00fa..402734c7d6 100644 --- a/web/src/routes/admin/maintenance/+page.svelte +++ b/web/src/routes/admin/maintenance/+page.svelte @@ -30,7 +30,7 @@ let integrityReport: IntegrityReportSummaryResponseDto = $state(data.integrityReport); const TYPES: IntegrityReportType[] = [ - IntegrityReportType.OrphanFile, + IntegrityReportType.UntrackedFile, IntegrityReportType.MissingFile, IntegrityReportType.ChecksumMismatch, ]; @@ -53,8 +53,8 @@ async function runJob(reportType: IntegrityReportType, refreshOnly?: boolean) { let name: ManualJobName; switch (reportType) { - case IntegrityReportType.OrphanFile: { - name = refreshOnly ? ManualJobName.IntegrityOrphanFilesRefresh : ManualJobName.IntegrityOrphanFiles; + case IntegrityReportType.UntrackedFile: { + name = refreshOnly ? ManualJobName.IntegrityUntrackedFilesRefresh : ManualJobName.IntegrityUntrackedFiles; break; } case IntegrityReportType.MissingFile: { diff --git a/web/src/routes/admin/maintenance/integrity-report/[type]/+page.svelte b/web/src/routes/admin/maintenance/integrity-report/[type]/+page.svelte index 59256c1513..a153b2f4eb 100644 --- a/web/src/routes/admin/maintenance/integrity-report/[type]/+page.svelte +++ b/web/src/routes/admin/maintenance/integrity-report/[type]/+page.svelte @@ -57,8 +57,8 @@ if (confirm) { let name: ManualJobName; switch (data.type) { - case IntegrityReportType.OrphanFile: { - name = ManualJobName.IntegrityOrphanFilesDeleteAll; + case IntegrityReportType.UntrackedFile: { + name = ManualJobName.IntegrityUntrackedFilesDeleteAll; break; } case IntegrityReportType.MissingFile: { @@ -108,7 +108,7 @@ const handleOpen = async (event: Event, props: Partial, reportId: string) => { const items: MenuItems = []; - if (data.type === IntegrityReportType.OrphanFile || data.type === IntegrityReportType.ChecksumMismatch) { + if (data.type === IntegrityReportType.UntrackedFile || data.type === IntegrityReportType.ChecksumMismatch) { items.push({ title: $t('download'), icon: mdiDownload,