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:
@@ -436,6 +436,8 @@ pub struct IndexerSettings {
|
|||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub max_indexed_job_log_size: Option<u64>,
|
pub max_indexed_job_log_size: Option<u64>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[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>,
|
pub should_clear_job_index: Option<bool>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub should_clear_log_index: Option<bool>,
|
pub should_clear_log_index: Option<bool>,
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ export interface Setting {
|
|||||||
export type SettingStorage = 'setting'
|
export type SettingStorage = 'setting'
|
||||||
|
|
||||||
const positiveNumber = z.number().positive('Must be a positive number')
|
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
|
const indexerSettingsSchema = z
|
||||||
.object({
|
.object({
|
||||||
@@ -89,7 +90,7 @@ const indexerSettingsSchema = z
|
|||||||
max_indexed_job_log_size: positiveNumber.optional(),
|
max_indexed_job_log_size: positiveNumber.optional(),
|
||||||
commit_log_max_batch_size: positiveNumber.optional(),
|
commit_log_max_batch_size: positiveNumber.optional(),
|
||||||
refresh_log_index_period: positiveNumber.optional(),
|
refresh_log_index_period: positiveNumber.optional(),
|
||||||
max_index_time_window_secs: positiveNumber.optional()
|
max_index_time_window_secs: nonNegativeNumber.optional()
|
||||||
})
|
})
|
||||||
.passthrough()
|
.passthrough()
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
import IntegerInput from '../IntegerInput.svelte'
|
import IntegerInput from '../IntegerInput.svelte'
|
||||||
import InputError from '../InputError.svelte'
|
import InputError from '../InputError.svelte'
|
||||||
import Label from '../Label.svelte'
|
import Label from '../Label.svelte'
|
||||||
|
import Toggle from '../Toggle.svelte'
|
||||||
import { Loader2, RefreshCw } from 'lucide-svelte'
|
import { Loader2, RefreshCw } from 'lucide-svelte'
|
||||||
import type { Writable } from 'svelte/store'
|
import type { Writable } from 'svelte/store'
|
||||||
|
|
||||||
@@ -20,6 +21,20 @@
|
|||||||
|
|
||||||
let { values, disabled = false, errors = {} }: Props = $props()
|
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 clearJobsIndexModalOpen = $state(false)
|
||||||
let clearServiceLogsIndexModalOpen = $state(false)
|
let clearServiceLogsIndexModalOpen = $state(false)
|
||||||
|
|
||||||
@@ -91,36 +106,49 @@
|
|||||||
/>
|
/>
|
||||||
<InputError error={errors.writer_memory_budget ?? ''} />
|
<InputError error={errors.writer_memory_budget ?? ''} />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-2">
|
||||||
<label for="max_index_time_window_secs" class="block text-xs font-semibold text-emphasis">
|
<div class="flex flex-row items-center gap-2">
|
||||||
Index time window (days)
|
<span class="block text-xs font-semibold text-emphasis">
|
||||||
<Tooltip>
|
Index time window
|
||||||
Maximum age of items to include in the index. Jobs and logs older than this window will not
|
<Tooltip>
|
||||||
be indexed and will be cleaned up from the index. Set to 0 to disable (index everything
|
Cap the age of items the indexer keeps. Jobs and logs older than this window are not
|
||||||
within the retention period).
|
indexed and are cleaned up from the index. Disable the cap to index everything within the
|
||||||
</Tooltip>
|
retention period.
|
||||||
</label>
|
</Tooltip>
|
||||||
<IntegerInput
|
</span>
|
||||||
placeholder="7"
|
<div class="ml-auto">
|
||||||
id="max_index_time_window_secs"
|
<Toggle
|
||||||
{disabled}
|
{disabled}
|
||||||
error={errors.max_index_time_window_secs ?? ''}
|
checked={isTimeWindowCapped}
|
||||||
value={$values['indexer_settings'].max_index_time_window_secs != null
|
on:change={(e) => setTimeWindowCapped(e.detail)}
|
||||||
? Math.round($values['indexer_settings'].max_index_time_window_secs / 86400)
|
options={{ right: 'Cap by time window' }}
|
||||||
: undefined}
|
/>
|
||||||
oninput={(v) => {
|
</div>
|
||||||
if (v == null) {
|
</div>
|
||||||
const { max_index_time_window_secs: _, ...rest } = $values['indexer_settings']
|
{#if isTimeWindowCapped}
|
||||||
$values['indexer_settings'] = rest
|
<IntegerInput
|
||||||
} else {
|
placeholder="7"
|
||||||
$values['indexer_settings'] = {
|
id="max_index_time_window_secs"
|
||||||
...$values['indexer_settings'],
|
{disabled}
|
||||||
max_index_time_window_secs: v * 86400
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
<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 ?? ''} />
|
<InputError error={errors.max_index_time_window_secs ?? ''} />
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<Label label="Indexer status">
|
<Label label="Indexer status">
|
||||||
{#snippet action()}
|
{#snippet action()}
|
||||||
|
|||||||
Reference in New Issue
Block a user