Add config-sync cycle retention alongside config history keep.

Mirror LLDP job retention so finished sync cycles are pruned by policy while keeping per-NE config version history separate.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
hansjone 2026-08-02 03:44:35 +00:00
parent 53ddb3b520
commit a6c7267b47
10 changed files with 162 additions and 7 deletions

View file

@ -304,7 +304,8 @@ const en = {
enabled: "Enable scheduled sync",
intervalDays: "Interval (days)",
concurrency: "Concurrency",
historyKeep: "History keep",
historyKeep: "Config versions to keep",
cycleKeep: "Jobs to keep",
scope: "Scope",
scopeAll: "All NEs",
scopeSelected: "Selected NEs",

View file

@ -304,7 +304,8 @@ const zh = {
enabled: "启用周期调度",
intervalDays: "周期(天)",
concurrency: "并发",
historyKeep: "历史保留",
historyKeep: "配置历史保留",
cycleKeep: "任务保留数",
scope: "范围",
scopeAll: "全部网元",
scopeSelected: "指定网元",

View file

@ -37,6 +37,7 @@ export function ConfigSyncPage() {
const [concurrency, setConcurrency] = useState(5);
const [scopeMode, setScopeMode] = useState<"all" | "selected">("all");
const [historyKeep, setHistoryKeep] = useState(3);
const [cycleKeep, setCycleKeep] = useState(30);
const [selectedMap, setSelectedMap] = useState<Record<string, ConfigSyncTargetRef>>({});
const [policyHydrated, setPolicyHydrated] = useState(false);
@ -63,6 +64,7 @@ export function ConfigSyncPage() {
setConcurrency(Number(p.concurrency || 5));
setScopeMode(p.scope_mode === "selected" ? "selected" : "all");
setHistoryKeep(Number(p.history_keep ?? 3));
setCycleKeep(Math.max(0, Math.min(200, Number(p.cycle_keep ?? 30))));
const map: Record<string, ConfigSyncTargetRef> = {};
for (const ref of p.selected_targets || []) {
map[`${ref.source}:${ref.id}`] = { source: ref.source, id: ref.id };
@ -117,6 +119,7 @@ export function ConfigSyncPage() {
concurrency,
scope_mode: scopeMode,
history_keep: historyKeep,
cycle_keep: cycleKeep,
selected_targets: Object.values(selectedMap),
}),
onSuccess: async (saved) => {
@ -127,6 +130,7 @@ export function ConfigSyncPage() {
setConcurrency(Number(saved.concurrency || 5));
setScopeMode(saved.scope_mode === "selected" ? "selected" : "all");
setHistoryKeep(Number(saved.history_keep ?? 3));
setCycleKeep(Math.max(0, Math.min(200, Number(saved.cycle_keep ?? 30))));
const map: Record<string, ConfigSyncTargetRef> = {};
for (const ref of saved.selected_targets || []) {
map[`${ref.source}:${ref.id}`] = { source: ref.source, id: ref.id };
@ -313,6 +317,16 @@ export function ConfigSyncPage() {
onChange={(e) => setHistoryKeep(Math.max(0, Math.min(30, Number(e.target.value) || 0)))}
/>
</label>
<label className="config-sync-policy-field">
<span>{t("configSync.cycleKeep")}</span>
<input
type="number"
min={0}
max={200}
value={cycleKeep}
onChange={(e) => setCycleKeep(Math.max(0, Math.min(200, Number(e.target.value) || 0)))}
/>
</label>
<label className="config-sync-policy-field">
<span>{t("configSync.scope")}</span>
<select

View file

@ -670,6 +670,7 @@ export type ConfigSyncPolicy = {
scope_mode: string;
selected_targets: ConfigSyncTargetRef[];
history_keep: number;
cycle_keep: number;
updated_at?: string | null;
};