linera_storage_service/
common.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::path::PathBuf;
5
6use linera_base::command::resolve_binary;
7use linera_views::{lru_caching::LruCachingConfig, store::KeyValueStoreError};
8use serde::{Deserialize, Serialize};
9use thiserror::Error;
10use tonic::Status;
11
12// The maximal block size on GRPC is 4M.
13//
14// That size occurs in almost every use of GRPC and in particular the
15// `tonic` library. In particular for the `tonic` library, the limit is
16// both for incoming and outgoing messages.
17// We decrease the 4194304 to 4000000 to leave space for the rest of the message
18// (that includes length prefixes)
19pub const MAX_PAYLOAD_SIZE: usize = 4000000;
20
21/// Key tags to create the sub keys used for storing data on storage.
22#[repr(u8)]
23pub enum KeyPrefix {
24    /// Key prefix for the storage of the keys of the map
25    Key,
26    /// Key prefix for the storage of existence or not of the namespaces.
27    Namespace,
28    /// Key prefix for the root key
29    RootKey,
30}
31
32#[derive(Debug, Error)]
33pub enum ServiceStoreError {
34    /// Store already exists during a create operation
35    #[error("Store already exists during a create operation")]
36    StoreAlreadyExists,
37
38    /// Not matching entry
39    #[error("Not matching entry")]
40    NotMatchingEntry,
41
42    /// Failed to find the linera-storage-server binary
43    #[error("Failed to find the linera-storage-server binary")]
44    FailedToFindStorageServerBinary,
45
46    /// gRPC error
47    #[error(transparent)]
48    GrpcError(#[from] Box<Status>),
49
50    /// The key size must be at most 1 MB
51    #[error("The key size must be at most 1 MB")]
52    KeyTooLong,
53
54    /// Transport error
55    #[error(transparent)]
56    TransportError(#[from] tonic::transport::Error),
57
58    /// Var error
59    #[error(transparent)]
60    VarError(#[from] std::env::VarError),
61
62    /// An error occurred during BCS serialization
63    #[error(transparent)]
64    BcsError(#[from] bcs::Error),
65}
66
67impl From<Status> for ServiceStoreError {
68    fn from(error: Status) -> Self {
69        Box::new(error).into()
70    }
71}
72
73impl KeyValueStoreError for ServiceStoreError {
74    const BACKEND: &'static str = "service";
75}
76
77pub fn storage_service_test_endpoint() -> Result<String, ServiceStoreError> {
78    Ok(std::env::var("LINERA_STORAGE_SERVICE")?)
79}
80
81#[derive(Clone, Debug, Deserialize, Serialize)]
82pub struct ServiceStoreInternalConfig {
83    /// The endpoint used by the shared store
84    pub endpoint: String,
85    /// Maximum number of concurrent database queries allowed for this client.
86    pub max_concurrent_queries: Option<usize>,
87    /// Preferred buffer size for async streams.
88    pub max_stream_queries: usize,
89}
90
91/// The config type
92pub type ServiceStoreConfig = LruCachingConfig<ServiceStoreInternalConfig>;
93
94impl ServiceStoreInternalConfig {
95    pub fn http_address(&self) -> String {
96        format!("http://{}", self.endpoint)
97    }
98}
99
100/// Obtains the binary of the executable.
101/// The path depends whether the test are run in the directory "linera-storage-service"
102/// or in the main directory
103pub async fn get_service_storage_binary() -> Result<PathBuf, ServiceStoreError> {
104    let binary = resolve_binary("linera-storage-server", "linera-storage-service").await;
105    if let Ok(binary) = binary {
106        return Ok(binary);
107    }
108    let binary = resolve_binary("../linera-storage-server", "linera-storage-service").await;
109    if let Ok(binary) = binary {
110        return Ok(binary);
111    }
112    Err(ServiceStoreError::FailedToFindStorageServerBinary)
113}