docs: add spec for polish and optimization items
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>master
parent
ee6d833d70
commit
825c7212e1
@ -0,0 +1,90 @@
|
||||
# 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_secret` field from `AppConfig` struct
|
||||
- Remove `required_var("SESSION_SECRET")` from config loading
|
||||
- Remove the `session_secret` length 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`
|
||||
Loading…
Reference in New Issue