refactor: compile the crate once — main.rs uses the library
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>
This commit is contained in:
1 parent
4f35f87ea3
commit
640cd3833a
9 files changed
+27
-82
No files matched your search
@@ -4677,10 +4677,6 @@ Return ONLY the summary, nothing else."#,
|
||||
///
|
||||
/// Calls `execute_tool` with empty file/image context; enabled tools
|
||||
/// never read those fields.
|
||||
///
|
||||
/// Only used by the `reels` module (compiled in `main.rs`, not `lib.rs`),
|
||||
/// so the `#[allow(dead_code)]` suppresses the lib-target warning.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) async fn run_readonly_tool_loop(
|
||||
&self,
|
||||
backend: &ResolvedBackend,
|
||||
|
||||
@@ -13,9 +13,6 @@
|
||||
//! is request-scoped and stays in `ResolvedBackend`. This is only the
|
||||
//! local stack: embeddings and offline single-shot generation.
|
||||
|
||||
// Constructed by binaries, not the server — dead code from main.rs's view.
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
@@ -26,11 +26,6 @@
|
||||
//! The pass operates on the database alone — no filesystem access —
|
||||
//! so it doesn't need the library availability gate.
|
||||
|
||||
// The lib doesn't call into this module directly — the watcher (in the
|
||||
// bin) does. Dead-code analysis at the lib level can't see that, so
|
||||
// suppress at the module level. Tests still exercise every function.
|
||||
#![allow(dead_code)]
|
||||
|
||||
use diesel::prelude::*;
|
||||
use diesel::sql_query;
|
||||
use diesel::sqlite::SqliteConnection;
|
||||
|
||||
+1
-2
@@ -1342,8 +1342,7 @@ pub struct RealFileSystem {
|
||||
}
|
||||
|
||||
impl RealFileSystem {
|
||||
#[allow(dead_code)] // Used in main.rs binary and tests
|
||||
pub(crate) fn new(base_path: String) -> RealFileSystem {
|
||||
pub fn new(base_path: String) -> RealFileSystem {
|
||||
RealFileSystem { base_path }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ extern crate diesel;
|
||||
|
||||
pub mod ai;
|
||||
pub mod auth;
|
||||
pub mod backfill;
|
||||
pub mod bin_progress;
|
||||
pub mod camera_tz;
|
||||
pub mod cleanup;
|
||||
@@ -25,6 +26,9 @@ pub mod file_types;
|
||||
pub mod filename_audit;
|
||||
pub mod files;
|
||||
pub mod geo;
|
||||
pub mod handlers;
|
||||
pub mod hls_stats;
|
||||
pub mod knowledge;
|
||||
pub mod libraries;
|
||||
pub mod library_maintenance;
|
||||
pub mod memories;
|
||||
@@ -33,6 +37,7 @@ pub mod parsers;
|
||||
pub mod perceptual_hash;
|
||||
pub mod personas;
|
||||
pub mod prefs;
|
||||
pub mod reels;
|
||||
pub mod service;
|
||||
pub mod state;
|
||||
pub mod tags;
|
||||
@@ -42,6 +47,7 @@ pub mod thumbnails;
|
||||
pub mod unified_search;
|
||||
pub mod utils;
|
||||
pub mod video;
|
||||
pub mod watcher;
|
||||
|
||||
// Re-export commonly used types
|
||||
pub use data::{Claims, ThumbnailRequest};
|
||||
|
||||
+14
-62
@@ -1,9 +1,7 @@
|
||||
//! The server binary. Everything it runs lives in the `image_api`
|
||||
//! library so the crate compiles once, shared with the `src/bin` tools.
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate diesel;
|
||||
extern crate rayon;
|
||||
|
||||
use actix_web::web::Data;
|
||||
use actix_web_prom::PrometheusMetricsBuilder;
|
||||
use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations};
|
||||
@@ -18,62 +16,16 @@ use actix_web::{App, HttpResponse, HttpServer, middleware, web};
|
||||
use diesel::sqlite::Sqlite;
|
||||
use std::error::Error;
|
||||
|
||||
use crate::ai::InsightGenerator;
|
||||
use crate::auth::login;
|
||||
use crate::data::*;
|
||||
use crate::database::*;
|
||||
use crate::files::{RealFileSystem, move_file};
|
||||
use crate::service::ServiceBuilder;
|
||||
use crate::state::AppState;
|
||||
use crate::tags::*;
|
||||
use image_api::ai::InsightGenerator;
|
||||
use image_api::auth::login;
|
||||
use image_api::database::*;
|
||||
use image_api::files::{RealFileSystem, move_file};
|
||||
use image_api::service::ServiceBuilder;
|
||||
use image_api::state::AppState;
|
||||
use image_api::tags::*;
|
||||
use image_api::*;
|
||||
use log::{error, info};
|
||||
|
||||
mod ai;
|
||||
mod auth;
|
||||
mod backfill;
|
||||
// Display-zone helpers land in the read-side cutover (#119/#120); the
|
||||
// binary's private copy of this module doesn't use them yet.
|
||||
#[allow(dead_code)]
|
||||
mod camera_tz;
|
||||
mod clip_search;
|
||||
mod clip_watch;
|
||||
mod content_hash;
|
||||
mod data;
|
||||
mod database;
|
||||
mod date_resolver;
|
||||
mod date_view;
|
||||
mod duplicates;
|
||||
mod error;
|
||||
mod exif;
|
||||
mod face_watch;
|
||||
mod faces;
|
||||
mod file_scan;
|
||||
mod file_types;
|
||||
mod files;
|
||||
mod geo;
|
||||
mod handlers;
|
||||
mod hls_stats;
|
||||
mod libraries;
|
||||
mod library_maintenance;
|
||||
mod perceptual_hash;
|
||||
mod state;
|
||||
mod tags;
|
||||
mod thumbnails;
|
||||
mod unified_search;
|
||||
mod utils;
|
||||
mod video;
|
||||
mod watcher;
|
||||
|
||||
mod knowledge;
|
||||
mod memories;
|
||||
mod otel;
|
||||
mod personas;
|
||||
mod prefs;
|
||||
mod reels;
|
||||
mod service;
|
||||
#[cfg(test)]
|
||||
mod testhelpers;
|
||||
|
||||
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
@@ -85,7 +37,7 @@ fn main() -> std::io::Result<()> {
|
||||
|
||||
// Recover orphaned insight generation jobs from a previous crash.
|
||||
{
|
||||
use crate::database::{InsightGenerationJobDao, SqliteInsightGenerationJobDao};
|
||||
use image_api::database::{InsightGenerationJobDao, SqliteInsightGenerationJobDao};
|
||||
let mut dao = SqliteInsightGenerationJobDao::new();
|
||||
match dao.recover_orphaned_jobs() {
|
||||
Ok(n) if n > 0 => {
|
||||
@@ -228,9 +180,9 @@ fn main() -> std::io::Result<()> {
|
||||
|
||||
// Spawn background job to generate daily conversation summaries
|
||||
{
|
||||
use crate::ai::generate_daily_summaries;
|
||||
use crate::database::{DailySummaryDao, SqliteDailySummaryDao};
|
||||
use chrono::NaiveDate;
|
||||
use image_api::ai::generate_daily_summaries;
|
||||
use image_api::database::{DailySummaryDao, SqliteDailySummaryDao};
|
||||
|
||||
// Configure date range for summary generation
|
||||
// Default: August 2024 ±30 days (July 1 - September 30, 2024)
|
||||
@@ -453,7 +405,7 @@ fn main() -> std::io::Result<()> {
|
||||
Box::new(database::SqlitePersonaDao::new()),
|
||||
)))
|
||||
.app_data::<Data<Mutex<faces::SqliteFaceDao>>>(Data::new(Mutex::new(face_dao)))
|
||||
.app_data::<Data<crate::ai::face_client::FaceClient>>(Data::new(
|
||||
.app_data::<Data<image_api::ai::face_client::FaceClient>>(Data::new(
|
||||
app_data.face_client.clone(),
|
||||
))
|
||||
.app_data(mp::form::MultipartFormConfig::default().total_limit(1024 * 1024 * 1024)) // 1GB upload limit
|
||||
|
||||
+2
-2
@@ -1045,7 +1045,7 @@ fn load_pregen_params(app_state: &AppState) -> (String, Option<String>, String)
|
||||
}
|
||||
|
||||
/// Spawn the nightly pre-generation scheduler. Runs behind `REEL_PREGEN_ENABLED`.
|
||||
pub(crate) async fn spawn_pregen_scheduler(app_state: web::Data<AppState>) {
|
||||
pub async fn spawn_pregen_scheduler(app_state: web::Data<AppState>) {
|
||||
if std::env::var("REEL_PREGEN_ENABLED").ok() != Some("1".to_string()) {
|
||||
log::info!("Reel pre-generation scheduler disabled (REEL_PREGEN_ENABLED != 1)");
|
||||
return;
|
||||
@@ -1270,7 +1270,7 @@ fn reel_cache_max_age_secs() -> u64 {
|
||||
/// Spawn the periodic on-disk reel-cache sweeper. Runs independently of the
|
||||
/// pre-gen scheduler because the on-demand cache grows whether or not pre-gen
|
||||
/// is enabled. Disable with `REEL_CACHE_SWEEP_ENABLED=0`.
|
||||
pub(crate) async fn spawn_reel_cache_sweeper(app_state: web::Data<AppState>) {
|
||||
pub async fn spawn_reel_cache_sweeper(app_state: web::Data<AppState>) {
|
||||
if std::env::var("REEL_CACHE_SWEEP_ENABLED").ok().as_deref() == Some("0") {
|
||||
log::info!("Reel cache sweeper disabled (REEL_CACHE_SWEEP_ENABLED=0)");
|
||||
return;
|
||||
|
||||
+3
-3
@@ -628,11 +628,11 @@ pub fn watch_files(
|
||||
// See database::reconcile and CLAUDE.md "Multi-library data
|
||||
// model" for the rules.
|
||||
{
|
||||
let mut conn = image_api::database::connect();
|
||||
let mut conn = crate::database::connect();
|
||||
if is_full_scan {
|
||||
library_maintenance::refresh_planner_stats(&mut conn);
|
||||
}
|
||||
let _ = image_api::database::reconcile::run(&mut conn);
|
||||
let _ = crate::database::reconcile::run(&mut conn);
|
||||
|
||||
// Back-ref refresh: hash-keyed rows whose
|
||||
// (library_id, rel_path) tuple no longer matches any
|
||||
@@ -721,7 +721,7 @@ pub fn process_new_files(
|
||||
// filters. See `file_scan` for why exclusion has to happen at WalkDir
|
||||
// time (filter_entry) rather than at face-detect time.
|
||||
let files: Vec<(PathBuf, String)> =
|
||||
image_api::file_scan::enumerate_indexable_files(base_path, excluded_dirs, modified_since);
|
||||
crate::file_scan::enumerate_indexable_files(base_path, excluded_dirs, modified_since);
|
||||
|
||||
if files.is_empty() {
|
||||
debug!("No files to process");
|
||||
|
||||
Reference in new issue
Block a user