JavaScript is disabled, refresh for a better experience. ambee/giterated-api

ambee/giterated-api

Git repository hosting, collaboration, and discovery for the Fediverse.

Error handling fixes

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨5eaea71

Showing ⁨⁨4⁩ changed files⁩ with ⁨⁨48⁩ insertions⁩ and ⁨⁨99⁩ deletions⁩

src/daemon_backend.rs

View file
@@ -1,9 +1,10 @@
1 use std::{fmt::Debug, sync::Arc};
1 use std::{fmt::Debug, str::FromStr, sync::Arc};
2 2
3 3 use futures_util::{SinkExt, StreamExt};
4 4 use giterated_models::{
5 5 authenticated::{Authenticated, AuthenticationSourceProviders},
6 6 error::OperationError,
7 error::{IntoInternalError, NetworkOperationError},
7 8 message::GiteratedMessage,
8 9 object::{GiteratedObject, Object, ObjectRequest, ObjectRequestError, ObjectResponse},
9 10 object_backend::ObjectBackend,
@@ -49,11 +50,9 @@ impl ObjectBackend<NetworkOperationState> for DaemonConnectionPool {
49 50 payload,
50 51 };
51 52
52 let mut connection = self
53 .0
54 .get()
55 .await
56 .map_err(|e| OperationError::Internal(e.to_string()))?;
53 let mut connection = self.0.get().await.map_err(|e| {
54 OperationError::Internal(anyhow::Error::from(ConnectionFailed(e.to_string())))
55 })?;
57 56
58 57 let mut authenticated = Authenticated::new(message);
59 58 for authentication in &operation_state.authentication {
@@ -76,11 +75,9 @@ impl ObjectBackend<NetworkOperationState> for DaemonConnectionPool {
76 75 payload: operation,
77 76 };
78 77
79 let mut connection = self
80 .0
81 .get()
82 .await
83 .map_err(|e| OperationError::Internal(e.to_string()))?;
78 let mut connection = self.0.get().await.map_err(|e| {
79 OperationError::Internal(anyhow::Error::from(ConnectionFailed(e.to_string())))
80 })?;
84 81
85 82 let mut authenticated = Authenticated::new(message);
86 83 for authentication in &operation_state.authentication {
@@ -88,13 +85,12 @@ impl ObjectBackend<NetworkOperationState> for DaemonConnectionPool {
88 85 }
89 86
90 87 let object_raw: ObjectResponse = send_expect(&mut connection, authenticated).await?;
91 Ok(unsafe {
92 Object::new_unchecked(
93 O::from_str(&object_raw.0)
94 .map_err(|_e| OperationError::Internal("heck".to_string()))?,
95 self.clone(),
96 )
97 })
88
89 if let Ok(object) = O::from_str(&object_raw.0) {
90 Ok(unsafe { Object::new_unchecked(object, self.clone()) })
91 } else {
92 panic!()
93 }
98 94 }
99 95 }
100 96
@@ -112,30 +108,33 @@ async fn send_expect<
112 108 socket
113 109 .send(Message::Binary(payload))
114 110 .await
115 .map_err(|e| OperationError::Internal(e.to_string()))?;
111 .as_internal_error()?;
116 112
117 113 while let Some(message) = socket.next().await {
118 let payload = match message.map_err(|e| OperationError::Internal(e.to_string()))? {
114 let payload = match message.as_internal_error()? {
119 115 Message::Binary(payload) => payload,
120 116 _ => {
121 117 continue;
122 118 }
123 119 };
124 120
125 let raw_result = bincode::deserialize::<Result<Vec<u8>, OperationError<Vec<u8>>>>(&payload)
126 .map_err(|e| OperationError::Internal(e.to_string()))?;
121 let raw_result =
122 bincode::deserialize::<Result<Vec<u8>, NetworkOperationError<Vec<u8>>>>(&payload)
123 .map_err(|e| OperationError::Internal(anyhow::Error::from(e)))?;
127 124
128 125 // Map ok
129 126 let raw_result = match raw_result {
130 127 Ok(raw) => Ok(serde_json::from_slice(&raw)
131 .map_err(|e| OperationError::Internal(e.to_string()))?),
128 .map_err(|e| OperationError::Internal(anyhow::Error::from(e)))?),
132 129 Err(err) => Err(match err {
133 OperationError::Operation(err) => OperationError::Operation(
130 NetworkOperationError::Operation(err) => OperationError::Operation(
134 131 serde_json::from_slice(&err)
135 .map_err(|e| OperationError::Internal(e.to_string()))?,
132 .map_err(|e| OperationError::Internal(anyhow::Error::from(e)))?,
136 133 ),
137 OperationError::Internal(err) => OperationError::Internal(err),
138 OperationError::Unhandled => OperationError::Unhandled,
134 NetworkOperationError::Internal => {
135 OperationError::Internal(anyhow::Error::from(NetworkError))
136 }
137 NetworkOperationError::Unhandled => OperationError::Unhandled,
139 138 }),
140 139 };
141 140
@@ -144,3 +143,11 @@ async fn send_expect<
144 143
145 144 panic!()
146 145 }
146
147 #[derive(Debug, thiserror::Error)]
148 #[error("a remote internal error occurred")]
149 pub struct NetworkError;
150
151 #[derive(Debug, thiserror::Error)]
152 #[error("failed to get connection from pool: {0}")]
153 pub struct ConnectionFailed(String);

src/lib.rs

View file
@@ -27,9 +27,7 @@ impl Debug for DaemonConnectionPool {
27 27 }
28 28
29 29 impl DaemonConnectionPool {
30 pub fn connect(
31 instance: impl ToOwned<Owned = Instance>,
32 ) -> Result<Self, BuildError> {
30 pub fn connect(instance: impl ToOwned<Owned = Instance>) -> Result<Self, BuildError> {
33 31 let instance = instance.to_owned();
34 32 Ok(Self(
35 33 Pool::builder(GiteratedConnectionPool {

src/main.rs

View file
@@ -5,9 +5,9 @@ use giterated_models::{
5 5 authenticated::{InstanceAuthenticator, UserAuthenticator},
6 6 instance::Instance,
7 7 object_backend::ObjectBackend,
8 repository::{AccessList, Repository},
8 repository::{AccessList, Description, Repository},
9 9 settings::AnySetting,
10 user::{DisplayName, User},
10 user::{Bio, DisplayName, User},
11 11 };
12 12
13 13 use color_eyre::eyre::Result;
@@ -29,88 +29,32 @@ async fn main() -> Result<()> {
29 29 let mut operation_state = NetworkOperationState::new();
30 30
31 31 let mut user = pool
32 .get_object::<User>("ambee:giterated.dev", &operation_state)
32 .get_object::<User>("test:giterated.dev", &operation_state)
33 33 .await?;
34 34
35 // info!("Getting display name for {}!", user);
35 let bio = user.get::<Bio>(&operation_state).await?;
36 36
37 let display_name = user.get::<DisplayName>(&operation_state).await?;
38
39 // info!("{}'s display name is {}", user, display_name);
37 info!("Bio: {}", bio);
40 38
41 39 let repositories = user
42 .repositories(
43 &Instance::from_str("giterated.dev").unwrap(),
44 &operation_state,
45 )
40 .repositories(&Instance::from_str("giterated.dev")?, &operation_state)
46 41 .await?;
47 42
48 // info!("Repository: {:#?}", repositories);
43 let repository = repositories.first().unwrap();
49 44
50 45 let mut repository = pool
51 .get_object::<Repository>(
52 &repositories.first().unwrap().repository.to_string(),
53 &operation_state,
54 )
46 .get_object::<Repository>(&repository.repository.to_string(), &operation_state)
55 47 .await?;
56 48
57 // info!("First repository: {}", repository.object().to_string());
58
59 // info!("First repository description: {}", repository.get::<Description>().await?);
60 // info!("First repository visibility: {:?}", repository.get::<Visibility>().await?);
61 // info!("First repository default branch: {}", repository.get::<DefaultBranch>().await?);
62
63 49 info!(
64 "First repository info: {:#?}",
65 repository.info(false, None, None, &operation_state).await?
50 "Repository description: {}",
51 repository.get::<Description>(&operation_state).await?
66 52 );
67 53
68 let cold_duration = start.elapsed();
69 let warm_start = Instant::now();
70
71 let mut operation_state = NetworkOperationState::new();
72
73 let mut user = pool
74 .get_object::<User>("ambee:giterated.dev", &operation_state)
75 .await?;
76
77 // info!("Getting display name for {}!", user);
78
79 let display_name = user.get::<DisplayName>(&operation_state).await?;
80
81 // info!("{}'s display name is {}", user, display_name);
82
83 let repositories = user
84 .repositories(
85 &Instance::from_str("giterated.dev").unwrap(),
86 &operation_state,
87 )
88 .await?;
89
90 // info!("Repository: {:#?}", repositories);
91
92 let mut repository = pool
93 .get_object::<Repository>(
94 &repositories.first().unwrap().repository.to_string(),
95 &operation_state,
96 )
97 .await?;
98
99 // info!("First repository: {}", repository.object().to_string());
100
101 // info!("First repository description: {}", repository.get::<Description>().await?);
102 // info!("First repository visibility: {:?}", repository.get::<Visibility>().await?);
103 // info!("First repository default branch: {}", repository.get::<DefaultBranch>().await?);
104
105 54 info!(
106 "First repository info: {:#?}",
107 repository.info(false, None, None, &operation_state).await?
55 "User Bio Setting: {}",
56 user.get_setting::<Bio>(&operation_state).await?
108 57 );
109 58
110 let warm_duration = warm_start.elapsed();
111
112 info!("Cold request time: {}ms", cold_duration.as_millis());
113 info!("Warm request time: {}ms", warm_duration.as_millis());
114
115 59 Ok(())
116 60 }

src/pool.rs

View file
@@ -1,6 +1,6 @@
1 1 use std::net::SocketAddr;
2 2
3 use deadpool::managed::{Manager, RecycleError, RecycleResult, Metrics};
3 use deadpool::managed::{Manager, Metrics, RecycleError, RecycleResult};
4 4 use futures_util::SinkExt;
5 5 use giterated_models::instance::Instance;
6 6 use tokio_tungstenite::{connect_async, tungstenite::Message};