Relax type bounds (#17)

* relax type bounds

* remove Send bound on NoOperator

* fix tests

* remove bound on service message

* re-add type bound on Relay

* remove duplicate PhantomBound
This commit is contained in:
Giacomo Pasini 2023-01-17 14:45:22 +01:00 committed by GitHub
parent 6d12e83c35
commit 4efc467d84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 25 deletions

View File

@ -3,13 +3,13 @@
// crates // crates
use crate::overwatch::commands::{OverwatchCommand, OverwatchLifeCycleCommand, SettingsCommand}; use crate::overwatch::commands::{OverwatchCommand, OverwatchLifeCycleCommand, SettingsCommand};
use crate::overwatch::Services; use crate::overwatch::Services;
use crate::services::ServiceData;
use tokio::runtime::Handle; use tokio::runtime::Handle;
use tokio::sync::mpsc::Sender; use tokio::sync::mpsc::Sender;
use tracing::{error, info, instrument}; use tracing::{error, info, instrument};
// internal // internal
use crate::services::relay::Relay; use crate::services::relay::Relay;
use crate::services::ServiceCore;
/// Handler object over the main Overwatch runner /// Handler object over the main Overwatch runner
/// It handles communications to the main Overwatch runner. /// It handles communications to the main Overwatch runner.
@ -28,8 +28,8 @@ impl OverwatchHandle {
} }
} }
/// Request for a relay to an specific service by type /// Request for a relay
pub fn relay<S: ServiceCore>(&self) -> Relay<S> { pub fn relay<S: ServiceData>(&self) -> Relay<S> {
Relay::new(self.clone()) Relay::new(self.clone())
} }

View File

