mirror of
https://github.com/hinto-janai/cuprate.git
synced 2025-01-10 21:04:59 +00:00
Boog900
ecd077b402
* init config * split sections * finish initial config. * fix clap * misc changes * fix doc * fix test & clippy * fix test 2 * try fix windows * testing * testing 2 * fix windows test * fix windows: the remix. * review comments * fix imports * rename & fix default config file * fix cargo hack * enable serde on `cuprate-helper` * changes from matrix chats * fix ci * fix doc * fix doc test * move Cuprated.toml * remove default.rs * `size` -> `bytes` * `addressbook_path` -> `address_book_path` * fix config output * fix ci * Update binaries/cuprated/src/config/args.rs Co-authored-by: hinto-janai <hinto.janai@protonmail.com> --------- Co-authored-by: hinto-janai <hinto.janai@protonmail.com>
136 lines
4.7 KiB
Rust
136 lines
4.7 KiB
Rust
//! [`tower::Service`] integeration + thread-pool.
|
|
//!
|
|
//! ## `service`
|
|
//! The `service` module implements the [`tower`] integration,
|
|
//! along with the reader/writer thread-pool system.
|
|
//!
|
|
//! The thread-pool allows outside crates to communicate with it by
|
|
//! sending database [`Request`][req_r]s and receiving [`Response`][resp]s `async`hronously -
|
|
//! without having to actually worry and handle the database themselves.
|
|
//!
|
|
//! The system is managed by this crate, and only requires [`init`] by the user.
|
|
//!
|
|
//! ## Handles
|
|
//! The 2 handles to the database are:
|
|
//! - [`BlockchainReadHandle`]
|
|
//! - [`BlockchainWriteHandle`]
|
|
//!
|
|
//! The 1st allows any caller to send [`ReadRequest`][req_r]s.
|
|
//!
|
|
//! The 2nd allows any caller to send [`WriteRequest`][req_w]s.
|
|
//!
|
|
//! The [`BlockchainReadHandle`] can be shared as it is cheaply [`Clone`]able, however,
|
|
//! the [`BlockchainWriteHandle`] cannot be cloned. There is only 1 place in Cuprate that
|
|
//! writes, so it is passed there and used.
|
|
//!
|
|
//! ## Initialization
|
|
//! The database & thread-pool system can be initialized with [`init()`].
|
|
//!
|
|
//! This causes the underlying database/threads to be setup
|
|
//! and returns a read/write handle to that database.
|
|
//!
|
|
//! ## Shutdown
|
|
//! Upon the above handles being dropped, the corresponding thread(s) will automatically exit, i.e:
|
|
//! - The last [`BlockchainReadHandle`] is dropped => reader thread-pool exits
|
|
//! - The last [`BlockchainWriteHandle`] is dropped => writer thread exits
|
|
//!
|
|
//! TODO: update this when `ConcreteEnv` is removed
|
|
//!
|
|
//! Upon dropping the [`cuprate_database::ConcreteEnv`]:
|
|
//! - All un-processed database transactions are completed
|
|
//! - All data gets flushed to disk (caused by [`Drop::drop`] impl on `ConcreteEnv`)
|
|
//!
|
|
//! ## Request and Response
|
|
//! To interact with the database (whether reading or writing data),
|
|
//! a `Request` can be sent using one of the above handles.
|
|
//!
|
|
//! Both the handles implement `tower::Service`, so they can be [`tower::Service::call`]ed.
|
|
//!
|
|
//! An `async`hronous channel will be returned from the call.
|
|
//! This channel can be `.await`ed upon to (eventually) receive
|
|
//! the corresponding `Response` to your `Request`.
|
|
//!
|
|
//! [req_r]: cuprate_types::blockchain::BlockchainReadRequest
|
|
//!
|
|
//! [req_w]: cuprate_types::blockchain::BlockchainWriteRequest
|
|
//!
|
|
//! [resp]: cuprate_types::blockchain::BlockchainResponse
|
|
//!
|
|
//! # Example
|
|
//! Simple usage of `service`.
|
|
//!
|
|
//! ```rust
|
|
//! use hex_literal::hex;
|
|
//! use tower::{Service, ServiceExt};
|
|
//!
|
|
//! use cuprate_types::{blockchain::{BlockchainReadRequest, BlockchainWriteRequest, BlockchainResponse}, Chain};
|
|
//! use cuprate_test_utils::data::BLOCK_V16_TX0;
|
|
//!
|
|
//! use cuprate_blockchain::{
|
|
//! cuprate_database::Env,
|
|
//! config::ConfigBuilder,
|
|
//! };
|
|
//!
|
|
//! # #[tokio::main]
|
|
//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
//! // Create a configuration for the database environment.
|
|
//! let tmp_dir = tempfile::tempdir()?;
|
|
//! let db_dir = tmp_dir.path().to_owned();
|
|
//! let config = ConfigBuilder::new()
|
|
//! .data_directory(db_dir.into())
|
|
//! .build();
|
|
//!
|
|
//! // Initialize the database thread-pool.
|
|
//! let (mut read_handle, mut write_handle, _) = cuprate_blockchain::service::init(config)?;
|
|
//!
|
|
//! // Prepare a request to write block.
|
|
//! let mut block = BLOCK_V16_TX0.clone();
|
|
//! # block.height = 0_usize; // must be 0th height or panic in `add_block()`
|
|
//! let request = BlockchainWriteRequest::WriteBlock(block);
|
|
//!
|
|
//! // Send the request.
|
|
//! // We receive back an `async` channel that will
|
|
//! // eventually yield the result when `service`
|
|
//! // is done writing the block.
|
|
//! let response_channel = write_handle.ready().await?.call(request);
|
|
//!
|
|
//! // Block write was OK.
|
|
//! let response = response_channel.await?;
|
|
//! assert_eq!(response, BlockchainResponse::Ok);
|
|
//!
|
|
//! // Now, let's try getting the block hash
|
|
//! // of the block we just wrote.
|
|
//! let request = BlockchainReadRequest::BlockHash(0, Chain::Main);
|
|
//! let response_channel = read_handle.ready().await?.call(request);
|
|
//! let response = response_channel.await?;
|
|
//! assert_eq!(
|
|
//! response,
|
|
//! BlockchainResponse::BlockHash(
|
|
//! hex!("43bd1f2b6556dcafa413d8372974af59e4e8f37dbf74dc6b2a9b7212d0577428")
|
|
//! )
|
|
//! );
|
|
//!
|
|
//! // This causes the writer thread on the
|
|
//! // other side of this handle to exit...
|
|
//! drop(write_handle);
|
|
//! // ...and this causes the reader thread-pool to exit.
|
|
//! drop(read_handle);
|
|
//! # Ok(()) }
|
|
//! ```
|
|
|
|
// needed for docs
|
|
use tower as _;
|
|
|
|
mod read;
|
|
pub use read::{init_read_service, init_read_service_with_pool};
|
|
|
|
mod write;
|
|
pub use write::init_write_service;
|
|
|
|
mod free;
|
|
pub use free::init;
|
|
mod types;
|
|
pub use types::{BlockchainReadHandle, BlockchainWriteHandle};
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|