4.2 KiB
Design: Polish & Optimization Items (Audit Medium Priority)
Date: 2026-03-26
Scope: 8 polish/optimization items from the code audit
Source: docs/audit/00-consolidated-summary.md — Medium Priority section
1. Batch article history INSERTs
Problem: Each trace_article call does an individual INSERT. 20+ sequential DB round-trips per generation.
Fix: Add batch_insert_entries(pool, entries: &[ArticleHistoryEntry]) in db/article_history.rs using unnest() arrays for bulk INSERT. In synthesis.rs, collect traces into a Vec and flush in a single batch call at the end of each processing phase.
Files: backend/src/db/article_history.rs, backend/src/services/synthesis.rs
2. Reduce .clone() in pipeline with Arc
Problem: model_research, classification_categories, classify_schema, and other immutable values are cloned into every spawned task (59 clones identified).
Fix: Wrap these values in Arc<str> or Arc<Value> at the start of run_generation_inner. Spawned tasks clone the Arc (cheap pointer copy) instead of the full string/JSON value. Target the heaviest clones inside the batch loops.
Files: backend/src/services/synthesis.rs
3. Cache CSS selectors with LazyLock
Problem: Selector::parse("a[href]") is called on every invocation of link extraction functions, re-parsing the same static selector.
Fix: Use std::sync::LazyLock<Selector> for static selectors in source_scraper.rs and scraper.rs.
Files: backend/src/services/source_scraper.rs, backend/src/services/scraper.rs
4. Standardize frontend data fetching on createResource
Problem: Some pages use createResource, others use onMount + manual signals for data loading. Inconsistent patterns.
Fix: Convert pages that use onMount + createSignal for data loading to use createResource. Only change pages where the pattern is clearly onMount → fetch → setSignal and createResource is a direct fit. Don't force conversions where the pattern is more complex (e.g. SSE, conditional fetching).
Files: Frontend pages using the onMount + signal pattern (identify by reading each page)
5. Use existing Button component
Problem: A reusable Button component exists but inline Tailwind button classes are duplicated across pages.
Fix: Replace obvious inline button markup with the existing Button component. Only do clear-cut cases where the button matches the component's API — don't force every button into it.
Files: Frontend pages with inline button markup
6. Align default settings between frontend and backend
Problem: DEFAULT_SETTINGS in frontend and Default for UserSettings in backend have different category lists and potentially other divergent values.
Fix: The backend is authoritative. Update DEFAULT_SETTINGS in frontend/src/types.ts to match Default for UserSettings in backend/src/models/settings.rs. The frontend defaults are only used as initial form state before the API response arrives, so they should match what the backend would return for a new user.
Files: frontend/src/types.ts
7. Remove unused SESSION_SECRET
Problem: session_secret is loaded from env, validated (min 64 chars), stored in AppConfig, but never referenced anywhere in the codebase. The app uses DB-backed session tokens, not signed cookies.
Fix:
- Remove
session_secretfield fromAppConfigstruct - Remove
required_var("SESSION_SECRET")from config loading - Remove the
session_secretlength validation - Remove from
.env.example - Update related tests
Files: backend/src/config.rs, .env.example
8. Wrap AppConfig master key in Arc
Problem: master_encryption_key is a cloneable String in AppConfig. Since AppConfig is cloned into AppState, the secret exists in multiple memory locations.
Fix: Change master_encryption_key: String to master_encryption_key: Arc<String> in AppConfig. Update all call sites that reference state.config.master_encryption_key — they already call MasterKey::from_hex(&...) which takes &str, so Arc<String> derefs transparently.
Files: backend/src/config.rs, and any files that access config.master_encryption_key