mirror of
https://github.com/immich-app/immich.git
synced 2025-12-19 09:13:14 +03:00
feat: add config options & cron entries for checks
This commit is contained in:
3
mobile/openapi/README.md
generated
3
mobile/openapi/README.md
generated
@@ -569,6 +569,9 @@ Class | Method | HTTP request | Description
|
|||||||
- [SystemConfigGeneratedFullsizeImageDto](doc//SystemConfigGeneratedFullsizeImageDto.md)
|
- [SystemConfigGeneratedFullsizeImageDto](doc//SystemConfigGeneratedFullsizeImageDto.md)
|
||||||
- [SystemConfigGeneratedImageDto](doc//SystemConfigGeneratedImageDto.md)
|
- [SystemConfigGeneratedImageDto](doc//SystemConfigGeneratedImageDto.md)
|
||||||
- [SystemConfigImageDto](doc//SystemConfigImageDto.md)
|
- [SystemConfigImageDto](doc//SystemConfigImageDto.md)
|
||||||
|
- [SystemConfigIntegrityChecks](doc//SystemConfigIntegrityChecks.md)
|
||||||
|
- [SystemConfigIntegrityChecksumJob](doc//SystemConfigIntegrityChecksumJob.md)
|
||||||
|
- [SystemConfigIntegrityJob](doc//SystemConfigIntegrityJob.md)
|
||||||
- [SystemConfigJobDto](doc//SystemConfigJobDto.md)
|
- [SystemConfigJobDto](doc//SystemConfigJobDto.md)
|
||||||
- [SystemConfigLibraryDto](doc//SystemConfigLibraryDto.md)
|
- [SystemConfigLibraryDto](doc//SystemConfigLibraryDto.md)
|
||||||
- [SystemConfigLibraryScanDto](doc//SystemConfigLibraryScanDto.md)
|
- [SystemConfigLibraryScanDto](doc//SystemConfigLibraryScanDto.md)
|
||||||
|
|||||||
3
mobile/openapi/lib/api.dart
generated
3
mobile/openapi/lib/api.dart
generated
@@ -321,6 +321,9 @@ part 'model/system_config_faces_dto.dart';
|
|||||||
part 'model/system_config_generated_fullsize_image_dto.dart';
|
part 'model/system_config_generated_fullsize_image_dto.dart';
|
||||||
part 'model/system_config_generated_image_dto.dart';
|
part 'model/system_config_generated_image_dto.dart';
|
||||||
part 'model/system_config_image_dto.dart';
|
part 'model/system_config_image_dto.dart';
|
||||||
|
part 'model/system_config_integrity_checks.dart';
|
||||||
|
part 'model/system_config_integrity_checksum_job.dart';
|
||||||
|
part 'model/system_config_integrity_job.dart';
|
||||||
part 'model/system_config_job_dto.dart';
|
part 'model/system_config_job_dto.dart';
|
||||||
part 'model/system_config_library_dto.dart';
|
part 'model/system_config_library_dto.dart';
|
||||||
part 'model/system_config_library_scan_dto.dart';
|
part 'model/system_config_library_scan_dto.dart';
|
||||||
|
|||||||
6
mobile/openapi/lib/api_client.dart
generated
6
mobile/openapi/lib/api_client.dart
generated
@@ -690,6 +690,12 @@ class ApiClient {
|
|||||||
return SystemConfigGeneratedImageDto.fromJson(value);
|
return SystemConfigGeneratedImageDto.fromJson(value);
|
||||||
case 'SystemConfigImageDto':
|
case 'SystemConfigImageDto':
|
||||||
return SystemConfigImageDto.fromJson(value);
|
return SystemConfigImageDto.fromJson(value);
|
||||||
|
case 'SystemConfigIntegrityChecks':
|
||||||
|
return SystemConfigIntegrityChecks.fromJson(value);
|
||||||
|
case 'SystemConfigIntegrityChecksumJob':
|
||||||
|
return SystemConfigIntegrityChecksumJob.fromJson(value);
|
||||||
|
case 'SystemConfigIntegrityJob':
|
||||||
|
return SystemConfigIntegrityJob.fromJson(value);
|
||||||
case 'SystemConfigJobDto':
|
case 'SystemConfigJobDto':
|
||||||
return SystemConfigJobDto.fromJson(value);
|
return SystemConfigJobDto.fromJson(value);
|
||||||
case 'SystemConfigLibraryDto':
|
case 'SystemConfigLibraryDto':
|
||||||
|
|||||||
10
mobile/openapi/lib/model/system_config_dto.dart
generated
10
mobile/openapi/lib/model/system_config_dto.dart
generated
@@ -16,6 +16,7 @@ class SystemConfigDto {
|
|||||||
required this.backup,
|
required this.backup,
|
||||||
required this.ffmpeg,
|
required this.ffmpeg,
|
||||||
required this.image,
|
required this.image,
|
||||||
|
required this.integrityChecks,
|
||||||
required this.job,
|
required this.job,
|
||||||
required this.library_,
|
required this.library_,
|
||||||
required this.logging,
|
required this.logging,
|
||||||
@@ -42,6 +43,8 @@ class SystemConfigDto {
|
|||||||
|
|
||||||
SystemConfigImageDto image;
|
SystemConfigImageDto image;
|
||||||
|
|
||||||
|
SystemConfigIntegrityChecks integrityChecks;
|
||||||
|
|
||||||
SystemConfigJobDto job;
|
SystemConfigJobDto job;
|
||||||
|
|
||||||
SystemConfigLibraryDto library_;
|
SystemConfigLibraryDto library_;
|
||||||
@@ -83,6 +86,7 @@ class SystemConfigDto {
|
|||||||
other.backup == backup &&
|
other.backup == backup &&
|
||||||
other.ffmpeg == ffmpeg &&
|
other.ffmpeg == ffmpeg &&
|
||||||
other.image == image &&
|
other.image == image &&
|
||||||
|
other.integrityChecks == integrityChecks &&
|
||||||
other.job == job &&
|
other.job == job &&
|
||||||
other.library_ == library_ &&
|
other.library_ == library_ &&
|
||||||
other.logging == logging &&
|
other.logging == logging &&
|
||||||
@@ -108,6 +112,7 @@ class SystemConfigDto {
|
|||||||
(backup.hashCode) +
|
(backup.hashCode) +
|
||||||
(ffmpeg.hashCode) +
|
(ffmpeg.hashCode) +
|
||||||
(image.hashCode) +
|
(image.hashCode) +
|
||||||
|
(integrityChecks.hashCode) +
|
||||||
(job.hashCode) +
|
(job.hashCode) +
|
||||||
(library_.hashCode) +
|
(library_.hashCode) +
|
||||||
(logging.hashCode) +
|
(logging.hashCode) +
|
||||||
@@ -128,13 +133,14 @@ class SystemConfigDto {
|
|||||||
(user.hashCode);
|
(user.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'SystemConfigDto[backup=$backup, ffmpeg=$ffmpeg, image=$image, job=$job, library_=$library_, logging=$logging, machineLearning=$machineLearning, map=$map, metadata=$metadata, newVersionCheck=$newVersionCheck, nightlyTasks=$nightlyTasks, notifications=$notifications, oauth=$oauth, passwordLogin=$passwordLogin, reverseGeocoding=$reverseGeocoding, server=$server, storageTemplate=$storageTemplate, templates=$templates, theme=$theme, trash=$trash, user=$user]';
|
String toString() => 'SystemConfigDto[backup=$backup, ffmpeg=$ffmpeg, image=$image, integrityChecks=$integrityChecks, job=$job, library_=$library_, logging=$logging, machineLearning=$machineLearning, map=$map, metadata=$metadata, newVersionCheck=$newVersionCheck, nightlyTasks=$nightlyTasks, notifications=$notifications, oauth=$oauth, passwordLogin=$passwordLogin, reverseGeocoding=$reverseGeocoding, server=$server, storageTemplate=$storageTemplate, templates=$templates, theme=$theme, trash=$trash, user=$user]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
json[r'backup'] = this.backup;
|
json[r'backup'] = this.backup;
|
||||||
json[r'ffmpeg'] = this.ffmpeg;
|
json[r'ffmpeg'] = this.ffmpeg;
|
||||||
json[r'image'] = this.image;
|
json[r'image'] = this.image;
|
||||||
|
json[r'integrityChecks'] = this.integrityChecks;
|
||||||
json[r'job'] = this.job;
|
json[r'job'] = this.job;
|
||||||
json[r'library'] = this.library_;
|
json[r'library'] = this.library_;
|
||||||
json[r'logging'] = this.logging;
|
json[r'logging'] = this.logging;
|
||||||
@@ -168,6 +174,7 @@ class SystemConfigDto {
|
|||||||
backup: SystemConfigBackupsDto.fromJson(json[r'backup'])!,
|
backup: SystemConfigBackupsDto.fromJson(json[r'backup'])!,
|
||||||
ffmpeg: SystemConfigFFmpegDto.fromJson(json[r'ffmpeg'])!,
|
ffmpeg: SystemConfigFFmpegDto.fromJson(json[r'ffmpeg'])!,
|
||||||
image: SystemConfigImageDto.fromJson(json[r'image'])!,
|
image: SystemConfigImageDto.fromJson(json[r'image'])!,
|
||||||
|
integrityChecks: SystemConfigIntegrityChecks.fromJson(json[r'integrityChecks'])!,
|
||||||
job: SystemConfigJobDto.fromJson(json[r'job'])!,
|
job: SystemConfigJobDto.fromJson(json[r'job'])!,
|
||||||
library_: SystemConfigLibraryDto.fromJson(json[r'library'])!,
|
library_: SystemConfigLibraryDto.fromJson(json[r'library'])!,
|
||||||
logging: SystemConfigLoggingDto.fromJson(json[r'logging'])!,
|
logging: SystemConfigLoggingDto.fromJson(json[r'logging'])!,
|
||||||
@@ -236,6 +243,7 @@ class SystemConfigDto {
|
|||||||
'backup',
|
'backup',
|
||||||
'ffmpeg',
|
'ffmpeg',
|
||||||
'image',
|
'image',
|
||||||
|
'integrityChecks',
|
||||||
'job',
|
'job',
|
||||||
'library',
|
'library',
|
||||||
'logging',
|
'logging',
|
||||||
|
|||||||
115
mobile/openapi/lib/model/system_config_integrity_checks.dart
generated
Normal file
115
mobile/openapi/lib/model/system_config_integrity_checks.dart
generated
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.18
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class SystemConfigIntegrityChecks {
|
||||||
|
/// Returns a new [SystemConfigIntegrityChecks] instance.
|
||||||
|
SystemConfigIntegrityChecks({
|
||||||
|
required this.checksumFiles,
|
||||||
|
required this.missingFiles,
|
||||||
|
required this.orphanedFiles,
|
||||||
|
});
|
||||||
|
|
||||||
|
SystemConfigIntegrityChecksumJob checksumFiles;
|
||||||
|
|
||||||
|
SystemConfigIntegrityJob missingFiles;
|
||||||
|
|
||||||
|
SystemConfigIntegrityJob orphanedFiles;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is SystemConfigIntegrityChecks &&
|
||||||
|
other.checksumFiles == checksumFiles &&
|
||||||
|
other.missingFiles == missingFiles &&
|
||||||
|
other.orphanedFiles == orphanedFiles;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(checksumFiles.hashCode) +
|
||||||
|
(missingFiles.hashCode) +
|
||||||
|
(orphanedFiles.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'SystemConfigIntegrityChecks[checksumFiles=$checksumFiles, missingFiles=$missingFiles, orphanedFiles=$orphanedFiles]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'checksumFiles'] = this.checksumFiles;
|
||||||
|
json[r'missingFiles'] = this.missingFiles;
|
||||||
|
json[r'orphanedFiles'] = this.orphanedFiles;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [SystemConfigIntegrityChecks] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static SystemConfigIntegrityChecks? fromJson(dynamic value) {
|
||||||
|
upgradeDto(value, "SystemConfigIntegrityChecks");
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return SystemConfigIntegrityChecks(
|
||||||
|
checksumFiles: SystemConfigIntegrityChecksumJob.fromJson(json[r'checksumFiles'])!,
|
||||||
|
missingFiles: SystemConfigIntegrityJob.fromJson(json[r'missingFiles'])!,
|
||||||
|
orphanedFiles: SystemConfigIntegrityJob.fromJson(json[r'orphanedFiles'])!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<SystemConfigIntegrityChecks> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <SystemConfigIntegrityChecks>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = SystemConfigIntegrityChecks.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, SystemConfigIntegrityChecks> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, SystemConfigIntegrityChecks>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = SystemConfigIntegrityChecks.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of SystemConfigIntegrityChecks-objects as value to a dart map
|
||||||
|
static Map<String, List<SystemConfigIntegrityChecks>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<SystemConfigIntegrityChecks>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = SystemConfigIntegrityChecks.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'checksumFiles',
|
||||||
|
'missingFiles',
|
||||||
|
'orphanedFiles',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
123
mobile/openapi/lib/model/system_config_integrity_checksum_job.dart
generated
Normal file
123
mobile/openapi/lib/model/system_config_integrity_checksum_job.dart
generated
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.18
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class SystemConfigIntegrityChecksumJob {
|
||||||
|
/// Returns a new [SystemConfigIntegrityChecksumJob] instance.
|
||||||
|
SystemConfigIntegrityChecksumJob({
|
||||||
|
required this.cronExpression,
|
||||||
|
required this.enabled,
|
||||||
|
required this.percentageLimit,
|
||||||
|
required this.timeLimit,
|
||||||
|
});
|
||||||
|
|
||||||
|
String cronExpression;
|
||||||
|
|
||||||
|
bool enabled;
|
||||||
|
|
||||||
|
num percentageLimit;
|
||||||
|
|
||||||
|
num timeLimit;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is SystemConfigIntegrityChecksumJob &&
|
||||||
|
other.cronExpression == cronExpression &&
|
||||||
|
other.enabled == enabled &&
|
||||||
|
other.percentageLimit == percentageLimit &&
|
||||||
|
other.timeLimit == timeLimit;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(cronExpression.hashCode) +
|
||||||
|
(enabled.hashCode) +
|
||||||
|
(percentageLimit.hashCode) +
|
||||||
|
(timeLimit.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'SystemConfigIntegrityChecksumJob[cronExpression=$cronExpression, enabled=$enabled, percentageLimit=$percentageLimit, timeLimit=$timeLimit]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'cronExpression'] = this.cronExpression;
|
||||||
|
json[r'enabled'] = this.enabled;
|
||||||
|
json[r'percentageLimit'] = this.percentageLimit;
|
||||||
|
json[r'timeLimit'] = this.timeLimit;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [SystemConfigIntegrityChecksumJob] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static SystemConfigIntegrityChecksumJob? fromJson(dynamic value) {
|
||||||
|
upgradeDto(value, "SystemConfigIntegrityChecksumJob");
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return SystemConfigIntegrityChecksumJob(
|
||||||
|
cronExpression: mapValueOfType<String>(json, r'cronExpression')!,
|
||||||
|
enabled: mapValueOfType<bool>(json, r'enabled')!,
|
||||||
|
percentageLimit: num.parse('${json[r'percentageLimit']}'),
|
||||||
|
timeLimit: num.parse('${json[r'timeLimit']}'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<SystemConfigIntegrityChecksumJob> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <SystemConfigIntegrityChecksumJob>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = SystemConfigIntegrityChecksumJob.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, SystemConfigIntegrityChecksumJob> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, SystemConfigIntegrityChecksumJob>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = SystemConfigIntegrityChecksumJob.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of SystemConfigIntegrityChecksumJob-objects as value to a dart map
|
||||||
|
static Map<String, List<SystemConfigIntegrityChecksumJob>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<SystemConfigIntegrityChecksumJob>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = SystemConfigIntegrityChecksumJob.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'cronExpression',
|
||||||
|
'enabled',
|
||||||
|
'percentageLimit',
|
||||||
|
'timeLimit',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
107
mobile/openapi/lib/model/system_config_integrity_job.dart
generated
Normal file
107
mobile/openapi/lib/model/system_config_integrity_job.dart
generated
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.18
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class SystemConfigIntegrityJob {
|
||||||
|
/// Returns a new [SystemConfigIntegrityJob] instance.
|
||||||
|
SystemConfigIntegrityJob({
|
||||||
|
required this.cronExpression,
|
||||||
|
required this.enabled,
|
||||||
|
});
|
||||||
|
|
||||||
|
String cronExpression;
|
||||||
|
|
||||||
|
bool enabled;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is SystemConfigIntegrityJob &&
|
||||||
|
other.cronExpression == cronExpression &&
|
||||||
|
other.enabled == enabled;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(cronExpression.hashCode) +
|
||||||
|
(enabled.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'SystemConfigIntegrityJob[cronExpression=$cronExpression, enabled=$enabled]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'cronExpression'] = this.cronExpression;
|
||||||
|
json[r'enabled'] = this.enabled;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [SystemConfigIntegrityJob] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static SystemConfigIntegrityJob? fromJson(dynamic value) {
|
||||||
|
upgradeDto(value, "SystemConfigIntegrityJob");
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return SystemConfigIntegrityJob(
|
||||||
|
cronExpression: mapValueOfType<String>(json, r'cronExpression')!,
|
||||||
|
enabled: mapValueOfType<bool>(json, r'enabled')!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<SystemConfigIntegrityJob> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <SystemConfigIntegrityJob>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = SystemConfigIntegrityJob.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, SystemConfigIntegrityJob> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, SystemConfigIntegrityJob>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = SystemConfigIntegrityJob.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of SystemConfigIntegrityJob-objects as value to a dart map
|
||||||
|
static Map<String, List<SystemConfigIntegrityJob>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<SystemConfigIntegrityJob>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = SystemConfigIntegrityJob.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'cronExpression',
|
||||||
|
'enabled',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@@ -21237,6 +21237,9 @@
|
|||||||
"image": {
|
"image": {
|
||||||
"$ref": "#/components/schemas/SystemConfigImageDto"
|
"$ref": "#/components/schemas/SystemConfigImageDto"
|
||||||
},
|
},
|
||||||
|
"integrityChecks": {
|
||||||
|
"$ref": "#/components/schemas/SystemConfigIntegrityChecks"
|
||||||
|
},
|
||||||
"job": {
|
"job": {
|
||||||
"$ref": "#/components/schemas/SystemConfigJobDto"
|
"$ref": "#/components/schemas/SystemConfigJobDto"
|
||||||
},
|
},
|
||||||
@@ -21296,6 +21299,7 @@
|
|||||||
"backup",
|
"backup",
|
||||||
"ffmpeg",
|
"ffmpeg",
|
||||||
"image",
|
"image",
|
||||||
|
"integrityChecks",
|
||||||
"job",
|
"job",
|
||||||
"library",
|
"library",
|
||||||
"logging",
|
"logging",
|
||||||
@@ -21542,6 +21546,63 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"SystemConfigIntegrityChecks": {
|
||||||
|
"properties": {
|
||||||
|
"checksumFiles": {
|
||||||
|
"$ref": "#/components/schemas/SystemConfigIntegrityChecksumJob"
|
||||||
|
},
|
||||||
|
"missingFiles": {
|
||||||
|
"$ref": "#/components/schemas/SystemConfigIntegrityJob"
|
||||||
|
},
|
||||||
|
"orphanedFiles": {
|
||||||
|
"$ref": "#/components/schemas/SystemConfigIntegrityJob"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"checksumFiles",
|
||||||
|
"missingFiles",
|
||||||
|
"orphanedFiles"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"SystemConfigIntegrityChecksumJob": {
|
||||||
|
"properties": {
|
||||||
|
"cronExpression": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"percentageLimit": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"timeLimit": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"cronExpression",
|
||||||
|
"enabled",
|
||||||
|
"percentageLimit",
|
||||||
|
"timeLimit"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"SystemConfigIntegrityJob": {
|
||||||
|
"properties": {
|
||||||
|
"cronExpression": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"cronExpression",
|
||||||
|
"enabled"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"SystemConfigJobDto": {
|
"SystemConfigJobDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"backgroundTask": {
|
"backgroundTask": {
|
||||||
|
|||||||
@@ -1454,6 +1454,21 @@ export type SystemConfigImageDto = {
|
|||||||
preview: SystemConfigGeneratedImageDto;
|
preview: SystemConfigGeneratedImageDto;
|
||||||
thumbnail: SystemConfigGeneratedImageDto;
|
thumbnail: SystemConfigGeneratedImageDto;
|
||||||
};
|
};
|
||||||
|
export type SystemConfigIntegrityChecksumJob = {
|
||||||
|
cronExpression: string;
|
||||||
|
enabled: boolean;
|
||||||
|
percentageLimit: number;
|
||||||
|
timeLimit: number;
|
||||||
|
};
|
||||||
|
export type SystemConfigIntegrityJob = {
|
||||||
|
cronExpression: string;
|
||||||
|
enabled: boolean;
|
||||||
|
};
|
||||||
|
export type SystemConfigIntegrityChecks = {
|
||||||
|
checksumFiles: SystemConfigIntegrityChecksumJob;
|
||||||
|
missingFiles: SystemConfigIntegrityJob;
|
||||||
|
orphanedFiles: SystemConfigIntegrityJob;
|
||||||
|
};
|
||||||
export type JobSettingsDto = {
|
export type JobSettingsDto = {
|
||||||
concurrency: number;
|
concurrency: number;
|
||||||
};
|
};
|
||||||
@@ -1606,6 +1621,7 @@ export type SystemConfigDto = {
|
|||||||
backup: SystemConfigBackupsDto;
|
backup: SystemConfigBackupsDto;
|
||||||
ffmpeg: SystemConfigFFmpegDto;
|
ffmpeg: SystemConfigFFmpegDto;
|
||||||
image: SystemConfigImageDto;
|
image: SystemConfigImageDto;
|
||||||
|
integrityChecks: SystemConfigIntegrityChecks;
|
||||||
job: SystemConfigJobDto;
|
job: SystemConfigJobDto;
|
||||||
library: SystemConfigLibraryDto;
|
library: SystemConfigLibraryDto;
|
||||||
logging: SystemConfigLoggingDto;
|
logging: SystemConfigLoggingDto;
|
||||||
|
|||||||
@@ -46,6 +46,22 @@ export interface SystemConfig {
|
|||||||
accelDecode: boolean;
|
accelDecode: boolean;
|
||||||
tonemap: ToneMapping;
|
tonemap: ToneMapping;
|
||||||
};
|
};
|
||||||
|
integrityChecks: {
|
||||||
|
missingFiles: {
|
||||||
|
enabled: boolean;
|
||||||
|
cronExpression: string;
|
||||||
|
};
|
||||||
|
orphanedFiles: {
|
||||||
|
enabled: boolean;
|
||||||
|
cronExpression: string;
|
||||||
|
};
|
||||||
|
checksumFiles: {
|
||||||
|
enabled: boolean;
|
||||||
|
cronExpression: string;
|
||||||
|
timeLimit: number;
|
||||||
|
percentageLimit: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
job: Record<ConcurrentQueueName, { concurrency: number }>;
|
job: Record<ConcurrentQueueName, { concurrency: number }>;
|
||||||
logging: {
|
logging: {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
@@ -222,6 +238,22 @@ export const defaults = Object.freeze<SystemConfig>({
|
|||||||
accel: TranscodeHardwareAcceleration.Disabled,
|
accel: TranscodeHardwareAcceleration.Disabled,
|
||||||
accelDecode: false,
|
accelDecode: false,
|
||||||
},
|
},
|
||||||
|
integrityChecks: {
|
||||||
|
missingFiles: {
|
||||||
|
enabled: true,
|
||||||
|
cronExpression: CronExpression.EVERY_DAY_AT_3AM,
|
||||||
|
},
|
||||||
|
orphanedFiles: {
|
||||||
|
enabled: true,
|
||||||
|
cronExpression: CronExpression.EVERY_DAY_AT_3AM,
|
||||||
|
},
|
||||||
|
checksumFiles: {
|
||||||
|
enabled: true,
|
||||||
|
cronExpression: CronExpression.EVERY_DAY_AT_3AM,
|
||||||
|
timeLimit: 60 * 60 * 1000, // 1 hour
|
||||||
|
percentageLimit: 1.0, // 100% of assets
|
||||||
|
},
|
||||||
|
},
|
||||||
job: {
|
job: {
|
||||||
[QueueName.BackgroundTask]: { concurrency: 5 },
|
[QueueName.BackgroundTask]: { concurrency: 5 },
|
||||||
[QueueName.SmartSearch]: { concurrency: 2 },
|
[QueueName.SmartSearch]: { concurrency: 2 },
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ const isOAuthEnabled = (config: SystemConfigOAuthDto) => config.enabled;
|
|||||||
const isOAuthOverrideEnabled = (config: SystemConfigOAuthDto) => config.mobileOverrideEnabled;
|
const isOAuthOverrideEnabled = (config: SystemConfigOAuthDto) => config.mobileOverrideEnabled;
|
||||||
const isEmailNotificationEnabled = (config: SystemConfigSmtpDto) => config.enabled;
|
const isEmailNotificationEnabled = (config: SystemConfigSmtpDto) => config.enabled;
|
||||||
const isDatabaseBackupEnabled = (config: DatabaseBackupConfig) => config.enabled;
|
const isDatabaseBackupEnabled = (config: DatabaseBackupConfig) => config.enabled;
|
||||||
|
const isEnabledProperty = (config: { enabled: boolean }) => config.enabled;
|
||||||
|
|
||||||
export class DatabaseBackupConfig {
|
export class DatabaseBackupConfig {
|
||||||
@ValidateBoolean()
|
@ValidateBoolean()
|
||||||
@@ -145,6 +146,42 @@ export class SystemConfigFFmpegDto {
|
|||||||
tonemap!: ToneMapping;
|
tonemap!: ToneMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SystemConfigIntegrityJob {
|
||||||
|
@ValidateBoolean()
|
||||||
|
enabled!: boolean;
|
||||||
|
|
||||||
|
@ValidateIf(isEnabledProperty)
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsCronExpression()
|
||||||
|
@IsString()
|
||||||
|
cronExpression!: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SystemConfigIntegrityChecksumJob extends SystemConfigIntegrityJob {
|
||||||
|
@IsInt()
|
||||||
|
timeLimit!: number;
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
percentageLimit!: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SystemConfigIntegrityChecks {
|
||||||
|
@Type(() => SystemConfigIntegrityJob)
|
||||||
|
@ValidateNested()
|
||||||
|
@IsObject()
|
||||||
|
missingFiles!: SystemConfigIntegrityJob;
|
||||||
|
|
||||||
|
@Type(() => SystemConfigIntegrityJob)
|
||||||
|
@ValidateNested()
|
||||||
|
@IsObject()
|
||||||
|
orphanedFiles!: SystemConfigIntegrityJob;
|
||||||
|
|
||||||
|
@Type(() => SystemConfigIntegrityChecksumJob)
|
||||||
|
@ValidateNested()
|
||||||
|
@IsObject()
|
||||||
|
checksumFiles!: SystemConfigIntegrityChecksumJob;
|
||||||
|
}
|
||||||
|
|
||||||
class JobSettingsDto {
|
class JobSettingsDto {
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsPositive()
|
@IsPositive()
|
||||||
@@ -649,6 +686,11 @@ export class SystemConfigDto implements SystemConfig {
|
|||||||
@IsObject()
|
@IsObject()
|
||||||
ffmpeg!: SystemConfigFFmpegDto;
|
ffmpeg!: SystemConfigFFmpegDto;
|
||||||
|
|
||||||
|
@Type(() => SystemConfigIntegrityChecks)
|
||||||
|
@ValidateNested()
|
||||||
|
@IsObject()
|
||||||
|
integrityChecks!: SystemConfigIntegrityChecks;
|
||||||
|
|
||||||
@Type(() => SystemConfigLoggingDto)
|
@Type(() => SystemConfigLoggingDto)
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
|
|||||||
@@ -694,6 +694,7 @@ export enum DatabaseLock {
|
|||||||
GetSystemConfig = 69,
|
GetSystemConfig = 69,
|
||||||
BackupDatabase = 42,
|
BackupDatabase = 42,
|
||||||
MemoryCreation = 777,
|
MemoryCreation = 777,
|
||||||
|
IntegrityCheck = 67,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum MaintenanceAction {
|
export enum MaintenanceAction {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { JOBS_LIBRARY_PAGINATION_SIZE } from 'src/constants';
|
|||||||
import { StorageCore } from 'src/cores/storage.core';
|
import { StorageCore } from 'src/cores/storage.core';
|
||||||
import { OnEvent, OnJob } from 'src/decorators';
|
import { OnEvent, OnJob } from 'src/decorators';
|
||||||
import {
|
import {
|
||||||
|
DatabaseLock,
|
||||||
ImmichWorker,
|
ImmichWorker,
|
||||||
IntegrityReportType,
|
IntegrityReportType,
|
||||||
JobName,
|
JobName,
|
||||||
@@ -19,6 +20,7 @@ import {
|
|||||||
import { ArgOf } from 'src/repositories/event.repository';
|
import { ArgOf } from 'src/repositories/event.repository';
|
||||||
import { BaseService } from 'src/services/base.service';
|
import { BaseService } from 'src/services/base.service';
|
||||||
import { IIntegrityOrphanedFilesJob, IIntegrityPathWithReportJob } from 'src/types';
|
import { IIntegrityOrphanedFilesJob, IIntegrityPathWithReportJob } from 'src/types';
|
||||||
|
import { handlePromiseError } from 'src/utils/misc';
|
||||||
|
|
||||||
async function* chunk<T>(generator: AsyncIterableIterator<T>, n: number) {
|
async function* chunk<T>(generator: AsyncIterableIterator<T>, n: number) {
|
||||||
let chunk: T[] = [];
|
let chunk: T[] = [];
|
||||||
@@ -38,25 +40,49 @@ async function* chunk<T>(generator: AsyncIterableIterator<T>, n: number) {
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class IntegrityService extends BaseService {
|
export class IntegrityService extends BaseService {
|
||||||
// private backupLock = false;
|
private integrityLock = false;
|
||||||
|
|
||||||
@OnEvent({ name: 'ConfigInit', workers: [ImmichWorker.Microservices] })
|
@OnEvent({ name: 'ConfigInit', workers: [ImmichWorker.Microservices] })
|
||||||
async onConfigInit({
|
async onConfigInit({
|
||||||
newConfig: {
|
newConfig: {
|
||||||
backup: { database },
|
integrityChecks: { orphanedFiles, missingFiles, checksumFiles },
|
||||||
},
|
},
|
||||||
}: ArgOf<'ConfigInit'>) {
|
}: ArgOf<'ConfigInit'>) {
|
||||||
// this.backupLock = await this.databaseRepository.tryLock(DatabaseLock.BackupDatabase);
|
this.integrityLock = await this.databaseRepository.tryLock(DatabaseLock.IntegrityCheck);
|
||||||
// if (this.backupLock) {
|
if (this.integrityLock) {
|
||||||
// this.cronRepository.create({
|
this.cronRepository.create({
|
||||||
// name: 'backupDatabase',
|
name: 'integrityOrphanedFiles',
|
||||||
// expression: database.cronExpression,
|
expression: orphanedFiles.cronExpression,
|
||||||
// onTick: () => handlePromiseError(this.jobRepository.queue({ name: JobName.DatabaseBackup }), this.logger),
|
onTick: () =>
|
||||||
// start: database.enabled,
|
handlePromiseError(
|
||||||
// });
|
this.jobRepository.queue({ name: JobName.IntegrityOrphanedFilesQueueAll, data: {} }),
|
||||||
// }
|
this.logger,
|
||||||
|
),
|
||||||
|
start: orphanedFiles.enabled,
|
||||||
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
this.cronRepository.create({
|
||||||
|
name: 'integrityMissingFiles',
|
||||||
|
expression: missingFiles.cronExpression,
|
||||||
|
onTick: () =>
|
||||||
|
handlePromiseError(
|
||||||
|
this.jobRepository.queue({ name: JobName.IntegrityMissingFilesQueueAll, data: {} }),
|
||||||
|
this.logger,
|
||||||
|
),
|
||||||
|
start: missingFiles.enabled,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.cronRepository.create({
|
||||||
|
name: 'integrityChecksumFiles',
|
||||||
|
expression: checksumFiles.cronExpression,
|
||||||
|
onTick: () =>
|
||||||
|
handlePromiseError(this.jobRepository.queue({ name: JobName.IntegrityChecksumFiles, data: {} }), this.logger),
|
||||||
|
start: checksumFiles.enabled,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug: run on boot
|
||||||
|
setImmediate(() => {
|
||||||
this.jobRepository.queue({
|
this.jobRepository.queue({
|
||||||
name: JobName.IntegrityOrphanedFilesQueueAll,
|
name: JobName.IntegrityOrphanedFilesQueueAll,
|
||||||
data: {},
|
data: {},
|
||||||
@@ -71,19 +97,36 @@ export class IntegrityService extends BaseService {
|
|||||||
name: JobName.IntegrityChecksumFiles,
|
name: JobName.IntegrityChecksumFiles,
|
||||||
data: {},
|
data: {},
|
||||||
});
|
});
|
||||||
}, 1000);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'ConfigUpdate', server: true })
|
@OnEvent({ name: 'ConfigUpdate', server: true })
|
||||||
async onConfigUpdate({ newConfig: { backup } }: ArgOf<'ConfigUpdate'>) {
|
async onConfigUpdate({
|
||||||
// if (!this.backupLock) {
|
newConfig: {
|
||||||
// return;
|
integrityChecks: { orphanedFiles, missingFiles, checksumFiles },
|
||||||
// }
|
},
|
||||||
// this.cronRepository.update({
|
}: ArgOf<'ConfigUpdate'>) {
|
||||||
// name: 'backupDatabase',
|
if (!this.integrityLock) {
|
||||||
// expression: backup.database.cronExpression,
|
return;
|
||||||
// start: backup.database.enabled,
|
}
|
||||||
// });
|
|
||||||
|
this.cronRepository.update({
|
||||||
|
name: 'integrityOrphanedFiles',
|
||||||
|
expression: orphanedFiles.cronExpression,
|
||||||
|
start: orphanedFiles.enabled,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.cronRepository.update({
|
||||||
|
name: 'integrityMissingFiles',
|
||||||
|
expression: missingFiles.cronExpression,
|
||||||
|
start: missingFiles.enabled,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.cronRepository.update({
|
||||||
|
name: 'integrityChecksumFiles',
|
||||||
|
expression: checksumFiles.cronExpression,
|
||||||
|
start: checksumFiles.enabled,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnJob({ name: JobName.IntegrityOrphanedFilesQueueAll, queue: QueueName.BackgroundTask })
|
@OnJob({ name: JobName.IntegrityOrphanedFilesQueueAll, queue: QueueName.BackgroundTask })
|
||||||
|
|||||||
Reference in New Issue
Block a user