Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SPIKE] Explore possible advancements of the Service framework #4180

Open
iambriccardo opened this issue Oct 28, 2024 · 1 comment
Open

[SPIKE] Explore possible advancements of the Service framework #4180

iambriccardo opened this issue Oct 28, 2024 · 1 comment
Assignees

Comments

@iambriccardo
Copy link
Member

No description provided.

@iambriccardo iambriccardo self-assigned this Oct 28, 2024
@iambriccardo
Copy link
Member Author

I took a first step at the implementation by completely rewriting the service with cleaner boundaries and a much simpler interface but realized that our services are not behaving as simple actors since they not only receive messages but also subscribe to several data sources. This made my decision not suitable for our use cases.

This is an example counter implemented with the new (discarded) service abstraction:

#[derive(Debug)]
pub enum CounterRequest {
    Increment,
    GetCount,
}

impl MessageRequest for CounterRequest {}

#[derive(Debug)]
pub enum CounterResponse {
    Count(u64),
}

impl MessageResponse for CounterResponse {}

#[derive(Debug)]
pub struct InnerCounterState {
    count: u64,
}

#[derive(Debug, Clone)]
pub struct CounterState(Arc<RwLock<InnerCounterState>>);

impl State for CounterState {
    type Public = CounterState;

    type Private = CounterState;

    fn split(self) -> (Self::Public, Self::Private) {
        (self.clone(), self)
    }
}

pub struct CounterService {}

impl CounterService {
    pub fn new() -> Self {
        Self {}
    }
}

impl ServiceNew for CounterService {
    type MessageRequest = CounterRequest;

    type MessageResponse = CounterResponse;

    type State = CounterState;

    fn initialize_state(self) -> Self::State {
        CounterState(Arc::new(RwLock::new(InnerCounterState { count: 0 })))
    }

    async fn handle(
        state: &mut CounterState,
        message: InnerMessage<Self::MessageRequest>,
    ) -> Result<Option<Self::MessageResponse>, HandlingError> {
        match message {
            InnerMessage::User(message) => match message {
                CounterRequest::Increment => {
                    state.0.write().await.count += 1;
                    Ok(None)
                }
                CounterRequest::GetCount => {
                    Ok(Some(CounterResponse::Count(state.0.read().await.count)))
                }
            },
            InnerMessage::System(message) => {
                match message {
                    SystemMessage::Shutdown(timeout) => {
                        // TODO: handle shutdown.
                    }
                }

                Ok(None)
            }
        }
    }
}

I iterated other versions with more improvements but decided to resort to solving individual problems in our implementation rather than rewriting it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant