Skip to content

Commit

Permalink
Update documentation of layers
Browse files Browse the repository at this point in the history
hannobraun committed Feb 14, 2024
1 parent dc1fc60 commit a814e05
Showing 4 changed files with 50 additions and 36 deletions.
44 changes: 22 additions & 22 deletions crates/fj-core/src/layers/layer.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
use std::ops::Deref;

/// A service that controls access to some state
/// A generic layer, which controls access to layer state
///
/// `Service` is a generic wrapper around some state, as well as code that knows
/// how to operate on that state. It processes commands, changes the state based
/// on those command, and produces events that capture these changes. These
/// events are stored, providing a log of all changes to the state, and can be
/// replayed later to re-create the state at any point in time.
/// `Layer` is a generic wrapper around some state and controls access to it. It
/// [`Deref`]s to the state it wraps, for easy read access, but prevents any
/// direct write access.
///
/// The wrapped state must implement [`State`], which defines the type of
/// command that this service processes, and the type of event that captures
/// state changes. It also defines methods that operate on the state, commands,
/// and events.
/// Instead, each write access to state is reified as a command, which are
/// processed by [`Layer::process`]. Processing a command can result in any
/// number of events, which can then be used as commands for other layers.
///
/// Implementations of [`State`] might also define an extension trait for a
/// specific `Service<MyState>`, to provide a convenient API to callers.
/// All of this is mediated through [`State`], which the wrapped state must
/// implement.
///
/// This design takes inspiration from, and uses the nomenclature of, this
/// article:
@@ -24,15 +21,15 @@ pub struct Layer<S: State> {
}

impl<S: State> Layer<S> {
/// Create an instance of `Service`
/// Create an instance of `Layer`
pub fn new(state: S) -> Self {
Self { state }
}

/// Execute a command
/// Process a command
///
/// The command is executed synchronously. When this method returns, the
/// state has been updated and any events have been logged.
/// The command is processed synchronously. When this method returns, the
/// state has been updated.
pub fn process(&mut self, command: S::Command, events: &mut Vec<S::Event>) {
self.state.decide(command, events);

@@ -64,16 +61,19 @@ where
}
}

/// Implemented for state that can be wrapped by a [`Layer`]
/// The state of a specific layer
///
/// See [`Layer`] for a detailed explanation.
/// Implementations of this trait are wrapped by the generic [`Layer`], which is
/// the consumer of this trait's API.
///
/// See [`Layer`] for a more detailed explanation.
pub trait State {
/// A command that relates to the state
/// A command that encodes a request to update the state
///
/// Commands are processed by [`State::decide`].
type Command;

/// An event that captures modifications to this state
/// An event that encodes a change to the state
///
/// Events are produced by [`State::decide`] and processed by
/// [`State::evolve`].
@@ -87,8 +87,8 @@ pub trait State {

/// Evolve the state according to the provided event
///
/// This is the only method gets mutable access to the state, making sure
/// that all changes to the state are captured as events.
/// This is the only method that gets mutable access to the state, making
/// sure that all changes to the state are captured as events.
///
/// Implementations of this method are supposed to be relatively dumb. Any
/// decisions that go into updating the state should be made in
32 changes: 23 additions & 9 deletions crates/fj-core/src/layers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Service API that promotes monitoring and interactivity
//! Loosely coupled layers, that together define shapes
//!
//! See [`Layers`].
@@ -17,27 +17,41 @@ pub use self::{
validation::{Validation, ValidationCommand, ValidationEvent},
};

/// The kernel services
/// # Loosely coupled layers, that together define shapes
///
/// Shapes are not a monolithic thing in Fornjot, but instead are defined by
/// several, loosely coupled layers. These layers are owned by this struct.
///
/// ## Implementation Note
///
/// It is totally conceivable that one day, this system of layers is extensible
/// and more layers can be defined by third-party code. The foundation for that,
/// the loose coupling and inter-layer communication via events, is already
/// there, conceptually.
///
/// For now, there is no need for this, and all layers are just hardcoded here.
/// That can be changed, once necessary.
#[derive(Default)]
pub struct Layers {
/// The objects service
/// The objects layers
///
/// Allows for inserting objects into a store after they were created.
/// Manages the stores of topological and geometric objects that make up
/// shapes.
pub objects: Layer<Objects>,

/// The validation service
/// The validation layer
///
/// Validates objects that are inserted using the objects service.
/// Monitors objects and validates them, as they are inserted.
pub validation: Layer<Validation>,
}

impl Layers {
/// Construct an instance of `Services`
/// Construct an instance of `Layers`
pub fn new() -> Self {
Self::default()
}

/// Construct an instance of `Services`, using the provided configuration
/// Construct an instance of `Layers`, using the provided configuration
pub fn with_validation_config(config: ValidationConfig) -> Self {
let objects = Layer::default();
let validation = Layer::new(Validation::with_validation_config(config));
@@ -62,7 +76,7 @@ impl Layers {
}
}

/// Drop `Services`; return any unhandled validation error
/// Drop `Layers`; return any unhandled validation error
pub fn drop_and_validate(self) -> Result<(), ValidationErrors> {
let errors = self.validation.into_state().into_errors();

4 changes: 2 additions & 2 deletions crates/fj-core/src/layers/objects.rs
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ impl State for Objects {
}
}

/// Command for `Service<Objects>`
/// Command for `Layer<Objects>`
#[derive(Debug)]
pub enum Operation {
/// Insert an object into the stores
@@ -29,7 +29,7 @@ pub enum Operation {
},
}

/// Event produced by `Service<Objects>`
/// Event produced by `Layer<Objects>`
#[derive(Clone, Debug)]
pub struct InsertObject {
/// The object to insert
6 changes: 3 additions & 3 deletions crates/fj-core/src/layers/validation.rs
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ pub struct Validation {
}

impl Validation {
/// A constructor for the validation service that allows a validation configuration to be set for the service
/// Construct an instance of `Validation`, using the provided configuration
pub fn with_validation_config(config: ValidationConfig) -> Self {
let errors = HashMap::new();
Self { errors, config }
@@ -91,7 +91,7 @@ impl State for Validation {
}
}

/// The command accepted by the validation service
/// Command for `Layer<Validation>`
pub enum ValidationCommand {
/// Validate the provided object
ValidateObject {
@@ -100,7 +100,7 @@ pub enum ValidationCommand {
},
}

/// The event produced by the validation service
/// Event produced by `Layer<Validation>`
#[derive(Clone)]
pub enum ValidationEvent {
/// Validation of an object failed

0 comments on commit a814e05

Please sign in to comment.