A better Rust ATProto crate

tracing span issue caused weirdness

Orual 5bd87b46 c3a48931

Changed files
+68 -13
crates
jacquard
src
jacquard-common
src
types
+36
crates/jacquard-common/src/types/aturi.rs
··· 1 + use crate::cowstr::ToCowStr; 1 2 use crate::types::ident::AtIdentifier; 2 3 use crate::types::nsid::Nsid; 3 4 use crate::types::recordkey::{RecordKey, Rkey}; ··· 104 105 pub collection: Nsid<'u>, 105 106 /// Optional record key identifying a specific record 106 107 pub rkey: Option<RecordKey<Rkey<'u>>>, 108 + } 109 + 110 + impl fmt::Display for RepoPath<'_> { 111 + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 112 + write!(f, "/{}", self.collection)?; 113 + if let Some(rkey) = &self.rkey { 114 + write!(f, "/{}", rkey.as_ref())?; 115 + } 116 + Ok(()) 117 + } 107 118 } 108 119 109 120 impl IntoStatic for RepoPath<'_> { ··· 341 352 } 342 353 343 354 impl AtUri<'static> { 355 + /// Fallible owned constructor from typical parts 356 + pub fn from_parts_owned( 357 + authority: impl AsRef<str>, 358 + collection: impl AsRef<str>, 359 + rkey: impl AsRef<str>, 360 + ) -> Result<Self, AtStrError> { 361 + let (authority, collection, rkey) = 362 + (authority.as_ref(), collection.as_ref(), rkey.as_ref()); 363 + if authority.is_empty() || (collection.is_empty() && !rkey.is_empty()) { 364 + Err(AtStrError::missing( 365 + "at-uri-scheme", 366 + &format!("at://{}/{}/{}", authority, collection, rkey), 367 + "correct uri path", 368 + )) 369 + } else if !authority.is_empty() && collection.is_empty() && rkey.is_empty() { 370 + let uri = format!("at://{}", authority); 371 + Self::new_owned(uri) 372 + } else if !collection.is_empty() && rkey.is_empty() { 373 + let uri = format!("at://{}/{}", authority, collection); 374 + Self::new_owned(uri) 375 + } else { 376 + let uri = format!("at://{}/{}/{}", authority, collection, rkey); 377 + Self::new_owned(uri) 378 + } 379 + } 344 380 /// Owned constructor 345 381 /// 346 382 /// Uses ouroboros self-referential tricks internally to make sure everything
+32 -13
crates/jacquard/src/client.rs
··· 667 667 R: Collection + serde::Serialize, 668 668 { 669 669 async move { 670 - #[cfg(feature = "tracing")] 671 - let _span = tracing::debug_span!("create_record", collection = %R::nsid()).entered(); 672 - 673 670 use jacquard_api::com_atproto::repo::create_record::CreateRecord; 674 671 use jacquard_common::types::ident::AtIdentifier; 675 672 use jacquard_common::types::value::to_data; ··· 679 676 .await 680 677 .ok_or_else(AgentError::no_session)?; 681 678 679 + #[cfg(feature = "tracing")] 680 + let _span = tracing::debug_span!("create_record", collection = %R::nsid()).entered(); 681 + 682 682 let data = 683 683 to_data(&record).map_err(|e| AgentError::sub_operation("serialize record", e))?; 684 684 ··· 688 688 .record(data) 689 689 .maybe_rkey(rkey) 690 690 .build(); 691 + 692 + #[cfg(feature = "tracing")] 693 + _span.exit(); 691 694 692 695 let response = self.send(request).await?; 693 696 response.into_output().map_err(|e| match e { ··· 752 755 ClientError::invalid_request("AtUri missing rkey") 753 756 .with_help("ensure the URI includes a record key after the collection") 754 757 })?; 758 + 759 + #[cfg(feature = "tracing")] 760 + _span.exit(); 755 761 756 762 // Resolve authority (DID or handle) to get DID and PDS 757 763 use jacquard_common::types::ident::AtIdentifier; ··· 818 824 .rkey(rkey.clone()) 819 825 .build(); 820 826 827 + #[cfg(feature = "tracing")] 828 + _span.exit(); 829 + 821 830 let response: Response<GetRecordResponse> = { 822 831 use url::Url; 823 832 ··· 918 927 for<'a> CollectionError<'a, R>: Send + Sync + std::error::Error + IntoStatic, 919 928 { 920 929 async move { 930 + // Fetch the record - Response<R::Record> where R::Record::Output<'de> = R<'de> 931 + let response = self.get_record::<R>(uri).await?; 932 + 921 933 #[cfg(feature = "tracing")] 922 934 let _span = tracing::debug_span!("update_record", collection = %R::nsid(), uri = %uri) 923 935 .entered(); 924 - 925 - // Fetch the record - Response<R::Record> where R::Record::Output<'de> = R<'de> 926 - let response = self.get_record::<R>(uri).await?; 927 936 928 937 // Parse to get R<'_> borrowing from response buffer 929 938 let record = response.parse().map_err(|e| match e { ··· 952 961 })? 953 962 .clone() 954 963 .into_static(); 964 + 965 + #[cfg(feature = "tracing")] 966 + _span.exit(); 955 967 self.put_record::<R>(rkey, owned).await 956 968 } 957 969 } ··· 968 980 R: Collection, 969 981 { 970 982 async { 983 + let (did, _) = self 984 + .session_info() 985 + .await 986 + .ok_or_else(AgentError::no_session)?; 971 987 #[cfg(feature = "tracing")] 972 988 let _span = tracing::debug_span!("delete_record", collection = %R::nsid()).entered(); 973 989 974 990 use jacquard_api::com_atproto::repo::delete_record::DeleteRecord; 975 991 use jacquard_common::types::ident::AtIdentifier; 976 992 977 - let (did, _) = self 978 - .session_info() 979 - .await 980 - .ok_or_else(AgentError::no_session)?; 981 - 982 993 let request = DeleteRecord::new() 983 994 .repo(AtIdentifier::Did(did)) 984 995 .collection(R::nsid()) 985 996 .rkey(rkey) 986 997 .build(); 987 998 999 + #[cfg(feature = "tracing")] 1000 + _span.exit(); 1001 + 988 1002 let response = self.send(request).await?; 989 1003 response.into_output().map_err(|e| match e { 990 1004 XrpcError::Auth(auth) => AgentError::from(auth), ··· 1028 1042 .rkey(rkey) 1029 1043 .record(data) 1030 1044 .build(); 1045 + 1046 + #[cfg(feature = "tracing")] 1047 + _span.exit(); 1031 1048 1032 1049 let response = self.send(request).await?; 1033 1050 response.into_output().map_err(|e| match e { ··· 1081 1098 http::HeaderValue::from_str(mime_type.as_str()) 1082 1099 .map_err(|e| AgentError::sub_operation("set Content-Type header", e))?, 1083 1100 )); 1101 + 1102 + #[cfg(feature = "tracing")] 1103 + _span.exit(); 1104 + 1084 1105 let response = self.send_with_opts(request, opts).await?; 1085 - let debug: serde_json::Value = serde_json::from_slice(response.buffer()).unwrap(); 1086 - println!("json: {}", serde_json::to_string_pretty(&debug).unwrap()); 1087 1106 let output = response.into_output().map_err(|e| match e { 1088 1107 XrpcError::Auth(auth) => AgentError::from(auth), 1089 1108 e @ (XrpcError::Generic(_) | XrpcError::Decode(_)) => AgentError::xrpc(e),