refactor: compile the crate once — main.rs uses the library #184

Merged
cameron merged 1 commits from refactor/main-uses-lib into master 2026-10-17 16:04:12 +00:00
Owner

Problem

main.rs declared nearly every module itself (mod ai; mod database; …), and lib.rs declared the same modules as pub mod. Rust treats those as two separate crates, so:

  • every build compiled the ~100k-line crate twice: once as the library (for the src/bin tools) and once as the server binary
  • cargo test ran most tests twice, as the 749 + 841 result blocks
  • watcher.rs, compiled as part of the binary, reached into the library's copy through image_api::

Change

  • The six modules only the binary had (backfill, handlers, hls_stats, knowledge, reels, watcher) move into lib.rs.
  • main.rs keeps only the startup wiring, using image_api::….
  • Three items the binary calls become pub: RealFileSystem::new and the two reel spawners.
  • Four dead_code allowances that existed only because each copy saw half the callers are removed. Clippy stays clean.
  • CLAUDE.md now says not to add mod declarations to main.rs.

Log targets are unchanged (image_api::watcher and so on), because the binary's crate name was already image_api.

Build times

Release builds of --bin image-api with nice -n 19 -j 3. Absolute numbers are inflated; compare relative changes.

before after
warm rebuild, lto = "thin" 195s 156s (−20%)
warm rebuild, lto = "off" 126s 78s (−38%)
cold build, lto = "thin" 353s 299s
warm rebuild, all 14 bins (old deploy.sh) 459s 437s

With thin LTO the link step is now most of a rebuild. Turning LTO off would halve the deploy rebuild again, but at an unmeasured runtime cost; I left it as thin for now.

Testing

  • cargo test: 860 passed, each test now runs once.
  • cargo clippy --all-targets and cargo fmt --check are clean.
  • Smoke test: started the server built from this branch on port 8093 against a copy of the e2e state. The e2e date check passed (97/97), and the watcher and reel jobs started with no errors.

🤖 Generated with Claude Code

## Problem `main.rs` declared nearly every module itself (`mod ai; mod database; …`), and `lib.rs` declared the same modules as `pub mod`. Rust treats those as two separate crates, so: - every build compiled the ~100k-line crate twice: once as the library (for the `src/bin` tools) and once as the server binary - `cargo test` ran most tests twice, as the 749 + 841 result blocks - `watcher.rs`, compiled as part of the binary, reached into the library's copy through `image_api::` ## Change - The six modules only the binary had (`backfill`, `handlers`, `hls_stats`, `knowledge`, `reels`, `watcher`) move into `lib.rs`. - `main.rs` keeps only the startup wiring, using `image_api::…`. - Three items the binary calls become `pub`: `RealFileSystem::new` and the two reel spawners. - Four `dead_code` allowances that existed only because each copy saw half the callers are removed. Clippy stays clean. - CLAUDE.md now says not to add `mod` declarations to `main.rs`. Log targets are unchanged (`image_api::watcher` and so on), because the binary's crate name was already `image_api`. ## Build times Release builds of `--bin image-api` with `nice -n 19 -j 3`. Absolute numbers are inflated; compare relative changes. | | before | after | |---|---|---| | warm rebuild, `lto = "thin"` | 195s | **156s** (−20%) | | warm rebuild, `lto = "off"` | 126s | **78s** (−38%) | | cold build, `lto = "thin"` | 353s | 299s | | warm rebuild, all 14 bins (old deploy.sh) | 459s | 437s | With thin LTO the link step is now most of a rebuild. Turning LTO off would halve the deploy rebuild again, but at an unmeasured runtime cost; I left it as `thin` for now. ## Testing - `cargo test`: **860 passed**, each test now runs once. - `cargo clippy --all-targets` and `cargo fmt --check` are clean. - Smoke test: started the server built from this branch on port 8093 against a copy of the e2e state. The e2e date check passed (97/97), and the watcher and reel jobs started with no errors. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
cameron added 1 commit 2026-10-17 16:03:36 +00:00
main.rs re-declared nearly every module (`mod ai; mod database; …`)
that lib.rs also declared, so the ~100k-line crate compiled twice in
every build (lib for the src/bin tools, bin for the server) and the
test suite ran most tests twice. watcher.rs even reached into the lib
copy via `image_api::` from inside the bin copy.

The six bin-only modules (backfill, handlers, hls_stats, knowledge,
reels, watcher) move into lib.rs; main.rs keeps only startup wiring
over `use image_api::…`. A few items main calls become `pub`, and the
dead_code allowances that only existed because each copy saw half the
callers are gone. CLAUDE.md says not to reintroduce `mod` in main.rs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cameron force-pushed refactor/main-uses-lib from 2e207c5fa0 to 640cd3833a 2026-10-17 16:03:36 +00:00 Compare
cameron merged commit 783fcb8dbe into master 2026-10-17 16:04:12 +00:00
cameron deleted branch refactor/main-uses-lib 2026-10-17 16:04:13 +00:00
Sign in to join this conversation.