bee_runtime/
node.rs

1// Copyright 2020-2021 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4//! Traits used to represent bee nodes and allow for their instantiation.
5
6use std::any::Any;
7
8use async_trait::async_trait;
9use bee_storage::backend::StorageBackend;
10use futures::{channel::oneshot, future::Future};
11
12use crate::{event::Bus, resource::ResourceHandle, worker::Worker};
13
14/// A type holding information about a node.
15pub struct NodeInfo {
16    /// Name of the node.
17    pub name: String,
18    /// Version of the node.
19    pub version: String,
20}
21
22/// A trait representing a node framework through which node workers may communicate.
23#[async_trait]
24pub trait Node: Send + Sized + 'static {
25    /// The builder type used to create instances of this node.
26    type Builder: NodeBuilder<Self>;
27    /// The storage backend used by this node.
28    type Backend: StorageBackend;
29    /// The type of errors that may be emitted as a result of the build process.
30    type Error: std::error::Error;
31
32    /// Stop the node, ending the execution of all workers in a timely manner.
33    async fn stop(mut self) -> Result<(), Self::Error>;
34
35    /// Spawn a new node task associated with the given worker.
36    ///
37    /// The task will be shut down with the worker to preserve topological worker ordering.
38    fn spawn<W, G, F>(&mut self, g: G)
39    where
40        W: Worker<Self>,
41        G: FnOnce(oneshot::Receiver<()>) -> F,
42        F: Future<Output = ()> + Send + 'static;
43
44    /// Get a reference to the state of a worker.
45    fn worker<W>(&self) -> Option<&W>
46    where
47        W: Worker<Self> + Send + Sync;
48
49    /// Register a new resource with the node such that other workers may access it via [`Node::resource`].
50    fn register_resource<R: Any + Send + Sync>(&mut self, res: R);
51
52    /// Attempt to remove a resource from the node, returning `None` if no such resource was registered with the node.
53    fn remove_resource<R: Any + Send + Sync>(&mut self) -> Option<R>;
54
55    /// Obtain an owning handle to a node resource.
56    #[track_caller]
57    fn resource<R: Any + Send + Sync>(&self) -> ResourceHandle<R>;
58
59    /// Obtain an owning handle to the node's info.
60    #[track_caller]
61    fn info(&self) -> ResourceHandle<NodeInfo> {
62        self.resource()
63    }
64
65    /// Obtain an owning handle to the node's storage backend.
66    #[track_caller]
67    fn storage(&self) -> ResourceHandle<Self::Backend> {
68        self.resource()
69    }
70
71    /// Obtain an owning handle to the node's event bus.
72    #[track_caller]
73    fn bus(&self) -> ResourceHandle<Bus<'static>> {
74        self.resource()
75    }
76}
77
78/// A trait that provides generic build configuration capabilities for a node.
79#[async_trait(?Send)]
80pub trait NodeBuilder<N: Node>: Sized {
81    /// The type of errors that may be emitted as a result of the build process.
82    type Error: std::error::Error;
83    /// Global configuration provided to the node on creation.
84    type Config;
85
86    /// Begin building a new node with the provided configuration state.
87    fn new(config: Self::Config) -> Result<Self, Self::Error>;
88
89    /// Register a worker, with default configuration state, that should be started with the node.
90    #[must_use]
91    fn with_worker<W: Worker<N> + 'static>(self) -> Self
92    where
93        W::Config: Default;
94
95    /// Register a worker, with the given configuration state, that should be started with the node.
96    #[must_use]
97    fn with_worker_cfg<W: Worker<N> + 'static>(self, config: W::Config) -> Self;
98
99    /// Provide a resource that should be registered with the node upon start.
100    #[must_use]
101    fn with_resource<R: Any + Send + Sync>(self, res: R) -> Self;
102
103    /// Finish building the node, returning the final node.
104    async fn finish(self) -> Result<N, Self::Error>;
105}