@ -6,14 +6,14 @@ use crate::overwatch::handle::OverwatchHandle;
use crate::services::relay::{relay, InboundRelay, OutboundRelay}; use crate::services::relay::{relay, InboundRelay, OutboundRelay};
use crate::services::settings::{SettingsNotifier, SettingsUpdater}; use crate::services::settings::{SettingsNotifier, SettingsUpdater};
use crate::services::state::{StateHandle, StateOperator, StateUpdater}; use crate::services::state::{StateHandle, StateOperator, StateUpdater};
use crate::services::{ServiceCore, ServiceId, ServiceState}; use crate::services::{ServiceCore, ServiceData, ServiceId, ServiceState};
// TODO: Abstract handle over state, to diferentiate when the service is running and when it is not // TODO: Abstract handle over state, to diferentiate when the service is running and when it is not
// that way we can expose a better API depending on what is happenning. Would get rid of the probably // that way we can expose a better API depending on what is happenning. Would get rid of the probably
// unnecessary Option and cloning. // unnecessary Option and cloning.
/// Service handle /// Service handle
/// This is used to access different parts of the service /// This is used to access different parts of the service
pub struct ServiceHandle<S: ServiceCore> { pub struct ServiceHandle<S: ServiceData> {
/// Message channel relay /// Message channel relay
/// Would be None if service is not running /// Would be None if service is not running
/// Will contain the channel if service is running /// Will contain the channel if service is running
@ -26,7 +26,7 @@ pub struct ServiceHandle<S: ServiceCore> {
/// Service core resources /// Service core resources
/// It contains whatever is necessary to start a new service runner /// It contains whatever is necessary to start a new service runner
pub struct ServiceStateHandle<S: ServiceCore> { pub struct ServiceStateHandle<S: ServiceData> {
/// Relay channel to communicate with the service runner /// Relay channel to communicate with the service runner
pub inbound_relay: InboundRelay<S::Message>, pub inbound_relay: InboundRelay<S::Message>,
/// Overwatch handle /// Overwatch handle
@ -38,12 +38,12 @@ pub struct ServiceStateHandle<S: ServiceCore> {
/// Main service executor /// Main service executor
/// It is the object that hold the necessary information for the service to run /// It is the object that hold the necessary information for the service to run
pub struct ServiceRunner<S: ServiceCore> { pub struct ServiceRunner<S: ServiceData> {
service_state: ServiceStateHandle<S>, service_state: ServiceStateHandle<S>,
state_handle: StateHandle<S::State, S::StateOperator>, state_handle: StateHandle<S::State, S::StateOperator>,
} }
impl<S: ServiceCore> ServiceHandle<S> { impl<S: ServiceData> ServiceHandle<S> {
pub fn new( pub fn new(
settings: S::Settings, settings: S::Settings,
overwatch_handle: OverwatchHandle, overwatch_handle: OverwatchHandle,
@ -109,7 +109,7 @@ impl<S: ServiceCore> ServiceHandle<S> {
} }
} }
impl<S: ServiceCore> ServiceStateHandle<S> { impl<S: ServiceData> ServiceStateHandle<S> {
pub fn id(&self) -> ServiceId { pub fn id(&self) -> ServiceId {
S::SERVICE_ID S::SERVICE_ID
} }

View File

@ -36,7 +36,7 @@ pub trait ServiceData {
/// State operator /// State operator
type StateOperator: StateOperator<StateInput = Self::State> + Clone; type StateOperator: StateOperator<StateInput = Self::State> + Clone;
/// Service messages that the service itself understands and can react to /// Service messages that the service itself understands and can react to
type Message: RelayMessage + Debug + Send + Sync; type Message: RelayMessage + Debug;
} }
/// Main trait for Services initialization and main loop hook /// Main trait for Services initialization and main loop hook

View File

@ -14,7 +14,7 @@ use tracing::{error, instrument};
// internal // internal
use crate::overwatch::commands::{OverwatchCommand, RelayCommand, ReplyChannel}; use crate::overwatch::commands::{OverwatchCommand, RelayCommand, ReplyChannel};
use crate::overwatch::handle::OverwatchHandle; use crate::overwatch::handle::OverwatchHandle;
use crate::services::{ServiceCore, ServiceId}; use crate::services::{ServiceData, ServiceId};
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum RelayError { pub enum RelayError {
@ -66,20 +66,21 @@ pub struct OutboundRelay<M> {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Relay<S: ServiceCore> { pub struct Relay<S> {
_marker: PhantomData<S>,
overwatch_handle: OverwatchHandle, overwatch_handle: OverwatchHandle,
_bound: PhantomBound<S>,
} }
impl<S: ServiceCore> Clone for Relay<S> { // Like PhantomData<T> but without
fn clone(&self) -> Self { // ownership of T
Self { #[derive(Debug)]
_marker: PhantomData, struct PhantomBound<T> {
overwatch_handle: self.overwatch_handle.clone(), _inner: PhantomData<*const T>,
}
}
} }
unsafe impl<T> Send for PhantomBound<T> {}
unsafe impl<T> Sync for PhantomBound<T> {}
impl<M> Clone for OutboundRelay<M> { impl<M> Clone for OutboundRelay<M> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
@ -142,11 +143,13 @@ impl<M: Send + 'static> OutboundRelay<M> {
} }
} }
impl<S: ServiceCore> Relay<S> { impl<S: ServiceData> Relay<S> {
pub fn new(overwatch_handle: OverwatchHandle) -> Self { pub fn new(overwatch_handle: OverwatchHandle) -> Self {
Self { Self {
overwatch_handle, overwatch_handle,
_marker: PhantomData, _bound: PhantomBound {
_inner: PhantomData,
},
} }
} }

View File

@ -1,7 +1,7 @@
// std // std
use std::marker::PhantomData; use std::marker::PhantomData;
use std::pin::Pin;
use std::sync::Arc; use std::sync::Arc;
// crates // crates
use async_trait::async_trait; use async_trait::async_trait;
use futures::StreamExt; use futures::StreamExt;
@ -54,14 +54,23 @@ impl<T> Clone for NoOperator<T> {
} }
#[async_trait] #[async_trait]
impl<StateInput: ServiceState + Send> StateOperator for NoOperator<StateInput> { impl<StateInput: ServiceState> StateOperator for NoOperator<StateInput> {
type StateInput = StateInput; type StateInput = StateInput;
fn from_settings<Settings>(_settings: Settings) -> Self { fn from_settings<Settings>(_settings: Settings) -> Self {
NoOperator(PhantomData::default()) NoOperator(PhantomData::default())
} }
async fn run(&mut self, _state: Self::StateInput) {} fn run<'borrow, 'fut>(
&'borrow mut self,
_state: Self::StateInput,
) -> Pin<Box<dyn std::future::Future<Output = ()> + Send + 'fut>>
where
'borrow: 'fut,
Self: 'fut,
{
Box::pin(async {})
}
} }
/// Empty state /// Empty state