mirror of
https://github.com/nicotsx/ironmount.git
synced 2025-12-10 12:10:51 +01:00
chore: pr feedbacks
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
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 { BackendStatus, BackendType, volumeConfigSchema } from "~/schemas/volumes";
|
||||
import type { NotificationType, notificationConfigSchema } from "~/schemas/notifications";
|
||||
@@ -160,20 +160,24 @@ export type BackupScheduleNotification = typeof backupScheduleNotificationsTable
|
||||
* Backup Schedule Mirrors Junction Table (Many-to-Many)
|
||||
* Allows copying snapshots to secondary repositories after backup completes
|
||||
*/
|
||||
export const backupScheduleMirrorsTable = sqliteTable("backup_schedule_mirrors_table", {
|
||||
id: int().primaryKey({ autoIncrement: true }),
|
||||
scheduleId: int("schedule_id")
|
||||
.notNull()
|
||||
.references(() => backupSchedulesTable.id, { onDelete: "cascade" }),
|
||||
repositoryId: text("repository_id")
|
||||
.notNull()
|
||||
.references(() => repositoriesTable.id, { onDelete: "cascade" }),
|
||||
enabled: int("enabled", { mode: "boolean" }).notNull().default(true),
|
||||
lastCopyAt: int("last_copy_at", { mode: "number" }),
|
||||
lastCopyStatus: text("last_copy_status").$type<"success" | "error">(),
|
||||
lastCopyError: text("last_copy_error"),
|
||||
createdAt: int("created_at", { mode: "number" }).notNull().default(sql`(unixepoch() * 1000)`),
|
||||
});
|
||||
export const backupScheduleMirrorsTable = sqliteTable(
|
||||
"backup_schedule_mirrors_table",
|
||||
{
|
||||
id: int().primaryKey({ autoIncrement: true }),
|
||||
scheduleId: int("schedule_id")
|
||||
.notNull()
|
||||
.references(() => backupSchedulesTable.id, { onDelete: "cascade" }),
|
||||
repositoryId: text("repository_id")
|
||||
.notNull()
|
||||
.references(() => repositoriesTable.id, { onDelete: "cascade" }),
|
||||
enabled: int("enabled", { mode: "boolean" }).notNull().default(true),
|
||||
lastCopyAt: int("last_copy_at", { mode: "number" }),
|
||||
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 }) => ({
|
||||
schedule: one(backupSchedulesTable, {
|
||||
|
||||
@@ -522,13 +522,25 @@ const copyToMirrors = async (
|
||||
repositoryName: mirror.repository.name,
|
||||
});
|
||||
|
||||
await restic.copy(sourceRepository.config, mirror.repository.config, {
|
||||
tag: scheduleId.toString(),
|
||||
});
|
||||
const releaseSource = await repoMutex.acquireShared(sourceRepository.id, `mirror_source:${scheduleId}`);
|
||||
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) {
|
||||
logger.info(`[Background] Applying retention policy to mirror repository: ${mirror.repository.name}`);
|
||||
await restic.forget(mirror.repository.config, retentionPolicy, { tag: scheduleId.toString() });
|
||||
const releaseForget = await repoMutex.acquireExclusive(mirror.repository.id, `forget:mirror:${scheduleId}`);
|
||||
|
||||
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
|
||||
|
||||
@@ -202,7 +202,7 @@ const init = async (config: RepositoryConfig) => {
|
||||
const env = await buildEnv(config);
|
||||
|
||||
const args = ["init", "--repo", repoUrl];
|
||||
addCommonArgs(args, config, env);
|
||||
addCommonArgs(args, env);
|
||||
|
||||
const res = await $`restic ${args}`.env(env).nothrow();
|
||||
await cleanupTemporaryKeys(config, env);
|
||||
@@ -278,7 +278,7 @@ const backup = async (
|
||||
}
|
||||
}
|
||||
|
||||
addCommonArgs(args, config, env);
|
||||
addCommonArgs(args, env);
|
||||
|
||||
const logData = throttle((data: string) => {
|
||||
logger.info(data.trim());
|
||||
@@ -404,7 +404,7 @@ const restore = async (
|
||||
}
|
||||
}
|
||||
|
||||
addCommonArgs(args, config, env);
|
||||
addCommonArgs(args, env);
|
||||
|
||||
logger.debug(`Executing: restic ${args.join(" ")}`);
|
||||
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();
|
||||
await cleanupTemporaryKeys(config, env);
|
||||
@@ -516,7 +516,7 @@ const forget = async (config: RepositoryConfig, options: RetentionPolicy, extra:
|
||||
}
|
||||
|
||||
args.push("--prune");
|
||||
addCommonArgs(args, config, env);
|
||||
addCommonArgs(args, env);
|
||||
|
||||
const res = await $`restic ${args}`.env(env).nothrow();
|
||||
await cleanupTemporaryKeys(config, env);
|
||||
@@ -534,7 +534,7 @@ const deleteSnapshot = async (config: RepositoryConfig, snapshotId: string) => {
|
||||
const env = await buildEnv(config);
|
||||
|
||||
const args: string[] = ["--repo", repoUrl, "forget", snapshotId, "--prune"];
|
||||
addCommonArgs(args, config, env);
|
||||
addCommonArgs(args, env);
|
||||
|
||||
const res = await $`restic ${args}`.env(env).nothrow();
|
||||
await cleanupTemporaryKeys(config, env);
|
||||
@@ -584,7 +584,7 @@ const ls = async (config: RepositoryConfig, snapshotId: string, path?: string) =
|
||||
args.push(path);
|
||||
}
|
||||
|
||||
addCommonArgs(args, config, env);
|
||||
addCommonArgs(args, env);
|
||||
|
||||
const res = await safeSpawn({ command: "restic", args, env });
|
||||
await cleanupTemporaryKeys(config, env);
|
||||
@@ -635,7 +635,7 @@ const unlock = async (config: RepositoryConfig) => {
|
||||
const env = await buildEnv(config);
|
||||
|
||||
const args = ["unlock", "--repo", repoUrl, "--remove-all"];
|
||||
addCommonArgs(args, config, env);
|
||||
addCommonArgs(args, env);
|
||||
|
||||
const res = await $`restic ${args}`.env(env).nothrow();
|
||||
await cleanupTemporaryKeys(config, env);
|
||||
@@ -659,7 +659,7 @@ const check = async (config: RepositoryConfig, options?: { readData?: boolean })
|
||||
args.push("--read-data");
|
||||
}
|
||||
|
||||
addCommonArgs(args, config, env);
|
||||
addCommonArgs(args, env);
|
||||
|
||||
const res = await $`restic ${args}`.env(env).nothrow();
|
||||
await cleanupTemporaryKeys(config, env);
|
||||
@@ -693,7 +693,7 @@ const repairIndex = async (config: RepositoryConfig) => {
|
||||
const env = await buildEnv(config);
|
||||
|
||||
const args = ["repair", "index", "--repo", repoUrl];
|
||||
addCommonArgs(args, config, env);
|
||||
addCommonArgs(args, env);
|
||||
|
||||
const res = await $`restic ${args}`.env(env).nothrow();
|
||||
await cleanupTemporaryKeys(config, env);
|
||||
@@ -746,7 +746,7 @@ const copy = async (
|
||||
args.push("latest");
|
||||
}
|
||||
|
||||
addCommonArgs(args, destConfig, destEnv);
|
||||
addCommonArgs(args, env);
|
||||
|
||||
if (sourceConfig.backend === "sftp" && 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");
|
||||
if (config.backend === "sftp" && env._SFTP_SSH_ARGS) {
|
||||
|
||||
if (env._SFTP_SSH_ARGS) {
|
||||
args.push("-o", `sftp.args=${env._SFTP_SSH_ARGS}`);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user