Repository navigation
feat(search): configurable automatic-search sweep interval, per-book cooldown and book delay - #714
Conversation
95c03ae to
b4fbe84
Compare
therobbiedavis
left a comment
There was a problem hiding this comment.
@kevinheneveld Could we keep this PR focused on configurable search timing and leave the fallback to #1072 and the identity-matching follow-ups already underway?
I’d separate the sweep interval from the per-book cooldown: the worker could check hourly while each book remains eligible only once every 24 hours. The delay between books would remain a separate throttle to protect indexers. Currently, AutomaticSearchIntervalHours controls both the sweep cadence and eligibility cutoff; could we give the cutoff its own setting? One shared cooldown for all books should be enough for now.
b4fbe84 to
853be7e
Compare
|
@therobbiedavis reworked as suggested, thanks for the rebase:
Description updated to match. No UI in this PR — say the word if you'd like a Settings block for the three and I'll add it as a follow-up. |
therobbiedavis
left a comment
There was a problem hiding this comment.
@kevinheneveld reviewed and tested the updated head. The fallback is removed and the sweep interval, per-book cooldown, and delay are separate now. 57 tests passed with 2 platform skips, along with 19 live container checks. No remaining blockers from me.
|
@kevinheneveld Thanks, this matches what we discussed. API-only is fine for this PR. Yes, let’s do a follow-up to add the Settings block. |
853be7e to
5bdf118
Compare
|
@kevinheneveld Please fix the failing tests. Thank you! |
5bdf118 to
950bb94
Compare
|
Fixed in 950bb94 (amended, same single commit on your rebase): |
50d65af to
461460f
Compare
…cooldown and book delay The automatic-search sweep ran on a hardcoded 6-hour cadence that doubled as the "not searched since" cutoff, and it searched every eligible book back-to-back. Three settings replace that, read fresh each cycle: - AutomaticSearchIntervalHours (default 1, clamped [1,168]): how often the worker looks for eligible books. Only the cadence of the check. - AutomaticSearchCooldownHours (default 24, clamped [1,720]): how long a book stays ineligible after its last search. One shared cooldown for all books. - AutomaticSearchBookDelaySeconds (default 5, clamped [0,300]): pause between consecutive books inside one sweep. Manual "Search now" is unaffected. AutomaticSearchTiming resolves and clamps the three from ApplicationSettings so the service and the processor share one definition. The migration's column defaults match the property initializers so the existing settings row behaves like a fresh install. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
461460f to
b5b7c76
Compare
…v1.5.2) Upstream v1.3.24-v1.5.2: Listenarrs#757 indexer-timeout containment, Listenarrs#605 quality-profile picker, Listenarrs#714 automatic-search timing (sweep interval / per-book cooldown / book delay), Listenarrs#1072 author-free retry with title constraint, Listenarrs#990 post-nominal author folders. Resolutions: - ApplicationSettings / AutomaticSearchService / AutomaticSearchResultClassifier: upstream's three timing columns and author-free fallback replace the fork's AutomaticSearchIntervalHours-as-cooldown, trailing book delay and opt-out title-only fallback. Fork's SearchProgressReporter broadcasts, blocked-release and filter-pipeline hooks kept; SearchNow.cs no longer passes the fallback flag. - Migrations: fork-only 20261021212417_RetireForkAutomaticSearchTuning renames the July fork columns to Retired_* (native transactional ALTER, no rebuild) so upstream's 20261021212418_AddAutomaticSearchTiming applies unchanged. Snapshot = upstream's. SqliteMigrationSchemaTests expected history updated. - IndexerSearchWorkflow: fork's inner HttpClient-timeout catch removed in favor of upstream's per-indexer OperationCanceledException containment (Listenarrs#757 supersedes Listenarrs#967); the contradicted cooperative-cancellation test removed. Torznab provider catch and HttpClientTimeoutClassifier remain. - WantedView.vue: fork's server-side wanted-search strip/queue kept alongside Listenarrs#605's profile-recovery banner, modal and pending-refresh set; upstream's browser-loop remnants (sleep/abortDelay/showConfirmSearchAll) not reintroduced; duplicated useToast import collapsed. - AutomaticSearchProcessorFallbackTests: scorer mock adapted to the fork's three-parameter ScoreSearchResults. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Summary
The automatic-search sweep ran on a hardcoded 6-hour cadence that also served as the "not searched since" cutoff, and it searched every eligible book back-to-back. On a large wanted list that hammers the indexers (and a shared Prowlarr). This makes the timing configurable and, per review, keeps the sweep cadence and the per-book eligibility separate: the worker can check hourly while each book is only searched once per cooldown.
Scope is timing only. The title-only fallback from the earlier revision is gone; that lane belongs to #1072 and the identity-matching follow-ups.
Changes
Added
ApplicationSettings.AutomaticSearchIntervalHours(default 1, clamped [1, 168]) — how often the worker sweeps for eligible books. Only the cadence of the check.ApplicationSettings.AutomaticSearchCooldownHours(default 24, clamped [1, 720]) — how long a book stays ineligible after its last search. One shared cooldown for every book.ApplicationSettings.AutomaticSearchBookDelaySeconds(default 5, clamped [0, 300]) — pause between consecutive books inside one sweep.0disables it. Manual "Search now" is unaffected.AutomaticSearchTiming(HostedServices/Search/) — resolves and clamps the three from settings soAutomaticSearchServiceandAutomaticSearchProcessorshare one definition;EligibilityCutoff(now)isnow − cooldown.20261021212418_AddAutomaticSearchTiming(+ Designer, snapshot). Column defaults match the property initializers so the existing singleton settings row behaves exactly like a fresh install.Changed
AutomaticSearchService: the periodic runner'sintervalProviderreads the sweep interval from settings each cycle (falls back to the default on a read error), so a change takes effect without a restart.AutomaticSearchProcessor: the eligibility cutoff comes from the cooldown instead of the sweep interval; the per-book delay is applied between books (not after the last one).Removed
AutomaticSearchTitleOnlyFallback,BuildTitleOnlySearchQuery, the retry inProcessAudiobookAsync).Testing
AutomaticSearchTimingTests(new, 17 cases): defaults, each clamp at both bounds, and that the eligibility cutoff follows the cooldown rather than the sweep interval.MigrationMetadataTests.AddAutomaticSearchTiming_IsDiscoverableAndAddsSettingsColumnsWithDefaults: migration id, the threeAddColumnoperations with their defaults, the three drops, and the target model.SqliteMigrationSchemaTests(migrated-schema column parity, migration history, released-schema upgrades) andHostedServicesRegistrationTestspass with the new migration;ActiveProductionSourceFiles_RemainFocusedstill passes.dotnet format --verify-no-changesclean on the touched files.Notes
ApplicationSettingsfields reachable through the settings API like the other untuned knobs. Happy to add a small Settings block in a follow-up if you'd like them surfaced.20261002210137_AddOperationEvidencePublications.🤖 Generated with Claude Code