diff --git a/crates/libs/core/src/runtime/stateful.rs b/crates/libs/core/src/runtime/stateful.rs index 680a054b..8704df6e 100644 --- a/crates/libs/core/src/runtime/stateful.rs +++ b/crates/libs/core/src/runtime/stateful.rs @@ -13,7 +13,11 @@ use crate::types::{LoadMetric, LoadMetricListRef, ReplicaRole}; use super::stateful_types::{Epoch, OpenMode, ReplicaInfo, ReplicaSetConfig, ReplicaSetQuarumMode}; +/// Represents a stateful service factory that is responsible for creating replicas +/// of a specific type of stateful service. Stateful service factories are registered with +/// the FabricRuntime by service hosts via register_stateful_service_factory(). pub trait StatefulServiceFactory { + /// Called by Service Fabric to create a stateful service replica for a particular service. fn create_replica( &self, servicetypename: &HSTRING, @@ -24,28 +28,41 @@ pub trait StatefulServiceFactory { ) -> Result; } -// safe service instance -// The trait style is modeled by tonic server trait where send, sync and static are all required. -// This makes sure that bridge/proxy layer can work with rust async await easier. +/// Defines behavior that governs the lifecycle of a replica, such as startup, initialization, role changes, and shutdown. +/// Remarks: +/// Stateful service types must implement this interface. The logic of a stateful service type includes behavior that is +/// invoked on primary replicas and behavior that is invoked on secondary replicas. #[trait_variant::make(StatefulServiceReplica: Send)] pub trait LocalStatefulServiceReplica: Send + Sync + 'static { - // Note that open returns PrimaryReplicator instead of Replicator. - // The replicator that gives to SF has to implement primary replicator all the time. - // Ideally the return type should be Result, but in bridge impl - // primary replicator needs to be stored in a ctx, but impl trait cannot be a variable type and anonymous. - // We cannot use rust async trait because dynamic dispatch is not yet supported. + /// Opens an initialized service replica so that additional actions can be taken. + /// Returns PrimaryReplicator that is used by the stateful service. async fn open( &self, openmode: OpenMode, partition: &StatefulServicePartition, cancellation_token: CancellationToken, ) -> windows::core::Result; + + /// Changes the role of the service replica to one of the ReplicaRole. + /// Returns the service’s new connection address that is to be associated with the replica via Service Fabric Naming. + /// Remarks: + /// The new role is indicated as a parameter. When the service transitions to the new role, + /// the service has a chance to update its current listening address. The listening address is the address + /// where clients connect to it and the one returned via the ResolveAsync API. This enables the service when + /// it is a primary replica to only claim some resources such as ports when communication from clients is expected. async fn change_role( &self, newrole: ReplicaRole, cancellation_token: CancellationToken, - ) -> ::windows_core::Result; // replica address + ) -> ::windows_core::Result; + + /// Closes the service replica gracefully when it is being shut down. async fn close(&self, cancellation_token: CancellationToken) -> windows::core::Result<()>; + + /// Ungracefully terminates the service replica. + /// Remarks: Network issues resulting in Service Fabric process shutdown + /// and the use of ReportFault(FaultType) to report a Permanent fault are examples of ungraceful termination. + /// When this method is invoked, the service replica should immediately release and clean up all references and return. fn abort(&self); } @@ -75,6 +92,7 @@ impl From<&IFabricStatefulServicePartition> for StatefulServicePartition { } } +/// TODO: replicator has no public documentation #[trait_variant::make(Replicator: Send)] pub trait LocalReplicator: Send + Sync + 'static { async fn open(&self, cancellation_token: CancellationToken) -> ::windows_core::Result; // replicator address @@ -85,6 +103,15 @@ pub trait LocalReplicator: Send + Sync + 'static { role: &ReplicaRole, cancellation_token: CancellationToken, ) -> ::windows_core::Result<()>; + + /// (TODO: This doc is from IStateProvider but not Replicator.) + /// Indicates to a replica that the configuration of a replica set has changed due to + /// a change or attempted change to the primary replica. The change occurs due to failure + /// or load balancing of the previous primary replica. Epoch changes act as a barrier by + /// segmenting operations into the exact configuration periods in which they were sent + /// by a specific primary replica. + /// + /// Called only on active secondary replicas. Primary replica gets new epoch via change_role call. async fn update_epoch( &self, epoch: &Epoch, @@ -95,6 +122,7 @@ pub trait LocalReplicator: Send + Sync + 'static { fn abort(&self); } +/// TODO: primary replicator has no public documentation #[trait_variant::make(PrimaryReplicator: Send)] pub trait LocalPrimaryReplicator: Replicator { // SF calls this to indicate that possible data loss has occurred (write quorum loss), diff --git a/crates/libs/core/src/runtime/stateless.rs b/crates/libs/core/src/runtime/stateless.rs index 13de40bd..360e58a1 100644 --- a/crates/libs/core/src/runtime/stateless.rs +++ b/crates/libs/core/src/runtime/stateless.rs @@ -29,8 +29,11 @@ impl StatelessServicePartition { } } -// safe factory +/// Stateless service factories are registered with the FabricRuntime by service hosts via +/// Runtime::register_stateless_service_factory(). +/// pub trait StatelessServiceFactory { + /// Creates a stateless service instance for a particular service. This method is called by Service Fabric. fn create_instance( &self, servicetypename: &HSTRING, @@ -41,14 +44,28 @@ pub trait StatelessServiceFactory { ) -> windows_core::Result; } -// safe service instance +/// Defines behavior that governs the lifecycle of a stateless service instance, such as startup, initialization, and shutdown. #[trait_variant::make(StatelessServiceInstance: Send)] pub trait LocalStatelessServiceInstance: Send + Sync + 'static { + /// Opens an initialized service instance so that it can be contacted by clients. + /// Remarks: + /// Opening an instance stateless service indicates that the service is now resolvable + /// and discoverable by service clients. The string that is returned is the address of this service instance. + /// The address is associated with the service name via Service Fabric naming and returned to + /// clients that resolve the service via resolve_service_partition(uri). async fn open( &self, partition: &StatelessServicePartition, cancellation_token: CancellationToken, ) -> windows::core::Result; + + /// Closes this service instance gracefully when the service instance is being shut down. async fn close(&self, cancellation_token: CancellationToken) -> windows::core::Result<()>; + + /// Terminates this instance ungracefully with this synchronous method call. + /// Remarks: + /// Examples of ungraceful termination are network issues resulting in Service Fabric process shutdown and the + /// use of ReportFault(FaultType) to report a Permanent fault. When the service instance receives this method, + /// it should immediately release and clean up all references and return. fn abort(&self); }