Skip to content

refactor(server): move the catalog's SQL into repositories - #45

Merged
fylorn merged 1 commit into
devfrom
refactor/server-catalog-repositories
Sep 24, 2026
Merged

fylorn merged 1 commit into
devfrom
refactor/server-catalog-repositories

Conversation

@fylorn

@fylorn fylorn commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

First of the per-domain PRs that take SQL out of crates/server/src/handlers (238 direct sqlx::query calls across ~30 handler files). This one covers the catalog: models.rs (32), providers.rs (10), platform_pricing.rs (2).

What moved

  • services::model_repository — models and model_routes: paging/filtering, insert/update/delete, bulk toggles and deletes, route CRUD, the flat route listing, the batch import (its transaction now lives here), batch weights (same), and the route's log identity for the history sparkline.
  • services::provider_repository — live-provider lookups, insert/update, clearing learned protocols, and the soft delete + route drop transaction.
  • services::pricing_repository — the platform_pricing singleton.
  • The row types the queries return (ModelRow, ModelIdRow, ModelRouteRow, PlatformPricing) move with them; openapi.rs imports ModelRow from there.

Every statement is carried over verbatim. Handlers keep permission checks, validation, audit, and the router / weight-cache / cost-tracker refresh. This follows the convention services/mod.rs already lays down (handlers call repositories; user_repository was the first).

No behaviour change — checked

admin_catalog.rs adds integration tests for the endpoints no test reached: route create (duplicate / unknown model / unknown provider), PATCH with clear-vs-absent semantics and cap validation, delete, the flat listing unfiltered and filtered, batch weights, batch enable toggle, batch delete, list status filters (active / disabled / unrouted), model ids, bulk set-enabled (only changed rows count), bulk delete, single delete, unrouted cleanup, provider get/list/rename/base-URL change (learned protocols cleared) / delete (routes dropped), pricing get/patch/validation. They pass against the code before this change and after it.

Incremental build: measured, no crate split

The plan considered splitting the biggest handler groups into their own crates. Measured on this machine (4 cargo jobs, other builds running; median of 3, after warm-up), cargo build -p think-watch-server after editing one string literal:

edit in rebuild
handlers/models.rs 4.6 s
handlers/admin/users.rs 3.4 s
main.rs (binary only — the link floor) 3.4 s

cargo check -p think-watch-server after the same edits: 2.0–2.1 s for the whole 37k-line crate. The rebuild is dominated by linking the binary, which a crate split does not shorten; the most a split could save is the ~1 s of the server crate's own incremental codegen, while every integration-test binary still links everything. Not worth a crate boundary, so the restructuring stays inside the crate.

Checks

fmt, clippy (--all-targets, --lib), 679 unit tests, full integration suite on own containers (273 passed).

🤖 Generated with Claude Code

The models, routes, providers and platform-pricing handlers no longer
carry SQL: services::{model,provider,pricing}_repository hold every
statement, verbatim, one function per statement or transaction. The
handlers keep validation, audit and the router / cache refresh. The row
types those queries return (ModelRow, ModelIdRow, ModelRouteRow,
PlatformPricing) move with them.

No behaviour change. admin_catalog.rs pins the endpoints that had no
integration test (route PATCH/delete, the flat route listing, batch
weights and toggles, bulk model operations, the unrouted cleanup,
provider edit and delete, pricing); it passes against both the old and
the new code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@fylorn
fylorn merged commit d3f36fc into dev Sep 24, 2026
6 checks passed
@fylorn
fylorn deleted the refactor/server-catalog-repositories branch September 24, 2026 08:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant