mirror of
https://github.com/nicotsx/ironmount.git
synced 2025-12-10 12:10:51 +01:00
Compare commits
1 Commits
16b8be2cd9
...
v0.16.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc6f628dd4 |
@@ -73,7 +73,7 @@ export const ScheduleMirrorsConfig = ({ scheduleId, primaryRepositoryId, reposit
|
|||||||
}, [compatibility]);
|
}, [compatibility]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentMirrors) {
|
if (currentMirrors && !hasChanges) {
|
||||||
const map = new Map<string, MirrorAssignment>();
|
const map = new Map<string, MirrorAssignment>();
|
||||||
for (const mirror of currentMirrors) {
|
for (const mirror of currentMirrors) {
|
||||||
map.set(mirror.repositoryId, {
|
map.set(mirror.repositoryId, {
|
||||||
@@ -87,7 +87,7 @@ export const ScheduleMirrorsConfig = ({ scheduleId, primaryRepositoryId, reposit
|
|||||||
|
|
||||||
setAssignments(map);
|
setAssignments(map);
|
||||||
}
|
}
|
||||||
}, [currentMirrors]);
|
}, [currentMirrors, hasChanges]);
|
||||||
|
|
||||||
const addRepository = (repositoryId: string) => {
|
const addRepository = (repositoryId: string) => {
|
||||||
const newAssignments = new Map(assignments);
|
const newAssignments = new Map(assignments);
|
||||||
@@ -155,10 +155,6 @@ export const ScheduleMirrorsConfig = ({ scheduleId, primaryRepositoryId, reposit
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getRepositoryById = (id: string) => {
|
|
||||||
return repositories?.find((r) => r.id === id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectableRepositories =
|
const selectableRepositories =
|
||||||
repositories?.filter((r) => {
|
repositories?.filter((r) => {
|
||||||
if (r.id === primaryRepositoryId) return false;
|
if (r.id === primaryRepositoryId) return false;
|
||||||
@@ -172,16 +168,16 @@ export const ScheduleMirrorsConfig = ({ scheduleId, primaryRepositoryId, reposit
|
|||||||
});
|
});
|
||||||
|
|
||||||
const assignedRepositories = Array.from(assignments.keys())
|
const assignedRepositories = Array.from(assignments.keys())
|
||||||
.map((id) => getRepositoryById(id))
|
.map((id) => repositories?.find((r) => r.id === id))
|
||||||
.filter((r) => r !== undefined);
|
.filter((r) => r !== undefined);
|
||||||
|
|
||||||
const getStatusVariant = (status: "success" | "error" | null): "success" | "error" | "neutral" => {
|
const getStatusVariant = (status: "success" | "error" | null) => {
|
||||||
if (status === "success") return "success";
|
if (status === "success") return "success";
|
||||||
if (status === "error") return "error";
|
if (status === "error") return "error";
|
||||||
return "neutral";
|
return "neutral";
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStatusLabel = (assignment: MirrorAssignment): string => {
|
const getStatusLabel = (assignment: MirrorAssignment) => {
|
||||||
if (assignment.lastCopyStatus === "error" && assignment.lastCopyError) {
|
if (assignment.lastCopyStatus === "error" && assignment.lastCopyError) {
|
||||||
return assignment.lastCopyError;
|
return assignment.lastCopyError;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ CREATE TABLE `__new_app_metadata` (
|
|||||||
INSERT INTO `__new_app_metadata`("key", "value", "created_at", "updated_at") SELECT "key", "value", "created_at", "updated_at" FROM `app_metadata`;--> statement-breakpoint
|
INSERT INTO `__new_app_metadata`("key", "value", "created_at", "updated_at") SELECT "key", "value", "created_at", "updated_at" FROM `app_metadata`;--> statement-breakpoint
|
||||||
DROP TABLE `app_metadata`;--> statement-breakpoint
|
DROP TABLE `app_metadata`;--> statement-breakpoint
|
||||||
ALTER TABLE `__new_app_metadata` RENAME TO `app_metadata`;--> statement-breakpoint
|
ALTER TABLE `__new_app_metadata` RENAME TO `app_metadata`;--> statement-breakpoint
|
||||||
PRAGMA foreign_keys=ON;--> statement-breakpoint
|
|
||||||
CREATE TABLE `__new_backup_schedule_notifications_table` (
|
CREATE TABLE `__new_backup_schedule_notifications_table` (
|
||||||
`schedule_id` integer NOT NULL,
|
`schedule_id` integer NOT NULL,
|
||||||
`destination_id` integer NOT NULL,
|
`destination_id` integer NOT NULL,
|
||||||
@@ -137,3 +136,4 @@ DROP TABLE `volumes_table`;--> statement-breakpoint
|
|||||||
ALTER TABLE `__new_volumes_table` RENAME TO `volumes_table`;--> statement-breakpoint
|
ALTER TABLE `__new_volumes_table` RENAME TO `volumes_table`;--> statement-breakpoint
|
||||||
CREATE UNIQUE INDEX `volumes_table_short_id_unique` ON `volumes_table` (`short_id`);--> statement-breakpoint
|
CREATE UNIQUE INDEX `volumes_table_short_id_unique` ON `volumes_table` (`short_id`);--> statement-breakpoint
|
||||||
CREATE UNIQUE INDEX `volumes_table_name_unique` ON `volumes_table` (`name`);
|
CREATE UNIQUE INDEX `volumes_table_name_unique` ON `volumes_table` (`name`);
|
||||||
|
PRAGMA foreign_keys=ON;--> statement-breakpoint
|
||||||
|
|||||||
1
app/drizzle/0019_heavy_shen.sql
Normal file
1
app/drizzle/0019_heavy_shen.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
CREATE UNIQUE INDEX `backup_schedule_mirrors_table_schedule_id_repository_id_unique` ON `backup_schedule_mirrors_table` (`schedule_id`,`repository_id`);
|
||||||
792
app/drizzle/meta/0019_snapshot.json
Normal file
792
app/drizzle/meta/0019_snapshot.json
Normal file
@@ -0,0 +1,792 @@
|
|||||||
|
{
|
||||||
|
"version": "6",
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"id": "dedfb246-68e7-4590-af52-6476eb2999d1",
|
||||||
|
"prevId": "121ef03c-eb5a-4b97-b2f1-4add6adfb080",
|
||||||
|
"tables": {
|
||||||
|
"app_metadata": {
|
||||||
|
"name": "app_metadata",
|
||||||
|
"columns": {
|
||||||
|
"key": {
|
||||||
|
"name": "key",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"name": "value",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"backup_schedule_mirrors_table": {
|
||||||
|
"name": "backup_schedule_mirrors_table",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"schedule_id": {
|
||||||
|
"name": "schedule_id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"repository_id": {
|
||||||
|
"name": "repository_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"name": "enabled",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"last_copy_at": {
|
||||||
|
"name": "last_copy_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"last_copy_status": {
|
||||||
|
"name": "last_copy_status",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"last_copy_error": {
|
||||||
|
"name": "last_copy_error",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"backup_schedule_mirrors_table_schedule_id_repository_id_unique": {
|
||||||
|
"name": "backup_schedule_mirrors_table_schedule_id_repository_id_unique",
|
||||||
|
"columns": [
|
||||||
|
"schedule_id",
|
||||||
|
"repository_id"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {
|
||||||
|
"backup_schedule_mirrors_table_schedule_id_backup_schedules_table_id_fk": {
|
||||||
|
"name": "backup_schedule_mirrors_table_schedule_id_backup_schedules_table_id_fk",
|
||||||
|
"tableFrom": "backup_schedule_mirrors_table",
|
||||||
|
"tableTo": "backup_schedules_table",
|
||||||
|
"columnsFrom": [
|
||||||
|
"schedule_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"backup_schedule_mirrors_table_repository_id_repositories_table_id_fk": {
|
||||||
|
"name": "backup_schedule_mirrors_table_repository_id_repositories_table_id_fk",
|
||||||
|
"tableFrom": "backup_schedule_mirrors_table",
|
||||||
|
"tableTo": "repositories_table",
|
||||||
|
"columnsFrom": [
|
||||||
|
"repository_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"backup_schedule_notifications_table": {
|
||||||
|
"name": "backup_schedule_notifications_table",
|
||||||
|
"columns": {
|
||||||
|
"schedule_id": {
|
||||||
|
"name": "schedule_id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"destination_id": {
|
||||||
|
"name": "destination_id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"notify_on_start": {
|
||||||
|
"name": "notify_on_start",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"notify_on_success": {
|
||||||
|
"name": "notify_on_success",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"notify_on_failure": {
|
||||||
|
"name": "notify_on_failure",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"backup_schedule_notifications_table_schedule_id_backup_schedules_table_id_fk": {
|
||||||
|
"name": "backup_schedule_notifications_table_schedule_id_backup_schedules_table_id_fk",
|
||||||
|
"tableFrom": "backup_schedule_notifications_table",
|
||||||
|
"tableTo": "backup_schedules_table",
|
||||||
|
"columnsFrom": [
|
||||||
|
"schedule_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"backup_schedule_notifications_table_destination_id_notification_destinations_table_id_fk": {
|
||||||
|
"name": "backup_schedule_notifications_table_destination_id_notification_destinations_table_id_fk",
|
||||||
|
"tableFrom": "backup_schedule_notifications_table",
|
||||||
|
"tableTo": "notification_destinations_table",
|
||||||
|
"columnsFrom": [
|
||||||
|
"destination_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {
|
||||||
|
"backup_schedule_notifications_table_schedule_id_destination_id_pk": {
|
||||||
|
"columns": [
|
||||||
|
"schedule_id",
|
||||||
|
"destination_id"
|
||||||
|
],
|
||||||
|
"name": "backup_schedule_notifications_table_schedule_id_destination_id_pk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"backup_schedules_table": {
|
||||||
|
"name": "backup_schedules_table",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"volume_id": {
|
||||||
|
"name": "volume_id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"repository_id": {
|
||||||
|
"name": "repository_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"name": "enabled",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"cron_expression": {
|
||||||
|
"name": "cron_expression",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"retention_policy": {
|
||||||
|
"name": "retention_policy",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"exclude_patterns": {
|
||||||
|
"name": "exclude_patterns",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
},
|
||||||
|
"include_patterns": {
|
||||||
|
"name": "include_patterns",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
},
|
||||||
|
"last_backup_at": {
|
||||||
|
"name": "last_backup_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"last_backup_status": {
|
||||||
|
"name": "last_backup_status",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"last_backup_error": {
|
||||||
|
"name": "last_backup_error",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"next_backup_at": {
|
||||||
|
"name": "next_backup_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"backup_schedules_table_volume_id_volumes_table_id_fk": {
|
||||||
|
"name": "backup_schedules_table_volume_id_volumes_table_id_fk",
|
||||||
|
"tableFrom": "backup_schedules_table",
|
||||||
|
"tableTo": "volumes_table",
|
||||||
|
"columnsFrom": [
|
||||||
|
"volume_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"backup_schedules_table_repository_id_repositories_table_id_fk": {
|
||||||
|
"name": "backup_schedules_table_repository_id_repositories_table_id_fk",
|
||||||
|
"tableFrom": "backup_schedules_table",
|
||||||
|
"tableTo": "repositories_table",
|
||||||
|
"columnsFrom": [
|
||||||
|
"repository_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"notification_destinations_table": {
|
||||||
|
"name": "notification_destinations_table",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"name": "enabled",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"name": "type",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"name": "config",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"notification_destinations_table_name_unique": {
|
||||||
|
"name": "notification_destinations_table_name_unique",
|
||||||
|
"columns": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"repositories_table": {
|
||||||
|
"name": "repositories_table",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"short_id": {
|
||||||
|
"name": "short_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"name": "type",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"name": "config",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"compression_mode": {
|
||||||
|
"name": "compression_mode",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'auto'"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"name": "status",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'unknown'"
|
||||||
|
},
|
||||||
|
"last_checked": {
|
||||||
|
"name": "last_checked",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"last_error": {
|
||||||
|
"name": "last_error",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"repositories_table_short_id_unique": {
|
||||||
|
"name": "repositories_table_short_id_unique",
|
||||||
|
"columns": [
|
||||||
|
"short_id"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
},
|
||||||
|
"repositories_table_name_unique": {
|
||||||
|
"name": "repositories_table_name_unique",
|
||||||
|
"columns": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"sessions_table": {
|
||||||
|
"name": "sessions_table",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"expires_at": {
|
||||||
|
"name": "expires_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"sessions_table_user_id_users_table_id_fk": {
|
||||||
|
"name": "sessions_table_user_id_users_table_id_fk",
|
||||||
|
"tableFrom": "sessions_table",
|
||||||
|
"tableTo": "users_table",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"users_table": {
|
||||||
|
"name": "users_table",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"name": "username",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"password_hash": {
|
||||||
|
"name": "password_hash",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"has_downloaded_restic_password": {
|
||||||
|
"name": "has_downloaded_restic_password",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"users_table_username_unique": {
|
||||||
|
"name": "users_table_username_unique",
|
||||||
|
"columns": [
|
||||||
|
"username"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"volumes_table": {
|
||||||
|
"name": "volumes_table",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"short_id": {
|
||||||
|
"name": "short_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"name": "type",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"name": "status",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'unmounted'"
|
||||||
|
},
|
||||||
|
"last_error": {
|
||||||
|
"name": "last_error",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"last_health_check": {
|
||||||
|
"name": "last_health_check",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(unixepoch() * 1000)"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"name": "config",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"auto_remount": {
|
||||||
|
"name": "auto_remount",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"volumes_table_short_id_unique": {
|
||||||
|
"name": "volumes_table_short_id_unique",
|
||||||
|
"columns": [
|
||||||
|
"short_id"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
},
|
||||||
|
"volumes_table_name_unique": {
|
||||||
|
"name": "volumes_table_name_unique",
|
||||||
|
"columns": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"views": {},
|
||||||
|
"enums": {},
|
||||||
|
"_meta": {
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {},
|
||||||
|
"columns": {}
|
||||||
|
},
|
||||||
|
"internal": {
|
||||||
|
"indexes": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,139 +1,146 @@
|
|||||||
{
|
{
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"dialect": "sqlite",
|
"dialect": "sqlite",
|
||||||
"entries": [
|
"entries": [
|
||||||
{
|
{
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1755765658194,
|
"when": 1755765658194,
|
||||||
"tag": "0000_known_madelyne_pryor",
|
"tag": "0000_known_madelyne_pryor",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1755775437391,
|
"when": 1755775437391,
|
||||||
"tag": "0001_far_frank_castle",
|
"tag": "0001_far_frank_castle",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 2,
|
"idx": 2,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1756930554198,
|
"when": 1756930554198,
|
||||||
"tag": "0002_cheerful_randall",
|
"tag": "0002_cheerful_randall",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 3,
|
"idx": 3,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1758653407064,
|
"when": 1758653407064,
|
||||||
"tag": "0003_mature_hellcat",
|
"tag": "0003_mature_hellcat",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 4,
|
"idx": 4,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1758961535488,
|
"when": 1758961535488,
|
||||||
"tag": "0004_wealthy_tomas",
|
"tag": "0004_wealthy_tomas",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 5,
|
"idx": 5,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1759416698274,
|
"when": 1759416698274,
|
||||||
"tag": "0005_simple_alice",
|
"tag": "0005_simple_alice",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 6,
|
"idx": 6,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1760734377440,
|
"when": 1760734377440,
|
||||||
"tag": "0006_secret_micromacro",
|
"tag": "0006_secret_micromacro",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 7,
|
"idx": 7,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1761224911352,
|
"when": 1761224911352,
|
||||||
"tag": "0007_watery_sersi",
|
"tag": "0007_watery_sersi",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 8,
|
"idx": 8,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1761414054481,
|
"when": 1761414054481,
|
||||||
"tag": "0008_silent_lady_bullseye",
|
"tag": "0008_silent_lady_bullseye",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 9,
|
"idx": 9,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1762095226041,
|
"when": 1762095226041,
|
||||||
"tag": "0009_little_adam_warlock",
|
"tag": "0009_little_adam_warlock",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 10,
|
"idx": 10,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1762610065889,
|
"when": 1762610065889,
|
||||||
"tag": "0010_perfect_proemial_gods",
|
"tag": "0010_perfect_proemial_gods",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 11,
|
"idx": 11,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1763644043601,
|
"when": 1763644043601,
|
||||||
"tag": "0011_familiar_stone_men",
|
"tag": "0011_familiar_stone_men",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 12,
|
"idx": 12,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1764100562084,
|
"when": 1764100562084,
|
||||||
"tag": "0012_add_short_ids",
|
"tag": "0012_add_short_ids",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 13,
|
"idx": 13,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1764182159797,
|
"when": 1764182159797,
|
||||||
"tag": "0013_elite_sprite",
|
"tag": "0013_elite_sprite",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 14,
|
"idx": 14,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1764182405089,
|
"when": 1764182405089,
|
||||||
"tag": "0014_wild_echo",
|
"tag": "0014_wild_echo",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 15,
|
"idx": 15,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1764182465287,
|
"when": 1764182465287,
|
||||||
"tag": "0015_jazzy_sersi",
|
"tag": "0015_jazzy_sersi",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 16,
|
"idx": 16,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1764194697035,
|
"when": 1764194697035,
|
||||||
"tag": "0016_fix-timestamps-to-ms",
|
"tag": "0016_fix-timestamps-to-ms",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 17,
|
"idx": 17,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1764357897219,
|
"when": 1764357897219,
|
||||||
"tag": "0017_fix-compression-modes",
|
"tag": "0017_fix-compression-modes",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idx": 18,
|
"idx": 18,
|
||||||
"version": "6",
|
"version": "6",
|
||||||
"when": 1764619898949,
|
"when": 1764619898949,
|
||||||
"tag": "0018_bizarre_zzzax",
|
"tag": "0018_bizarre_zzzax",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
}
|
},
|
||||||
]
|
{
|
||||||
}
|
"idx": 19,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1764790151212,
|
||||||
|
"tag": "0019_heavy_shen",
|
||||||
|
"breakpoints": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { relations, sql } from "drizzle-orm";
|
import { relations, sql } from "drizzle-orm";
|
||||||
import { int, integer, sqliteTable, text, primaryKey } from "drizzle-orm/sqlite-core";
|
import { int, integer, sqliteTable, text, primaryKey, uniqueIndex, unique } from "drizzle-orm/sqlite-core";
|
||||||
import type { CompressionMode, RepositoryBackend, repositoryConfigSchema, RepositoryStatus } from "~/schemas/restic";
|
import type { CompressionMode, RepositoryBackend, repositoryConfigSchema, RepositoryStatus } from "~/schemas/restic";
|
||||||
import type { BackendStatus, BackendType, volumeConfigSchema } from "~/schemas/volumes";
|
import type { BackendStatus, BackendType, volumeConfigSchema } from "~/schemas/volumes";
|
||||||
import type { NotificationType, notificationConfigSchema } from "~/schemas/notifications";
|
import type { NotificationType, notificationConfigSchema } from "~/schemas/notifications";
|
||||||
@@ -160,20 +160,24 @@ export type BackupScheduleNotification = typeof backupScheduleNotificationsTable
|
|||||||
* Backup Schedule Mirrors Junction Table (Many-to-Many)
|
* Backup Schedule Mirrors Junction Table (Many-to-Many)
|
||||||
* Allows copying snapshots to secondary repositories after backup completes
|
* Allows copying snapshots to secondary repositories after backup completes
|
||||||
*/
|
*/
|
||||||
export const backupScheduleMirrorsTable = sqliteTable("backup_schedule_mirrors_table", {
|
export const backupScheduleMirrorsTable = sqliteTable(
|
||||||
id: int().primaryKey({ autoIncrement: true }),
|
"backup_schedule_mirrors_table",
|
||||||
scheduleId: int("schedule_id")
|
{
|
||||||
.notNull()
|
id: int().primaryKey({ autoIncrement: true }),
|
||||||
.references(() => backupSchedulesTable.id, { onDelete: "cascade" }),
|
scheduleId: int("schedule_id")
|
||||||
repositoryId: text("repository_id")
|
.notNull()
|
||||||
.notNull()
|
.references(() => backupSchedulesTable.id, { onDelete: "cascade" }),
|
||||||
.references(() => repositoriesTable.id, { onDelete: "cascade" }),
|
repositoryId: text("repository_id")
|
||||||
enabled: int("enabled", { mode: "boolean" }).notNull().default(true),
|
.notNull()
|
||||||
lastCopyAt: int("last_copy_at", { mode: "number" }),
|
.references(() => repositoriesTable.id, { onDelete: "cascade" }),
|
||||||
lastCopyStatus: text("last_copy_status").$type<"success" | "error">(),
|
enabled: int("enabled", { mode: "boolean" }).notNull().default(true),
|
||||||
lastCopyError: text("last_copy_error"),
|
lastCopyAt: int("last_copy_at", { mode: "number" }),
|
||||||
createdAt: int("created_at", { mode: "number" }).notNull().default(sql`(unixepoch() * 1000)`),
|
lastCopyStatus: text("last_copy_status").$type<"success" | "error">(),
|
||||||
});
|
lastCopyError: text("last_copy_error"),
|
||||||
|
createdAt: int("created_at", { mode: "number" }).notNull().default(sql`(unixepoch() * 1000)`),
|
||||||
|
},
|
||||||
|
(table) => [unique().on(table.scheduleId, table.repositoryId)],
|
||||||
|
);
|
||||||
|
|
||||||
export const backupScheduleMirrorRelations = relations(backupScheduleMirrorsTable, ({ one }) => ({
|
export const backupScheduleMirrorRelations = relations(backupScheduleMirrorsTable, ({ one }) => ({
|
||||||
schedule: one(backupSchedulesTable, {
|
schedule: one(backupSchedulesTable, {
|
||||||
|
|||||||
@@ -522,13 +522,25 @@ const copyToMirrors = async (
|
|||||||
repositoryName: mirror.repository.name,
|
repositoryName: mirror.repository.name,
|
||||||
});
|
});
|
||||||
|
|
||||||
await restic.copy(sourceRepository.config, mirror.repository.config, {
|
const releaseSource = await repoMutex.acquireShared(sourceRepository.id, `mirror_source:${scheduleId}`);
|
||||||
tag: scheduleId.toString(),
|
const releaseMirror = await repoMutex.acquireShared(mirror.repository.id, `mirror:${scheduleId}`);
|
||||||
});
|
|
||||||
|
try {
|
||||||
|
await restic.copy(sourceRepository.config, mirror.repository.config, { tag: scheduleId.toString() });
|
||||||
|
} finally {
|
||||||
|
releaseSource();
|
||||||
|
releaseMirror();
|
||||||
|
}
|
||||||
|
|
||||||
if (retentionPolicy) {
|
if (retentionPolicy) {
|
||||||
logger.info(`[Background] Applying retention policy to mirror repository: ${mirror.repository.name}`);
|
const releaseForget = await repoMutex.acquireExclusive(mirror.repository.id, `forget:mirror:${scheduleId}`);
|
||||||
await restic.forget(mirror.repository.config, retentionPolicy, { tag: scheduleId.toString() });
|
|
||||||
|
try {
|
||||||
|
logger.info(`[Background] Applying retention policy to mirror repository: ${mirror.repository.name}`);
|
||||||
|
await restic.forget(mirror.repository.config, retentionPolicy, { tag: scheduleId.toString() });
|
||||||
|
} finally {
|
||||||
|
releaseForget();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await db
|
await db
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ const init = async (config: RepositoryConfig) => {
|
|||||||
const env = await buildEnv(config);
|
const env = await buildEnv(config);
|
||||||
|
|
||||||
const args = ["init", "--repo", repoUrl];
|
const args = ["init", "--repo", repoUrl];
|
||||||
addCommonArgs(args, config, env);
|
addCommonArgs(args, env);
|
||||||
|
|
||||||
const res = await $`restic ${args}`.env(env).nothrow();
|
const res = await $`restic ${args}`.env(env).nothrow();
|
||||||
await cleanupTemporaryKeys(config, env);
|
await cleanupTemporaryKeys(config, env);
|
||||||
@@ -278,7 +278,7 @@ const backup = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addCommonArgs(args, config, env);
|
addCommonArgs(args, env);
|
||||||
|
|
||||||
const logData = throttle((data: string) => {
|
const logData = throttle((data: string) => {
|
||||||
logger.info(data.trim());
|
logger.info(data.trim());
|
||||||
@@ -404,7 +404,7 @@ const restore = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addCommonArgs(args, config, env);
|
addCommonArgs(args, env);
|
||||||
|
|
||||||
logger.debug(`Executing: restic ${args.join(" ")}`);
|
logger.debug(`Executing: restic ${args.join(" ")}`);
|
||||||
const res = await $`restic ${args}`.env(env).nothrow();
|
const res = await $`restic ${args}`.env(env).nothrow();
|
||||||
@@ -467,7 +467,7 @@ const snapshots = async (config: RepositoryConfig, options: { tags?: string[] }
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addCommonArgs(args, config, env);
|
addCommonArgs(args, env);
|
||||||
|
|
||||||
const res = await $`restic ${args}`.env(env).nothrow().quiet();
|
const res = await $`restic ${args}`.env(env).nothrow().quiet();
|
||||||
await cleanupTemporaryKeys(config, env);
|
await cleanupTemporaryKeys(config, env);
|
||||||
@@ -516,7 +516,7 @@ const forget = async (config: RepositoryConfig, options: RetentionPolicy, extra:
|
|||||||
}
|
}
|
||||||
|
|
||||||
args.push("--prune");
|
args.push("--prune");
|
||||||
addCommonArgs(args, config, env);
|
addCommonArgs(args, env);
|
||||||
|
|
||||||
const res = await $`restic ${args}`.env(env).nothrow();
|
const res = await $`restic ${args}`.env(env).nothrow();
|
||||||
await cleanupTemporaryKeys(config, env);
|
await cleanupTemporaryKeys(config, env);
|
||||||
@@ -534,7 +534,7 @@ const deleteSnapshot = async (config: RepositoryConfig, snapshotId: string) => {
|
|||||||
const env = await buildEnv(config);
|
const env = await buildEnv(config);
|
||||||
|
|
||||||
const args: string[] = ["--repo", repoUrl, "forget", snapshotId, "--prune"];
|
const args: string[] = ["--repo", repoUrl, "forget", snapshotId, "--prune"];
|
||||||
addCommonArgs(args, config, env);
|
addCommonArgs(args, env);
|
||||||
|
|
||||||
const res = await $`restic ${args}`.env(env).nothrow();
|
const res = await $`restic ${args}`.env(env).nothrow();
|
||||||
await cleanupTemporaryKeys(config, env);
|
await cleanupTemporaryKeys(config, env);
|
||||||
@@ -584,7 +584,7 @@ const ls = async (config: RepositoryConfig, snapshotId: string, path?: string) =
|
|||||||
args.push(path);
|
args.push(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
addCommonArgs(args, config, env);
|
addCommonArgs(args, env);
|
||||||
|
|
||||||
const res = await safeSpawn({ command: "restic", args, env });
|
const res = await safeSpawn({ command: "restic", args, env });
|
||||||
await cleanupTemporaryKeys(config, env);
|
await cleanupTemporaryKeys(config, env);
|
||||||
@@ -635,7 +635,7 @@ const unlock = async (config: RepositoryConfig) => {
|
|||||||
const env = await buildEnv(config);
|
const env = await buildEnv(config);
|
||||||
|
|
||||||
const args = ["unlock", "--repo", repoUrl, "--remove-all"];
|
const args = ["unlock", "--repo", repoUrl, "--remove-all"];
|
||||||
addCommonArgs(args, config, env);
|
addCommonArgs(args, env);
|
||||||
|
|
||||||
const res = await $`restic ${args}`.env(env).nothrow();
|
const res = await $`restic ${args}`.env(env).nothrow();
|
||||||
await cleanupTemporaryKeys(config, env);
|
await cleanupTemporaryKeys(config, env);
|
||||||
@@ -659,7 +659,7 @@ const check = async (config: RepositoryConfig, options?: { readData?: boolean })
|
|||||||
args.push("--read-data");
|
args.push("--read-data");
|
||||||
}
|
}
|
||||||
|
|
||||||
addCommonArgs(args, config, env);
|
addCommonArgs(args, env);
|
||||||
|
|
||||||
const res = await $`restic ${args}`.env(env).nothrow();
|
const res = await $`restic ${args}`.env(env).nothrow();
|
||||||
await cleanupTemporaryKeys(config, env);
|
await cleanupTemporaryKeys(config, env);
|
||||||
@@ -693,7 +693,7 @@ const repairIndex = async (config: RepositoryConfig) => {
|
|||||||
const env = await buildEnv(config);
|
const env = await buildEnv(config);
|
||||||
|
|
||||||
const args = ["repair", "index", "--repo", repoUrl];
|
const args = ["repair", "index", "--repo", repoUrl];
|
||||||
addCommonArgs(args, config, env);
|
addCommonArgs(args, env);
|
||||||
|
|
||||||
const res = await $`restic ${args}`.env(env).nothrow();
|
const res = await $`restic ${args}`.env(env).nothrow();
|
||||||
await cleanupTemporaryKeys(config, env);
|
await cleanupTemporaryKeys(config, env);
|
||||||
@@ -746,7 +746,7 @@ const copy = async (
|
|||||||
args.push("latest");
|
args.push("latest");
|
||||||
}
|
}
|
||||||
|
|
||||||
addCommonArgs(args, destConfig, destEnv);
|
addCommonArgs(args, env);
|
||||||
|
|
||||||
if (sourceConfig.backend === "sftp" && sourceEnv._SFTP_SSH_ARGS) {
|
if (sourceConfig.backend === "sftp" && sourceEnv._SFTP_SSH_ARGS) {
|
||||||
args.push("-o", `sftp.args=${sourceEnv._SFTP_SSH_ARGS}`);
|
args.push("-o", `sftp.args=${sourceEnv._SFTP_SSH_ARGS}`);
|
||||||
@@ -785,9 +785,10 @@ const cleanupTemporaryKeys = async (config: RepositoryConfig, env: Record<string
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const addCommonArgs = (args: string[], config: RepositoryConfig, env: Record<string, string>) => {
|
const addCommonArgs = (args: string[], env: Record<string, string>) => {
|
||||||
args.push("--retry-lock", "1m", "--json");
|
args.push("--retry-lock", "1m", "--json");
|
||||||
if (config.backend === "sftp" && env._SFTP_SSH_ARGS) {
|
|
||||||
|
if (env._SFTP_SSH_ARGS) {
|
||||||
args.push("-o", `sftp.args=${env._SFTP_SSH_ARGS}`);
|
args.push("-o", `sftp.args=${env._SFTP_SSH_ARGS}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user