fix: persist indexer max_index_time_window_secs setting (#8821)

* fix: persist indexer max_index_time_window_secs setting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: toggle UX for indexer time window cap

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ruben Fiszel
2026-04-13 19:56:38 -04:00
committed by GitHub
parent 89c8e4bb96
commit 4dc54ca3aa
3 changed files with 61 additions and 30 deletions

View File

@@ -436,6 +436,8 @@ pub struct IndexerSettings {
#[serde(skip_serializing_if = "Option::is_none")]
pub max_indexed_job_log_size: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_index_time_window_secs: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub should_clear_job_index: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub should_clear_log_index: Option<bool>,

View File

@@ -80,6 +80,7 @@ export interface Setting {
export type SettingStorage = 'setting'
const positiveNumber = z.number().positive('Must be a positive number')
const nonNegativeNumber = z.number().nonnegative('Must be zero or a positive number')
const indexerSettingsSchema = z
.object({
@@ -89,7 +90,7 @@ const indexerSettingsSchema = z
max_indexed_job_log_size: positiveNumber.optional(),
commit_log_max_batch_size: positiveNumber.optional(),
refresh_log_index_period: positiveNumber.optional(),
max_index_time_window_secs: positiveNumber.optional()
max_index_time_window_secs: nonNegativeNumber.optional()
})
.passthrough()

View File

@@ -9,6 +9,7 @@
import IntegerInput from '../IntegerInput.svelte'
import InputError from '../InputError.svelte'
import Label from '../Label.svelte'
import Toggle from '../Toggle.svelte'
import { Loader2, RefreshCw } from 'lucide-svelte'
import type { Writable } from 'svelte/store'
@@ -20,6 +21,20 @@
let { values, disabled = false, errors = {} }: Props = $props()
let isTimeWindowCapped = $derived($values['indexer_settings'].max_index_time_window_secs !== 0)
function setTimeWindowCapped(checked: boolean) {
if (checked) {
const { max_index_time_window_secs: _, ...rest } = $values['indexer_settings']
$values['indexer_settings'] = rest
} else {
$values['indexer_settings'] = {
...$values['indexer_settings'],
max_index_time_window_secs: 0
}
}
}
let clearJobsIndexModalOpen = $state(false)
let clearServiceLogsIndexModalOpen = $state(false)
@@ -91,36 +106,49 @@
/>
<InputError error={errors.writer_memory_budget ?? ''} />
</div>
<div class="flex flex-col gap-1">
<label for="max_index_time_window_secs" class="block text-xs font-semibold text-emphasis">
Index time window (days)
<Tooltip>
Maximum age of items to include in the index. Jobs and logs older than this window will not
be indexed and will be cleaned up from the index. Set to 0 to disable (index everything
within the retention period).
</Tooltip>
</label>
<IntegerInput
placeholder="7"
id="max_index_time_window_secs"
{disabled}
error={errors.max_index_time_window_secs ?? ''}
value={$values['indexer_settings'].max_index_time_window_secs != null
? Math.round($values['indexer_settings'].max_index_time_window_secs / 86400)
: undefined}
oninput={(v) => {
if (v == null) {
const { max_index_time_window_secs: _, ...rest } = $values['indexer_settings']
$values['indexer_settings'] = rest
} else {
$values['indexer_settings'] = {
...$values['indexer_settings'],
max_index_time_window_secs: v * 86400
<div class="flex flex-col gap-2">
<div class="flex flex-row items-center gap-2">
<span class="block text-xs font-semibold text-emphasis">
Index time window
<Tooltip>
Cap the age of items the indexer keeps. Jobs and logs older than this window are not
indexed and are cleaned up from the index. Disable the cap to index everything within the
retention period.
</Tooltip>
</span>
<div class="ml-auto">
<Toggle
{disabled}
checked={isTimeWindowCapped}
on:change={(e) => setTimeWindowCapped(e.detail)}
options={{ right: 'Cap by time window' }}
/>
</div>
</div>
{#if isTimeWindowCapped}
<IntegerInput
placeholder="7"
id="max_index_time_window_secs"
{disabled}
error={errors.max_index_time_window_secs ?? ''}
value={$values['indexer_settings'].max_index_time_window_secs != null
? Math.round($values['indexer_settings'].max_index_time_window_secs / 86400)
: undefined}
oninput={(v) => {
if (v == null) {
const { max_index_time_window_secs: _, ...rest } = $values['indexer_settings']
$values['indexer_settings'] = rest
} else {
$values['indexer_settings'] = {
...$values['indexer_settings'],
max_index_time_window_secs: v * 86400
}
}
}
}}
/>
<InputError error={errors.max_index_time_window_secs ?? ''} />
}}
/>
<span class="text-2xs text-tertiary">days (leave blank to use the default of 7 days)</span>
<InputError error={errors.max_index_time_window_secs ?? ''} />
{/if}
</div>
<Label label="Indexer status">
{#snippet action()}