Skip to main content

tari_service_framework/
lib.rs

1// Copyright 2022 The Tari Project
2// SPDX-License-Identifier: BSD-3-Clause
3
4//! # Service framework
5//!
6//! This module contains the building blocks for async services.
7//!
8//! It consists of the following modules:
9//!
10//! ## `initializer`
11//!
12//! This module contains the [ServiceInitializer] trait. Service modules should implement this trait and pass
13//! that implementation to the [StackBuilder].
14//!
15//! ## `stack`
16//!
17//! Contains the [StackBuilder] that is responsible for collecting and 'executing' the implementations of
18//! [ServiceInitializer].
19//!
20//! ## `handles`
21//!
22//! A set of utilities used to collect and share handles between services. The [StackBuilder] is responsible for
23//! initializing a [ServiceHandlesFuture] and making it available to [ServiceInitializer] implementations.
24//!
25//! Handles are simply a way to communicate with their corresponding service. Typically, a [SenderService] would
26//! be used for this purpose but a handle can be implemented in any way the implementor sees fit.
27//!
28//! ## `reply_channel`
29//!
30//! This provides for query messages to be sent to services along with a "reply channel" for the service to send back
31//! results. The `reply_channel::unbounded` function is used to create a sender/receiver pair. The sender
32//! implements `tower_service::Service` and can be used to make requests of a applicable type. The receiver
33//! implements `futures::Stream` and will provide a `RequestContext` object that contains a `oneshot` reply channel
34//! that the service can use to reply back to the caller.
35//!
36//! ## Examples
37//!
38//! ### `reply_channel`
39//!
40//! ```edition2018
41//! # use futures::executor::block_on;
42//! # use futures::StreamExt;
43//! # use futures::join;
44//! use tari_service_framework::{reply_channel, tower::ServiceExt};
45//!
46//! block_on(async {
47//!     let (mut sender, mut receiver) = reply_channel::unbounded();
48//!
49//!     let (result, _) = futures::join!(
50//!         // Make the request and make progress on the resulting future
51//!         sender.call_ready("upper"),
52//!         // At the same time receive the request and reply
53//!         async move {
54//!             let req_context = receiver.next().await.unwrap();
55//!             let msg = req_context.request().clone();
56//!             req_context.reply(msg.to_uppercase());
57//!         }
58//!     );
59//!
60//!     assert_eq!(result.unwrap(), "UPPER");
61//! });
62//! ```
63//!
64//! [ServiceInitializer]: ./initializer/trait.ServiceInitializer.html
65//! [StackBuilder]: ./stack/struct.StackBuilder.html
66//! [ServiceHandlesFuture]: ./handles/future/struct.ServiceHandlesFuture.html
67//! [SenderService]: ./reply_channel/struct.SenderService.html
68
69mod context;
70pub use context::{LazyService, ServiceHandles, ServiceInitializerContext};
71
72mod initializer;
73pub use initializer::{ServiceInitializationError, ServiceInitializer};
74
75mod stack;
76pub use stack::StackBuilder;
77
78pub mod reply_channel;
79pub mod tower;
80
81mod utilities;
82// Re-export
83pub use async_trait::async_trait;
84pub use tower_service::Service;
85pub use utilities::RegisterHandle;