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

ambee/giterated

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

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

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨708dea4

Showing ⁨⁨20⁩ changed files⁩ with ⁨⁨1391⁩ insertions⁩ and ⁨⁨123⁩ deletions⁩

giterated-daemon/src/backend/mod.rs

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -0,0 +1 @@
1 pub struct InstanceUpdate {}

giterated-models/src/update/mod.rs

View file
@@ -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

View file
@@ -0,0 +1 @@
1

giterated-models/src/update/user.rs

View file
@@ -0,0 +1 @@
1

giterated-models/src/value.rs

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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 }