Rust AppView - highly experimental!
1//! Database-free event processing 2//! 3//! This module converts parsed events into `ProcessedEvent` structures 4//! containing all data needed for database operations, without touching 5//! the database itself. Workers become pure functions. 6 7use super::handlers; 8use crate::database_writer::{EventSource, ProcessedEvent}; 9use crate::relay::types::RecordTypes; 10use ipld_core::cid::Cid; 11 12/// Process a record operation into database operations (no I/O) 13/// 14/// This is the database-free equivalent of `index_op_impl`. 15/// Instead of writing to the database, it returns a list of operations to perform. 16/// 17/// # Parameters 18/// - `actor_id`: The resolved actor ID for the repo (caller must resolve via ensure_actor_id) 19/// - `resolved_actor_ids`: All resolved actor IDs from the record (subject, parent, root, quoted, mentioned) 20/// 21/// NOTE: With Tap filtering, all events are from allowlisted DIDs. 22/// We always enqueue related posts (replies/quotes) for fetching to ensure completeness. 23#[expect(clippy::too_many_arguments, reason = "Comprehensive record processing requires multiple resolved IDs and metadata")] 24pub fn process_record_to_operations( 25 repo: &str, 26 actor_id: i32, 27 resolved_actor_ids: super::ResolvedActorIds, 28 cid: Cid, 29 record: RecordTypes, 30 at_uri: String, 31 rkey: String, 32 source: EventSource, 33) -> ProcessedEvent { 34 let subject_actor_id = resolved_actor_ids.subject_actor_id; 35 36 // Create context for handlers that need it 37 let ctx = handlers::RecordContext { 38 repo: repo.to_string(), 39 actor_id, 40 subject_actor_id, 41 via_repost_key: resolved_actor_ids.via_repost_key, 42 service_actor_id: resolved_actor_ids.service_actor_id, 43 cid, 44 at_uri: at_uri.clone(), 45 rkey: rkey.clone(), 46 source, 47 }; 48 49 let operations = match record { 50 RecordTypes::AppBskyActorProfile(record) => handlers::handle_profile(&ctx, record), 51 RecordTypes::AppBskyActorStatus(record) => handlers::handle_status(&ctx, record), 52 RecordTypes::AppBskyFeedGenerator(record) => handlers::handle_feedgen(&ctx, record), 53 RecordTypes::AppBskyFeedLike(record) => handlers::handle_like(&ctx, record), 54 RecordTypes::AppBskyFeedPost(record) => { 55 let post_ctx = handlers::PostContext { 56 ctx: ctx.clone(), 57 parent_author_actor_id: resolved_actor_ids.parent_author_actor_id, 58 root_author_actor_id: resolved_actor_ids.root_author_actor_id, 59 quoted_author_actor_id: resolved_actor_ids.quoted_author_actor_id, 60 mentioned_actor_ids: resolved_actor_ids.mentioned_actor_ids, 61 }; 62 handlers::handle_post(&post_ctx, record) 63 }, 64 RecordTypes::AppBskyFeedPostgate(record) => handlers::handle_postgate(&ctx, record), 65 RecordTypes::AppBskyFeedRepost(record) => handlers::handle_repost(&ctx, record), 66 RecordTypes::AppBskyFeedThreadgate(record) => handlers::handle_threadgate(&ctx, record), 67 RecordTypes::AppBskyGraphBlock(record) => handlers::handle_block(&ctx, record), 68 RecordTypes::AppBskyGraphFollow(record) => handlers::handle_follow(&ctx, record), 69 RecordTypes::AppBskyGraphList(record) => handlers::handle_list(&ctx, record), 70 RecordTypes::AppBskyGraphListBlock(record) => handlers::handle_list_block(&ctx, record), 71 RecordTypes::AppBskyGraphListItem(record) => handlers::handle_list_item(&ctx, record), 72 RecordTypes::AppBskyGraphStarterPack(record) => handlers::handle_starterpack(&ctx, record), 73 RecordTypes::AppBskyGraphVerification(record) => handlers::handle_verification(&ctx, record), 74 RecordTypes::AppBskyLabelerService(record) => handlers::handle_labeler(&ctx, record), 75 RecordTypes::AppBskyNotificationDeclaration(record) => { 76 handlers::handle_notification_declaration(&ctx, record) 77 } 78 RecordTypes::ChatBskyActorDeclaration(record) => { 79 handlers::handle_chat_declaration(&ctx, record) 80 } 81 RecordTypes::CommunityLexiconBookmark(record) => handlers::handle_bookmark(&ctx, record), 82 RecordTypes::FmTealAlpaActorStatus(record) => handlers::handle_alpa_status(&ctx, record), 83 RecordTypes::Unknown(_value) => { 84 // Unknown record types are skipped 85 vec![] 86 } 87 }; 88 89 ProcessedEvent { 90 operations, 91 cursor: None, 92 source, 93 } 94}