diff --git a/src/banner/api.rs b/src/banner/api.rs index dba9221..34cdfac 100644 --- a/src/banner/api.rs +++ b/src/banner/api.rs @@ -7,7 +7,7 @@ use std::{ }; use crate::banner::{ - BannerSession, SessionPool, create_shared_rate_limiter_with_config, + BannerSession, SessionPool, create_shared_rate_limiter, errors::BannerApiError, json::parse_json_with_context, middleware::TransparentMiddleware, @@ -15,7 +15,7 @@ use crate::banner::{ nonce, query::SearchQuery, rate_limit_middleware::RateLimitMiddleware, - rate_limiter::{RateLimitConfig, SharedRateLimiter, create_shared_rate_limiter}, + rate_limiter::{RateLimitConfig, SharedRateLimiter}, util::user_agent, }; use anyhow::{Context, Result, anyhow}; @@ -35,6 +35,7 @@ pub struct BannerApi { base_url: String, } +#[allow(dead_code)] impl BannerApi { /// Creates a new Banner API client. pub fn new(base_url: String) -> Result { @@ -43,7 +44,7 @@ impl BannerApi { /// Creates a new Banner API client with custom rate limiting configuration. pub fn new_with_config(base_url: String, rate_limit_config: RateLimitConfig) -> Result { - let rate_limiter = create_shared_rate_limiter_with_config(rate_limit_config); + let rate_limiter = create_shared_rate_limiter(Some(rate_limit_config)); let http = ClientBuilder::new( Client::builder() diff --git a/src/banner/models/meetings.rs b/src/banner/models/meetings.rs index de423ae..80551d4 100644 --- a/src/banner/models/meetings.rs +++ b/src/banner/models/meetings.rs @@ -258,6 +258,7 @@ impl TimeRange { } /// Get duration in minutes + #[allow(dead_code)] pub fn duration_minutes(&self) -> i64 { let start_minutes = self.start.hour() as i64 * 60 + self.start.minute() as i64; let end_minutes = self.end.hour() as i64 * 60 + self.end.minute() as i64; @@ -302,6 +303,7 @@ impl DateRange { } /// Check if a specific date falls within this range + #[allow(dead_code)] pub fn contains_date(&self, date: NaiveDate) -> bool { date >= self.start && date <= self.end } diff --git a/src/banner/models/terms.rs b/src/banner/models/terms.rs index c131d8f..15b2866 100644 --- a/src/banner/models/terms.rs +++ b/src/banner/models/terms.rs @@ -147,11 +147,6 @@ impl Term { }, } } - - /// Returns a long string representation of the term (e.g., "Fall 2025") - pub fn to_long_string(&self) -> String { - format!("{} {}", self.season, self.year) - } } impl TermPoint { diff --git a/src/banner/query.rs b/src/banner/query.rs index 7fe0231..e8c8703 100644 --- a/src/banner/query.rs +++ b/src/banner/query.rs @@ -32,6 +32,7 @@ pub struct SearchQuery { course_number_range: Option, } +#[allow(dead_code)] impl SearchQuery { /// Creates a new SearchQuery with default values pub fn new() -> Self { diff --git a/src/banner/rate_limiter.rs b/src/banner/rate_limiter.rs index 0cac69a..7a9ae7b 100644 --- a/src/banner/rate_limiter.rs +++ b/src/banner/rate_limiter.rs @@ -61,7 +61,6 @@ pub struct BannerRateLimiter { search_limiter: RateLimiter, metadata_limiter: RateLimiter, reset_limiter: RateLimiter, - config: RateLimitConfig, } impl BannerRateLimiter { @@ -88,7 +87,6 @@ impl BannerRateLimiter { search_limiter: RateLimiter::direct(search_quota), metadata_limiter: RateLimiter::direct(metadata_quota), reset_limiter: RateLimiter::direct(reset_quota), - config, } } @@ -108,32 +106,6 @@ impl BannerRateLimiter { trace!(request_type = ?request_type, "Rate limit permission granted"); } - - /// Checks if a request of the given type would be allowed immediately - pub fn check_permission(&self, request_type: RequestType) -> bool { - let limiter = match request_type { - RequestType::Session => &self.session_limiter, - RequestType::Search => &self.search_limiter, - RequestType::Metadata => &self.metadata_limiter, - RequestType::Reset => &self.reset_limiter, - }; - - limiter.check().is_ok() - } - - /// Gets the current configuration - pub fn config(&self) -> &RateLimitConfig { - &self.config - } - - /// Updates the rate limit configuration - pub fn update_config(&mut self, config: RateLimitConfig) { - self.config = config; - // Note: In a production system, you'd want to recreate the limiters - // with the new configuration, but for simplicity we'll just update - // the config field here. - warn!("Rate limit configuration updated - restart required for full effect"); - } } impl Default for BannerRateLimiter { @@ -145,14 +117,9 @@ impl Default for BannerRateLimiter { /// A shared rate limiter instance pub type SharedRateLimiter = Arc; -/// Creates a new shared rate limiter with default configuration -pub fn create_shared_rate_limiter() -> SharedRateLimiter { - Arc::new(BannerRateLimiter::default()) -} - /// Creates a new shared rate limiter with custom configuration -pub fn create_shared_rate_limiter_with_config(config: RateLimitConfig) -> SharedRateLimiter { - Arc::new(BannerRateLimiter::new(config)) +pub fn create_shared_rate_limiter(config: Option) -> SharedRateLimiter { + Arc::new(BannerRateLimiter::new(config.unwrap_or_default())) } /// Conversion from config module's RateLimitingConfig to this module's RateLimitConfig diff --git a/src/data/models.rs b/src/data/models.rs index cbc3a28..aebc130 100644 --- a/src/data/models.rs +++ b/src/data/models.rs @@ -3,6 +3,7 @@ use chrono::{DateTime, Utc}; use serde_json::Value; +#[allow(dead_code)] #[derive(sqlx::FromRow, Debug, Clone)] pub struct Course { pub id: i32, @@ -18,6 +19,7 @@ pub struct Course { pub last_scraped_at: DateTime, } +#[allow(dead_code)] #[derive(sqlx::FromRow, Debug, Clone)] pub struct CourseMetric { pub id: i32, @@ -28,6 +30,7 @@ pub struct CourseMetric { pub seats_available: i32, } +#[allow(dead_code)] #[derive(sqlx::FromRow, Debug, Clone)] pub struct CourseAudit { pub id: i32, @@ -59,6 +62,7 @@ pub enum TargetType { } /// Represents a queryable job from the database. +#[allow(dead_code)] #[derive(sqlx::FromRow, Debug, Clone)] pub struct ScrapeJob { pub id: i32, diff --git a/src/main.rs b/src/main.rs index bab4545..d01c8ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -229,9 +229,7 @@ async fn main() { let app_state = AppState::new(banner_api_arc.clone(), db_pool.clone()); // Create BannerState for web service - let banner_state = BannerState { - api: banner_api_arc.clone(), - }; + let banner_state = BannerState {}; // Configure the client with your Discord bot token in the environment let intents = GatewayIntents::non_privileged(); diff --git a/src/scraper/jobs/mod.rs b/src/scraper/jobs/mod.rs index ca64c38..0396290 100644 --- a/src/scraper/jobs/mod.rs +++ b/src/scraper/jobs/mod.rs @@ -12,7 +12,6 @@ use std::fmt; pub enum JobParseError { InvalidJson(serde_json::Error), UnsupportedTargetType(TargetType), - MissingRequiredField(String), } impl fmt::Display for JobParseError { @@ -22,9 +21,6 @@ impl fmt::Display for JobParseError { JobParseError::UnsupportedTargetType(t) => { write!(f, "Unsupported target type: {:?}", t) } - JobParseError::MissingRequiredField(field) => { - write!(f, "Missing required field: {}", field) - } } } } @@ -67,6 +63,7 @@ impl std::error::Error for JobError { #[async_trait::async_trait] pub trait Job: Send + Sync { /// The target type this job handles + #[allow(dead_code)] fn target_type(&self) -> TargetType; /// Process the job with the given API client and database pool @@ -99,14 +96,9 @@ impl JobType { } /// Convert to a Job trait object - pub fn as_job(self) -> Box { + pub fn boxed(self) -> Box { match self { JobType::Subject(job) => Box::new(job), } } } - -/// Helper function to create a subject job -pub fn create_subject_job(subject: String) -> JobType { - JobType::Subject(subject::SubjectJob::new(subject)) -} diff --git a/src/scraper/worker.rs b/src/scraper/worker.rs index 8e8654d..9d7c987 100644 --- a/src/scraper/worker.rs +++ b/src/scraper/worker.rs @@ -135,7 +135,7 @@ impl Worker { .map_err(|e| JobError::Unrecoverable(anyhow::anyhow!(e)))?; // Parse errors are unrecoverable // Get the job implementation - let job_impl = job_type.as_job(); + let job_impl = job_type.boxed(); debug!( worker_id = self.id, diff --git a/src/web/routes.rs b/src/web/routes.rs index b41ffc1..75d9e19 100644 --- a/src/web/routes.rs +++ b/src/web/routes.rs @@ -11,7 +11,7 @@ use axum::{ use http::header; use serde::Serialize; use serde_json::{Value, json}; -use std::{collections::BTreeMap, sync::Arc, time::Duration}; +use std::{collections::BTreeMap, time::Duration}; use tower_http::timeout::TimeoutLayer; use tower_http::{ classify::ServerErrorsFailureClass, @@ -22,8 +22,6 @@ use tracing::{Span, debug, info, warn}; use crate::web::assets::{WebAssets, get_asset_metadata_cached}; -use crate::banner::BannerApi; - /// Set appropriate caching headers based on asset type fn set_caching_headers(response: &mut Response, path: &str, etag: &str) { let headers = response.headers_mut(); @@ -62,9 +60,7 @@ fn set_caching_headers(response: &mut Response, path: &str, etag: &str) { /// Shared application state for web server #[derive(Clone)] -pub struct BannerState { - pub api: Arc, -} +pub struct BannerState {} /// Creates the web server router pub fn create_router(state: BannerState) -> Router {