From d24d0a69538e1d99a6e8130be559d137f831364b Mon Sep 17 00:00:00 2001 From: Timothy Quilling Date: Fri, 14 Nov 2025 14:43:00 -0500 Subject: [PATCH] fix: lints --- .../operations/notifications.rs | 21 ++++++------ .../database_writer/operations/processor.rs | 2 +- consumer/src/database_writer/routing.rs | 2 +- consumer/src/database_writer/workers.rs | 4 +-- consumer/src/external/pg_notifications.rs | 2 +- consumer/src/indexer/conversion.rs | 6 ++-- consumer/src/relay/indexer.rs | 2 +- consumer/src/sources/jetstream/types.rs | 2 +- consumer/src/utils.rs | 2 +- .../src/workers/backfill/car_processing.rs | 2 +- consumer/src/workers/backfill/downloader.rs | 2 +- consumer/src/workers/backfill/mod.rs | 8 ++--- consumer/src/workers/backfill/ratelimit.rs | 4 +-- consumer/src/workers/backfill/types.rs | 14 ++++---- consumer/src/workers/fetch/mod.rs | 2 +- dataloader-rs/src/cached.rs | 2 +- parakeet-db/src/notifications.rs | 1 - parakeet-index/src/lib.rs | 2 +- parakeet-lexgen/src/types.rs | 34 +++++++++---------- parakeet-lexgen/src/validate.rs | 2 +- parakeet/src/admin/mod.rs | 6 ++-- parakeet/src/allowlist.rs | 4 +-- parakeet/src/db/search.rs | 4 +++ parakeet/src/db/states.rs | 6 ++-- parakeet/src/db/threads.rs | 2 +- parakeet/src/hydration/embed.rs | 2 +- parakeet/src/loaders/embed.rs | 2 +- parakeet/src/loaders/feed.rs | 7 ++-- parakeet/src/loaders/labeler.rs | 5 +-- parakeet/src/loaders/mod.rs | 4 +-- parakeet/src/loaders/post.rs | 6 ++-- parakeet/src/loaders/profile.rs | 4 +-- parakeet/src/main.rs | 2 +- parakeet/src/xrpc/app_bsky/bookmark.rs | 2 +- .../src/xrpc/app_bsky/feed/posts/feeds.rs | 2 +- .../src/xrpc/app_bsky/notification/mod.rs | 4 +-- parakeet/src/xrpc/app_bsky/unspecced/mod.rs | 2 +- .../unspecced/thread_v2/thread_builder.rs | 3 +- 38 files changed, 90 insertions(+), 93 deletions(-) diff --git a/consumer/src/database_writer/operations/notifications.rs b/consumer/src/database_writer/operations/notifications.rs index 01c93c28..072471a1 100644 --- a/consumer/src/database_writer/operations/notifications.rs +++ b/consumer/src/database_writer/operations/notifications.rs @@ -9,6 +9,7 @@ use super::DatabaseOperation; use chrono::{DateTime, Utc}; +use parakeet_db::notifications::reasons; /// Create a notification for a like /// @@ -35,10 +36,10 @@ pub fn create_like_notification( DatabaseOperation::InsertNotification { recipient_actor_id: post_author_actor_id, author_actor_id: liker_actor_id, - record_type: "like".to_string(), + record_type: reasons::LIKE.to_string(), record_rkey: like_rkey.to_string(), record_cid: cid.to_string(), - reason: "like".to_string(), + reason: reasons::LIKE.to_string(), subject_actor_id: Some(post_author_actor_id), subject_record_type: Some("post".to_string()), subject_rkey: Some(post_rkey.to_string()), @@ -71,10 +72,10 @@ pub fn create_repost_notification( DatabaseOperation::InsertNotification { recipient_actor_id: post_author_actor_id, author_actor_id: reposter_actor_id, - record_type: "repost".to_string(), + record_type: reasons::REPOST.to_string(), record_rkey: repost_rkey.to_string(), record_cid: cid.to_string(), - reason: "repost".to_string(), + reason: reasons::REPOST.to_string(), subject_actor_id: Some(post_author_actor_id), subject_record_type: Some("post".to_string()), subject_rkey: Some(post_rkey.to_string()), @@ -105,10 +106,10 @@ pub fn create_follow_notification( DatabaseOperation::InsertNotification { recipient_actor_id: target_actor_id, author_actor_id: follower_actor_id, - record_type: "follow".to_string(), + record_type: reasons::FOLLOW.to_string(), record_rkey: follow_rkey.to_string(), record_cid: cid.to_string(), - reason: "follow".to_string(), + reason: reasons::FOLLOW.to_string(), subject_actor_id: None, // Follows don't have a subject subject_record_type: None, subject_rkey: None, @@ -132,7 +133,7 @@ pub fn create_follow_notification( /// # Returns /// /// DatabaseOperation::InsertNotification for the reply -#[allow(clippy::too_many_arguments)] +#[expect(clippy::too_many_arguments, reason = "All parameters semantically required for reply notification")] pub fn create_reply_notification( reply_rkey: &str, replier_actor_id: i32, @@ -156,7 +157,7 @@ pub fn create_reply_notification( record_type: "post".to_string(), record_rkey: reply_rkey.to_string(), record_cid: cid.to_string(), - reason: "reply".to_string(), + reason: reasons::REPLY.to_string(), subject_actor_id: Some(subject_actor_id), subject_record_type: Some("post".to_string()), subject_rkey: Some(subject_rkey.to_string()), @@ -192,7 +193,7 @@ pub fn create_quote_notification( record_type: "post".to_string(), record_rkey: quote_rkey.to_string(), record_cid: cid.to_string(), - reason: "quote".to_string(), + reason: reasons::QUOTE.to_string(), subject_actor_id: Some(quoted_author_actor_id), subject_record_type: Some("post".to_string()), subject_rkey: Some(quoted_post_rkey.to_string()), @@ -228,7 +229,7 @@ pub fn create_mention_notifications( record_type: "post".to_string(), record_rkey: post_rkey.to_string(), record_cid: cid.to_string(), - reason: "mention".to_string(), + reason: reasons::MENTION.to_string(), subject_actor_id: Some(author_actor_id), // The post author (where they were mentioned) subject_record_type: Some("post".to_string()), subject_rkey: Some(post_rkey.to_string()), diff --git a/consumer/src/database_writer/operations/processor.rs b/consumer/src/database_writer/operations/processor.rs index 745b380a..6787cdd0 100644 --- a/consumer/src/database_writer/operations/processor.rs +++ b/consumer/src/database_writer/operations/processor.rs @@ -20,7 +20,7 @@ use ipld_core::cid::Cid; /// /// NOTE: With Jetstream server-side filtering, all events are from allowlisted DIDs. /// We always enqueue related posts (replies/quotes) for fetching to ensure completeness. -#[allow(clippy::too_many_arguments)] +#[expect(clippy::too_many_arguments, reason = "Comprehensive record processing requires multiple resolved IDs and metadata")] pub fn process_record_to_operations( repo: &str, actor_id: i32, diff --git a/consumer/src/database_writer/routing.rs b/consumer/src/database_writer/routing.rs index 206f2c2d..494c3964 100644 --- a/consumer/src/database_writer/routing.rs +++ b/consumer/src/database_writer/routing.rs @@ -100,7 +100,7 @@ pub struct WorkerPools { impl WorkerPools { /// Create a new WorkerPools with the provided worker senders - #[allow(clippy::too_many_arguments)] + #[expect(clippy::too_many_arguments, reason = "Constructor mirrors 15 worker pool structure (3 sources × 5 types)")] pub fn new( jetstream_actor: Vec>, jetstream_like: Vec>, diff --git a/consumer/src/database_writer/workers.rs b/consumer/src/database_writer/workers.rs index 694f352b..b3337230 100644 --- a/consumer/src/database_writer/workers.rs +++ b/consumer/src/database_writer/workers.rs @@ -158,7 +158,7 @@ async fn extract_and_resolve_references( /// - Updates counters and metrics /// /// Workers are already specialized by source, so no priority management needed. -#[allow(clippy::too_many_arguments)] +#[expect(clippy::too_many_arguments, reason = "Dispatcher requires multiple shared state components")] fn spawn_source_dispatcher( name: &'static str, source: super::EventSource, @@ -265,7 +265,7 @@ fn spawn_source_dispatcher( /// /// Cursors are batched and saved to PostgreSQL every 10 seconds. /// In-memory cursor is updated immediately for accurate logging. -#[allow(clippy::too_many_arguments)] +#[expect(clippy::too_many_arguments, reason = "Database writer requires extensive configuration state")] pub fn spawn_database_writer( pool: Pool, index_tx: tokio::sync::mpsc::Sender, diff --git a/consumer/src/external/pg_notifications.rs b/consumer/src/external/pg_notifications.rs index 55be5106..e49e687b 100644 --- a/consumer/src/external/pg_notifications.rs +++ b/consumer/src/external/pg_notifications.rs @@ -26,7 +26,7 @@ use eyre::Result; /// * `subject_record_type` - Optional: type of subject record /// * `subject_rkey` - Optional: rkey of subject record /// * `indexed_at` - When the notification was created -#[allow(clippy::too_many_arguments)] +#[expect(clippy::too_many_arguments, reason = "Mirrors notification table schema structure")] pub async fn add_notification( pool: &deadpool_postgres::Pool, recipient_actor_id: i32, diff --git a/consumer/src/indexer/conversion.rs b/consumer/src/indexer/conversion.rs index 5a6cc6b6..9aa4e20f 100644 --- a/consumer/src/indexer/conversion.rs +++ b/consumer/src/indexer/conversion.rs @@ -5,7 +5,7 @@ use ipld_core::cid::Cid; use serde_bytes::ByteBuf; /// Convert a Jetstream commit event to an internal commit event (worker version) -#[allow(clippy::too_many_lines)] +#[expect(clippy::too_many_lines, reason = "Comprehensive handling of all Jetstream operation types")] pub fn convert_jetstream_commit_worker( commit_event: &crate::sources::jetstream::CommitEvent, ) -> Option { @@ -159,9 +159,9 @@ pub fn convert_jetstream_commit_worker( since: None, // Jetstream doesn't provide this blocks: ByteBuf::new(), // Fields are deprecated but still required by struct - #[allow(deprecated)] + #[expect(deprecated, reason = "Required by legacy AtpCommitEvent structure")] too_big: false, - #[allow(deprecated)] + #[expect(deprecated, reason = "Required by legacy AtpCommitEvent structure")] blobs: vec![], prev_data: None, // Jetstream doesn't provide prev_cid }; diff --git a/consumer/src/relay/indexer.rs b/consumer/src/relay/indexer.rs index 8b36636a..f582696c 100644 --- a/consumer/src/relay/indexer.rs +++ b/consumer/src/relay/indexer.rs @@ -694,7 +694,7 @@ pub struct RelayIndexerFactory { } impl RelayIndexerFactory { - #[allow(clippy::too_many_arguments)] + #[expect(clippy::too_many_arguments, reason = "Factory constructor mirrors RelayIndexer configuration")] pub fn new( pool: Pool, consumer_opts: RelayIndexerOpts, diff --git a/consumer/src/sources/jetstream/types.rs b/consumer/src/sources/jetstream/types.rs index dc7f3308..10ab6ef0 100644 --- a/consumer/src/sources/jetstream/types.rs +++ b/consumer/src/sources/jetstream/types.rs @@ -186,7 +186,7 @@ pub struct JetstreamError { /// Options for filtering events from Jetstream #[derive(Debug, Clone, Serialize)] -#[allow(non_snake_case)] +#[expect(non_snake_case, reason = "External Jetstream API requires camelCase field names")] pub struct SubscriberOptions { #[serde(skip_serializing_if = "Option::is_none")] pub wantedCollections: Option>, diff --git a/consumer/src/utils.rs b/consumer/src/utils.rs index 8bc02fd3..e5f5b9c4 100644 --- a/consumer/src/utils.rs +++ b/consumer/src/utils.rs @@ -9,7 +9,7 @@ pub fn safe_string<'de, D: Deserializer<'de>>(deserializer: D) -> Result) -> Option { blob.map(|blob| blob.cid.to_string()) } diff --git a/consumer/src/workers/backfill/car_processing.rs b/consumer/src/workers/backfill/car_processing.rs index b8c29c45..7d08313b 100644 --- a/consumer/src/workers/backfill/car_processing.rs +++ b/consumer/src/workers/backfill/car_processing.rs @@ -16,7 +16,7 @@ pub struct RecordWithMetadata { pub cid: Cid, pub path: String, // collection/rkey pub record: RecordTypes, - #[allow(dead_code)] + #[expect(dead_code, reason = "Reserved for future timestamp-based filtering")] pub created_at: Option, // microseconds since epoch } diff --git a/consumer/src/workers/backfill/downloader.rs b/consumer/src/workers/backfill/downloader.rs index 3d79e670..098db1cc 100644 --- a/consumer/src/workers/backfill/downloader.rs +++ b/consumer/src/workers/backfill/downloader.rs @@ -83,7 +83,7 @@ pub struct DownloaderConfig { /// /// Polls the backfill queue, resolves DIDs, checks allowlist, and dispatches /// download jobs to worker threads. -#[allow(clippy::too_many_lines)] +#[expect(clippy::too_many_lines, reason = "Sequential orchestration logic for job processing")] pub async fn downloader(config: DownloaderConfig) { let mut rc = config.redis; let pool = config.pool; diff --git a/consumer/src/workers/backfill/mod.rs b/consumer/src/workers/backfill/mod.rs index 28fab56f..b739dd75 100644 --- a/consumer/src/workers/backfill/mod.rs +++ b/consumer/src/workers/backfill/mod.rs @@ -39,14 +39,14 @@ pub struct BackfillManagerInner { pub struct BackfillManager { pool: Pool, - #[allow(dead_code)] + #[expect(dead_code, reason = "Stored for potential future use in diagnostics")] resolver: Arc, semaphore: Arc, - #[allow(dead_code)] + #[expect(dead_code, reason = "Configuration stored for future extensibility")] opts: BackfillConfig, inner: BackfillManagerInner, event_tx: tokio::sync::mpsc::Sender, - #[allow(dead_code)] + #[expect(dead_code, reason = "Stored for future timestamp-based filtering features")] retention_cutoff: Option>, } @@ -374,7 +374,7 @@ async fn backfill_actor_streaming( // The dequeue() function automatically recovers stale processing jobs and schedules retries. // Failed jobs are marked with 'failed.retry' status and scheduled_at timestamp for next attempt. -#[allow(dead_code)] +#[expect(dead_code, reason = "Infrastructure for future PDS health monitoring")] async fn check_pds_repo_status( client: &Client, pds: &str, diff --git a/consumer/src/workers/backfill/ratelimit.rs b/consumer/src/workers/backfill/ratelimit.rs index 2c048565..193b5e19 100644 --- a/consumer/src/workers/backfill/ratelimit.rs +++ b/consumer/src/workers/backfill/ratelimit.rs @@ -4,7 +4,7 @@ use reqwest::header::HeaderMap; /// /// Currently disabled - rate limiting is not implemented. /// This could be reimplemented with PostgreSQL-based rate limit tracking in the future. -#[allow(dead_code)] +#[expect(dead_code, reason = "Infrastructure for future rate limiting feature")] pub async fn enforce_ratelimit(_pds: &str) -> eyre::Result<()> { // Rate limiting is currently disabled Ok(()) @@ -13,7 +13,7 @@ pub async fn enforce_ratelimit(_pds: &str) -> eyre::Result<()> { /// Extract an integer value from an HTTP header /// /// Common use case is extracting rate limit headers like "ratelimit-remaining" or "ratelimit-reset" -#[allow(dead_code)] +#[expect(dead_code, reason = "Infrastructure for future rate limiting feature")] pub fn header_to_int(headers: &HeaderMap, name: &str) -> Option { let v = headers.get(name).and_then(|v| v.to_str().ok())?; v.parse().ok() diff --git a/consumer/src/workers/backfill/types.rs b/consumer/src/workers/backfill/types.rs index 042009dc..3e2d1d36 100644 --- a/consumer/src/workers/backfill/types.rs +++ b/consumer/src/workers/backfill/types.rs @@ -17,7 +17,7 @@ pub enum CarEntry { #[derive(Debug, Deserialize)] pub struct CarMstEntry { /// Left pointer (required for deserialization) - #[expect(dead_code)] + #[expect(dead_code, reason = "Required by CBOR format spec")] pub l: Option, /// Entry nodes pub e: Vec, @@ -30,7 +30,7 @@ pub struct CarMstEntryNode { pub k: ByteBuf, pub v: Cid, /// Tree pointer (required for deserialization) - #[expect(dead_code)] + #[expect(dead_code, reason = "Required by CBOR format spec")] pub t: Option, } @@ -39,20 +39,20 @@ pub struct CarMstEntryNode { #[derive(Debug, Deserialize)] pub struct CarCommitEntry { /// DID of the repository owner (required for deserialization) - #[expect(dead_code)] + #[expect(dead_code, reason = "Required by CBOR format spec")] pub did: String, /// Repository version (required for deserialization) - #[expect(dead_code)] + #[expect(dead_code, reason = "Required by CBOR format spec")] pub version: i32, /// CID of the MST root pub data: Cid, /// Repository revision string pub rev: String, /// Previous commit CID (required for deserialization) - #[expect(dead_code)] + #[expect(dead_code, reason = "Required by CBOR format spec")] pub prev: Option, /// Commit signature (required for deserialization) - #[expect(dead_code)] + #[expect(dead_code, reason = "Required by CBOR format spec")] pub sig: ByteBuf, } @@ -69,7 +69,7 @@ pub enum CarRecordEntry { /// Response from com.atproto.sync.getRepoStatus /// Fields marked dead_code are required for JSON deserialization but not directly accessed #[derive(Debug, Deserialize)] -#[allow(dead_code)] +#[expect(dead_code, reason = "Required by JSON format spec")] pub struct GetRepoStatusRes { /// DID of the repository (required for deserialization) pub did: String, diff --git a/consumer/src/workers/fetch/mod.rs b/consumer/src/workers/fetch/mod.rs index c7d103ab..3fc0097c 100644 --- a/consumer/src/workers/fetch/mod.rs +++ b/consumer/src/workers/fetch/mod.rs @@ -187,7 +187,7 @@ mod tests { use did_resolver::ResolverOpts; #[tokio::test] - #[allow(clippy::print_stdout)] + #[expect(clippy::print_stdout, reason = "Test code uses println! for diagnostic output")] async fn test_fetch_and_parse_profile() { let config = RecordFetchConfig { slingshot_url: "https://slingshot.microcosm.blue".to_owned(), diff --git a/dataloader-rs/src/cached.rs b/dataloader-rs/src/cached.rs index 40cc577a..f1bce03c 100644 --- a/dataloader-rs/src/cached.rs +++ b/dataloader-rs/src/cached.rs @@ -92,7 +92,7 @@ where } } -#[allow(clippy::implicit_hasher)] +#[allow(clippy::implicit_hasher, reason = "Vendored crate - default HashMap hasher is appropriate")] impl Loader> where K: Eq + Hash + Clone + Debug, diff --git a/parakeet-db/src/notifications.rs b/parakeet-db/src/notifications.rs index e9379500..c843e89c 100644 --- a/parakeet-db/src/notifications.rs +++ b/parakeet-db/src/notifications.rs @@ -105,7 +105,6 @@ pub struct NotificationState { } /// Notification reason types -#[allow(dead_code)] pub mod reasons { pub const LIKE: &str = "like"; pub const REPOST: &str = "repost"; diff --git a/parakeet-index/src/lib.rs b/parakeet-index/src/lib.rs index df212566..4254a6a3 100644 --- a/parakeet-index/src/lib.rs +++ b/parakeet-index/src/lib.rs @@ -1,4 +1,4 @@ -#[allow(clippy::all)] +#[allow(clippy::all, reason = "Generated gRPC/protobuf code from tonic")] pub mod index { tonic::include_proto!("parakeet"); } diff --git a/parakeet-lexgen/src/types.rs b/parakeet-lexgen/src/types.rs index 658e4314..3b5d1ec9 100644 --- a/parakeet-lexgen/src/types.rs +++ b/parakeet-lexgen/src/types.rs @@ -1,7 +1,7 @@ use serde::Deserialize; use std::collections::BTreeMap; -#[expect(dead_code)] +#[expect(dead_code, reason = "Lexicon type used for parsing AT Protocol lexicon schemas")] #[derive(Debug, Deserialize)] pub struct Lexicon { /// Lexicon language version @@ -13,7 +13,7 @@ pub struct Lexicon { pub defs: BTreeMap, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Enum variants used for lexicon definition deserialization")] #[derive(Debug, Deserialize)] #[serde(tag = "type")] #[serde(rename_all = "lowercase")] @@ -28,7 +28,7 @@ pub enum LexiconDef { Token { description: Option }, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Schema variants used for AT Protocol type definitions")] #[derive(Debug, Deserialize)] #[serde(tag = "type")] #[serde(rename_all = "kebab-case")] @@ -81,7 +81,7 @@ pub enum RKey { Any, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Used for AT Protocol lexicon schema deserialization")] #[derive(Debug, Deserialize)] #[serde(untagged)] pub enum RecordKey { @@ -105,7 +105,7 @@ pub enum StringFormats { Language, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Used for AT Protocol lexicon schema deserialization")] #[derive(Debug, Deserialize)] pub struct HttpApiExchange { pub description: Option, @@ -113,21 +113,21 @@ pub struct HttpApiExchange { pub schema: Option, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Used for AT Protocol lexicon schema deserialization")] #[derive(Debug, Deserialize)] pub struct LexiconError { pub name: String, pub description: Option, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Used for AT Protocol lexicon schema deserialization")] #[derive(Debug, Deserialize)] pub struct LexiconSubMessage { pub description: Option, pub schema: Option, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Used for AT Protocol lexicon schema deserialization")] #[derive(Debug, Deserialize)] pub struct LexiconRecord { pub description: Option, @@ -135,7 +135,7 @@ pub struct LexiconRecord { pub record: LexiconObject, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Used for AT Protocol lexicon schema deserialization")] #[derive(Debug, Deserialize)] pub struct LexiconQuery { pub description: Option, @@ -144,7 +144,7 @@ pub struct LexiconQuery { pub errors: Option>, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Used for AT Protocol lexicon schema deserialization")] #[derive(Debug, Deserialize)] pub struct LexiconProcedure { pub description: Option, @@ -154,7 +154,7 @@ pub struct LexiconProcedure { pub errors: Option>, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Used for AT Protocol lexicon schema deserialization")] #[derive(Debug, Deserialize)] pub struct LexiconSubscription { pub description: Option, @@ -163,7 +163,7 @@ pub struct LexiconSubscription { pub errors: Option>, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Used for AT Protocol lexicon schema deserialization")] #[derive(Debug, Deserialize)] pub struct LexiconInteger { pub description: Option, @@ -177,7 +177,7 @@ pub struct LexiconInteger { pub constant: Option, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Used for AT Protocol lexicon schema deserialization")] #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct LexiconString { @@ -199,7 +199,7 @@ pub struct LexiconString { pub constant: Option, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Used for AT Protocol lexicon schema deserialization")] #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct LexiconArray { @@ -210,7 +210,7 @@ pub struct LexiconArray { pub items: Box, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Used for AT Protocol lexicon schema deserialization")] #[derive(Debug, Deserialize)] #[serde(tag = "type")] #[serde(rename = "object")] @@ -221,7 +221,7 @@ pub struct LexiconObject { pub nullable: Option>, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Used for AT Protocol lexicon schema deserialization")] #[derive(Debug, Deserialize)] #[serde(tag = "type")] #[serde(rename = "params")] @@ -230,7 +230,7 @@ pub struct LexiconParams { pub properties: BTreeMap, } -#[expect(dead_code)] +#[expect(dead_code, reason = "Used for AT Protocol lexicon schema deserialization")] #[derive(Debug, Deserialize)] #[serde(tag = "type")] #[serde(rename = "union")] diff --git a/parakeet-lexgen/src/validate.rs b/parakeet-lexgen/src/validate.rs index ae657b46..f151f756 100644 --- a/parakeet-lexgen/src/validate.rs +++ b/parakeet-lexgen/src/validate.rs @@ -4,7 +4,7 @@ use crate::types::{ }; use std::collections::BTreeMap; -#[expect(dead_code)] +#[expect(dead_code, reason = "Error type for future lexicon validation functionality")] #[derive(Debug)] pub enum ValidationError { InvalidReference(String), diff --git a/parakeet/src/admin/mod.rs b/parakeet/src/admin/mod.rs index 758e21fb..5a6ae8ec 100644 --- a/parakeet/src/admin/mod.rs +++ b/parakeet/src/admin/mod.rs @@ -167,7 +167,7 @@ struct AllowlistAndBackfillRequest { /// Whether to reset the repo_rev (forces full re-download) /// Defaults to true for new allowlist additions #[serde(default = "default_reset_repo_rev")] - #[allow(dead_code)] + #[expect(dead_code, reason = "reset_repo_rev accepted for API compatibility but backfill reset logic not yet implemented")] reset_repo_rev: bool, } @@ -196,7 +196,7 @@ struct BackfillRequest { dids: Vec, /// Whether to reset the repo_rev (forces full re-download) #[serde(default)] - #[allow(dead_code)] + #[expect(dead_code, reason = "reset_repo_rev accepted for API compatibility but backfill reset logic not yet implemented")] reset_repo_rev: bool, } @@ -396,7 +396,7 @@ async fn check_actor_exists( use diesel::sql_types::{Bool, Text}; #[derive(diesel::QueryableByName)] - #[allow(unused_qualifications)] + #[allow(unused_qualifications, reason = "Diesel QueryableByName macro generates unnecessary qualifications")] struct ExistsResult { #[diesel(sql_type = Bool)] exists: bool, diff --git a/parakeet/src/allowlist.rs b/parakeet/src/allowlist.rs index 246c45de..95d97c69 100644 --- a/parakeet/src/allowlist.rs +++ b/parakeet/src/allowlist.rs @@ -13,7 +13,7 @@ use tracing::debug; /// Raw database model for allowlist entries from SQL queries #[derive(Debug, QueryableByName)] #[diesel(check_for_backend(diesel::pg::Pg))] -#[allow(unused_qualifications)] +#[allow(unused_qualifications, reason = "Diesel QueryableByName macro generates unnecessary qualifications")] pub struct AllowlistEntryRaw { #[diesel(sql_type = Integer)] pub id: i32, @@ -139,7 +139,7 @@ pub async fn is_allowed(conn: &mut AsyncPgConnection, did: &str) -> QueryResult< }; #[derive(QueryableByName)] - #[allow(unused_qualifications)] + #[allow(unused_qualifications, reason = "Diesel QueryableByName macro generates unnecessary qualifications")] struct ExistsResult { #[diesel(sql_type = Bool)] exists: bool, diff --git a/parakeet/src/db/search.rs b/parakeet/src/db/search.rs index c4dec8ea..fdfed792 100644 --- a/parakeet/src/db/search.rs +++ b/parakeet/src/db/search.rs @@ -7,6 +7,7 @@ use diesel_async::{AsyncPgConnection, RunQueryDsl}; /// Result type for starter pack search with ranking #[derive(QueryableByName, Debug)] #[diesel(check_for_backend(diesel::pg::Pg))] +#[allow(unused_qualifications, reason = "Diesel QueryableByName macro generates unnecessary qualifications")] pub struct StarterPackSearchResult { #[diesel(sql_type = Text)] pub uri: String, @@ -64,6 +65,7 @@ pub async fn search_starter_packs( /// Result type for full actor search with ranking #[derive(QueryableByName, Debug)] #[diesel(check_for_backend(diesel::pg::Pg))] +#[allow(unused_qualifications, reason = "Diesel QueryableByName macro generates unnecessary qualifications")] pub struct ActorSearchResult { #[diesel(sql_type = Text)] pub did: String, @@ -74,6 +76,7 @@ pub struct ActorSearchResult { /// Result type for typeahead search with priority #[derive(QueryableByName, Debug)] #[diesel(check_for_backend(diesel::pg::Pg))] +#[allow(unused_qualifications, reason = "Diesel QueryableByName macro generates unnecessary qualifications")] pub struct ActorTypeaheadResult { #[diesel(sql_type = Text)] pub did: String, @@ -165,6 +168,7 @@ pub async fn search_actors_typeahead( /// Result type for post search with ranking #[derive(QueryableByName, Debug)] #[diesel(check_for_backend(diesel::pg::Pg))] +#[allow(unused_qualifications, reason = "Diesel QueryableByName macro generates unnecessary qualifications")] pub struct PostSearchResult { #[diesel(sql_type = Text)] pub uri: String, diff --git a/parakeet/src/db/states.rs b/parakeet/src/db/states.rs index 4d7ac3f9..4396107c 100644 --- a/parakeet/src/db/states.rs +++ b/parakeet/src/db/states.rs @@ -7,7 +7,7 @@ use diesel_async::AsyncPgConnection; #[derive(Clone, Debug, QueryableByName)] #[diesel(check_for_backend(diesel::pg::Pg))] -#[allow(unused_qualifications)] +#[allow(unused_qualifications, reason = "Diesel QueryableByName macro generates unnecessary qualifications")] pub struct ProfileStateRet { #[diesel(sql_type = Text)] pub did: String, @@ -88,7 +88,7 @@ pub async fn get_profile_states( #[derive(Clone, Debug, QueryableByName)] #[diesel(check_for_backend(diesel::pg::Pg))] -#[allow(unused_qualifications)] +#[allow(unused_qualifications, reason = "Diesel QueryableByName macro generates unnecessary qualifications")] pub struct PostStateRet { #[diesel(sql_type = Text)] pub did: String, @@ -200,7 +200,7 @@ pub async fn get_post_states( #[derive(Clone, Debug, QueryableByName)] #[diesel(check_for_backend(diesel::pg::Pg))] -#[allow(unused_qualifications)] +#[allow(unused_qualifications, reason = "Diesel QueryableByName macro generates unnecessary qualifications")] pub struct ListStateRet { #[diesel(sql_type = Text)] pub list_did: String, diff --git a/parakeet/src/db/threads.rs b/parakeet/src/db/threads.rs index f2fc7d79..9d5abda6 100644 --- a/parakeet/src/db/threads.rs +++ b/parakeet/src/db/threads.rs @@ -6,7 +6,7 @@ use diesel_async::{AsyncPgConnection, RunQueryDsl}; #[derive(Debug, QueryableByName)] #[diesel(check_for_backend(diesel::pg::Pg))] -#[allow(unused)] +#[allow(unused, reason = "ThreadItem fields populated by SQL query and accessed via public API")] pub struct ThreadItem { #[diesel(sql_type = Text)] pub at_uri: String, diff --git a/parakeet/src/hydration/embed.rs b/parakeet/src/hydration/embed.rs index 23f4d812..ba81f846 100644 --- a/parakeet/src/hydration/embed.rs +++ b/parakeet/src/hydration/embed.rs @@ -27,7 +27,7 @@ fn build_record_view(post: PostView) -> RecordView { } } -#[allow(clippy::unreachable)] +#[expect(clippy::unreachable, reason = "EmbedLoaderRet::Record variants handled separately before calling this function")] fn build_embed(embed: EmbedLoaderRet, did: &str, cdn: &BskyCdn) -> Embed { match embed { EmbedLoaderRet::Images(images) => Embed::Images { diff --git a/parakeet/src/loaders/embed.rs b/parakeet/src/loaders/embed.rs index 652533e1..59daeb95 100644 --- a/parakeet/src/loaders/embed.rs +++ b/parakeet/src/loaders/embed.rs @@ -106,6 +106,7 @@ impl BatchFn for EmbedLoader { let query = build_embeds_batch_query(); #[derive(diesel::QueryableByName)] + #[allow(dead_code, reason = "Diesel QueryableByName requires all SQL columns; embedded_record_id used only for SQL joins")] struct EmbedRow { #[diesel(sql_type = diesel::sql_types::Text)] author_did: String, @@ -147,7 +148,6 @@ impl BatchFn for EmbedLoader { #[diesel(sql_type = diesel::sql_types::Nullable)] record_post_id: Option, #[diesel(sql_type = diesel::sql_types::Nullable)] - #[allow(dead_code)] embedded_record_id: Option, #[diesel(sql_type = diesel::sql_types::Nullable)] record_detached: Option, diff --git a/parakeet/src/loaders/feed.rs b/parakeet/src/loaders/feed.rs index 864ce15b..798fa28d 100644 --- a/parakeet/src/loaders/feed.rs +++ b/parakeet/src/loaders/feed.rs @@ -53,10 +53,7 @@ pub fn build_feedgens_batch_query() -> &'static str { AND f.status = 'complete'" } -pub struct FeedGenLoader( - pub(super) Pool, - #[expect(dead_code)] pub(super) parakeet_index::Client, -); +pub struct FeedGenLoader(pub(super) Pool); impl BatchFn for FeedGenLoader { async fn load(&mut self, keys: &[String]) -> HashMap { let mut conn = self.0.get().await.unwrap(); @@ -150,7 +147,7 @@ pub struct LikeLoader( pub(super) std::sync::Arc, ); impl BatchFn for LikeLoader { - #[allow(clippy::redundant_closure_for_method_calls)] + #[expect(clippy::redundant_closure_for_method_calls, reason = "Closure provides better error context in filter_map chain")] async fn load(&mut self, keys: &[String]) -> HashMap { if keys.is_empty() { return HashMap::new(); diff --git a/parakeet/src/loaders/labeler.rs b/parakeet/src/loaders/labeler.rs index 1ce32650..aeb38940 100644 --- a/parakeet/src/loaders/labeler.rs +++ b/parakeet/src/loaders/labeler.rs @@ -74,10 +74,7 @@ pub struct EnrichedLabeler { pub created_at: chrono::DateTime, } -pub struct LabelServiceLoader( - pub(super) Pool, - #[expect(dead_code)] pub(super) parakeet_index::Client, -); +pub struct LabelServiceLoader(pub(super) Pool); pub type LabelServiceLoaderRet = (EnrichedLabeler, Vec); impl BatchFn for LabelServiceLoader { async fn load(&mut self, keys: &[String]) -> HashMap { diff --git a/parakeet/src/loaders/mod.rs b/parakeet/src/loaders/mod.rs index 0afc81f2..3d5de393 100644 --- a/parakeet/src/loaders/mod.rs +++ b/parakeet/src/loaders/mod.rs @@ -100,8 +100,8 @@ impl Dataloaders { // 1 hour TTL, 50k capacity for profiles profile: new_plc_loader(ProfileLoader(pool.clone()), "profile:", 3600, 50_000), // 1 hour TTL, 10k capacity for feeds/lists/etc - feedgen: new_plc_loader(FeedGenLoader(pool.clone(), idxc.clone()), "feedgen:", 3600, 10_000), - labeler: new_plc_loader(LabelServiceLoader(pool.clone(), idxc.clone()), "labeler:", 3600, 10_000), + feedgen: new_plc_loader(FeedGenLoader(pool.clone()), "feedgen:", 3600, 10_000), + labeler: new_plc_loader(LabelServiceLoader(pool.clone()), "labeler:", 3600, 10_000), list: new_plc_loader(ListLoader(pool.clone()), "list:", 3600, 10_000), starterpacks: new_plc_loader(StarterPackLoader(pool.clone()), "starterpacks:", 3600, 10_000), verification: new_plc_loader(VerificationLoader(pool.clone()), "verification:", 3600, 10_000), diff --git a/parakeet/src/loaders/post.rs b/parakeet/src/loaders/post.rs index cc6766ea..bec2b5d4 100644 --- a/parakeet/src/loaders/post.rs +++ b/parakeet/src/loaders/post.rs @@ -112,8 +112,8 @@ pub fn build_threadgates_batch_query() -> &'static str { } /// Facet data loaded from database +#[allow(dead_code, reason = "facet_index used for SQL ordering but not in reconstruction logic")] struct FacetData { - #[allow(dead_code)] facet_index: i16, byte_start: i32, byte_end: i32, @@ -124,7 +124,7 @@ struct FacetData { } /// Reconstruct AT Protocol post record JSON from decomposed database fields -#[allow(clippy::too_many_arguments)] +#[expect(clippy::too_many_arguments, reason = "AT Protocol post record builder requires all decomposed database fields")] fn build_post_record( content: &Option, langs: &[parakeet_db::types::LanguageCode], @@ -332,7 +332,7 @@ impl BatchFn for PostLoader { // Define a struct to capture the SQL results #[derive(diesel::QueryableByName)] - #[allow(dead_code)] + #[allow(dead_code, reason = "Diesel QueryableByName requires all SQL columns even if unused")] struct PostWithComputed { // Actual fields from posts table #[diesel(sql_type = diesel::sql_types::BigInt)] diff --git a/parakeet/src/loaders/profile.rs b/parakeet/src/loaders/profile.rs index 0f31f363..199d3316 100644 --- a/parakeet/src/loaders/profile.rs +++ b/parakeet/src/loaders/profile.rs @@ -75,7 +75,7 @@ pub struct EnrichedStatus { } /// Reconstruct AT Protocol status record JSON from decomposed database fields -#[allow(clippy::too_many_arguments)] +#[expect(clippy::too_many_arguments, reason = "AT Protocol status record builder requires all decomposed database fields")] fn build_status_record( status_type: ¶keet_db::types::StatusType, duration: &Option, @@ -184,6 +184,7 @@ impl BatchFn for ProfileLoader { let dids: Vec<&str> = keys.iter().map(|s| s.as_str()).collect(); #[derive(diesel::QueryableByName)] + #[allow(dead_code, reason = "Diesel QueryableByName requires all SQL columns even if unused")] struct ActorRow { #[diesel(sql_type = diesel::sql_types::Text)] did: String, @@ -192,7 +193,6 @@ impl BatchFn for ProfileLoader { #[diesel(sql_type = diesel::sql_types::Nullable)] account_created_at: Option>, #[diesel(sql_type = parakeet_db::schema::sql_types::ActorSyncState)] - #[allow(dead_code)] sync_state: parakeet_db::types::ActorSyncState, #[diesel(sql_type = diesel::sql_types::Nullable)] actor_id: Option, diff --git a/parakeet/src/main.rs b/parakeet/src/main.rs index b2c2a832..ef6d4f6f 100644 --- a/parakeet/src/main.rs +++ b/parakeet/src/main.rs @@ -78,7 +78,7 @@ async fn main() -> eyre::Result<()> { let cdn = Arc::new(xrpc::cdn::BskyCdn::new(conf.cdn.base, conf.cdn.video_base)); - #[allow(unused)] + #[expect(unused, reason = "TRUSTED_VERIFIERS is infrastructure for future verification feature")] hydration::TRUSTED_VERIFIERS.set(conf.trusted_verifiers); // Initialize shared HTTP client with connection pooling diff --git a/parakeet/src/xrpc/app_bsky/bookmark.rs b/parakeet/src/xrpc/app_bsky/bookmark.rs index 3a024405..4f18d6af 100644 --- a/parakeet/src/xrpc/app_bsky/bookmark.rs +++ b/parakeet/src/xrpc/app_bsky/bookmark.rs @@ -15,7 +15,7 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Deserialize)] pub struct CreateBookmarkReq { pub uri: String, - #[allow(dead_code)] + #[expect(dead_code, reason = "CID required for XRPC API spec but not used in server-side bookmark creation")] pub cid: String, } diff --git a/parakeet/src/xrpc/app_bsky/feed/posts/feeds.rs b/parakeet/src/xrpc/app_bsky/feed/posts/feeds.rs index 86a126a0..9d9131cd 100644 --- a/parakeet/src/xrpc/app_bsky/feed/posts/feeds.rs +++ b/parakeet/src/xrpc/app_bsky/feed/posts/feeds.rs @@ -155,7 +155,7 @@ pub async fn get_feed( #[derive(Debug, Default, Eq, PartialEq, Deserialize)] #[serde(rename_all = "snake_case")] -#[allow(clippy::enum_variant_names)] // Matches Bluesky API spec +#[expect(clippy::enum_variant_names, reason = "Matches Bluesky API spec naming convention")] pub enum GetAuthorFeedFilter { #[default] PostsWithReplies, diff --git a/parakeet/src/xrpc/app_bsky/notification/mod.rs b/parakeet/src/xrpc/app_bsky/notification/mod.rs index 1dffdb79..5113d175 100644 --- a/parakeet/src/xrpc/app_bsky/notification/mod.rs +++ b/parakeet/src/xrpc/app_bsky/notification/mod.rs @@ -14,7 +14,7 @@ pub struct ListNotificationsQuery { #[serde(default)] pub cursor: Option, #[serde(default)] - #[allow(dead_code)] + #[expect(dead_code, reason = "seen_at parameter accepted for API compatibility but not yet used for filtering")] pub seen_at: Option>, } @@ -322,7 +322,7 @@ pub async fn list_notifications( #[derive(Debug, Deserialize)] pub struct GetUnreadCountQuery { #[serde(default)] - #[allow(dead_code)] + #[expect(dead_code, reason = "seen_at parameter accepted for API compatibility but not yet used for calculation")] pub seen_at: Option>, } diff --git a/parakeet/src/xrpc/app_bsky/unspecced/mod.rs b/parakeet/src/xrpc/app_bsky/unspecced/mod.rs index f8d34298..eac5742e 100644 --- a/parakeet/src/xrpc/app_bsky/unspecced/mod.rs +++ b/parakeet/src/xrpc/app_bsky/unspecced/mod.rs @@ -201,7 +201,7 @@ pub async fn get_suggested_feeds( #[derive(Debug, Deserialize)] pub struct GetSuggestedUsersQuery { - #[allow(dead_code)] + #[expect(dead_code, reason = "Category parameter accepted for API compatibility but not yet implemented")] pub category: Option, pub limit: Option, } diff --git a/parakeet/src/xrpc/app_bsky/unspecced/thread_v2/thread_builder.rs b/parakeet/src/xrpc/app_bsky/unspecced/thread_v2/thread_builder.rs index 118ef893..854edff1 100644 --- a/parakeet/src/xrpc/app_bsky/unspecced/thread_v2/thread_builder.rs +++ b/parakeet/src/xrpc/app_bsky/unspecced/thread_v2/thread_builder.rs @@ -6,17 +6,16 @@ use super::models::{PostThreadSort, ThreadItemPost, ThreadV2Item, ThreadV2ItemTy use super::sorting::sort_replies; /// Helper struct for building thread structures +#[expect(dead_code, reason = "threadgate and prioritize_followed_users are infrastructure for future thread filtering features")] pub struct ThreadBuilder<'a> { pub hydrater: &'a StatefulHydrator<'a>, pub anchor_uri: String, pub anchor_post: PostView, - #[allow(dead_code)] pub threadgate: Option, pub above: bool, pub below: i32, pub branching_factor: i32, pub sort: PostThreadSort, - #[allow(dead_code)] pub prioritize_followed_users: bool, } -- 2.51.2