fix a lot of the coderabbit warnings

This commit is contained in:
Raj Dave 2026-01-10 14:23:39 +03:00
parent db127afe5a
commit a7a4ccef6b
4 changed files with 66 additions and 25 deletions

View file

@ -10,7 +10,13 @@ import {
import { Input } from "../../../../components/ui/input";
import { Textarea } from "../../../../components/ui/textarea";
import { Checkbox } from "../../../../components/ui/checkbox";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../../components/ui/select";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue
} from "../../../../components/ui/select";
import { Tooltip, TooltipContent, TooltipTrigger } from "../../../../components/ui/tooltip";
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../../../../components/ui/collapsible";
import type { RepositoryFormValues } from "../create-repository-form";
@ -103,7 +109,7 @@ export const AdvancedForm = ({ form }: Props) => {
name="uploadLimit.unit"
render={({ field }) => (
<FormItem className="w-24">
<Select onValueChange={field.onChange} defaultValue={field.value || "MB/s"} value={field.value || "MB/s"}>
<Select onValueChange={field.onChange} defaultValue={field.value || "Mbps"} value={field.value || "Mbps"}>
<FormControl>
<SelectTrigger className="text-xs">
<SelectValue />
@ -186,7 +192,7 @@ export const AdvancedForm = ({ form }: Props) => {
name="downloadLimit.unit"
render={({ field }) => (
<FormItem className="w-24">
<Select onValueChange={field.onChange} defaultValue={field.value || "MB/s"} value={field.value || "MB/s"}>
<Select onValueChange={field.onChange} defaultValue={field.value || "Mbps"} value={field.value || "Mbps"}>
<FormControl>
<SelectTrigger className="text-xs">
<SelectValue />

View file

@ -14,9 +14,9 @@ export const REPOSITORY_BACKENDS = {
export type RepositoryBackend = keyof typeof REPOSITORY_BACKENDS;
export const BANDWIDTH_UNITS = {
"KB/s": "KB/s",
"MB/s": "MB/s",
"GB/s": "GB/s",
"Kbps": "Kbps",
"Mbps": "Mbps",
"Gbps": "Gbps",
} as const;
export type BandwidthUnit = keyof typeof BANDWIDTH_UNITS;
@ -24,8 +24,8 @@ export type BandwidthUnit = keyof typeof BANDWIDTH_UNITS;
// Bandwidth limit configuration
export const bandwidthLimitSchema = type({
enabled: "boolean = false",
value: "number >= 0",
unit: type.valueOf(BANDWIDTH_UNITS).default("MB/s"),
value: "number >= 0 = 0",
unit: type.valueOf(BANDWIDTH_UNITS).default("Mbps"),
});
export type BandwidthLimit = typeof bandwidthLimitSchema.infer;

View file

@ -1,6 +1,6 @@
import { relations, sql } from "drizzle-orm";
import { index, int, integer, sqliteTable, text, primaryKey, unique } from "drizzle-orm/sqlite-core";
import type { CompressionMode, RepositoryBackend, repositoryConfigSchema, RepositoryStatus } from "~/schemas/restic";
import { index, int, integer, sqliteTable, text, real, primaryKey, unique } from "drizzle-orm/sqlite-core";
import type { CompressionMode, RepositoryBackend, repositoryConfigSchema, RepositoryStatus, BandwidthUnit } from "~/schemas/restic";
import type { BackendStatus, BackendType, volumeConfigSchema } from "~/schemas/volumes";
import type { NotificationType, notificationConfigSchema } from "~/schemas/notifications";
@ -161,11 +161,11 @@ export const repositoriesTable = sqliteTable("repositories_table", {
lastError: text("last_error"),
// Bandwidth limit fields
uploadLimitEnabled: int("upload_limit_enabled", { mode: "boolean" }).notNull().default(false),
uploadLimitValue: int("upload_limit_value").notNull().default(0),
uploadLimitUnit: text("upload_limit_unit").notNull().default("MB/s"),
uploadLimitValue: real("upload_limit_value").notNull().default(0),
uploadLimitUnit: text("upload_limit_unit").$type<BandwidthUnit>().notNull().default("Mbps"),
downloadLimitEnabled: int("download_limit_enabled", { mode: "boolean" }).notNull().default(false),
downloadLimitValue: int("download_limit_value").notNull().default(0),
downloadLimitUnit: text("download_limit_unit").notNull().default("MB/s"),
downloadLimitValue: real("download_limit_value").notNull().default(0),
downloadLimitUnit: text("download_limit_unit").$type<BandwidthUnit>().notNull().default("Mbps"),
createdAt: int("created_at", { mode: "number" })
.notNull()
.default(sql`(unixepoch() * 1000)`),

View file

@ -846,8 +846,39 @@ const copy = async (
args.push("latest");
}
// Apply bandwidth limits from both source and destination configs
// First apply destination config limits (for the main operation)
addCommonArgs(args, env, destConfig);
// Then explicitly apply source-side bandwidth limits for the from-repo operation
if (sourceConfig.uploadLimit?.enabled) {
const sourceUploadLimit = formatBandwidthLimit(sourceConfig.uploadLimit);
if (sourceUploadLimit) {
if (sourceConfig.backend === "rclone") {
// For rclone source backends, use rclone.bwlimit for the from-repo
args.push("-o", `rclone.from.bwlimit=${sourceUploadLimit}`);
} else {
// For restic source backends, the download from source becomes an upload limit
args.push("--limit-upload", sourceUploadLimit);
}
}
}
if (sourceConfig.downloadLimit?.enabled) {
const sourceDownloadLimit = formatBandwidthLimit(sourceConfig.downloadLimit);
if (sourceDownloadLimit) {
if (sourceConfig.backend === "rclone") {
// For rclone source backends
const sourceUploadLimit = sourceConfig.uploadLimit?.enabled ? formatBandwidthLimit(sourceConfig.uploadLimit) : "";
const effectiveLimit = sourceUploadLimit && parseInt(sourceUploadLimit) < parseInt(sourceDownloadLimit) ? sourceUploadLimit : sourceDownloadLimit;
args.push("-o", `rclone.from.bwlimit=${effectiveLimit}`);
} else {
// For restic source backends, this affects reading from the source repo
args.push("--limit-download", sourceDownloadLimit);
}
}
}
if (sourceConfig.backend === "sftp" && sourceEnv._SFTP_SSH_ARGS) {
args.push("-o", `sftp.args=${sourceEnv._SFTP_SSH_ARGS}`);
}
@ -874,29 +905,33 @@ const copy = async (
};
};
// Helper function to convert bandwidth limit to restic format
// Helper function to convert bandwidth limit to restic/rclone format
const formatBandwidthLimit = (limit: BandwidthLimit): string => {
if (!limit.enabled || limit.value <= 0) {
return "";
}
// Convert to bytes per second for restic
let bytesPerSecond: number;
// Convert to KiB/s for restic compatibility, or use suffixed format for rclone
let kibibytesPerSecond: number;
switch (limit.unit) {
case "KB/s":
bytesPerSecond = limit.value * 1024;
case "Kbps":
// Kilobits per second to KiB/s: divide by 8 (bits to bytes), then by 1024 (bytes to KiB)
kibibytesPerSecond = limit.value / (8 * 1024);
break;
case "MB/s":
bytesPerSecond = limit.value * 1024 * 1024;
case "Mbps":
// Megabits per second to KiB/s: multiply by 1000000 (Mb to bits), divide by 8 (bits to bytes), then by 1024 (bytes to KiB)
kibibytesPerSecond = (limit.value * 1000000) / (8 * 1024);
break;
case "GB/s":
bytesPerSecond = limit.value * 1024 * 1024 * 1024;
case "Gbps":
// Gigabits per second to KiB/s: multiply by 1000000000 (Gb to bits), divide by 8 (bits to bytes), then by 1024 (bytes to KiB)
kibibytesPerSecond = (limit.value * 1000000000) / (8 * 1024);
break;
default:
return "";
}
return `${Math.floor(bytesPerSecond)}`;
// Return as integer KiB/s for restic
return `${Math.floor(kibibytesPerSecond)}`;
};
export const addCommonArgs = (args: string[], env: Record<string, string>, config?: RepositoryConfig) => {
@ -968,7 +1003,7 @@ export const restic = {
// Helper function to clean up temporary files
const cleanupTemporaryKeys = async (env: Record<string, string>) => {
const keysToClean = ['_SFTP_KEY_PATH', '_SFTP_KNOWN_HOSTS_PATH', 'RESTIC_CACERT', 'GOOGLE_APPLICATION_CREDENTIALS'];
const keysToClean = ["_SFTP_KEY_PATH", "_SFTP_KNOWN_HOSTS_PATH", "RESTIC_CACERT", "GOOGLE_APPLICATION_CREDENTIALS"];
for (const key of keysToClean) {
if (env[key]) {