Beginning of `stack-next` refactor
-Refactoring the protocol stack into something similar to a runtime. -Handles merging handler builders which is placing the ground work for plugins in. - Increased metadata generation during compilation enables less ser/de during execution. - Goal is to have an O(1) time from incoming operation to calling handlers. - Decreased penalty for using the statically typed API from within your code, now avoids some allocation. # Changes - Added `GiteratedRuntime` which is to replace the current unified stack - Added `RuntimeBuilder` which does what the current `OperationHandlers` struct does, but much better. - Added `RuntimeMetadata` to store type metadata for new `Any` based internals - Refactored serde_json out of the internal operation handling
parent: tbd commit: 708dea4
Showing 20 changed files with 1391 insertions and 123 deletions
giterated-daemon/src/backend/mod.rs
@@ -78,7 +78,7 @@ pub trait RepositoryBackend { | ||
78 | 78 | async fn get_setting(&mut self, user: &Repository, name: &str) -> Result<AnySetting, Error>; |
79 | 79 | async fn write_setting( |
80 | 80 | &mut self, |
81 | user: &Repository, | |
81 | repository: &Repository, | |
82 | 82 | name: &str, |
83 | 83 | setting: &Value, |
84 | 84 | ) -> Result<(), Error>; |
giterated-daemon/src/database_backend/handler.rs
@@ -9,17 +9,19 @@ use giterated_models::{ | ||
9 | 9 | }, |
10 | 10 | object_backend::ObjectBackend, |
11 | 11 | repository::{ |
12 | Commit, DefaultBranch, Description, LatestCommit, Repository, | |
12 | AccessList, Commit, DefaultBranch, Description, LatestCommit, Repository, | |
13 | 13 | RepositoryCommitBeforeRequest, RepositoryDiff, RepositoryDiffPatchRequest, |
14 | 14 | RepositoryDiffRequest, RepositoryFile, RepositoryFileFromIdRequest, |
15 | 15 | RepositoryFileFromPathRequest, RepositoryFileInspectRequest, RepositoryInfoRequest, |
16 | 16 | RepositorySummary, RepositoryView, Visibility, |
17 | 17 | }, |
18 | 18 | settings::{AnySetting, GetSetting, GetSettingError, SetSetting, SetSettingError}, |
19 | user::{User, UserRepositoriesRequest}, | |
19 | user::{Bio, DisplayName, User, UserRepositoriesRequest}, | |
20 | 20 | value::{AnyValue, GetValue}, |
21 | 21 | }; |
22 | use giterated_stack::{AuthenticatedUser, AuthorizedInstance, BackendWrapper, StackOperationState}; | |
22 | use giterated_stack::{ | |
23 | AuthenticatedUser, AuthorizedInstance, AuthorizedUser, BackendWrapper, StackOperationState, | |
24 | }; | |
23 | 25 | |
24 | 26 | use super::DatabaseBackend; |
25 | 27 | |
@@ -44,7 +46,11 @@ pub fn user_get_repositories( | ||
44 | 46 | let mut repositories = vec![]; |
45 | 47 | |
46 | 48 | for repository in repositories_response { |
47 | if repositories_backend.exists(&requester, &repository.repository).await.map_err(|e| OperationError::Internal(e.to_string()))? { | |
49 | if repositories_backend | |
50 | .exists(&requester, &repository.repository) | |
51 | .await | |
52 | .map_err(|e| OperationError::Internal(e.to_string()))? | |
53 | { | |
48 | 54 | repositories.push(repository); |
49 | 55 | } |
50 | 56 | } |
@@ -92,24 +98,24 @@ pub fn user_get_setting( | ||
92 | 98 | .boxed() |
93 | 99 | } |
94 | 100 | |
95 | pub fn user_set_setting( | |
96 | object: &User, | |
97 | operation: SetSetting<AnySetting>, | |
98 | state: DatabaseBackend, | |
99 | ) -> BoxFuture<'static, Result<(), OperationError<SetSettingError>>> { | |
100 | let object = object.clone(); | |
101 | ||
102 | async move { | |
103 | let mut user_backend = state.user_backend.lock().await; | |
104 | let value = user_backend | |
105 | .write_setting(&object, &operation.setting_name, &operation.value.0) | |
106 | .await | |
107 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
108 | ||
109 | Ok(value) | |
110 | } | |
111 | .boxed() | |
112 | } | |
101 | // pub fn user_set_setting( | |
102 | // object: &User, | |
103 | // operation: SetSetting<AnySetting>, | |
104 | // state: DatabaseBackend, | |
105 | // ) -> BoxFuture<'static, Result<(), OperationError<SetSettingError>>> { | |
106 | // let object = object.clone(); | |
107 | ||
108 | // async move { | |
109 | // let mut user_backend = state.user_backend.lock().await; | |
110 | // let value = user_backend | |
111 | // .write_setting(&object, &operation.setting_name, &operation.value.0) | |
112 | // .await | |
113 | // .map_err(|e| OperationError::Internal(e.to_string()))?; | |
114 | ||
115 | // Ok(value) | |
116 | // } | |
117 | // .boxed() | |
118 | // } | |
113 | 119 | |
114 | 120 | pub fn repository_info( |
115 | 121 | object: &Repository, |
@@ -356,24 +362,24 @@ pub fn repository_get_setting( | ||
356 | 362 | .boxed() |
357 | 363 | } |
358 | 364 | |
359 | pub fn repository_set_setting( | |
360 | object: &Repository, | |
361 | operation: SetSetting<AnySetting>, | |
362 | state: DatabaseBackend, | |
363 | ) -> BoxFuture<'static, Result<(), OperationError<SetSettingError>>> { | |
364 | let object = object.clone(); | |
365 | ||
366 | async move { | |
367 | let mut repository_backend = state.repository_backend.lock().await; | |
368 | let value = repository_backend | |
369 | .write_setting(&object, &operation.setting_name, &operation.value.0) | |
370 | .await | |
371 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
372 | ||
373 | Ok(value) | |
374 | } | |
375 | .boxed() | |
376 | } | |
365 | // pub fn repository_set_setting( | |
366 | // object: &Repository, | |
367 | // operation: SetSetting<AnySetting>, | |
368 | // state: DatabaseBackend, | |
369 | // ) -> BoxFuture<'static, Result<(), OperationError<SetSettingError>>> { | |
370 | // let object = object.clone(); | |
371 | ||
372 | // async move { | |
373 | // let mut repository_backend = state.repository_backend.lock().await; | |
374 | // let value = repository_backend | |
375 | // .write_setting(&object, &operation.setting_name, &operation.value.0) | |
376 | // .await | |
377 | // .map_err(|e| OperationError::Internal(e.to_string()))?; | |
378 | ||
379 | // Ok(value) | |
380 | // } | |
381 | // .boxed() | |
382 | // } | |
377 | 383 | |
378 | 384 | pub fn instance_authentication_request( |
379 | 385 | object: &Instance, |
@@ -430,3 +436,88 @@ pub fn instance_create_repository_request( | ||
430 | 436 | } |
431 | 437 | .boxed() |
432 | 438 | } |
439 | ||
440 | pub fn user_get_value_display_name( | |
441 | object: &User, | |
442 | operation: GetValue<DisplayName>, | |
443 | state: DatabaseBackend, | |
444 | _requester: AuthorizedUser, | |
445 | ) -> BoxFuture<'static, Result<DisplayName, OperationError<GetValueError>>> { | |
446 | let object = object.clone(); | |
447 | ||
448 | async move { | |
449 | let mut backend = state.user_backend.lock().await; | |
450 | ||
451 | let raw_value = backend | |
452 | .get_value(&object, &operation.value_name) | |
453 | .await | |
454 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
455 | ||
456 | Ok(serde_json::from_value(raw_value.into_inner()) | |
457 | .map_err(|e| OperationError::Internal(e.to_string()))?) | |
458 | } | |
459 | .boxed() | |
460 | } | |
461 | ||
462 | pub fn user_get_value_bio( | |
463 | object: &User, | |
464 | operation: GetValue<Bio>, | |
465 | state: DatabaseBackend, | |
466 | ) -> BoxFuture<'static, Result<Bio, OperationError<GetValueError>>> { | |
467 | let object = object.clone(); | |
468 | ||
469 | async move { | |
470 | let mut backend = state.user_backend.lock().await; | |
471 | ||
472 | let raw_value = backend | |
473 | .get_value(&object, &operation.value_name) | |
474 | .await | |
475 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
476 | ||
477 | Ok(serde_json::from_value(raw_value.into_inner()) | |
478 | .map_err(|e| OperationError::Internal(e.to_string()))?) | |
479 | } | |
480 | .boxed() | |
481 | } | |
482 | ||
483 | pub fn repository_get_value_description( | |
484 | object: &Repository, | |
485 | operation: GetValue<Description>, | |
486 | state: DatabaseBackend, | |
487 | ) -> BoxFuture<'static, Result<Description, OperationError<GetValueError>>> { | |
488 | let object = object.clone(); | |
489 | ||
490 | async move { | |
491 | let mut backend = state.repository_backend.lock().await; | |
492 | ||
493 | let raw_value = backend | |
494 | .get_value(&object, &operation.value_name) | |
495 | .await | |
496 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
497 | ||
498 | Ok(serde_json::from_value(raw_value.into_inner()) | |
499 | .map_err(|e| OperationError::Internal(e.to_string()))?) | |
500 | } | |
501 | .boxed() | |
502 | } | |
503 | ||
504 | pub fn repository_get_value_visibility( | |
505 | object: &Repository, | |
506 | operation: GetValue<Visibility>, | |
507 | state: DatabaseBackend, | |
508 | ) -> BoxFuture<'static, Result<Visibility, OperationError<GetValueError>>> { | |
509 | let object = object.clone(); | |
510 | ||
511 | async move { | |
512 | let mut backend = state.repository_backend.lock().await; | |
513 | ||
514 | let raw_value = backend | |
515 | .get_value(&object, &operation.value_name) | |
516 | .await | |
517 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
518 | ||
519 | Ok(serde_json::from_value(raw_value.into_inner()) | |
520 | .map_err(|e| OperationError::Internal(e.to_string()))?) | |
521 | } | |
522 | .boxed() | |
523 | } |
giterated-daemon/src/database_backend/mod.rs
@@ -1,4 +1,5 @@ | ||
1 | 1 | pub mod handler; |
2 | pub mod updates; | |
2 | 3 | |
3 | 4 | use std::sync::Arc; |
4 | 5 | |
@@ -7,8 +8,8 @@ use giterated_models::instance::Instance; | ||
7 | 8 | use giterated_models::object::{GiteratedObject, Object, ObjectRequestError}; |
8 | 9 | use giterated_models::object_backend::ObjectBackend; |
9 | 10 | use giterated_models::operation::GiteratedOperation; |
10 | use giterated_models::repository::Repository; | |
11 | use giterated_models::user::User; | |
11 | use giterated_models::repository::{DefaultBranch, Description, Repository, Visibility}; | |
12 | use giterated_models::user::{Bio, DisplayName, User}; | |
12 | 13 | use giterated_stack::handler::GiteratedBackend; |
13 | 14 | use giterated_stack::{OperationHandlers, StackOperationState}; |
14 | 15 | use std::fmt::Debug; |
@@ -20,8 +21,12 @@ use self::handler::{ | ||
20 | 21 | instance_authentication_request, instance_create_repository_request, |
21 | 22 | instance_registration_request, repository_commit_before, repository_diff, |
22 | 23 | repository_diff_patch, repository_file_from_id, repository_file_from_path, |
23 | repository_get_setting, repository_get_value, repository_info, repository_set_setting, | |
24 | user_get_repositories, user_get_setting, user_get_value, user_set_setting, | |
24 | repository_get_setting, repository_get_value, repository_get_value_description, | |
25 | repository_get_value_visibility, repository_info, user_get_repositories, user_get_setting, | |
26 | user_get_value, user_get_value_bio, user_get_value_display_name, | |
27 | }; | |
28 | use self::updates::{ | |
29 | repository_set_setting, repository_set_value, user_set_setting, user_set_value, | |
25 | 30 | }; |
26 | 31 | |
27 | 32 | #[derive(Clone, Debug)] |
@@ -75,24 +80,29 @@ impl DatabaseBackend { | ||
75 | 80 | |
76 | 81 | handlers |
77 | 82 | .insert(user_get_repositories) |
78 | .insert(user_get_value) | |
79 | .insert(user_get_setting) | |
80 | .insert(user_set_setting) | |
81 | 83 | .insert(repository_info) |
82 | 84 | .insert(repository_file_from_id) |
83 | 85 | .insert(repository_file_from_path) |
84 | 86 | .insert(repository_diff) |
85 | 87 | .insert(repository_diff_patch) |
86 | 88 | .insert(repository_commit_before) |
87 | .insert(repository_get_value) | |
88 | .insert(repository_get_setting) | |
89 | .insert(repository_set_setting) | |
90 | 89 | .insert(instance_registration_request) |
91 | 90 | .insert(instance_authentication_request) |
92 | 91 | .insert(instance_create_repository_request) |
93 | .register_object::<Instance>() | |
94 | .register_object::<Repository>() | |
95 | .register_object::<User>(); | |
92 | .setting_getter(user_get_setting) | |
93 | .setting_getter(repository_get_setting) | |
94 | .value_getter(user_get_value_display_name) | |
95 | .value_getter(user_get_value_bio) | |
96 | .value_getter(repository_get_value_description) | |
97 | .value_getter(repository_get_value_visibility) | |
98 | .setting::<DisplayName>() | |
99 | .setting::<Bio>() | |
100 | .setting::<Description>() | |
101 | .setting::<Visibility>() | |
102 | .setting::<DefaultBranch>() | |
103 | .object::<Instance>() | |
104 | .object::<Repository>() | |
105 | .object::<User>(); | |
96 | 106 | |
97 | 107 | GiteratedBackend::new(self.clone(), handlers) |
98 | 108 | } |
giterated-daemon/src/database_backend/updates.rs
@@ -0,0 +1,87 @@ | ||
1 | use futures_util::{future::BoxFuture, FutureExt}; | |
2 | use giterated_models::{ | |
3 | repository::{DefaultBranch, Description, Repository}, | |
4 | settings::{AnySetting, Setting}, | |
5 | update::ValueUpdate, | |
6 | user::User, | |
7 | value::{AnyValue, GiteratedObjectValue}, | |
8 | }; | |
9 | use giterated_stack::{AuthorizedUser, StackOperationState}; | |
10 | ||
11 | use super::DatabaseBackend; | |
12 | ||
13 | pub fn user_set_value( | |
14 | object: User, | |
15 | value_name: String, | |
16 | value: AnyValue<User>, | |
17 | operation_state: &StackOperationState, | |
18 | ) -> BoxFuture<'static, Result<(), ()>> { | |
19 | todo!() | |
20 | } | |
21 | ||
22 | pub fn user_set_setting( | |
23 | object: User, | |
24 | value_name: String, | |
25 | value: AnySetting, | |
26 | operation_state: &StackOperationState, | |
27 | ) -> BoxFuture<'static, Result<(), ()>> { | |
28 | todo!() | |
29 | } | |
30 | ||
31 | pub fn repository_set_value( | |
32 | object: Repository, | |
33 | value_name: String, | |
34 | value: AnyValue<Repository>, | |
35 | operation_state: &StackOperationState, | |
36 | ) -> BoxFuture<'static, Result<(), ()>> { | |
37 | todo!() | |
38 | } | |
39 | ||
40 | pub fn repository_set_setting( | |
41 | object: Repository, | |
42 | value_name: String, | |
43 | value: AnySetting, | |
44 | operation_state: &StackOperationState, | |
45 | ) -> BoxFuture<'static, Result<(), ()>> { | |
46 | todo!() | |
47 | } | |
48 | ||
49 | pub fn repository_set_description( | |
50 | object: Repository, | |
51 | description: Description, | |
52 | user: AuthorizedUser, | |
53 | ) -> BoxFuture<'static, Result<(), ()>> { | |
54 | async { Ok(()) }.boxed() | |
55 | } | |
56 | ||
57 | pub fn repository_set_default_branch( | |
58 | object: Repository, | |
59 | default_branch: DefaultBranch, | |
60 | // Ensure user is authorized for this request | |
61 | _user: AuthorizedUser, | |
62 | backend: DatabaseBackend, | |
63 | ) -> BoxFuture<'static, Result<(), ()>> { | |
64 | async move { | |
65 | let mut repository_backend = backend.repository_backend.lock().await; | |
66 | ||
67 | repository_backend | |
68 | .write_setting( | |
69 | &object, | |
70 | DefaultBranch::name(), | |
71 | &serde_json::to_value(default_branch.clone()).unwrap(), | |
72 | ) | |
73 | .await | |
74 | .unwrap(); | |
75 | ||
76 | let set_value = ValueUpdate { | |
77 | object: object.to_string(), | |
78 | value_name: DefaultBranch::value_name().to_owned(), | |
79 | value: unsafe { AnyValue::from_raw(serde_json::to_value(default_branch).unwrap()) }, | |
80 | }; | |
81 | ||
82 | // Submit value update back to the daemon | |
83 | // state.value_update(set_value); | |
84 | Ok(()) | |
85 | } | |
86 | .boxed() | |
87 | } |
giterated-models/src/authenticated.rs
@@ -14,7 +14,7 @@ use crate::{ | ||
14 | 14 | instance::Instance, |
15 | 15 | message::GiteratedMessage, |
16 | 16 | object::{AnyObject, GiteratedObject}, |
17 | operation::{AnyOperation, GiteratedOperation}, | |
17 | operation::{AnyOperation, AnyOperationV2, GiteratedOperation}, | |
18 | 18 | user::User, |
19 | 19 | }; |
20 | 20 | |
@@ -48,6 +48,14 @@ impl AuthenticatedPayload { | ||
48 | 48 | payload: AnyOperation(payload), |
49 | 49 | } |
50 | 50 | } |
51 | pub fn into_message_v2(self) -> GiteratedMessage<AnyObject, AnyOperationV2> { | |
52 | let payload = serde_json::from_slice::<Value>(&self.payload).unwrap(); | |
53 | GiteratedMessage { | |
54 | object: AnyObject(self.object), | |
55 | operation: self.operation, | |
56 | payload: AnyOperationV2(serde_json::to_vec(&self.payload).unwrap()), | |
57 | } | |
58 | } | |
51 | 59 | } |
52 | 60 | |
53 | 61 | pub trait AuthenticationSourceProvider: Debug { |
giterated-models/src/lib.rs
@@ -13,5 +13,6 @@ pub mod object_backend; | ||
13 | 13 | pub mod operation; |
14 | 14 | pub mod repository; |
15 | 15 | pub mod settings; |
16 | pub mod update; | |
16 | 17 | pub mod user; |
17 | 18 | pub mod value; |
giterated-models/src/object.rs
@@ -10,7 +10,7 @@ use crate::{ | ||
10 | 10 | error::{GetValueError, OperationError}, |
11 | 11 | object_backend::ObjectBackend, |
12 | 12 | operation::GiteratedOperation, |
13 | settings::{GetSetting, GetSettingError, SetSetting, SetSettingError, Setting}, | |
13 | settings::{AnySetting, GetSetting, GetSettingError, SetSetting, SetSettingError, Setting}, | |
14 | 14 | value::{GetValue, GiteratedObjectValue}, |
15 | 15 | }; |
16 | 16 | |
@@ -56,14 +56,18 @@ impl< | ||
56 | 56 | } |
57 | 57 | } |
58 | 58 | |
59 | pub trait GiteratedObject: Send + Display + FromStr { | |
59 | pub trait GiteratedObject: Send + Display + FromStr + Sync { | |
60 | 60 | fn object_name() -> &'static str; |
61 | 61 | |
62 | 62 | fn from_object_str(object_str: &str) -> Result<Self, Error>; |
63 | 63 | } |
64 | 64 | |
65 | impl<'b, I: Clone + Send + Sync, O: GiteratedObject + Clone + Debug, B: ObjectBackend<I>> | |
66 | Object<'b, I, O, B> | |
65 | impl< | |
66 | 'b, | |
67 | I: Clone + Send + Sync, | |
68 | O: GiteratedObject + Clone + Debug + 'static, | |
69 | B: ObjectBackend<I>, | |
70 | > Object<'b, I, O, B> | |
67 | 71 | { |
68 | 72 | pub async fn get<V: GiteratedObjectValue<Object = O> + Send + Debug>( |
69 | 73 | &mut self, |
@@ -89,11 +93,11 @@ impl<'b, I: Clone + Send + Sync, O: GiteratedObject + Clone + Debug, B: ObjectBa | ||
89 | 93 | self.request( |
90 | 94 | GetSetting { |
91 | 95 | setting_name: S::name().to_string(), |
92 | _marker: PhantomData, | |
93 | 96 | }, |
94 | 97 | operation_state, |
95 | 98 | ) |
96 | 99 | .await |
100 | .map(|success| serde_json::from_value(success).unwrap()) | |
97 | 101 | } |
98 | 102 | |
99 | 103 | pub async fn set_setting<S: Setting + Send + Clone + Debug>( |
@@ -104,7 +108,7 @@ impl<'b, I: Clone + Send + Sync, O: GiteratedObject + Clone + Debug, B: ObjectBa | ||
104 | 108 | self.request( |
105 | 109 | SetSetting { |
106 | 110 | setting_name: S::name().to_string(), |
107 | value: setting, | |
111 | value: AnySetting(serde_json::to_value(setting).unwrap()), | |
108 | 112 | }, |
109 | 113 | operation_state, |
110 | 114 | ) |
giterated-models/src/object_backend.rs
@@ -16,7 +16,7 @@ pub trait ObjectBackend<S: Clone + Send + Sync>: Send + Sync + Sized + Clone { | ||
16 | 16 | operation_state: &S, |
17 | 17 | ) -> Result<D::Success, OperationError<D::Failure>> |
18 | 18 | where |
19 | O: GiteratedObject + Debug, | |
19 | O: GiteratedObject + Debug + 'static, | |
20 | 20 | D: GiteratedOperation<O> + Debug; |
21 | 21 | |
22 | 22 | async fn get_object<O: GiteratedObject + Debug>( |
giterated-models/src/operation.rs
@@ -5,7 +5,9 @@ use serde_json::Value; | ||
5 | 5 | |
6 | 6 | use crate::object::GiteratedObject; |
7 | 7 | |
8 | pub trait GiteratedOperation<O: GiteratedObject>: Send + Serialize + DeserializeOwned { | |
8 | pub trait GiteratedOperation<O: GiteratedObject>: | |
9 | Send + Sync + Serialize + DeserializeOwned | |
10 | { | |
9 | 11 | type Success: Serialize + DeserializeOwned + Send; |
10 | 12 | type Failure: Serialize + DeserializeOwned + Send; |
11 | 13 | |
@@ -25,6 +27,17 @@ impl<O: GiteratedObject> GiteratedOperation<O> for AnyOperation { | ||
25 | 27 | type Failure = Value; |
26 | 28 | } |
27 | 29 | |
30 | #[derive(Clone, Debug, Serialize, Deserialize)] | |
31 | #[serde(transparent)] | |
32 | #[repr(transparent)] | |
33 | pub struct AnyOperationV2(pub Vec<u8>); | |
34 | ||
35 | impl<O: GiteratedObject> GiteratedOperation<O> for AnyOperationV2 { | |
36 | type Success = Vec<u8>; | |
37 | ||
38 | type Failure = Vec<u8>; | |
39 | } | |
40 | ||
28 | 41 | /// The internal state of an operation, used to provide authentication information |
29 | 42 | /// and the ability to make giterated calls within handlers. |
30 | 43 | #[derive(Clone)] |
giterated-models/src/settings/mod.rs
@@ -4,7 +4,7 @@ pub use operations::*; | ||
4 | 4 | use serde::{de::DeserializeOwned, Deserialize, Serialize}; |
5 | 5 | use serde_json::Value; |
6 | 6 | |
7 | pub trait Setting: Serialize + DeserializeOwned { | |
7 | pub trait Setting: Serialize + DeserializeOwned + Send + Sync { | |
8 | 8 | fn name() -> &'static str; |
9 | 9 | } |
10 | 10 |
giterated-models/src/settings/operations.rs
@@ -1,26 +1,24 @@ | ||
1 | 1 | use std::{fmt::Debug, marker::PhantomData}; |
2 | 2 | |
3 | 3 | use serde::{de::DeserializeOwned, Deserialize, Serialize}; |
4 | use serde_json::Value; | |
4 | 5 | use thiserror::Error; |
5 | 6 | |
6 | 7 | use crate::{object::GiteratedObject, operation::GiteratedOperation}; |
7 | 8 | |
8 | use super::Setting; | |
9 | use super::{AnySetting, Setting}; | |
9 | 10 | |
10 | 11 | #[derive(Serialize, Deserialize, Debug, Clone)] |
11 | pub struct GetSetting<S: Setting + std::fmt::Debug + Clone> { | |
12 | pub struct GetSetting { | |
12 | 13 | pub setting_name: String, |
13 | pub _marker: PhantomData<S>, | |
14 | 14 | } |
15 | 15 | |
16 | impl<O: GiteratedObject, S: Setting + Send + DeserializeOwned + Debug + Clone> GiteratedOperation<O> | |
17 | for GetSetting<S> | |
18 | { | |
16 | impl<O: GiteratedObject> GiteratedOperation<O> for GetSetting { | |
19 | 17 | fn operation_name() -> &'static str { |
20 | 18 | "get_setting" |
21 | 19 | } |
22 | 20 | |
23 | type Success = S; | |
21 | type Success = Value; | |
24 | 22 | |
25 | 23 | type Failure = GetSettingError; |
26 | 24 | } |
@@ -28,13 +26,12 @@ impl<O: GiteratedObject, S: Setting + Send + DeserializeOwned + Debug + Clone> G | ||
28 | 26 | #[derive(Error, Debug, Serialize, Deserialize)] |
29 | 27 | pub enum GetSettingError {} |
30 | 28 | #[derive(Serialize, Deserialize, Debug, Clone)] |
31 | #[serde(bound(deserialize = "S: Setting"))] | |
32 | pub struct SetSetting<S: Setting> { | |
29 | pub struct SetSetting { | |
33 | 30 | pub setting_name: String, |
34 | pub value: S, | |
31 | pub value: AnySetting, | |
35 | 32 | } |
36 | 33 | |
37 | impl<O: GiteratedObject, S: Setting + Send> GiteratedOperation<O> for SetSetting<S> { | |
34 | impl<O: GiteratedObject> GiteratedOperation<O> for SetSetting { | |
38 | 35 | fn operation_name() -> &'static str { |
39 | 36 | "set_setting" |
40 | 37 | } |
giterated-models/src/update/instance.rs
@@ -0,0 +1 @@ | ||
1 | pub struct InstanceUpdate {} |
giterated-models/src/update/mod.rs
@@ -0,0 +1,23 @@ | ||
1 | use crate::value::AnyValue; | |
2 | ||
3 | mod instance; | |
4 | mod repository; | |
5 | mod user; | |
6 | ||
7 | pub struct ValueUpdate { | |
8 | pub object: String, | |
9 | pub value_name: String, | |
10 | pub value: AnyValue<()>, | |
11 | } | |
12 | ||
13 | pub struct SettingUpdate { | |
14 | object: String, | |
15 | value_name: String, | |
16 | value: AnyValue<()>, | |
17 | } | |
18 | ||
19 | pub enum GiteratedUpdateKind { | |
20 | Instance, | |
21 | Repository, | |
22 | Value, | |
23 | } |
giterated-models/src/update/repository.rs
@@ -0,0 +1 @@ | ||
1 |
giterated-models/src/update/user.rs
@@ -0,0 +1 @@ | ||
1 |
giterated-models/src/value.rs
@@ -5,7 +5,7 @@ use serde_json::Value; | ||
5 | 5 | |
6 | 6 | use crate::{error::GetValueError, object::GiteratedObject, operation::GiteratedOperation}; |
7 | 7 | |
8 | pub trait GiteratedObjectValue: Serialize + DeserializeOwned { | |
8 | pub trait GiteratedObjectValue: Send + Sync + Serialize + DeserializeOwned { | |
9 | 9 | type Object: GiteratedObject; |
10 | 10 | |
11 | 11 | fn value_name() -> &'static str; |
@@ -17,6 +17,11 @@ pub struct GetValue<V: GiteratedObjectValue> { | ||
17 | 17 | pub(crate) _marker: PhantomData<V>, |
18 | 18 | } |
19 | 19 | |
20 | #[derive(Serialize, Deserialize, Debug, Clone)] | |
21 | pub struct GetValueV2 { | |
22 | pub value_name: String, | |
23 | } | |
24 | ||
20 | 25 | impl<O: GiteratedObject + Send, V: GiteratedObjectValue<Object = O> + Send> GiteratedOperation<O> |
21 | 26 | for GetValue<V> |
22 | 27 | { |
@@ -35,13 +40,17 @@ pub struct AnyValue<O> { | ||
35 | 40 | _marker: PhantomData<O>, |
36 | 41 | } |
37 | 42 | |
38 | impl<O: GiteratedObject> AnyValue<O> { | |
43 | impl<O> AnyValue<O> { | |
39 | 44 | pub unsafe fn from_raw(value: Value) -> Self { |
40 | 45 | Self { |
41 | 46 | value, |
42 | 47 | _marker: Default::default(), |
43 | 48 | } |
44 | 49 | } |
50 | ||
51 | pub fn into_inner(self) -> Value { | |
52 | self.value | |
53 | } | |
45 | 54 | } |
46 | 55 | |
47 | 56 | impl<O: GiteratedObject> GiteratedObjectValue for AnyValue<O> { |
giterated-stack/src/handler.rs
@@ -1,15 +1,21 @@ | ||
1 | 1 | use giterated_models::{ |
2 | 2 | error::OperationError, |
3 | instance::Instance, | |
3 | 4 | object::{ |
4 | 5 | AnyObject, GiteratedObject, Object, ObjectRequest, ObjectRequestError, ObjectResponse, |
5 | 6 | }, |
6 | 7 | object_backend::ObjectBackend, |
7 | 8 | operation::{AnyOperation, GiteratedOperation}, |
8 | 9 | }; |
9 | use std::{fmt::Debug, str::FromStr, sync::Arc}; | |
10 | use std::{any::Any, collections::HashMap, fmt::Debug, str::FromStr, sync::Arc}; | |
11 | use tokio::sync::Mutex; | |
10 | 12 | use tracing::warn; |
11 | 13 | |
12 | use crate::{state::HandlerState, OperationHandlers}; | |
14 | use crate::{ | |
15 | state::HandlerState, | |
16 | update::{HandleSettingUpdatedFunction, HandleValueUpdatedFunction, ValueUpdateKind}, | |
17 | OperationHandlers, | |
18 | }; | |
13 | 19 | |
14 | 20 | use crate::StackOperationState; |
15 | 21 | |
@@ -42,19 +48,23 @@ impl<S: HandlerState> ObjectBackend<StackOperationState> for GiteratedBackend<S> | ||
42 | 48 | operation_state: &StackOperationState, |
43 | 49 | ) -> Result<D::Success, OperationError<D::Failure>> |
44 | 50 | where |
45 | O: GiteratedObject + Debug, | |
51 | O: GiteratedObject + Debug + 'static, | |
46 | 52 | D: GiteratedOperation<O> + Debug, |
47 | 53 | { |
48 | 54 | let serialized = |
49 | 55 | serde_json::to_value(payload).map_err(|e| OperationError::Internal(e.to_string()))?; |
50 | let object = object.to_string(); | |
56 | let object = (Box::new(object) as Box<dyn Any + Send + Sync>) | |
57 | .downcast::<O>() | |
58 | .unwrap(); | |
51 | 59 | |
52 | 60 | if operation == ObjectRequest::operation_name() { |
53 | 61 | // We're doing an object request |
54 | 62 | let raw_result = self |
55 | 63 | .handlers |
56 | 64 | .resolve_object( |
57 | AnyObject(object.clone()), | |
65 | *(Box::new(object) as Box<dyn Any + Send + Sync>) | |
66 | .downcast() | |
67 | .unwrap(), | |
58 | 68 | serde_json::from_value(serialized).unwrap(), |
59 | 69 | self.state.clone(), |
60 | 70 | &operation_state, |
@@ -85,7 +95,7 @@ impl<S: HandlerState> ObjectBackend<StackOperationState> for GiteratedBackend<S> | ||
85 | 95 | let raw_result = self |
86 | 96 | .handlers |
87 | 97 | .handle( |
88 | &AnyObject(object), | |
98 | &*object, | |
89 | 99 | operation, |
90 | 100 | AnyOperation(serialized), |
91 | 101 | self.state.clone(), |
@@ -122,7 +132,7 @@ impl<S: HandlerState> ObjectBackend<StackOperationState> for GiteratedBackend<S> | ||
122 | 132 | let raw_result = self |
123 | 133 | .handlers |
124 | 134 | .resolve_object( |
125 | AnyObject("giterated.dev".to_string()), | |
135 | Instance::from_str("giterated.dev").unwrap(), | |
126 | 136 | ObjectRequest(object_str.to_string()), |
127 | 137 | self.state.clone(), |
128 | 138 | operation_state, |
giterated-stack/src/lib.rs
@@ -1,7 +1,11 @@ | ||
1 | 1 | pub mod handler; |
2 | pub mod runtime; | |
2 | 3 | pub mod state; |
4 | pub mod update; | |
3 | 5 | |
4 | use std::{collections::HashMap, future::Future, ops::Deref, pin::Pin, str::FromStr, sync::Arc}; | |
6 | use std::{ | |
7 | any::Any, collections::HashMap, future::Future, ops::Deref, pin::Pin, str::FromStr, sync::Arc, | |
8 | }; | |
5 | 9 | |
6 | 10 | use futures_util::FutureExt; |
7 | 11 | use giterated_models::{ |
@@ -14,15 +18,24 @@ use giterated_models::{ | ||
14 | 18 | }, |
15 | 19 | object_backend::ObjectBackend, |
16 | 20 | operation::{AnyOperation, GiteratedOperation}, |
17 | repository::Repository, | |
21 | repository::{AccessList, Repository}, | |
22 | settings::{AnySetting, GetSetting, SetSetting, Setting}, | |
18 | 23 | user::User, |
24 | value::{AnyValue, GetValue, GiteratedObjectValue}, | |
19 | 25 | }; |
20 | 26 | use handler::GiteratedBackend; |
21 | 27 | use serde::{de::DeserializeOwned, Serialize}; |
22 | 28 | use serde_json::Value; |
23 | 29 | use state::HandlerState; |
24 | use tokio::{sync::mpsc::channel, task::JoinHandle}; | |
30 | use tokio::{ | |
31 | sync::{mpsc::channel, Mutex}, | |
32 | task::JoinHandle, | |
33 | }; | |
25 | 34 | use tracing::{error, warn}; |
35 | use update::{ | |
36 | HandleSettingUpdate, HandleSettingUpdatedFunction, HandleValueUpdate, | |
37 | HandleValueUpdatedFunction, SettingUpdateKind, ValueUpdateKind, | |
38 | }; | |
26 | 39 | |
27 | 40 | #[derive(Clone, Debug, Hash, Eq, PartialEq)] |
28 | 41 | struct ObjectOperationPair { |
@@ -30,9 +43,48 @@ struct ObjectOperationPair { | ||
30 | 43 | operation_name: String, |
31 | 44 | } |
32 | 45 | |
46 | pub struct SettingMeta { | |
47 | name: String, | |
48 | deserialize: Box<dyn Fn(&[u8]) -> Result<Box<dyn Any>, serde_json::Error> + Send + Sync>, | |
49 | } | |
50 | ||
51 | pub struct ValueMeta { | |
52 | name: String, | |
53 | deserialize: Box<dyn Fn(&[u8]) -> Result<Box<dyn Any>, serde_json::Error> + Send + Sync>, | |
54 | } | |
55 | ||
56 | pub struct ObjectMeta { | |
57 | name: String, | |
58 | from_str: Box<dyn Fn(&str) -> Result<Box<dyn Any + Send + Sync>, ()> + Send + Sync>, | |
59 | any_is_same: Box<dyn Fn(&dyn Any) -> bool + Send + Sync>, | |
60 | } | |
61 | ||
62 | pub struct OperationMeta { | |
63 | name: String, | |
64 | object_kind: String, | |
65 | deserialize: Box<dyn Fn(&[u8]) -> Result<Box<dyn Any + Send + Sync>, ()> + Send + Sync>, | |
66 | any_is_same: Box<dyn Fn(&dyn Any) -> bool + Send + Sync>, | |
67 | serialize_success: | |
68 | Box<dyn Fn(Box<dyn Any>) -> Result<Vec<u8>, serde_json::Error> + Send + Sync>, | |
69 | serialize_error: Box<dyn Fn(Box<dyn Any>) -> Result<Vec<u8>, serde_json::Error> + Send + Sync>, | |
70 | } | |
71 | ||
33 | 72 | pub struct OperationHandlers<S: Send + Sync + Clone> { |
34 | 73 | operations: HashMap<ObjectOperationPair, OperationWrapper<S>>, |
35 | 74 | get_object: Vec<OperationWrapper<S>>, |
75 | value_getters: HashMap<ValueGetter, OperationWrapper<S>>, | |
76 | settings_getter: HashMap<String, OperationWrapper<S>>, | |
77 | settings: HashMap<String, SettingMeta>, | |
78 | objects: HashMap<String, ObjectMeta>, | |
79 | operations_meta: HashMap<ObjectOperationPair, OperationMeta>, | |
80 | value_updated: HashMap<ValueUpdateKind, HandleValueUpdatedFunction>, | |
81 | setting_updated: HashMap<SettingUpdateKind, HandleSettingUpdatedFunction>, | |
82 | } | |
83 | ||
84 | #[derive(Clone, Debug, Hash, Eq, PartialEq)] | |
85 | pub struct ObjectValuePair { | |
86 | pub object_kind: String, | |
87 | pub value_kind: String, | |
36 | 88 | } |
37 | 89 | |
38 | 90 | impl<S: Send + Sync + Clone> Default for OperationHandlers<S> { |
@@ -40,15 +92,58 @@ impl<S: Send + Sync + Clone> Default for OperationHandlers<S> { | ||
40 | 92 | Self { |
41 | 93 | operations: HashMap::new(), |
42 | 94 | get_object: Vec::new(), |
95 | value_updated: HashMap::default(), | |
96 | setting_updated: HashMap::default(), | |
97 | value_getters: HashMap::default(), | |
98 | settings_getter: HashMap::default(), | |
99 | settings: HashMap::default(), | |
100 | objects: HashMap::default(), | |
101 | operations_meta: HashMap::default(), | |
43 | 102 | } |
44 | 103 | } |
45 | 104 | } |
46 | 105 | |
47 | 106 | impl<S: Send + Sync + Clone + 'static> OperationHandlers<S> { |
107 | fn insert_operation<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync + 'static>( | |
108 | &mut self, | |
109 | ) { | |
110 | // let object_name = O::object_name().to_string(); | |
111 | // let operation_name = D::operation_name().to_string(); | |
112 | ||
113 | // self.operations_meta.insert( | |
114 | // ObjectOperationPair { | |
115 | // object_name: object_name.clone(), | |
116 | // operation_name: operation_name.clone(), | |
117 | // }, | |
118 | // OperationMeta { | |
119 | // name: operation_name, | |
120 | // object_kind: object_name, | |
121 | // deserialize: Box::new(|bytes| { | |
122 | // Ok(Box::new(serde_json::from_slice::<D>(bytes).unwrap()) | |
123 | // as Box<dyn Any + Send + Sync>) | |
124 | // }), | |
125 | // any_is_same: Box::new(|any_box| any_box.is::<D>()), | |
126 | // }, | |
127 | // ); | |
128 | } | |
129 | ||
130 | pub fn setting<T: Setting>(&mut self) -> &mut Self { | |
131 | let setting_meta = SettingMeta { | |
132 | name: T::name().to_string(), | |
133 | deserialize: Box::new(|slice| { | |
134 | Ok(Box::new(serde_json::from_slice(slice)?) as Box<dyn Any>) | |
135 | }), | |
136 | }; | |
137 | ||
138 | self.settings.insert(T::name().to_string(), setting_meta); | |
139 | ||
140 | self | |
141 | } | |
142 | ||
48 | 143 | pub fn insert< |
49 | 144 | A, |
50 | O: GiteratedObject + Send + Sync, | |
51 | D: GiteratedOperation<O> + 'static, | |
145 | O: GiteratedObject + Send + Sync + 'static, | |
146 | D: GiteratedOperation<O> + Send + Sync + 'static, | |
52 | 147 | H: GiteratedOperationHandler<A, O, D, S> + Send + Sync + 'static + Clone, |
53 | 148 | >( |
54 | 149 | &mut self, |
@@ -66,10 +161,21 @@ impl<S: Send + Sync + Clone + 'static> OperationHandlers<S> { | ||
66 | 161 | |
67 | 162 | assert!(self.operations.insert(pair, wrapped).is_none()); |
68 | 163 | |
164 | self.insert_operation::<O, D>(); | |
165 | ||
69 | 166 | self |
70 | 167 | } |
71 | 168 | |
72 | pub fn register_object<O: GiteratedObject + Send + Sync>(&mut self) -> &mut Self { | |
169 | pub fn object<O: GiteratedObject + Send + Sync + 'static>(&mut self) -> &mut Self { | |
170 | // let object_meta = ObjectMeta { | |
171 | // name: O::object_name().to_string(), | |
172 | // from_str: Box::new(|str| Ok(Box::new(O::from_str(&str).map_err(|_| ())?))), | |
173 | ||
174 | // }; | |
175 | ||
176 | // self.objects | |
177 | // .insert(O::object_name().to_string(), object_meta); | |
178 | ||
73 | 179 | let closure = |_: &Instance, operation: ObjectRequest, _state| { |
74 | 180 | async move { |
75 | 181 | if O::from_str(&operation.0).is_ok() { |
@@ -98,33 +204,32 @@ impl<S: Send + Sync + Clone + 'static> OperationHandlers<S> { | ||
98 | 204 | ) -> Result<Vec<u8>, OperationError<Vec<u8>>> { |
99 | 205 | // TODO |
100 | 206 | let object = object.to_string(); |
207 | let object_name = O::object_name().to_string(); | |
101 | 208 | |
102 | let object_name = { | |
103 | if User::from_str(&object).is_ok() { | |
104 | User::object_name() | |
105 | } else if Repository::from_str(&object).is_ok() { | |
106 | Repository::object_name() | |
107 | } else if Instance::from_str(&object).is_ok() { | |
108 | Instance::object_name() | |
109 | } else { | |
110 | return Err(OperationError::Unhandled); | |
111 | } | |
112 | } | |
113 | .to_string(); | |
209 | let object_meta = self | |
210 | .objects | |
211 | .get(&object_name) | |
212 | .ok_or_else(|| OperationError::Unhandled)?; | |
213 | ||
214 | let object_box = (object_meta.from_str)(&object).map_err(|_| OperationError::Unhandled)?; | |
114 | 215 | |
115 | 216 | let target_handler = ObjectOperationPair { |
116 | 217 | object_name, |
117 | 218 | operation_name: operation_name.to_string(), |
118 | 219 | }; |
119 | 220 | |
221 | let operation_meta = self | |
222 | .operations_meta | |
223 | .get(&target_handler) | |
224 | .ok_or_else(|| OperationError::Unhandled)?; | |
225 | ||
226 | let operation_box = | |
227 | (operation_meta.deserialize)(&serde_json::to_vec(&operation.0).unwrap()) | |
228 | .map_err(|_| OperationError::Unhandled)?; | |
229 | ||
120 | 230 | if let Some(handler) = self.operations.get(&target_handler) { |
121 | 231 | handler |
122 | .handle( | |
123 | AnyObject(object.to_string()), | |
124 | operation.clone(), | |
125 | state.clone(), | |
126 | operation_state, | |
127 | ) | |
232 | .handle(object_box, operation_box, state.clone(), operation_state) | |
128 | 233 | .await |
129 | 234 | } else { |
130 | 235 | Err(OperationError::Unhandled) |
@@ -133,7 +238,7 @@ impl<S: Send + Sync + Clone + 'static> OperationHandlers<S> { | ||
133 | 238 | |
134 | 239 | pub async fn resolve_object( |
135 | 240 | &self, |
136 | instance: AnyObject, | |
241 | instance: Instance, | |
137 | 242 | request: ObjectRequest, |
138 | 243 | state: S, |
139 | 244 | operation_state: &StackOperationState, |
@@ -141,8 +246,8 @@ impl<S: Send + Sync + Clone + 'static> OperationHandlers<S> { | ||
141 | 246 | for handler in self.get_object.iter() { |
142 | 247 | if let Ok(response) = handler |
143 | 248 | .handle( |
144 | instance.clone(), | |
145 | AnyOperation(serde_json::to_value(request.clone()).unwrap()), | |
249 | Box::new(instance.clone()) as _, | |
250 | Box::new(request.clone()) as _, | |
146 | 251 | state.clone(), |
147 | 252 | operation_state, |
148 | 253 | ) |
@@ -154,6 +259,96 @@ impl<S: Send + Sync + Clone + 'static> OperationHandlers<S> { | ||
154 | 259 | |
155 | 260 | Err(OperationError::Unhandled) |
156 | 261 | } |
262 | ||
263 | pub fn insert_value_update_handler< | |
264 | H: HandleValueUpdate<O, V> + Send + Sync + Clone + 'static, | |
265 | O: GiteratedObject + Send + Sync, | |
266 | V: GiteratedObjectValue<Object = O> + Send + Sync, | |
267 | >( | |
268 | &mut self, | |
269 | handler: H, | |
270 | ) -> &mut Self { | |
271 | let wrapper = HandleValueUpdatedFunction::new(handler, V::value_name()); | |
272 | ||
273 | assert!(self | |
274 | .value_updated | |
275 | .insert(wrapper.target.clone(), wrapper) | |
276 | .is_none()); | |
277 | ||
278 | self | |
279 | } | |
280 | ||
281 | pub fn insert_setting_update_handler< | |
282 | H: HandleSettingUpdate<O, T> + Send + Sync + Clone + 'static, | |
283 | O: GiteratedObject + Send + Sync, | |
284 | T: Setting + Send + Sync, | |
285 | >( | |
286 | &mut self, | |
287 | handler: H, | |
288 | ) -> &mut Self { | |
289 | let wrapper = HandleSettingUpdatedFunction::new(handler, T::name()); | |
290 | ||
291 | assert!(self | |
292 | .setting_updated | |
293 | .insert(wrapper.target.clone(), wrapper) | |
294 | .is_none()); | |
295 | ||
296 | self | |
297 | } | |
298 | ||
299 | pub fn value_getter<A, O, V, F>(&mut self, handler: F) -> &mut Self | |
300 | where | |
301 | O: GiteratedObject + Send + Sync + 'static, | |
302 | V: GiteratedObjectValue<Object = O> + Send + Sync + 'static, | |
303 | F: GiteratedOperationHandler<A, O, GetValue<V>, S> + Send + Sync + Clone + 'static, | |
304 | { | |
305 | let object_name = handler.object_name().to_string(); | |
306 | let value_name = V::value_name().to_string(); | |
307 | ||
308 | let wrapped = OperationWrapper::new(handler); | |
309 | ||
310 | assert!(self | |
311 | .value_getters | |
312 | .insert( | |
313 | ValueGetter { | |
314 | object_type: object_name, | |
315 | value_type: value_name | |
316 | }, | |
317 | wrapped | |
318 | ) | |
319 | .is_none()); | |
320 | ||
321 | self | |
322 | } | |
323 | ||
324 | pub fn setting_getter<A, O, F>(&mut self, handler: F) -> &mut Self | |
325 | where | |
326 | O: GiteratedObject + Send + Sync + 'static, | |
327 | F: GiteratedOperationHandler<A, O, GetSetting, S> + Send + Sync + Clone + 'static, | |
328 | { | |
329 | let object_name = handler.object_name().to_string(); | |
330 | ||
331 | let wrapped = OperationWrapper::new(handler); | |
332 | ||
333 | assert!(self.settings_getter.insert(object_name, wrapped).is_none()); | |
334 | ||
335 | self | |
336 | } | |
337 | } | |
338 | ||
339 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] | |
340 | pub struct ValueGetter { | |
341 | pub object_type: String, | |
342 | pub value_type: String, | |
343 | } | |
344 | ||
345 | impl Default for ValueGetter { | |
346 | fn default() -> Self { | |
347 | Self { | |
348 | object_type: AnyObject::object_name().to_string(), | |
349 | value_type: "any".to_string(), | |
350 | } | |
351 | } | |
157 | 352 | } |
158 | 353 | |
159 | 354 | #[async_trait::async_trait] |
@@ -162,7 +357,7 @@ pub trait GiteratedOperationHandler< | ||
162 | 357 | O: GiteratedObject, |
163 | 358 | D: GiteratedOperation<O>, |
164 | 359 | S: Send + Sync + Clone, |
165 | > | |
360 | >: Send + Sync | |
166 | 361 | { |
167 | 362 | fn operation_name(&self) -> &str; |
168 | 363 | fn object_name(&self) -> &str; |
@@ -353,8 +548,8 @@ where | ||
353 | 548 | pub struct OperationWrapper<S: Send + Sync + Clone> { |
354 | 549 | func: Box< |
355 | 550 | dyn Fn( |
356 | AnyObject, | |
357 | AnyOperation, | |
551 | Box<dyn Any + Send + Sync>, | |
552 | Box<dyn Any + Send + Sync>, | |
358 | 553 | S, |
359 | 554 | StackOperationState, |
360 | 555 | ) |
@@ -368,7 +563,7 @@ pub struct OperationWrapper<S: Send + Sync + Clone> { | ||
368 | 563 | impl<S: Send + Sync + Clone + 'static> OperationWrapper<S> { |
369 | 564 | pub fn new< |
370 | 565 | A, |
371 | O: GiteratedObject + Send + Sync, | |
566 | O: GiteratedObject + Send + Sync + 'static, | |
372 | 567 | D: GiteratedOperation<O> + 'static, |
373 | 568 | F: GiteratedOperationHandler<A, O, D, S> + Send + Sync + 'static + Clone, |
374 | 569 | >( |
@@ -376,17 +571,15 @@ impl<S: Send + Sync + Clone + 'static> OperationWrapper<S> { | ||
376 | 571 | ) -> Self { |
377 | 572 | let handler = Arc::new(Box::pin(handler)); |
378 | 573 | Self { |
379 | func: Box::new(move |any_object, any_operation, state, operation_state| { | |
574 | func: Box::new(move |object, operation, state, operation_state| { | |
380 | 575 | let handler = handler.clone(); |
381 | 576 | async move { |
382 | 577 | let handler = handler.clone(); |
383 | let object: O = | |
384 | O::from_object_str(&any_object.0).map_err(|_| OperationError::Unhandled)?; | |
385 | let operation: D = serde_json::from_value(any_operation.0.clone()) | |
386 | .map_err(|_| OperationError::Unhandled)?; | |
578 | let object: Box<O> = object.downcast().unwrap(); | |
579 | let operation: Box<D> = operation.downcast().unwrap(); | |
387 | 580 | |
388 | 581 | let result = handler |
389 | .handle(&object, operation, state, &operation_state) | |
582 | .handle(&object, *operation, state, &operation_state) | |
390 | 583 | .await; |
391 | 584 | result |
392 | 585 | .map(|success| serde_json::to_vec(&success).unwrap()) |
@@ -408,8 +601,8 @@ impl<S: Send + Sync + Clone + 'static> OperationWrapper<S> { | ||
408 | 601 | |
409 | 602 | async fn handle( |
410 | 603 | &self, |
411 | object: AnyObject, | |
412 | operation: AnyOperation, | |
604 | object: Box<dyn Any + Send + Sync>, | |
605 | operation: Box<dyn Any + Send + Sync>, | |
413 | 606 | state: S, |
414 | 607 | operation_state: &StackOperationState, |
415 | 608 | ) -> Result<Vec<u8>, OperationError<Vec<u8>>> { |
@@ -530,6 +723,129 @@ pub trait AuthorizedOperation<O: GiteratedObject>: GiteratedOperation<O> { | ||
530 | 723 | } |
531 | 724 | |
532 | 725 | #[async_trait::async_trait] |
726 | impl< | |
727 | O: GiteratedObject + Send + Sync + Debug, | |
728 | V: GiteratedObjectValue<Object = O> + Send + Sync, | |
729 | > AuthorizedOperation<O> for GetValue<V> | |
730 | { | |
731 | async fn authorize( | |
732 | &self, | |
733 | authorize_for: &O, | |
734 | operation_state: &StackOperationState, | |
735 | ) -> Result<bool, OperationError<()>> { | |
736 | Ok(operation_state | |
737 | .giterated_backend | |
738 | .get_object::<O>(&authorize_for.to_string(), operation_state) | |
739 | .await | |
740 | .is_ok()) | |
741 | } | |
742 | } | |
743 | ||
744 | #[async_trait::async_trait] | |
745 | impl AuthorizedOperation<User> for SetSetting { | |
746 | async fn authorize( | |
747 | &self, | |
748 | authorize_for: &User, | |
749 | operation_state: &StackOperationState, | |
750 | ) -> Result<bool, OperationError<()>> { | |
751 | let authenticated_user = operation_state | |
752 | .user | |
753 | .as_ref() | |
754 | .ok_or_else(|| OperationError::Operation(()))?; | |
755 | ||
756 | Ok(authorize_for == authenticated_user.deref()) | |
757 | } | |
758 | } | |
759 | ||
760 | #[async_trait::async_trait] | |
761 | impl AuthorizedOperation<User> for GetSetting { | |
762 | async fn authorize( | |
763 | &self, | |
764 | authorize_for: &User, | |
765 | operation_state: &StackOperationState, | |
766 | ) -> Result<bool, OperationError<()>> { | |
767 | let authenticated_user = operation_state | |
768 | .user | |
769 | .as_ref() | |
770 | .ok_or_else(|| OperationError::Operation(()))?; | |
771 | ||
772 | Ok(authorize_for == authenticated_user.deref()) | |
773 | } | |
774 | } | |
775 | ||
776 | #[async_trait::async_trait] | |
777 | impl AuthorizedOperation<Repository> for SetSetting { | |
778 | async fn authorize( | |
779 | &self, | |
780 | authorize_for: &Repository, | |
781 | operation_state: &StackOperationState, | |
782 | ) -> Result<bool, OperationError<()>> { | |
783 | let authenticated_user = operation_state | |
784 | .user | |
785 | .as_ref() | |
786 | .ok_or_else(|| OperationError::Operation(()))?; | |
787 | ||
788 | let mut object = operation_state | |
789 | .giterated_backend | |
790 | .get_object::<Repository>(&authorize_for.to_string(), operation_state) | |
791 | .await | |
792 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
793 | ||
794 | let access_list = object | |
795 | .get_setting::<AccessList>(operation_state) | |
796 | .await | |
797 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
798 | ||
799 | if access_list | |
800 | .0 | |
801 | .iter() | |
802 | .find(|user| *user == authenticated_user.deref()) | |
803 | .is_some() | |
804 | { | |
805 | Ok(true) | |
806 | } else { | |
807 | Ok(false) | |
808 | } | |
809 | } | |
810 | } | |
811 | ||
812 | #[async_trait::async_trait] | |
813 | impl AuthorizedOperation<Repository> for GetSetting { | |
814 | async fn authorize( | |
815 | &self, | |
816 | authorize_for: &Repository, | |
817 | operation_state: &StackOperationState, | |
818 | ) -> Result<bool, OperationError<()>> { | |
819 | let authenticated_user = operation_state | |
820 | .user | |
821 | .as_ref() | |
822 | .ok_or_else(|| OperationError::Operation(()))?; | |
823 | ||
824 | let mut object = operation_state | |
825 | .giterated_backend | |
826 | .get_object::<Repository>(&authorize_for.to_string(), operation_state) | |
827 | .await | |
828 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
829 | ||
830 | let access_list = object | |
831 | .get_setting::<AccessList>(operation_state) | |
832 | .await | |
833 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
834 | ||
835 | if access_list | |
836 | .0 | |
837 | .iter() | |
838 | .find(|user| *user == authenticated_user.deref()) | |
839 | .is_some() | |
840 | { | |
841 | Ok(true) | |
842 | } else { | |
843 | Ok(false) | |
844 | } | |
845 | } | |
846 | } | |
847 | ||
848 | #[async_trait::async_trait] | |
533 | 849 | impl AuthorizedOperation<Instance> for RegisterAccountRequest { |
534 | 850 | async fn authorize( |
535 | 851 | &self, |
giterated-stack/src/runtime.rs
@@ -0,0 +1,502 @@ | ||
1 | use std::{any::Any, collections::HashMap}; | |
2 | ||
3 | use giterated_models::{ | |
4 | authenticated::AuthenticatedPayload, | |
5 | error::OperationError, | |
6 | message::GiteratedMessage, | |
7 | object::{AnyObject, GiteratedObject}, | |
8 | operation::{AnyOperation, AnyOperationV2, GiteratedOperation}, | |
9 | settings::{AnySetting, GetSetting, SetSetting, Setting}, | |
10 | value::{GetValue, GetValueV2, GiteratedObjectValue}, | |
11 | }; | |
12 | use tracing::trace; | |
13 | ||
14 | use crate::{ | |
15 | GiteratedOperationHandler, ObjectMeta, ObjectOperationPair, ObjectValuePair, OperationMeta, | |
16 | OperationWrapper, SettingMeta, StackOperationState, ValueMeta, | |
17 | }; | |
18 | ||
19 | /// Temporary name for the next generation of Giterated stack | |
20 | pub struct GiteratedRuntime<S: GiteratedRuntimeState> { | |
21 | operation_handlers: HashMap<ObjectOperationPair, HandlerTree<S>>, | |
22 | value_getters: HashMap<ObjectValuePair, OperationWrapper<S>>, | |
23 | setting_getters: HashMap<String, OperationWrapper<S>>, | |
24 | metadata: RuntimeMetadata, | |
25 | } | |
26 | ||
27 | impl<S: GiteratedRuntimeState> GiteratedRuntime<S> { | |
28 | pub fn merge_builder(&mut self, builder: RuntimeBuilder<S>) -> &mut Self { | |
29 | for (target, handler) in builder.operation_handlers { | |
30 | let tree = self.get_or_create_tree(&target); | |
31 | ||
32 | tree.push(handler); | |
33 | } | |
34 | ||
35 | for (target, handler) in builder.value_getters { | |
36 | assert!(self.value_getters.insert(target, handler).is_none()); | |
37 | } | |
38 | ||
39 | for (target, handler) in builder.setting_getters { | |
40 | assert!(self.setting_getters.insert(target, handler).is_none()); | |
41 | } | |
42 | ||
43 | self.metadata.append(builder.metadata); | |
44 | ||
45 | self | |
46 | } | |
47 | ||
48 | fn get_or_create_tree(&mut self, target: &ObjectOperationPair) -> &mut HandlerTree<S> { | |
49 | if self.operation_handlers.contains_key(target) { | |
50 | self.operation_handlers.get_mut(target).unwrap() | |
51 | } else { | |
52 | self.operation_handlers | |
53 | .insert(target.clone(), HandlerTree::default()); | |
54 | ||
55 | self.operation_handlers.get_mut(target).unwrap() | |
56 | } | |
57 | } | |
58 | } | |
59 | ||
60 | pub struct HandlerTree<S: GiteratedRuntimeState> { | |
61 | elements: Vec<OperationWrapper<S>>, | |
62 | } | |
63 | ||
64 | impl<S: GiteratedRuntimeState> Default for HandlerTree<S> { | |
65 | fn default() -> Self { | |
66 | Self { elements: vec![] } | |
67 | } | |
68 | } | |
69 | ||
70 | impl<S: GiteratedRuntimeState> HandlerTree<S> { | |
71 | pub fn push(&mut self, handler: OperationWrapper<S>) { | |
72 | self.elements.push(handler); | |
73 | } | |
74 | ||
75 | pub fn handle( | |
76 | &self, | |
77 | object: &dyn Any, | |
78 | operation: Box<dyn Any>, | |
79 | state: &S, | |
80 | operation_state: &StackOperationState, | |
81 | ) -> Result<Box<dyn Any>, OperationError<Box<dyn Any>>> { | |
82 | todo!() | |
83 | } | |
84 | } | |
85 | ||
86 | /// Stores runtime metadata for all in-use Giterated protocol types. | |
87 | #[derive(Default)] | |
88 | struct RuntimeMetadata { | |
89 | objects: HashMap<String, ObjectMeta>, | |
90 | operations: HashMap<ObjectOperationPair, OperationMeta>, | |
91 | values: HashMap<ObjectValuePair, ValueMeta>, | |
92 | settings: HashMap<String, SettingMeta>, | |
93 | } | |
94 | ||
95 | /// Defines a type that is a valid Giterated runtime state. | |
96 | /// | |
97 | /// This allows for extraction of state in handlers, based on a | |
98 | /// [`FromOperationState<S>`] impl on (what is in this case) [`Self`]. | |
99 | pub trait GiteratedRuntimeState: Send + Sync + Clone {} | |
100 | ||
101 | impl<T: Send + Sync + Clone> GiteratedRuntimeState for T {} | |
102 | ||
103 | #[derive(Default)] | |
104 | pub struct RuntimeBuilder<S: GiteratedRuntimeState> { | |
105 | operation_handlers: HashMap<ObjectOperationPair, OperationWrapper<S>>, | |
106 | value_getters: HashMap<ObjectValuePair, OperationWrapper<S>>, | |
107 | setting_getters: HashMap<String, OperationWrapper<S>>, | |
108 | metadata: RuntimeMetadata, | |
109 | } | |
110 | ||
111 | impl<S: GiteratedRuntimeState + 'static> RuntimeBuilder<S> { | |
112 | /// Insert an operation handler into the runtime builder. | |
113 | /// | |
114 | /// # Type Registration | |
115 | /// Inserting the handler will automatically, if required, register the operation type of the | |
116 | /// handler. It will **not** register the object type automatically. | |
117 | pub fn operation<A, O, D, H>(&mut self, handler: H) -> &mut Self | |
118 | where | |
119 | O: GiteratedObject + 'static, | |
120 | D: GiteratedOperation<O> + 'static, | |
121 | H: GiteratedOperationHandler<A, O, D, S> + 'static + Clone, | |
122 | { | |
123 | let object_name = handler.object_name().to_string(); | |
124 | let operation_name = handler.operation_name().to_string(); | |
125 | ||
126 | let wrapped = OperationWrapper::new(handler); | |
127 | ||
128 | let pair = ObjectOperationPair { | |
129 | object_name, | |
130 | operation_name, | |
131 | }; | |
132 | ||
133 | assert!(self.operation_handlers.insert(pair, wrapped).is_none()); | |
134 | ||
135 | self.metadata.register_operation::<O, D>(); | |
136 | ||
137 | self | |
138 | } | |
139 | ||
140 | /// Register a [`GiteratedObject`] type with the runtime. | |
141 | /// | |
142 | /// # Type Registration | |
143 | /// This will register the provided object type. | |
144 | pub fn object<O: GiteratedObject + 'static>(&mut self) -> &mut Self { | |
145 | self.metadata.register_object::<O>(); | |
146 | ||
147 | self | |
148 | } | |
149 | ||
150 | /// Register a [`Setting`] type with the runtime. | |
151 | /// | |
152 | /// # Type Registration | |
153 | /// This will register the provided setting type. | |
154 | pub fn setting<T: Setting>(&mut self) -> &mut Self { | |
155 | self.metadata.register_setting::<T>(); | |
156 | ||
157 | self | |
158 | } | |
159 | ||
160 | /// Register a [`GiteratedObjectValue<O>`] type with the runtime, providing | |
161 | /// its associated handler for [`GetValue`]. | |
162 | /// | |
163 | /// # Type Registration | |
164 | /// This will register the provided [`GiteratedObjectValue`] type for its matching / specified | |
165 | /// object type. It will **not** register the object type automatically. | |
166 | pub fn value<O, V, A, F>(&mut self, handler: F) -> &mut Self | |
167 | where | |
168 | O: GiteratedObject + 'static, | |
169 | V: GiteratedObjectValue<Object = O> + 'static, | |
170 | F: GiteratedOperationHandler<A, O, GetValue<V>, S> + Clone + 'static, | |
171 | { | |
172 | let object_name = handler.object_name().to_string(); | |
173 | let value_name = V::value_name().to_string(); | |
174 | ||
175 | let wrapped = OperationWrapper::new(handler); | |
176 | ||
177 | assert!(self | |
178 | .value_getters | |
179 | .insert( | |
180 | ObjectValuePair { | |
181 | object_kind: object_name, | |
182 | value_kind: value_name | |
183 | }, | |
184 | wrapped | |
185 | ) | |
186 | .is_none()); | |
187 | ||
188 | self.metadata.register_value::<O, V>(); | |
189 | ||
190 | self | |
191 | } | |
192 | ||
193 | /// Register a handler for [`GetSetting`] for it's associated object type. | |
194 | pub fn object_settings<O, A, F>(&mut self, handler: F) -> &mut Self | |
195 | where | |
196 | O: GiteratedObject + 'static, | |
197 | F: GiteratedOperationHandler<A, O, GetSetting, S> + Clone + 'static, | |
198 | { | |
199 | let object_name = handler.object_name().to_string(); | |
200 | ||
201 | let wrapped = OperationWrapper::new(handler); | |
202 | ||
203 | assert!(self.setting_getters.insert(object_name, wrapped).is_none()); | |
204 | ||
205 | self | |
206 | } | |
207 | } | |
208 | ||
209 | impl RuntimeMetadata { | |
210 | fn register_object<O: GiteratedObject + 'static>(&mut self) { | |
211 | let object_name = O::object_name().to_string(); | |
212 | ||
213 | let object_meta = ObjectMeta { | |
214 | name: object_name.clone(), | |
215 | from_str: Box::new(|str| Ok(Box::new(O::from_str(&str).map_err(|_| ())?))), | |
216 | any_is_same: Box::new(|any| any.is::<O>()), | |
217 | }; | |
218 | ||
219 | if self.objects.insert(object_name, object_meta).is_some() { | |
220 | trace!( | |
221 | "Registration of object {} overwrote previous registration.", | |
222 | O::object_name() | |
223 | ); | |
224 | } else { | |
225 | trace!("Registration of object {}.", O::object_name()) | |
226 | } | |
227 | } | |
228 | ||
229 | fn register_operation<O: GiteratedObject + 'static, D: GiteratedOperation<O> + 'static>( | |
230 | &mut self, | |
231 | ) { | |
232 | let object_name = O::object_name().to_string(); | |
233 | let operation_name = D::operation_name().to_string(); | |
234 | ||
235 | if self | |
236 | .operations | |
237 | .insert( | |
238 | ObjectOperationPair { | |
239 | object_name: object_name.clone(), | |
240 | operation_name: operation_name.clone(), | |
241 | }, | |
242 | OperationMeta { | |
243 | name: operation_name, | |
244 | object_kind: object_name, | |
245 | deserialize: Box::new(|bytes| { | |
246 | Ok(Box::new(serde_json::from_slice::<D>(bytes).unwrap()) | |
247 | as Box<dyn Any + Send + Sync>) | |
248 | }), | |
249 | any_is_same: Box::new(|any_box| any_box.is::<D>()), | |
250 | serialize_success: Box::new(|any| { | |
251 | let to_serialize = any.downcast::<D::Success>().unwrap(); | |
252 | serde_json::to_vec(&to_serialize) | |
253 | }), | |
254 | serialize_error: Box::new(|any| { | |
255 | let to_serialize = any.downcast::<D::Failure>().unwrap(); | |
256 | serde_json::to_vec(&to_serialize) | |
257 | }), | |
258 | }, | |
259 | ) | |
260 | .is_some() | |
261 | { | |
262 | trace!( | |
263 | "Registration of object operation {}<{}> overwrote previous registration.", | |
264 | D::operation_name(), | |
265 | O::object_name() | |
266 | ); | |
267 | } else { | |
268 | trace!( | |
269 | "Registration of object operation {}<{}>.", | |
270 | D::operation_name(), | |
271 | O::object_name() | |
272 | ) | |
273 | } | |
274 | } | |
275 | ||
276 | fn register_value< | |
277 | O: GiteratedObject + 'static, | |
278 | V: GiteratedObjectValue<Object = O> + 'static, | |
279 | >( | |
280 | &mut self, | |
281 | ) { | |
282 | let object_name = O::object_name().to_string(); | |
283 | let value_name = V::value_name().to_string(); | |
284 | ||
285 | if self | |
286 | .values | |
287 | .insert( | |
288 | ObjectValuePair { | |
289 | object_kind: object_name.clone(), | |
290 | value_kind: value_name.clone(), | |
291 | }, | |
292 | ValueMeta { | |
293 | name: value_name, | |
294 | deserialize: Box::new(|bytes| Ok(Box::new(serde_json::from_slice(&bytes)?))), | |
295 | }, | |
296 | ) | |
297 | .is_some() | |
298 | { | |
299 | trace!( | |
300 | "Registration of value <{}>::{} overwrote previous registration.", | |
301 | O::object_name(), | |
302 | V::value_name() | |
303 | ); | |
304 | } else { | |
305 | trace!( | |
306 | "Registration of value <{}>::{}.", | |
307 | O::object_name(), | |
308 | V::value_name() | |
309 | ); | |
310 | } | |
311 | } | |
312 | ||
313 | fn register_setting<S: Setting>(&mut self) { | |
314 | let setting_name = S::name().to_string(); | |
315 | ||
316 | if self | |
317 | .settings | |
318 | .insert( | |
319 | setting_name.clone(), | |
320 | SettingMeta { | |
321 | name: setting_name, | |
322 | deserialize: Box::new(|bytes| Ok(Box::new(serde_json::from_slice(bytes)?))), | |
323 | }, | |
324 | ) | |
325 | .is_some() | |
326 | { | |
327 | trace!( | |
328 | "Registration of setting {} overwrote previous registration.", | |
329 | S::name() | |
330 | ); | |
331 | } else { | |
332 | trace!("Registration of setting {}.", S::name()); | |
333 | } | |
334 | } | |
335 | ||
336 | fn append(&mut self, other: Self) { | |
337 | self.objects.extend(other.objects); | |
338 | self.operations.extend(other.operations); | |
339 | self.values.extend(other.values); | |
340 | self.settings.extend(other.settings); | |
341 | } | |
342 | } | |
343 | ||
344 | #[async_trait::async_trait] | |
345 | impl<L, O, D, S> GiteratedOperationHandler<L, O, D, S> for GiteratedRuntime<S> | |
346 | where | |
347 | O: GiteratedObject + 'static, | |
348 | D: GiteratedOperation<O> + 'static, | |
349 | S: GiteratedRuntimeState, | |
350 | { | |
351 | fn operation_name(&self) -> &str { | |
352 | D::operation_name() | |
353 | } | |
354 | ||
355 | fn object_name(&self) -> &str { | |
356 | O::object_name() | |
357 | } | |
358 | ||
359 | async fn handle( | |
360 | &self, | |
361 | object: &O, | |
362 | operation: D, | |
363 | state: S, | |
364 | operation_state: &StackOperationState, | |
365 | ) -> Result<D::Success, OperationError<D::Failure>> { | |
366 | // Erase object and operation types. | |
367 | let object = object as &dyn Any; | |
368 | let operation = Box::new(operation) as Box<dyn Any>; | |
369 | ||
370 | // We need to determine the type of the object, iterate through all known | |
371 | // object types and check if the &dyn Any we have is the same type as the | |
372 | // object type. | |
373 | let object_type = { | |
374 | let mut object_type = None; | |
375 | ||
376 | for (object_name, object_meta) in self.metadata.objects.iter() { | |
377 | if (object_meta.any_is_same)(object) { | |
378 | object_type = Some(object_name.clone()); | |
379 | break; | |
380 | } | |
381 | } | |
382 | ||
383 | object_type | |
384 | } | |
385 | .ok_or_else(|| OperationError::Unhandled)?; | |
386 | ||
387 | // We need to hijack get_value, set_setting, and get_setting. | |
388 | if operation.is::<GetValueV2>() { | |
389 | todo!() | |
390 | } else if operation.is::<GetSetting>() { | |
391 | todo!() | |
392 | } else if operation.is::<SetSetting>() { | |
393 | todo!() | |
394 | } | |
395 | ||
396 | // Resolve the operation from the known operations table. | |
397 | let operation_type = { | |
398 | let mut operation_type = None; | |
399 | ||
400 | for (target, operation_meta) in self.metadata.operations.iter() { | |
401 | // Skip elements that we know will not match | |
402 | if target.object_name != object_type { | |
403 | continue; | |
404 | } | |
405 | ||
406 | if (operation_meta.any_is_same)(&operation) { | |
407 | operation_type = Some(target.clone()); | |
408 | break; | |
409 | } | |
410 | } | |
411 | ||
412 | operation_type | |
413 | } | |
414 | .ok_or_else(|| OperationError::Unhandled)?; | |
415 | ||
416 | // Resolve the handler from our handler tree | |
417 | let handler_tree = self | |
418 | .operation_handlers | |
419 | .get(&operation_type) | |
420 | .ok_or_else(|| OperationError::Unhandled)?; | |
421 | ||
422 | let raw_result = handler_tree.handle(object, operation, &state, operation_state); | |
423 | ||
424 | // Convert the dynamic result back into its concrete type | |
425 | match raw_result { | |
426 | Ok(result) => Ok(*result.downcast::<D::Success>().unwrap()), | |
427 | Err(err) => Err(match err { | |
428 | OperationError::Internal(internal) => OperationError::Internal(internal), | |
429 | OperationError::Operation(boxed_error) => { | |
430 | OperationError::Operation(*boxed_error.downcast::<D::Failure>().unwrap()) | |
431 | } | |
432 | OperationError::Unhandled => OperationError::Unhandled, | |
433 | }), | |
434 | } | |
435 | } | |
436 | } | |
437 | ||
438 | impl<S: GiteratedRuntimeState> GiteratedRuntime<S> { | |
439 | /// Handles a giterated network message, returning either a raw success | |
440 | /// payload or a serialized error payload. | |
441 | pub async fn handle_network_message( | |
442 | &self, | |
443 | message: AuthenticatedPayload, | |
444 | state: &S, | |
445 | operation_state: &StackOperationState, | |
446 | ) -> Result<Vec<u8>, OperationError<Vec<u8>>> { | |
447 | let message: GiteratedMessage<AnyObject, AnyOperationV2> = message.into_message_v2(); | |
448 | ||
449 | // Deserialize the object, also getting the object type's name | |
450 | let (object_type, object) = { | |
451 | let mut result = None; | |
452 | ||
453 | for (object_type, object_meta) in self.metadata.objects.iter() { | |
454 | if let Ok(object) = (object_meta.from_str)(&message.object.0) { | |
455 | result = Some((object_type.clone(), object)); | |
456 | break; | |
457 | } | |
458 | } | |
459 | ||
460 | result | |
461 | } | |
462 | .ok_or_else(|| OperationError::Unhandled)?; | |
463 | ||
464 | let target = ObjectOperationPair { | |
465 | object_name: object_type, | |
466 | operation_name: message.operation, | |
467 | }; | |
468 | ||
469 | // Resolve the target operations from the handlers table | |
470 | let handler = self | |
471 | .operation_handlers | |
472 | .get(&target) | |
473 | .ok_or_else(|| OperationError::Unhandled)?; | |
474 | ||
475 | // Deserialize the operation | |
476 | let meta = self | |
477 | .metadata | |
478 | .operations | |
479 | .get(&target) | |
480 | .ok_or_else(|| OperationError::Unhandled)?; | |
481 | ||
482 | let operation = | |
483 | (meta.deserialize)(&message.payload.0).map_err(|_| OperationError::Unhandled)?; | |
484 | ||
485 | // Get the raw result of the operation, where the return values are boxed. | |
486 | let raw_result = handler.handle(&object, operation, state, operation_state); | |
487 | ||
488 | // Deserialize the raw result for the network | |
489 | match raw_result { | |
490 | Ok(success) => Ok((meta.serialize_success)(success) | |
491 | .map_err(|e| OperationError::Internal(e.to_string()))?), | |
492 | Err(err) => Err(match err { | |
493 | OperationError::Operation(failure) => OperationError::Operation( | |
494 | (meta.serialize_error)(failure) | |
495 | .map_err(|e| OperationError::Internal(e.to_string()))?, | |
496 | ), | |
497 | OperationError::Internal(internal) => OperationError::Internal(internal), | |
498 | OperationError::Unhandled => OperationError::Unhandled, | |
499 | }), | |
500 | } | |
501 | } | |
502 | } |
giterated-stack/src/update.rs
@@ -0,0 +1,194 @@ | ||
1 | use std::sync::Arc; | |
2 | ||
3 | use futures_util::{future::BoxFuture, FutureExt}; | |
4 | use giterated_models::{ | |
5 | object::GiteratedObject, | |
6 | settings::{AnySetting, Setting}, | |
7 | value::{AnyValue, GiteratedObjectValue}, | |
8 | }; | |
9 | ||
10 | use crate::StackOperationState; | |
11 | ||
12 | #[async_trait::async_trait] | |
13 | pub trait HandleValueUpdate<O, V: GiteratedObjectValue<Object = O>> { | |
14 | async fn handle_value_update( | |
15 | &mut self, | |
16 | object: O, | |
17 | value_name: String, | |
18 | value: V, | |
19 | operation_state: &StackOperationState, | |
20 | ) -> Result<(), ()>; | |
21 | } | |
22 | ||
23 | #[async_trait::async_trait] | |
24 | impl<F, O, V> HandleValueUpdate<O, V> for F | |
25 | where | |
26 | F: Fn(O, String, V, &StackOperationState) -> BoxFuture<'static, Result<(), ()>> + Send + Sync, | |
27 | O: GiteratedObject + Send + Sync + 'static, | |
28 | V: GiteratedObjectValue<Object = O> + Send + Sync + 'static, | |
29 | { | |
30 | async fn handle_value_update( | |
31 | &mut self, | |
32 | object: O, | |
33 | value_name: String, | |
34 | value: V, | |
35 | operation_state: &StackOperationState, | |
36 | ) -> Result<(), ()> { | |
37 | self(object, value_name, value, operation_state).await | |
38 | } | |
39 | } | |
40 | ||
41 | #[async_trait::async_trait] | |
42 | pub trait HandleSettingUpdate<O, S: Setting> { | |
43 | async fn handle_setting_update( | |
44 | &mut self, | |
45 | object: O, | |
46 | setting_name: String, | |
47 | setting: S, | |
48 | operation_state: &StackOperationState, | |
49 | ) -> Result<(), ()>; | |
50 | } | |
51 | ||
52 | #[async_trait::async_trait] | |
53 | impl<F, O, S> HandleSettingUpdate<O, S> for F | |
54 | where | |
55 | F: Fn(O, String, S, &StackOperationState) -> BoxFuture<'static, Result<(), ()>> + Send + Sync, | |
56 | O: GiteratedObject + Send + Sync + 'static, | |
57 | S: Setting + Send + Sync + 'static, | |
58 | { | |
59 | async fn handle_setting_update( | |
60 | &mut self, | |
61 | object: O, | |
62 | setting_name: String, | |
63 | setting: S, | |
64 | operation_state: &StackOperationState, | |
65 | ) -> Result<(), ()> { | |
66 | self(object, setting_name, setting, operation_state).await | |
67 | } | |
68 | } | |
69 | ||
70 | #[async_trait::async_trait] | |
71 | pub trait ValueUpdatedHandler<O> { | |
72 | async fn value_updated(&mut self, object: &O, value_name: &str, value: AnyValue<()>); | |
73 | } | |
74 | ||
75 | #[async_trait::async_trait] | |
76 | pub trait SettingUpdatedHandler<O> { | |
77 | async fn setting_updated(&mut self, object: &O, setting_name: &str, setting: AnySetting); | |
78 | } | |
79 | ||
80 | #[derive(Debug, Clone, Hash, PartialEq, Eq)] | |
81 | pub struct ValueUpdateKind { | |
82 | pub object_kind: String, | |
83 | pub value_name: String, | |
84 | } | |
85 | ||
86 | #[derive(Debug, Clone, Hash, PartialEq, Eq)] | |
87 | pub struct SettingUpdateKind { | |
88 | pub object_kind: String, | |
89 | pub setting_name: String, | |
90 | } | |
91 | ||
92 | pub struct HandleSettingUpdatedFunction { | |
93 | pub target: SettingUpdateKind, | |
94 | pub function: Box< | |
95 | dyn FnOnce( | |
96 | String, | |
97 | String, | |
98 | AnySetting, | |
99 | StackOperationState, | |
100 | ) -> BoxFuture<'static, Result<(), ()>> | |
101 | + Send | |
102 | + Sync, | |
103 | >, | |
104 | } | |
105 | ||
106 | impl HandleSettingUpdatedFunction { | |
107 | pub fn new< | |
108 | S: Setting + Send + Sync, | |
109 | T: HandleSettingUpdate<O, S> + 'static + Clone + Send + Sync, | |
110 | O: GiteratedObject + Send + Sync, | |
111 | >( | |
112 | handler: T, | |
113 | setting_name: &str, | |
114 | ) -> Self { | |
115 | Self { | |
116 | target: SettingUpdateKind { | |
117 | object_kind: O::object_name().to_string(), | |
118 | setting_name: setting_name.to_string(), | |
119 | }, | |
120 | ||
121 | function: Box::new(move |object, setting_name, value, state| { | |
122 | async move { | |
123 | let mut handler = handler; | |
124 | ||
125 | let object = match O::from_str(&object) { | |
126 | Ok(object) => object, | |
127 | Err(_) => return Err(()), | |
128 | }; | |
129 | ||
130 | let setting: S = serde_json::from_value(value.0).unwrap(); | |
131 | ||
132 | handler | |
133 | .handle_setting_update(object, setting_name, setting, &state) | |
134 | .await; | |
135 | ||
136 | Ok(()) | |
137 | } | |
138 | .boxed() | |
139 | }), | |
140 | } | |
141 | } | |
142 | } | |
143 | ||
144 | pub struct HandleValueUpdatedFunction { | |
145 | pub target: ValueUpdateKind, | |
146 | pub function: Box< | |
147 | dyn FnOnce( | |
148 | String, | |
149 | String, | |
150 | AnySetting, | |
151 | StackOperationState, | |
152 | ) -> BoxFuture<'static, Result<(), ()>> | |
153 | + Send | |
154 | + Sync, | |
155 | >, | |
156 | } | |
157 | ||
158 | impl HandleValueUpdatedFunction { | |
159 | pub fn new< | |
160 | V: GiteratedObjectValue<Object = O> + Send + Sync, | |
161 | T: HandleValueUpdate<O, V> + 'static + Clone + Send + Sync, | |
162 | O: GiteratedObject + Send + Sync, | |
163 | >( | |
164 | handler: T, | |
165 | value_name: &str, | |
166 | ) -> Self { | |
167 | Self { | |
168 | target: ValueUpdateKind { | |
169 | object_kind: O::object_name().to_string(), | |
170 | value_name: value_name.to_string(), | |
171 | }, | |
172 | ||
173 | function: Box::new(move |object, setting_name, value, state| { | |
174 | async move { | |
175 | let mut handler = handler; | |
176 | ||
177 | let object = match O::from_str(&object) { | |
178 | Ok(object) => object, | |
179 | Err(_) => return Err(()), | |
180 | }; | |
181 | ||
182 | let setting: V = serde_json::from_value(value.0).unwrap(); | |
183 | ||
184 | handler | |
185 | .handle_value_update(object, setting_name, setting, &state) | |
186 | .await; | |
187 | ||
188 | Ok(()) | |
189 | } | |
190 | .boxed() | |
191 | }), | |
192 | } | |
193 | } | |
194 | } |