Skip to content

Commit

Permalink
refactor: Remove FromId in favour of Default + WithId traits
Browse files Browse the repository at this point in the history
  • Loading branch information
rcelha committed Sep 26, 2023
1 parent b2cf97e commit 1ebe7d3
Show file tree
Hide file tree
Showing 19 changed files with 160 additions and 128 deletions.
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub struct HelloMessage {
#[derive(TypeName, Message, Deserialize, Serialize)]
pub struct HelloResponse {}

#[derive(TypeName, FromId, Default)]
#[derive(TypeName, WithId, Default)]
pub struct HelloWorldService {
pub id: String,
}
Expand Down Expand Up @@ -66,7 +66,7 @@ use rio_rs::object_placement::sql::SqlObjectPlacementProvider;
# #[derive(TypeName, Message, Deserialize, Serialize)]
# pub struct HelloResponse {}
#
# #[derive(TypeName, FromId, Default)]
# #[derive(TypeName, WithId, Default)]
# pub struct HelloWorldService {
# pub id: String,
# }
Expand All @@ -90,7 +90,7 @@ async fn main() {

// Configure types on the server's registry
let mut registry = Registry::new();
registry.add_static_fn::<HelloWorldService, String, _>(FromId::from_id);
registry.add_type::<HelloWorldService>();
registry.add_handler::<HelloWorldService, HelloMessage>();

// Configure the Cluster Membership provider
Expand Down Expand Up @@ -148,7 +148,7 @@ use rio_rs::cluster::storage::sql::{SqlMembersStorage};
# #[derive(TypeName, Message, Deserialize, Serialize)]
# pub struct HelloResponse {}
#
# #[derive(TypeName, FromId, Default)]
# #[derive(TypeName, WithId, Default)]
# pub struct HelloWorldService {
# pub id: String,
# }
Expand Down Expand Up @@ -205,11 +205,13 @@ There are a few things that must be done before v0.1.0:
- [x] Public API renaming
- [x] Reduce Boxed objects
- [x] Create a Server builder
- [ ] Pub/sub
- [ ] Remove the need to pass the StateSaver to `ObjectStateManager::save_state`
- [ ] Error and panic handling on life cycle hooks (probably kill the object)
- [ ] Handle panics on messages handling
- [ ] Include registry configuration in Server builder
- [ ] Remove need to use `add_static_fn(FromId::from_id)`
- [x] Remove need to use `add_static_fn(FromId::from_id)`
- Removed in favour of `Registry::add_type`
- [ ] Create a getting started tutorial
- [ ] Cargo init
- [ ] Add deps (rio-rs, tokio, async_trait, serde, sqlx - optional)
Expand All @@ -227,8 +229,7 @@ There are a few things that must be done before v0.1.0:
- [ ] Reduce static lifetimes
- [ ] Increase public API test coverage
- [ ] 100% documentation of public API
- [ ] Pub/sub
- [ ] Placement strategies
- [ ] Placement strategies (nodes work with different sets of trait objects)
- [ ] Dockerized examples
- [ ] Add pgsql jsonb support
- [ ] Add all SQL storage behind a feature flag (sqlite, mysql, pgsql, etc)
Expand All @@ -239,8 +240,9 @@ There are a few things that must be done before v0.1.0:
- [ ] Object TTL
- [x] Support service background task
- [ ] Matrix test with different backends
- [ ] Support 'typed' message/response on client
- [ ] Support ephemeral port
- [?] Support 'typed' message/response on client
- [?] Support ephemeral port
- [ ] Remove the need for an Option<T> value for [managed_state] attributes (as long as it has a 'Default')
- [-] Examples covering most use cases
- [ ] Background async task on a service
- [x] Background blocking task on a service (_see_ [examples/black-jack]())
4 changes: 2 additions & 2 deletions examples/black-jack/src/rio_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ pub async fn build_server(

// Configure types on the server's registry
let mut registry = Registry::new();
registry.add_static_fn::<Cassino, String, _>(FromId::from_id);
registry.add_static_fn::<GameTable, String, _>(FromId::from_id);
registry.add_type::<Cassino>();
registry.add_type::<GameTable>();
registry.add_handler::<Cassino, LifecycleMessage>();
registry.add_handler::<Cassino, JoinGame>();
registry.add_handler::<GameTable, LifecycleMessage>();
Expand Down
2 changes: 1 addition & 1 deletion examples/black-jack/src/services/cassino.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub struct CassinoState {
pub table_ids: Vec<String>,
}

#[derive(Default, Debug, TypeName, FromId, ManagedState)]
#[derive(Default, Debug, TypeName, WithId, ManagedState)]
pub struct Cassino {
pub id: String,
#[managed_state(provider = SqlState)]
Expand Down
2 changes: 1 addition & 1 deletion examples/black-jack/src/services/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub struct TableState {
pub players: HashSet<String>,
}

#[derive(Default, Debug, TypeName, FromId, ManagedState)]
#[derive(Default, Debug, TypeName, WithId, ManagedState)]
pub struct GameTable {
pub id: String,
#[managed_state(provider = SqlState)]
Expand Down
2 changes: 1 addition & 1 deletion examples/metric-aggregator/src/bin/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ async fn main() {
.unwrap_or("sqlite:///tmp/placement.sqlite3?mode=rwc".to_string());

let mut registry = Registry::new();
registry.add_static_fn::<services::MetricAggregator, String, _>(FromId::from_id);
registry.add_type::<services::MetricAggregator>();
registry.add_handler::<services::MetricAggregator, LifecycleMessage>();
registry.add_handler::<services::MetricAggregator, messages::Ping>();
registry.add_handler::<services::MetricAggregator, messages::Metric>();
Expand Down
2 changes: 1 addition & 1 deletion examples/metric-aggregator/src/services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct MetricStats {
pub min: i32,
}

#[derive(Debug, Default, TypeName, FromId, ManagedState)]
#[derive(Debug, Default, TypeName, WithId, ManagedState)]
pub struct MetricAggregator {
pub id: String,
#[managed_state(provider = SqlState)]
Expand Down
2 changes: 1 addition & 1 deletion examples/ping-pong/src/bin/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ async fn main() {
.get_or_insert("sqlite:///tmp/placement.sqlite3?mode=rwc".to_string());

let mut registry = Registry::new();
registry.add_static_fn::<services::Room, String, _>(FromId::from_id);
registry.add_type::<services::Room>();
registry.add_handler::<services::Room, LifecycleMessage>();
registry.add_handler::<services::Room, messages::Ping>();

Expand Down
2 changes: 1 addition & 1 deletion examples/ping-pong/src/services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::sync::Arc;

use super::*;

#[derive(Debug, Default, TypeName, FromId)]
#[derive(Debug, Default, TypeName, WithId)]
pub struct Room {
pub id: String,
pub request_count: AtomicUsize,
Expand Down
11 changes: 8 additions & 3 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ _ := `ln -sf ${PWD}/pre-commit ${PWD}/.git/hooks/`

# Prints this message
help:
@just --list
@just --list

# Prints the TODOs found throughout the repository
todo:
@ag --rust -Q 'expect("TODO'

# Prints missing docs
todo-docs:
@ag --rust '/// TODO'


_fmt WORKDIR:
#!/usr/bin/env bash
set -euxo pipefail
Expand Down Expand Up @@ -42,9 +47,9 @@ test-macros:

# Runs tests for all the example projects
test-examples:
cargo nextest run --manifest-path ./examples/black-jack/Cargo.toml
cargo nextest run --manifest-path ./examples/black-jack/Cargo.toml
cargo nextest run --manifest-path ./examples/ping-pong/Cargo.toml
cargo nextest run --manifest-path ./examples/metric-aggregator/Cargo.toml
cargo nextest run --manifest-path ./examples/metric-aggregator/Cargo.toml

# Tests all the projects and examples
test-all: test test-macros test-examples
Expand Down
39 changes: 30 additions & 9 deletions rio-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ use proc_macro2::Ident as Ident2;
use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote};
use syn::parse_quote;
use syn::punctuated::Punctuated;
use syn::AngleBracketedGenericArguments;
use syn::ExprAssign;
use syn::ExprPath;
use syn::GenericArgument;
use syn::PathArguments;
use syn::PathSegment;
use syn::Stmt;
use syn::{parse2, ItemStruct, Lit, Meta, MetaNameValue};

Expand Down Expand Up @@ -82,20 +84,39 @@ pub fn derive_message(tokens: TokenStream) -> TokenStream {
TokenStream::from(output)
}

#[proc_macro_derive(FromId, attributes(rio_path))]
pub fn derive_from_id(tokens: TokenStream) -> TokenStream {
#[proc_macro_derive(WithId, attributes(rio_path))]
pub fn derive_with_id(tokens: TokenStream) -> TokenStream {
let input = TokenStream2::from(tokens);
let ast: ItemStruct = parse2(input).unwrap();
let struct_name = format_ident!("{}", ast.ident);
let rio_rs = get_crate_path(&ast);

let output = quote! {
impl #rio_rs::service_object::FromId for #struct_name {
fn from_id(id: String) -> Self {
Self {
id,
..Self::default()
// It has a field `id: String`
//
// This check here is not ideal yet, as I need to refine the type detection
let has_field_id = ast.fields.iter().any(|field| {
field
.ident
.as_ref()
.is_some_and(|field_ident| field_ident.to_string() == "id".to_string())
&& match &field.ty {
syn::Type::Path(path) => {
path.path.segments.last().unwrap().ident.to_string() == "String"
}
_ => false,
}
});
if !has_field_id {
panic!(
"{} doesn't have an `id` attribute of type `String`",
struct_name
);
}

let output = quote! {
impl #rio_rs::service_object::WithId for #struct_name {
fn set_id(&mut self, id: String) {
self.id = id;
}

fn id(&self) -> &str {
Expand Down Expand Up @@ -217,7 +238,7 @@ impl From<TokenStream2> for StateDefinition {
/// attributed decorated with #[managed_state]
///
/// ```ignore
/// #[derive(Default, FromId, TypeName, ManagedState)]
/// #[derive(Default, WithId, TypeName, ManagedState)]
/// struct Test2 {
/// id: String,
/// #[managed_state(provider = Option)]
Expand Down
8 changes: 8 additions & 0 deletions rio-macros/tests/ui_fail/with_id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use rio_macros::*;

#[derive(Default, WithId)]
struct StructWithId {
name: String,
}

fn main() {}
7 changes: 7 additions & 0 deletions rio-macros/tests/ui_fail/with_id.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: proc-macro derive panicked
--> tests/ui_fail/with_id.rs:3:19
|
3 | #[derive(Default, WithId)]
| ^^^^^^
|
= help: message: StructWithId doesn't have an `id` attribute of type `String`
6 changes: 3 additions & 3 deletions rio-macros/tests/ui_pass/managed_state.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rio_macros::*;
use rio_rs::ServiceObject;
use rio_rs::state::local::LocalState;
use rio_rs::state::ObjectStateManager;
use rio_rs::ServiceObject;

#[derive(ManagedState)]
struct Test {}
Expand All @@ -12,7 +12,7 @@ struct TestVec(Vec<usize>);
#[derive(TypeName, serde::Serialize, serde::Deserialize)]
struct NotTestVec(Vec<usize>);

#[derive(Default, FromId, TypeName, ManagedState)]
#[derive(Default, WithId, TypeName, ManagedState)]
struct Test2 {
id: String,
#[managed_state]
Expand All @@ -21,7 +21,7 @@ struct Test2 {
// not_tests: Option<NotTestVec>,
}

#[derive(Default, FromId, TypeName, ManagedState)]
#[derive(Default, WithId, TypeName, ManagedState)]
struct TestProvider {
id: String,
#[managed_state(provider = LocalState)]
Expand Down
14 changes: 14 additions & 0 deletions rio-macros/tests/ui_pass/with_id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use rio_macros::*;
use rio_rs::service_object::WithId;

#[derive(Default, WithId)]
struct StructWithId {
id: String,
name: String,
}

fn main() {
let mut a = StructWithId::default();
a.set_id("1".into());
assert_eq!(a.id(), "1");
}
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ pub mod tap_err;
pub use service_object::*;

pub mod derive {
pub use rio_macros::FromId;
pub use rio_macros::ManagedState;
pub use rio_macros::Message;
pub use rio_macros::TypeName;
pub use rio_macros::WithId;
}

pub mod prelude {
Expand All @@ -33,7 +33,7 @@ pub mod prelude {
};
pub use super::cluster::membership_protocol::ClusterProvider;
pub use super::cluster::storage::MembersStorage;
pub use super::derive::{FromId, ManagedState, Message, TypeName};
pub use super::derive::{ManagedState, Message, TypeName, WithId};
pub use super::errors::{ClientBuilderError, HandlerError, ServiceObjectLifeCycleError};
pub use super::protocol::{ClientError, ResponseError};

Expand All @@ -42,9 +42,9 @@ pub mod prelude {
pub use super::server::Server;
pub use super::server::ServerBuilder;
pub use super::state::ObjectStateManager;
pub use super::FromId;
pub use super::LifecycleMessage;
pub use super::ObjectId;
pub use super::ServiceObject;
pub use super::ServiceObjectStateLoad;
pub use super::WithId;
}
Loading

0 comments on commit 1ebe7d3

Please sign in to comment.