//! Work item types for queue processing. //! //! This module defines the various work item types that can be processed //! through the queue system, such as handle resolution requests. use serde::{Deserialize, Serialize}; /// Work item for handle resolution tasks. /// /// This structure represents a request to resolve an AT Protocol handle /// to its corresponding DID. It's the primary work type processed by /// the QuickDID service's background queue workers. /// /// # Examples /// /// ``` /// use quickdid::queue::HandleResolutionWork; /// /// let work = HandleResolutionWork::new("alice.bsky.social".to_string()); /// assert_eq!(work.handle, "alice.bsky.social"); /// ``` #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct HandleResolutionWork { /// The AT Protocol handle to resolve (e.g., "alice.bsky.social") pub handle: String, } impl HandleResolutionWork { /// Create a new handle resolution work item. /// /// # Arguments /// /// * `handle` - The AT Protocol handle to resolve /// /// # Examples /// /// ``` /// use quickdid::queue::HandleResolutionWork; /// /// let work = HandleResolutionWork::new("alice.bsky.social".to_string()); /// ``` pub fn new(handle: String) -> Self { Self { handle } } } impl std::fmt::Display for HandleResolutionWork { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "HandleResolution({})", self.handle) } } /// Trait for getting a unique deduplication key from a work item. /// This is used by the Redis queue adapter to prevent duplicate items. pub trait DedupKey { /// Get a unique key for deduplication purposes. /// This should return a consistent identifier for equivalent work items. fn dedup_key(&self) -> String; } impl DedupKey for HandleResolutionWork { fn dedup_key(&self) -> String { // Use the handle itself as the dedup key self.handle.clone() } } // For testing purposes, implement DedupKey for String #[cfg(test)] impl DedupKey for String { fn dedup_key(&self) -> String { self.clone() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_handle_resolution_work_creation() { let handle = "alice.example.com"; let work = HandleResolutionWork::new(handle.to_string()); assert_eq!(work.handle, handle); } #[test] fn test_handle_resolution_work_serialization() { let work = HandleResolutionWork::new("bob.example.com".to_string()); // Test JSON serialization (which is what we actually use in the queue adapters) let json = serde_json::to_string(&work).expect("Failed to serialize to JSON"); let deserialized: HandleResolutionWork = serde_json::from_str(&json).expect("Failed to deserialize from JSON"); assert_eq!(work, deserialized); // Verify the JSON structure let json_value: serde_json::Value = serde_json::from_str(&json).unwrap(); assert_eq!(json_value["handle"], "bob.example.com"); } #[test] fn test_handle_resolution_work_display() { let work = HandleResolutionWork::new("charlie.example.com".to_string()); let display = format!("{}", work); assert_eq!(display, "HandleResolution(charlie.example.com)"); } #[test] fn test_handle_resolution_work_equality() { let work1 = HandleResolutionWork::new("alice.example.com".to_string()); let work2 = HandleResolutionWork::new("alice.example.com".to_string()); let work3 = HandleResolutionWork::new("bob.example.com".to_string()); assert_eq!(work1, work2); assert_ne!(work1, work3); } #[test] fn test_handle_resolution_work_dedup_key() { let work1 = HandleResolutionWork::new("alice.example.com".to_string()); let work2 = HandleResolutionWork::new("alice.example.com".to_string()); let work3 = HandleResolutionWork::new("bob.example.com".to_string()); // Same handle should have same dedup key assert_eq!(work1.dedup_key(), work2.dedup_key()); assert_eq!(work1.dedup_key(), "alice.example.com"); // Different handle should have different dedup key assert_ne!(work1.dedup_key(), work3.dedup_key()); assert_eq!(work3.dedup_key(), "bob.example.com"); } }