From 5b18594a5084bc2f98fc14ee52078dffa2328eec Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Tue, 19 Mar 2024 14:58:46 +0100 Subject: [PATCH 01/63] replaced sample new to put/delete --- .../src/replica/aligner.rs | 2 +- .../src/replica/storage.rs | 250 ++++++++++-------- zenoh/src/sample.rs | 70 +++-- zenoh/src/session.rs | 6 +- 4 files changed, 192 insertions(+), 136 deletions(-) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs index fb46b78082..0df648409d 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs @@ -108,7 +108,7 @@ impl Aligner { let Value { payload, encoding, .. } = value; - let sample = Sample::new(key, payload) + let sample = Sample::put(key, payload) .with_encoding(encoding) .with_timestamp(ts); log::debug!("[ALIGNER] Adding {:?} to storage", sample); diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 0708dcabd9..9e4ae7ad0e 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -19,12 +19,12 @@ use async_trait::async_trait; use flume::{Receiver, Sender}; use futures::select; use std::collections::{HashMap, HashSet}; -use std::str::{self, FromStr}; +use std::str::FromStr; use std::time::{SystemTime, UNIX_EPOCH}; use zenoh::buffers::ZBuf; use zenoh::prelude::r#async::*; use zenoh::query::ConsolidationMode; -use zenoh::time::{Timestamp, NTP64}; +use zenoh::time::{new_reception_timestamp, Timestamp, NTP64}; use zenoh::{Result as ZResult, Session}; use zenoh_backend_traits::config::{GarbageCollectionConfig, StorageConfig}; use zenoh_backend_traits::{Capability, History, Persistence, StorageInsertionResult, StoredData}; @@ -39,9 +39,102 @@ pub const WILDCARD_UPDATES_FILENAME: &str = "wildcard_updates"; pub const TOMBSTONE_FILENAME: &str = "tombstones"; #[derive(Clone)] -struct Update { - kind: SampleKind, - data: StoredData, +enum Update { + Put(StoredData), + Delete(Timestamp), +} + +impl From for Update { + fn from(sample: Sample) -> Self { + let mut sample = sample; + let timestamp = *sample.ensure_timestamp(); + match sample.kind() { + SampleKind::Put => Update::Put(StoredData { + value: Value::from(sample), + timestamp, + }), + SampleKind::Delete => Update::Delete(timestamp), + } + } +} + +impl Update { + fn timestamp(&self) -> &Timestamp { + match self { + Update::Put(data) => &data.timestamp, + Update::Delete(ts) => ts, + } + } +} + +// implement from String for Update +impl TryFrom for Update { + type Error = zenoh::Error; + + fn try_from(value: String) -> Result { + let result: (String, String, String, Vec<&[u8]>) = serde_json::from_str(&value)?; + let mut payload = ZBuf::default(); + for slice in result.3 { + payload.push_zslice(slice.to_vec().into()); + } + let value = Value::new(payload).with_encoding(result.2); + let timestamp = Timestamp::from_str(&result.1).map_err(|_|"Error parsing timestamp")?; + if result .0.eq(&(SampleKind::Put).to_string()) { + Ok(Update::Put(StoredData { value, timestamp })) + } else { + Ok(Update::Delete(timestamp)) + } + } +} + +// implement to_string for Update +impl ToString for Update { + fn to_string(&self) -> String { + let result = match self { + Update::Put(data) => ( + SampleKind::Put.to_string(), + data.timestamp.to_string(), + data.value.encoding.to_string(), + data.value.payload.slices().collect::>(), + ), + Update::Delete(ts) => ( + SampleKind::Delete.to_string(), + ts.to_string(), + "".to_string(), + vec![], + ), + }; + serde_json::to_string_pretty(&result).unwrap() + } +} + +trait IntoSample { + fn into_sample(self, key_expr: IntoKeyExpr) -> Sample + where + IntoKeyExpr: Into>; +} + +impl IntoSample for StoredData { + fn into_sample(self, key_expr: IntoKeyExpr) -> Sample + where + IntoKeyExpr: Into>, + { + Sample::put(key_expr, self.value.payload) + .with_encoding(self.value.encoding) + .with_timestamp(self.timestamp) + } +} + +impl IntoSample for Update { + fn into_sample(self, key_expr: IntoKeyExpr) -> Sample + where + IntoKeyExpr: Into>, + { + match self { + Update::Put(data) => data.into_sample(key_expr), + Update::Delete(ts) => Sample::delete(key_expr).with_timestamp(ts), + } + } } pub struct ReplicationService { @@ -109,10 +202,10 @@ impl StorageService { let saved_wc = std::fs::read_to_string(zenoh_home().join(WILDCARD_UPDATES_FILENAME)).unwrap(); let saved_wc: HashMap = - serde_json::from_str(&saved_wc).unwrap(); + serde_json::from_str(&saved_wc).unwrap(); // TODO: Remove unwrap let mut wildcard_updates = storage_service.wildcard_updates.write().await; for (k, data) in saved_wc { - wildcard_updates.insert(&k, construct_update(data)); + wildcard_updates.insert(&k, Update::try_from(data).unwrap()); // TODO: Remove unwrap } } } @@ -269,6 +362,7 @@ impl StorageService { } else { sample }; + let sample_timestamp = *sample.timestamp().unwrap_or(&new_reception_timestamp()); // if wildcard, update wildcard_updates if sample.key_expr().is_wild() { @@ -297,28 +391,17 @@ impl StorageService { log::trace!( "Sample `{:?}` identified as neded processing for key {}", sample, - k + &k ); // there might be the case that the actual update was outdated due to a wild card update, but not stored yet in the storage. // get the relevant wild card entry and use that value and timestamp to update the storage - let sample_to_store = match self - .ovderriding_wild_update(&k, sample.timestamp().unwrap()) - .await - { - Some(overriding_update) => { - let Value { - payload, encoding, .. - } = overriding_update.data.value; - Sample::new(KeyExpr::from(k.clone()), payload) - .with_encoding(encoding) - .with_timestamp(overriding_update.data.timestamp) - .with_kind(overriding_update.kind) - } - None => Sample::new(KeyExpr::from(k.clone()), sample.payload().clone()) - .with_encoding(sample.encoding().clone()) - .with_timestamp(*sample.timestamp().unwrap()) - .with_kind(sample.kind()), - }; + let sample_to_store = + match self.ovderriding_wild_update(&k, &sample_timestamp).await { + Some(overriding_update) => overriding_update.into_sample(k.clone()), + + None => sample.clone(), + }; + let timestamp = sample_to_store.timestamp().unwrap_or(&sample_timestamp); let stripped_key = match self.strip_prefix(sample_to_store.key_expr()) { Ok(stripped) => stripped, @@ -341,11 +424,8 @@ impl StorageService { } SampleKind::Delete => { // register a tombstone - self.mark_tombstone(&k, *sample_to_store.timestamp().unwrap()) - .await; - storage - .delete(stripped_key, *sample_to_store.timestamp().unwrap()) - .await + self.mark_tombstone(&k, *timestamp).await; + storage.delete(stripped_key, *timestamp).await } }; drop(storage); @@ -393,22 +473,12 @@ impl StorageService { // @TODO: change into a better store that does incremental writes let key = sample.key_expr().clone(); let mut wildcards = self.wildcard_updates.write().await; - let timestamp = *sample.timestamp().unwrap(); - wildcards.insert( - &key, - Update { - kind: sample.kind(), - data: StoredData { - value: Value::from(sample), - timestamp, - }, - }, - ); + wildcards.insert(&key, sample.into()); if self.capability.persistence.eq(&Persistence::Durable) { // flush to disk to makeit durable let mut serialized_data = HashMap::new(); for (k, update) in wildcards.key_value_pairs() { - serialized_data.insert(k, serialize_update(update)); + serialized_data.insert(k, update.to_string()); } if let Err(e) = std::fs::write( zenoh_home().join(WILDCARD_UPDATES_FILENAME), @@ -437,34 +507,36 @@ impl StorageService { let mut update = None; for node in wildcards.intersecting_keys(key_expr) { let weight = wildcards.weight_at(&node); - if weight.is_some() && weight.unwrap().data.timestamp > *ts { - // if the key matches a wild card update, check whether it was saved in storage - // remember that wild card updates change only existing keys - let stripped_key = match self.strip_prefix(&key_expr.into()) { - Ok(stripped) => stripped, - Err(e) => { - log::error!("{}", e); - break; - } - }; - let mut storage = self.storage.lock().await; - match storage.get(stripped_key, "").await { - Ok(stored_data) => { - for entry in stored_data { - if entry.timestamp > *ts { - return None; + if let Some(weight) = weight { + if weight.timestamp() > ts { + // if the key matches a wild card update, check whether it was saved in storage + // remember that wild card updates change only existing keys + let stripped_key = match self.strip_prefix(&key_expr.into()) { + Ok(stripped) => stripped, + Err(e) => { + log::error!("{}", e); + break; + } + }; + let mut storage = self.storage.lock().await; + match storage.get(stripped_key, "").await { + Ok(stored_data) => { + for entry in stored_data { + if entry.timestamp > *ts { + return None; + } } } - } - Err(e) => { - log::warn!( - "Storage '{}' raised an error fetching a query on key {} : {}", - self.name, - key_expr, - e - ); - ts = &weight.unwrap().data.timestamp; - update = Some(weight.unwrap().clone()); + Err(e) => { + log::warn!( + "Storage '{}' raised an error fetching a query on key {} : {}", + self.name, + key_expr, + e + ); + ts = weight.timestamp(); + update = Some(weight.clone()); + } } } } @@ -517,12 +589,7 @@ impl StorageService { match storage.get(stripped_key, q.parameters()).await { Ok(stored_data) => { for entry in stored_data { - let Value { - payload, encoding, .. - } = entry.value; - let sample = Sample::new(key.clone(), payload) - .with_encoding(encoding) - .with_timestamp(entry.timestamp); + let sample = entry.into_sample(key.clone()); // apply outgoing interceptor on results let sample = if let Some(ref interceptor) = self.out_interceptor { interceptor(sample) @@ -558,7 +625,7 @@ impl StorageService { let Value { payload, encoding, .. } = entry.value; - let sample = Sample::new(q.key_expr().clone(), payload) + let sample = Sample::put(q.key_expr().clone(), payload) .with_encoding(encoding) .with_timestamp(entry.timestamp); // apply outgoing interceptor on results @@ -687,35 +754,6 @@ impl StorageService { } } -fn serialize_update(update: &Update) -> String { - let result = ( - update.kind.to_string(), - update.data.timestamp.to_string(), - update.data.value.encoding.to_string(), - update.data.value.payload.slices().collect::>(), - ); - serde_json::to_string_pretty(&result).unwrap() -} - -fn construct_update(data: String) -> Update { - let result: (String, String, String, Vec<&[u8]>) = serde_json::from_str(&data).unwrap(); // @TODO: remove the unwrap() - let mut payload = ZBuf::default(); - for slice in result.3 { - payload.push_zslice(slice.to_vec().into()); - } - let value = Value::new(payload).with_encoding(result.2); - let data = StoredData { - value, - timestamp: Timestamp::from_str(&result.1).unwrap(), // @TODO: remove the unwrap() - }; - let kind = if result.0.eq(&(SampleKind::Put).to_string()) { - SampleKind::Put - } else { - SampleKind::Delete - }; - Update { kind, data } -} - // Periodic event cleaning-up data info for old metadata struct GarbageCollectionEvent { config: GarbageCollectionConfig, @@ -747,7 +785,7 @@ impl Timed for GarbageCollectionEvent { let mut to_be_removed = HashSet::new(); for (k, update) in wildcard_updates.key_value_pairs() { - let ts = update.data.timestamp; + let ts = update.timestamp(); if ts.get_time() < &time_limit { // mark key to be removed to_be_removed.insert(k); diff --git a/zenoh/src/sample.rs b/zenoh/src/sample.rs index e294fd2c0c..757d65afd8 100644 --- a/zenoh/src/sample.rs +++ b/zenoh/src/sample.rs @@ -378,9 +378,9 @@ pub struct Sample { } impl Sample { - /// Creates a new Sample. + /// Creates a "put" Sample. #[inline] - pub fn new(key_expr: IntoKeyExpr, payload: IntoPayload) -> Self + pub fn put(key_expr: IntoKeyExpr, payload: IntoPayload) -> Self where IntoKeyExpr: Into>, IntoPayload: Into, @@ -389,7 +389,7 @@ impl Sample { key_expr: key_expr.into(), payload: payload.into(), encoding: Encoding::default(), - kind: SampleKind::default(), + kind: SampleKind::Put, timestamp: None, qos: QoS::default(), #[cfg(feature = "unstable")] @@ -398,29 +398,55 @@ impl Sample { attachment: None, } } - /// Creates a new Sample. + + /// Creates a "delete" Sample. #[inline] - pub fn try_from( - key_expr: TryIntoKeyExpr, - payload: IntoPayload, - ) -> Result + pub fn delete(key_expr: IntoKeyExpr) -> Self where - TryIntoKeyExpr: TryInto>, - >>::Error: Into, - IntoPayload: Into, + IntoKeyExpr: Into>, { - Ok(Sample { - key_expr: key_expr.try_into().map_err(Into::into)?, - payload: payload.into(), + Sample { + key_expr: key_expr.into(), + payload: Payload::empty(), encoding: Encoding::default(), - kind: SampleKind::default(), + kind: SampleKind::Delete, timestamp: None, qos: QoS::default(), #[cfg(feature = "unstable")] source_info: SourceInfo::empty(), #[cfg(feature = "unstable")] attachment: None, - }) + } + } + + /// Attempts to create a "put" Sample + #[inline] + pub fn try_put( + key_expr: TryIntoKeyExpr, + payload: TryIntoPayload, + ) -> Result + where + TryIntoKeyExpr: TryInto>, + >>::Error: Into, + TryIntoPayload: TryInto, + >::Error: Into, + { + let key_expr: KeyExpr<'static> = key_expr.try_into().map_err(Into::into)?; + let payload: Payload = payload.try_into().map_err(Into::into)?; + Ok(Self::put(key_expr, payload)) + } + + /// Attempts to create a "delete" Sample + #[inline] + pub fn try_delete( + key_expr: TryIntoKeyExpr, + ) -> Result + where + TryIntoKeyExpr: TryInto>, + >>::Error: Into, + { + let key_expr: KeyExpr<'static> = key_expr.try_into().map_err(Into::into)?; + Ok(Self::delete(key_expr)) } /// Creates a new Sample with optional data info. @@ -444,9 +470,10 @@ impl Sample { self } - /// Sets the encoding of this Sample. + /// Sets the encoding of this Sample #[inline] pub fn with_encoding(mut self, encoding: Encoding) -> Self { + assert!(self.kind == SampleKind::Put, "Cannot set encoding on a delete sample"); self.encoding = encoding; self } @@ -469,15 +496,6 @@ impl Sample { self.kind } - /// Sets the kind of this Sample. - #[inline] - #[doc(hidden)] - #[zenoh_macros::unstable] - pub fn with_kind(mut self, kind: SampleKind) -> Self { - self.kind = kind; - self - } - /// Gets the encoding of this sample #[inline] pub fn encoding(&self) -> &Encoding { diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index 5e706a0da8..93d1e2fb9d 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -1538,7 +1538,7 @@ impl Session { let zenoh_collections::single_or_vec::IntoIter { drain, last } = callbacks.into_iter(); for (cb, key_expr) in drain { #[allow(unused_mut)] - let mut sample = Sample::new(key_expr, payload.clone()).with_info(info.clone()); + let mut sample = Sample::put(key_expr, payload.clone()).with_info(info.clone()); #[cfg(feature = "unstable")] { sample.attachment = attachment.clone(); @@ -1547,7 +1547,7 @@ impl Session { } if let Some((cb, key_expr)) = last { #[allow(unused_mut)] - let mut sample = Sample::new(key_expr, payload).with_info(info); + let mut sample = Sample::put(key_expr, payload).with_info(info); #[cfg(feature = "unstable")] { sample.attachment = attachment; @@ -2257,7 +2257,7 @@ impl Primitives for Session { #[allow(unused_mut)] let mut sample = - Sample::new(key_expr.into_owned(), payload).with_info(Some(info)); + Sample::put(key_expr.into_owned(), payload).with_info(Some(info)); #[cfg(feature = "unstable")] { sample.attachment = attachment; From 1038beb92c438d477215813eaed9c173d9785f94 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Tue, 19 Mar 2024 16:14:06 +0100 Subject: [PATCH 02/63] interceptors removed --- .../src/replica/storage.rs | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 9e4ae7ad0e..ed7c6a1d9c 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -153,8 +153,6 @@ pub struct StorageService { capability: Capability, tombstones: Arc>>, wildcard_updates: Arc>>, - in_interceptor: Option Sample + Send + Sync>>, - out_interceptor: Option Sample + Send + Sync>>, replication: Option, } @@ -178,8 +176,6 @@ impl StorageService { capability: store_intercept.capability, tombstones: Arc::new(RwLock::new(KeBoxTree::default())), wildcard_updates: Arc::new(RwLock::new(KeBoxTree::default())), - in_interceptor: store_intercept.in_interceptor, - out_interceptor: store_intercept.out_interceptor, replication, }; if storage_service @@ -356,12 +352,6 @@ impl StorageService { // the trimming during PUT and GET should be handled by the plugin async fn process_sample(&self, sample: Sample) { log::trace!("[STORAGE] Processing sample: {:?}", sample); - // Call incoming data interceptor (if any) - let sample = if let Some(ref interceptor) = self.in_interceptor { - interceptor(sample) - } else { - sample - }; let sample_timestamp = *sample.timestamp().unwrap_or(&new_reception_timestamp()); // if wildcard, update wildcard_updates @@ -590,12 +580,6 @@ impl StorageService { Ok(stored_data) => { for entry in stored_data { let sample = entry.into_sample(key.clone()); - // apply outgoing interceptor on results - let sample = if let Some(ref interceptor) = self.out_interceptor { - interceptor(sample) - } else { - sample - }; if let Err(e) = q.reply_sample(sample).res().await { log::warn!( "Storage '{}' raised an error replying a query: {}", @@ -628,12 +612,6 @@ impl StorageService { let sample = Sample::put(q.key_expr().clone(), payload) .with_encoding(encoding) .with_timestamp(entry.timestamp); - // apply outgoing interceptor on results - let sample = if let Some(ref interceptor) = self.out_interceptor { - interceptor(sample) - } else { - sample - }; if let Err(e) = q.reply_sample(sample).res().await { log::warn!( "Storage '{}' raised an error replying a query: {}", From 09a84b34ad9be1fa39b4f0dd268d722d6a211f72 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Tue, 19 Mar 2024 16:29:14 +0100 Subject: [PATCH 03/63] interceptors removed --- plugins/zenoh-backend-example/src/lib.rs | 13 ++---------- plugins/zenoh-backend-traits/src/lib.rs | 8 -------- .../src/backends_mgt.rs | 7 ------- .../zenoh-plugin-storage-manager/src/lib.rs | 4 ---- .../src/memory_backend/mod.rs | 20 ------------------- 5 files changed, 2 insertions(+), 50 deletions(-) diff --git a/plugins/zenoh-backend-example/src/lib.rs b/plugins/zenoh-backend-example/src/lib.rs index 602d29f375..f81231a498 100644 --- a/plugins/zenoh-backend-example/src/lib.rs +++ b/plugins/zenoh-backend-example/src/lib.rs @@ -13,11 +13,8 @@ // use async_std::sync::RwLock; use async_trait::async_trait; -use std::{ - collections::{hash_map::Entry, HashMap}, - sync::Arc, -}; -use zenoh::{prelude::OwnedKeyExpr, sample::Sample, time::Timestamp, value::Value}; +use std::collections::{hash_map::Entry, HashMap}; +use zenoh::{prelude::OwnedKeyExpr, time::Timestamp, value::Value}; use zenoh_backend_traits::{ config::{StorageConfig, VolumeConfig}, Capability, History, Persistence, Storage, StorageInsertionResult, StoredData, Volume, @@ -71,12 +68,6 @@ impl Volume for ExampleBackend { async fn create_storage(&self, _props: StorageConfig) -> ZResult> { Ok(Box::::default()) } - fn incoming_data_interceptor(&self) -> Option Sample + Send + Sync>> { - None - } - fn outgoing_data_interceptor(&self) -> Option Sample + Send + Sync>> { - None - } } #[async_trait] diff --git a/plugins/zenoh-backend-traits/src/lib.rs b/plugins/zenoh-backend-traits/src/lib.rs index d17e6dfd77..91e030d361 100644 --- a/plugins/zenoh-backend-traits/src/lib.rs +++ b/plugins/zenoh-backend-traits/src/lib.rs @@ -210,14 +210,6 @@ pub trait Volume: Send + Sync { /// Creates a storage configured with some properties. async fn create_storage(&self, props: StorageConfig) -> ZResult>; - - /// Returns an interceptor that will be called before pushing any data - /// into a storage created by this backend. `None` can be returned for no interception point. - fn incoming_data_interceptor(&self) -> Option Sample + Send + Sync>>; - - /// Returns an interceptor that will be called before sending any reply - /// to a query from a storage created by this backend. `None` can be returned for no interception point. - fn outgoing_data_interceptor(&self) -> Option Sample + Send + Sync>>; } pub type VolumeInstance = Box; diff --git a/plugins/zenoh-plugin-storage-manager/src/backends_mgt.rs b/plugins/zenoh-plugin-storage-manager/src/backends_mgt.rs index aa7260e868..90a6ae6250 100644 --- a/plugins/zenoh-plugin-storage-manager/src/backends_mgt.rs +++ b/plugins/zenoh-plugin-storage-manager/src/backends_mgt.rs @@ -14,7 +14,6 @@ use super::storages_mgt::*; use flume::Sender; use std::sync::Arc; -use zenoh::prelude::r#async::*; use zenoh::Session; use zenoh_backend_traits::config::StorageConfig; use zenoh_backend_traits::{Capability, VolumeInstance}; @@ -23,16 +22,12 @@ use zenoh_result::ZResult; pub struct StoreIntercept { pub storage: Box, pub capability: Capability, - pub in_interceptor: Option Sample + Send + Sync>>, - pub out_interceptor: Option Sample + Send + Sync>>, } pub(crate) async fn create_and_start_storage( admin_key: String, config: StorageConfig, backend: &VolumeInstance, - in_interceptor: Option Sample + Send + Sync>>, - out_interceptor: Option Sample + Send + Sync>>, zenoh: Arc, ) -> ZResult> { log::trace!("Create storage '{}'", &admin_key); @@ -41,8 +36,6 @@ pub(crate) async fn create_and_start_storage( let store_intercept = StoreIntercept { storage, capability, - in_interceptor, - out_interceptor, }; start_storage(store_intercept, config, admin_key, zenoh).await diff --git a/plugins/zenoh-plugin-storage-manager/src/lib.rs b/plugins/zenoh-plugin-storage-manager/src/lib.rs index 0db30bbd6a..91df2f108d 100644 --- a/plugins/zenoh-plugin-storage-manager/src/lib.rs +++ b/plugins/zenoh-plugin-storage-manager/src/lib.rs @@ -239,14 +239,10 @@ impl StorageRuntimeInner { volume_id, backend.name() ); - let in_interceptor = backend.instance().incoming_data_interceptor(); - let out_interceptor = backend.instance().outgoing_data_interceptor(); let stopper = async_std::task::block_on(create_and_start_storage( admin_key, storage.clone(), backend.instance(), - in_interceptor, - out_interceptor, self.session.clone(), ))?; self.storages diff --git a/plugins/zenoh-plugin-storage-manager/src/memory_backend/mod.rs b/plugins/zenoh-plugin-storage-manager/src/memory_backend/mod.rs index ebb4922c9d..4e333b8592 100644 --- a/plugins/zenoh-plugin-storage-manager/src/memory_backend/mod.rs +++ b/plugins/zenoh-plugin-storage-manager/src/memory_backend/mod.rs @@ -61,26 +61,6 @@ impl Volume for MemoryBackend { log::debug!("Create Memory Storage with configuration: {:?}", properties); Ok(Box::new(MemoryStorage::new(properties).await?)) } - - fn incoming_data_interceptor(&self) -> Option Sample + Send + Sync>> { - // By default: no interception point - None - // To test interceptors, uncomment this line: - // Some(Arc::new(|sample| { - // trace!(">>>> IN INTERCEPTOR FOR {:?}", sample); - // sample - // })) - } - - fn outgoing_data_interceptor(&self) -> Option Sample + Send + Sync>> { - // By default: no interception point - None - // To test interceptors, uncomment this line: - // Some(Arc::new(|sample| { - // trace!("<<<< OUT INTERCEPTOR FOR {:?}", sample); - // sample - // })) - } } impl Drop for MemoryBackend { From 886c37c1922b7882fa3c670f5ad71b1662857729 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Tue, 19 Mar 2024 17:13:02 +0100 Subject: [PATCH 04/63] storage sample added --- .../src/replica/storage.rs | 144 +++++++++++------- 1 file changed, 91 insertions(+), 53 deletions(-) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index ed7c6a1d9c..41a456e344 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -27,7 +27,7 @@ use zenoh::query::ConsolidationMode; use zenoh::time::{new_reception_timestamp, Timestamp, NTP64}; use zenoh::{Result as ZResult, Session}; use zenoh_backend_traits::config::{GarbageCollectionConfig, StorageConfig}; -use zenoh_backend_traits::{Capability, History, Persistence, StorageInsertionResult, StoredData}; +use zenoh_backend_traits::{Capability, History, Persistence, Storage, StorageInsertionResult, StoredData}; use zenoh_keyexpr::key_expr::OwnedKeyExpr; use zenoh_keyexpr::keyexpr_tree::impls::KeyedSetProvider; use zenoh_keyexpr::keyexpr_tree::{support::NonWild, support::UnknownWildness, KeBoxTree}; @@ -38,22 +38,52 @@ use zenoh_util::{zenoh_home, Timed, TimedEvent, Timer}; pub const WILDCARD_UPDATES_FILENAME: &str = "wildcard_updates"; pub const TOMBSTONE_FILENAME: &str = "tombstones"; +#[derive(Clone, Debug)] +enum StorageSampleKind { + Put(Value), + Delete, +} + +#[derive(Clone, Debug)] +struct StorageSample { + pub key_expr: KeyExpr<'static>, + pub timestamp: Timestamp, + pub kind: StorageSampleKind, +} + +impl From for StorageSample { + fn from(sample: Sample) -> Self { + let timestamp = *sample.timestamp().unwrap_or(&new_reception_timestamp()); + // TODO: add API for disassembly of Sample + let key_expr = sample.key_expr().clone(); + let payload = sample.payload().clone(); + let encoding = sample.encoding().clone(); + let kind = match sample.kind() { + SampleKind::Put => StorageSampleKind::Put(Value::new(payload).with_encoding(encoding)), + SampleKind::Delete => StorageSampleKind::Delete, + }; + StorageSample { + key_expr, + timestamp, + kind, + } + } +} + #[derive(Clone)] enum Update { Put(StoredData), Delete(Timestamp), } -impl From for Update { - fn from(sample: Sample) -> Self { - let mut sample = sample; - let timestamp = *sample.ensure_timestamp(); - match sample.kind() { - SampleKind::Put => Update::Put(StoredData { - value: Value::from(sample), - timestamp, +impl From for Update { + fn from(value: StorageSample) -> Self { + match value.kind { + StorageSampleKind::Put(data) => Update::Put(StoredData { + value: data, + timestamp: value.timestamp, }), - SampleKind::Delete => Update::Delete(timestamp), + StorageSampleKind::Delete => Update::Delete(value.timestamp), } } } @@ -78,8 +108,8 @@ impl TryFrom for Update { payload.push_zslice(slice.to_vec().into()); } let value = Value::new(payload).with_encoding(result.2); - let timestamp = Timestamp::from_str(&result.1).map_err(|_|"Error parsing timestamp")?; - if result .0.eq(&(SampleKind::Put).to_string()) { + let timestamp = Timestamp::from_str(&result.1).map_err(|_| "Error parsing timestamp")?; + if result.0.eq(&(SampleKind::Put).to_string()) { Ok(Update::Put(StoredData { value, timestamp })) } else { Ok(Update::Delete(timestamp)) @@ -90,7 +120,7 @@ impl TryFrom for Update { // implement to_string for Update impl ToString for Update { fn to_string(&self) -> String { - let result = match self { + let result = match self { Update::Put(data) => ( SampleKind::Put.to_string(), data.timestamp.to_string(), @@ -108,31 +138,41 @@ impl ToString for Update { } } -trait IntoSample { - fn into_sample(self, key_expr: IntoKeyExpr) -> Sample +trait IntoStorageSample { + fn into_sample(self, key_expr: IntoKeyExpr) -> StorageSample where IntoKeyExpr: Into>; } -impl IntoSample for StoredData { - fn into_sample(self, key_expr: IntoKeyExpr) -> Sample +impl IntoStorageSample for StoredData { + fn into_sample(self, key_expr: IntoKeyExpr) -> StorageSample where IntoKeyExpr: Into>, { - Sample::put(key_expr, self.value.payload) - .with_encoding(self.value.encoding) - .with_timestamp(self.timestamp) + StorageSample { + key_expr: key_expr.into(), + timestamp: self.timestamp, + kind: StorageSampleKind::Put(self.value), + } } } -impl IntoSample for Update { - fn into_sample(self, key_expr: IntoKeyExpr) -> Sample +impl IntoStorageSample for Update { + fn into_sample(self, key_expr: IntoKeyExpr) -> StorageSample where IntoKeyExpr: Into>, { match self { - Update::Put(data) => data.into_sample(key_expr), - Update::Delete(ts) => Sample::delete(key_expr).with_timestamp(ts), + Update::Put(data) => StorageSample { + key_expr: key_expr.into(), + timestamp: data.timestamp, + kind: StorageSampleKind::Put(data.value), + }, + Update::Delete(ts) => StorageSample { + key_expr: key_expr.into(), + timestamp: ts, + kind: StorageSampleKind::Delete, + }, } } } @@ -201,7 +241,8 @@ impl StorageService { serde_json::from_str(&saved_wc).unwrap(); // TODO: Remove unwrap let mut wildcard_updates = storage_service.wildcard_updates.write().await; for (k, data) in saved_wc { - wildcard_updates.insert(&k, Update::try_from(data).unwrap()); // TODO: Remove unwrap + wildcard_updates.insert(&k, Update::try_from(data).unwrap()); + // TODO: Remove unwrap } } } @@ -272,7 +313,7 @@ impl StorageService { log::error!("Sample {:?} is not timestamped. Please timestamp samples meant for replicated storage.", sample); } else { - self.process_sample(sample).await; + self.process_sample(sample.into()).await; } }, // on query on key_expr @@ -350,33 +391,32 @@ impl StorageService { // The storage should only simply save the key, sample pair while put and retrieve the same during get // the trimming during PUT and GET should be handled by the plugin - async fn process_sample(&self, sample: Sample) { + async fn process_sample(&self, sample: StorageSample) { log::trace!("[STORAGE] Processing sample: {:?}", sample); - let sample_timestamp = *sample.timestamp().unwrap_or(&new_reception_timestamp()); // if wildcard, update wildcard_updates - if sample.key_expr().is_wild() { + if sample.key_expr.is_wild() { self.register_wildcard_update(sample.clone()).await; } - let matching_keys = if sample.key_expr().is_wild() { - self.get_matching_keys(sample.key_expr()).await + let matching_keys = if sample.key_expr.is_wild() { + self.get_matching_keys(&sample.key_expr).await } else { - vec![sample.key_expr().clone().into()] + vec![sample.key_expr.clone().into()] }; log::trace!( "The list of keys matching `{}` is : {:?}", - sample.key_expr(), + sample.key_expr, matching_keys ); for k in matching_keys { if !self - .is_deleted(&k.clone(), sample.timestamp().unwrap()) + .is_deleted(&k.clone(), &sample.timestamp) .await && (self.capability.history.eq(&History::All) || (self.capability.history.eq(&History::Latest) - && self.is_latest(&k, sample.timestamp().unwrap()).await)) + && self.is_latest(&k, &sample.timestamp).await)) { log::trace!( "Sample `{:?}` identified as neded processing for key {}", @@ -386,14 +426,13 @@ impl StorageService { // there might be the case that the actual update was outdated due to a wild card update, but not stored yet in the storage. // get the relevant wild card entry and use that value and timestamp to update the storage let sample_to_store = - match self.ovderriding_wild_update(&k, &sample_timestamp).await { + match self.ovderriding_wild_update(&k, &sample.timestamp).await { Some(overriding_update) => overriding_update.into_sample(k.clone()), - None => sample.clone(), + None => sample.into(), }; - let timestamp = sample_to_store.timestamp().unwrap_or(&sample_timestamp); - let stripped_key = match self.strip_prefix(sample_to_store.key_expr()) { + let stripped_key = match self.strip_prefix(&sample_to_store.key_expr) { Ok(stripped) => stripped, Err(e) => { log::error!("{}", e); @@ -401,22 +440,21 @@ impl StorageService { } }; let mut storage = self.storage.lock().await; - let result = match sample.kind() { - SampleKind::Put => { + let result = match sample_to_store.kind { + StorageSampleKind::Put(data) => { storage .put( stripped_key, - Value::new(sample_to_store.payload().clone()) - .with_encoding(sample_to_store.encoding().clone()), - *sample_to_store.timestamp().unwrap(), + data, + sample_to_store.timestamp, ) .await - } - SampleKind::Delete => { + }, + StorageSampleKind::Delete => { // register a tombstone - self.mark_tombstone(&k, *timestamp).await; - storage.delete(stripped_key, *timestamp).await - } + self.mark_tombstone(&k, sample_to_store.timestamp).await; + storage.delete(stripped_key, sample_to_store.timestamp).await + }, }; drop(storage); if self.replication.is_some() @@ -428,7 +466,7 @@ impl StorageService { .as_ref() .unwrap() .log_propagation - .send((k.clone(), *sample_to_store.timestamp().unwrap())); + .send((k.clone(), sample_to_store.timestamp)); match sending { Ok(_) => (), Err(e) => { @@ -459,9 +497,9 @@ impl StorageService { } } - async fn register_wildcard_update(&self, sample: Sample) { + async fn register_wildcard_update(&self, sample: StorageSample) { // @TODO: change into a better store that does incremental writes - let key = sample.key_expr().clone(); + let key = sample.key_expr.clone(); let mut wildcards = self.wildcard_updates.write().await; wildcards.insert(&key, sample.into()); if self.capability.persistence.eq(&Persistence::Durable) { @@ -719,7 +757,7 @@ impl StorageService { while let Ok(reply) = replies.recv_async().await { match reply.sample { Ok(sample) => { - self.process_sample(sample).await; + self.process_sample(sample.into()).await; } Err(e) => log::warn!( "Storage '{}' received an error to align query: {:?}", From 780c82a3cae1115e624141c929639648e6902e16 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Tue, 19 Mar 2024 17:35:38 +0100 Subject: [PATCH 05/63] some compile error fixes --- .../src/replica/aligner.rs | 18 ++++++++++-------- .../src/replica/storage.rs | 10 +++++----- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs index 0df648409d..3f672382f1 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs @@ -12,6 +12,9 @@ // ZettaScale Zenoh Team, // +use crate::replica::storage::StorageSampleKind; + +use super::storage::StorageSample; use super::{Digest, EraType, LogEntry, Snapshotter}; use super::{CONTENTS, ERA, INTERVALS, SUBINTERVALS}; use async_std::sync::{Arc, RwLock}; @@ -29,7 +32,7 @@ pub struct Aligner { digest_key: OwnedKeyExpr, snapshotter: Arc, rx_digest: Receiver<(String, Digest)>, - tx_sample: Sender, + tx_sample: Sender, digests_processed: RwLock>, } @@ -38,7 +41,7 @@ impl Aligner { session: Arc, digest_key: OwnedKeyExpr, rx_digest: Receiver<(String, Digest)>, - tx_sample: Sender, + tx_sample: Sender, snapshotter: Arc, ) { let aligner = Aligner { @@ -105,12 +108,11 @@ impl Aligner { log::trace!("[ALIGNER] Received queried samples: {missing_data:?}"); for (key, (ts, value)) in missing_data { - let Value { - payload, encoding, .. - } = value; - let sample = Sample::put(key, payload) - .with_encoding(encoding) - .with_timestamp(ts); + let sample = StorageSample { + key_expr: key.into(), + timestamp: ts, + kind: StorageSampleKind::Put(value), + }; log::debug!("[ALIGNER] Adding {:?} to storage", sample); self.tx_sample.send_async(sample).await.unwrap_or_else(|e| { log::error!("[ALIGNER] Error adding sample to storage: {}", e) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 41a456e344..307ca95680 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -39,13 +39,13 @@ pub const WILDCARD_UPDATES_FILENAME: &str = "wildcard_updates"; pub const TOMBSTONE_FILENAME: &str = "tombstones"; #[derive(Clone, Debug)] -enum StorageSampleKind { +pub enum StorageSampleKind { Put(Value), Delete, } #[derive(Clone, Debug)] -struct StorageSample { +pub struct StorageSample { pub key_expr: KeyExpr<'static>, pub timestamp: Timestamp, pub kind: StorageSampleKind, @@ -179,7 +179,7 @@ impl IntoStorageSample for Update { pub struct ReplicationService { pub empty_start: bool, - pub aligner_updates: Receiver, + pub aligner_updates: Receiver, pub log_propagation: Sender<(OwnedKeyExpr, Timestamp)>, } @@ -361,7 +361,7 @@ impl StorageService { } }; sample.ensure_timestamp(); - self.process_sample(sample).await; + self.process_sample(sample.into()).await; }, // on query on key_expr query = storage_queryable.recv_async() => { @@ -429,7 +429,7 @@ impl StorageService { match self.ovderriding_wild_update(&k, &sample.timestamp).await { Some(overriding_update) => overriding_update.into_sample(k.clone()), - None => sample.into(), + None => sample.clone().into(), }; let stripped_key = match self.strip_prefix(&sample_to_store.key_expr) { From af0d167f6a1b0bcdc6d09074c4e2960f93034e90 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Tue, 19 Mar 2024 17:54:31 +0100 Subject: [PATCH 06/63] removed interceptor proxy --- plugins/zenoh-backend-traits/src/lib.rs | 50 +------------------------ 1 file changed, 1 insertion(+), 49 deletions(-) diff --git a/plugins/zenoh-backend-traits/src/lib.rs b/plugins/zenoh-backend-traits/src/lib.rs index 91e030d361..16c00f64af 100644 --- a/plugins/zenoh-backend-traits/src/lib.rs +++ b/plugins/zenoh-backend-traits/src/lib.rs @@ -135,9 +135,7 @@ use async_trait::async_trait; use const_format::concatcp; -use std::sync::Arc; -use zenoh::prelude::{KeyExpr, OwnedKeyExpr, Sample, Selector}; -use zenoh::queryable::ReplyBuilder; +use zenoh::prelude::OwnedKeyExpr; use zenoh::time::Timestamp; use zenoh::value::Value; pub use zenoh::Result as ZResult; @@ -274,49 +272,3 @@ pub trait Storage: Send + Sync { /// Remember to fetch the entry corresponding to the `None` key async fn get_all_entries(&self) -> ZResult, Timestamp)>>; } - -/// A wrapper around the [`zenoh::queryable::Query`] allowing to call the -/// OutgoingDataInterceptor (if any) before to send the reply -pub struct Query { - q: zenoh::queryable::Query, - interceptor: Option Sample + Send + Sync>>, -} - -impl Query { - pub fn new( - q: zenoh::queryable::Query, - interceptor: Option Sample + Send + Sync>>, - ) -> Query { - Query { q, interceptor } - } - - /// The full [`Selector`] of this Query. - #[inline(always)] - pub fn selector(&self) -> Selector<'_> { - self.q.selector() - } - - /// The key selector part of this Query. - #[inline(always)] - pub fn key_expr(&self) -> &KeyExpr<'static> { - self.q.key_expr() - } - - /// This Query's selector parameters. - #[inline(always)] - pub fn parameters(&self) -> &str { - self.q.parameters() - } - - /// Sends a Sample as a reply to this Query - pub fn reply(&self, sample: Sample) -> ReplyBuilder<'_> { - // Call outgoing intercerceptor - let sample = if let Some(ref interceptor) = self.interceptor { - interceptor(sample) - } else { - sample - }; - // Send reply - self.q.reply_sample(sample) - } -} From 067823d3aa514735e60b684b0807fedfcfeb8069 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Wed, 20 Mar 2024 18:01:54 +0100 Subject: [PATCH 07/63] sample builders --- .../src/replica/storage.rs | 33 +- zenoh-ext/src/querying_subscriber.rs | 9 +- zenoh/src/sample.rs | 434 ++++++++++++------ zenoh/src/session.rs | 39 +- 4 files changed, 350 insertions(+), 165 deletions(-) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 307ca95680..5aa6b92a99 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -24,10 +24,13 @@ use std::time::{SystemTime, UNIX_EPOCH}; use zenoh::buffers::ZBuf; use zenoh::prelude::r#async::*; use zenoh::query::ConsolidationMode; +use zenoh::sample::SampleBuilder; use zenoh::time::{new_reception_timestamp, Timestamp, NTP64}; use zenoh::{Result as ZResult, Session}; use zenoh_backend_traits::config::{GarbageCollectionConfig, StorageConfig}; -use zenoh_backend_traits::{Capability, History, Persistence, Storage, StorageInsertionResult, StoredData}; +use zenoh_backend_traits::{ + Capability, History, Persistence, Storage, StorageInsertionResult, StoredData, +}; use zenoh_keyexpr::key_expr::OwnedKeyExpr; use zenoh_keyexpr::keyexpr_tree::impls::KeyedSetProvider; use zenoh_keyexpr::keyexpr_tree::{support::NonWild, support::UnknownWildness, KeBoxTree}; @@ -353,14 +356,20 @@ impl StorageService { select!( // on sample for key_expr sample = storage_sub.recv_async() => { - let mut sample = match sample { + let sample = match sample { Ok(sample) => sample, Err(e) => { log::error!("Error in sample: {}", e); continue; } }; - sample.ensure_timestamp(); + let sample = if sample.timestamp().is_none() { + SampleBuilder::new(sample).with_current_timestamp().res_sync() + + + } else { + sample + }; self.process_sample(sample.into()).await; }, // on query on key_expr @@ -411,9 +420,7 @@ impl StorageService { ); for k in matching_keys { - if !self - .is_deleted(&k.clone(), &sample.timestamp) - .await + if !self.is_deleted(&k.clone(), &sample.timestamp).await && (self.capability.history.eq(&History::All) || (self.capability.history.eq(&History::Latest) && self.is_latest(&k, &sample.timestamp).await)) @@ -443,18 +450,16 @@ impl StorageService { let result = match sample_to_store.kind { StorageSampleKind::Put(data) => { storage - .put( - stripped_key, - data, - sample_to_store.timestamp, - ) + .put(stripped_key, data, sample_to_store.timestamp) .await - }, + } StorageSampleKind::Delete => { // register a tombstone self.mark_tombstone(&k, sample_to_store.timestamp).await; - storage.delete(stripped_key, sample_to_store.timestamp).await - }, + storage + .delete(stripped_key, sample_to_store.timestamp) + .await + } }; drop(storage); if self.replication.is_some() diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index 8cb5480e58..7ca2730f57 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -20,6 +20,7 @@ use std::time::Duration; use zenoh::handlers::{locked, DefaultHandler}; use zenoh::prelude::r#async::*; use zenoh::query::{QueryConsolidation, QueryTarget, ReplyKeyExpr}; +use zenoh::sample::SampleBuilder; use zenoh::subscriber::{Reliability, Subscriber}; use zenoh::time::Timestamp; use zenoh::Result as ZResult; @@ -655,7 +656,7 @@ impl<'a, Receiver> FetchingSubscriber<'a, Receiver> { let sub_callback = { let state = state.clone(); let callback = callback.clone(); - move |mut s| { + move |s| { let state = &mut zlock!(state); if state.pending_fetches == 0 { callback(s); @@ -663,7 +664,11 @@ impl<'a, Receiver> FetchingSubscriber<'a, Receiver> { log::trace!("Sample received while fetch in progress: push it to merge_queue"); // ensure the sample has a timestamp, thus it will always be sorted into the MergeQueue // after any timestamped Sample possibly coming from a fetch reply. - s.ensure_timestamp(); + let s = if s.timestamp().is_none() { + SampleBuilder::new(s).with_current_timestamp().res_sync() + } else { + s + }; state.merge_queue.push(s); } } diff --git a/zenoh/src/sample.rs b/zenoh/src/sample.rs index 757d65afd8..395191a0d6 100644 --- a/zenoh/src/sample.rs +++ b/zenoh/src/sample.rs @@ -20,10 +20,8 @@ use crate::time::{new_reception_timestamp, Timestamp}; use crate::Priority; #[zenoh_macros::unstable] use serde::Serialize; -use std::{ - convert::{TryFrom, TryInto}, - fmt, -}; +use std::{convert::TryFrom, fmt}; +use zenoh_core::{zresult, AsyncResolve, Resolvable, SyncResolve}; use zenoh_protocol::core::EntityGlobalId; use zenoh_protocol::{core::CongestionControl, network::push::ext::QoSType}; @@ -57,6 +55,83 @@ pub(crate) struct DataInfo { pub qos: QoS, } +pub(crate) trait DataInfoIntoSample { + fn into_sample( + self, + key_expr: IntoKeyExpr, + payload: IntoPayload, + #[cfg(feature = "unstable")] attachment: Option, + ) -> Sample + where + IntoKeyExpr: Into>, + IntoPayload: Into; +} + +impl DataInfoIntoSample for DataInfo { + // TODO: this is internal function. + // Technically it may create invalid sample (e.g. a delete sample with a payload and encoding) + // The test for it is intentionally not added to avoid inserting extra "if" into hot path. + // This need to be additionally investigated and measured. + #[inline] + fn into_sample( + self, + key_expr: IntoKeyExpr, + payload: IntoPayload, + #[cfg(feature = "unstable")] attachment: Option, + ) -> Sample + where + IntoKeyExpr: Into>, + IntoPayload: Into, + { + Sample { + key_expr: key_expr.into(), + payload: payload.into(), + kind: self.kind, + encoding: self.encoding.unwrap_or_default(), + timestamp: self.timestamp, + qos: self.qos, + #[cfg(feature = "unstable")] + source_info: SourceInfo { + source_id: self.source_id, + source_sn: self.source_sn, + }, + #[cfg(feature = "unstable")] + attachment, + } + } +} + +impl DataInfoIntoSample for Option { + #[inline] + fn into_sample( + self, + key_expr: IntoKeyExpr, + payload: IntoPayload, + #[cfg(feature = "unstable")] attachment: Option, + ) -> Sample + where + IntoKeyExpr: Into>, + IntoPayload: Into, + { + if let Some(data_info) = self { + data_info.into_sample(key_expr, payload, attachment) + } else { + Sample { + key_expr: key_expr.into(), + payload: payload.into(), + kind: SampleKind::Put, + encoding: Encoding::default(), + timestamp: None, + qos: QoS::default(), + #[cfg(feature = "unstable")] + source_info: SourceInfo::empty(), + #[cfg(feature = "unstable")] + attachment, + } + } + } +} + /// Informations on the source of a zenoh [`Sample`]. #[zenoh_macros::unstable] #[derive(Debug, Clone)] @@ -359,125 +434,275 @@ impl TryFrom for SampleKind { #[zenoh_macros::unstable] pub use attachment::{Attachment, AttachmentBuilder, AttachmentIterator}; -/// A zenoh sample. -#[non_exhaustive] -#[derive(Clone, Debug)] -pub struct Sample { - pub(crate) key_expr: KeyExpr<'static>, - pub(crate) payload: Payload, - pub(crate) kind: SampleKind, - pub(crate) encoding: Encoding, - pub(crate) timestamp: Option, - pub(crate) qos: QoS, +pub struct SampleBuilder(Sample); - #[cfg(feature = "unstable")] - pub(crate) source_info: SourceInfo, +impl SampleBuilder { + pub fn new(sample: Sample) -> Self { + Self(sample) + } - #[cfg(feature = "unstable")] - pub(crate) attachment: Option, + pub fn with_keyexpr(mut self, key_expr: IntoKeyExpr) -> Self + where + IntoKeyExpr: Into>, + { + self.0.key_expr = key_expr.into(); + self + } + + // pub(crate) fn with_kind(mut self, kind: SampleKind) -> Self { + // self.0.kind = kind; + // self + // } + + pub(crate) fn with_encoding(mut self, encoding: Encoding) -> Self { + self.0.encoding = encoding; + self + } + + pub(crate) fn with_payload(mut self, payload: IntoPayload) -> Self + where + IntoPayload: Into, + { + self.0.payload = payload.into(); + self + } + + pub fn with_timestamp(mut self, timestamp: Timestamp) -> Self { + self.0.timestamp = Some(timestamp); + self + } + + pub fn with_current_timestamp(mut self) -> Self { + self.0.timestamp = Some(new_reception_timestamp()); + self + } + + pub fn with_qos(mut self, qos: QoS) -> Self { + self.0.qos = qos; + self + } + + pub fn with_source_info(mut self, source_info: SourceInfo) -> Self { + self.0.source_info = source_info; + self + } + + pub fn with_attachment(mut self, attachment: Attachment) -> Self { + self.0.attachment = Some(attachment); + self + } } -impl Sample { - /// Creates a "put" Sample. - #[inline] - pub fn put(key_expr: IntoKeyExpr, payload: IntoPayload) -> Self +pub struct PutSampleBuilder(SampleBuilder); + +impl PutSampleBuilder { + pub fn new(key_expr: IntoKeyExpr, payload: IntoPayload) -> Self where IntoKeyExpr: Into>, IntoPayload: Into, { - Sample { + Self(SampleBuilder::new(Sample { key_expr: key_expr.into(), payload: payload.into(), - encoding: Encoding::default(), kind: SampleKind::Put, + encoding: Encoding::default(), timestamp: None, qos: QoS::default(), #[cfg(feature = "unstable")] source_info: SourceInfo::empty(), #[cfg(feature = "unstable")] attachment: None, - } + })) } - /// Creates a "delete" Sample. - #[inline] - pub fn delete(key_expr: IntoKeyExpr) -> Self + pub fn with_payload(mut self, payload: IntoPayload) -> Self + where + IntoPayload: Into, + { + self.0 = self.0.with_payload(payload); + self + } + + pub fn with_encoding(mut self, encoding: Encoding) -> Self { + self.0 = self.0.with_encoding(encoding); + self + } + + pub fn with_timestamp(mut self, timestamp: Timestamp) -> Self { + self.0 = self.0.with_timestamp(timestamp); + self + } + + pub fn with_current_timestamp(mut self) -> Self { + self.0 = self.0.with_current_timestamp(); + self + } + + pub fn with_qos(mut self, qos: QoS) -> Self { + self.0 = self.0.with_qos(qos); + self + } + + #[zenoh_macros::unstable] + pub fn with_source_info(mut self, source_info: SourceInfo) -> Self { + self.0 = self.0.with_source_info(source_info); + self + } + + #[zenoh_macros::unstable] + pub fn with_attachment(mut self, attachment: Attachment) -> Self { + self.0 = self.0.with_attachment(attachment); + self + } +} + +pub struct DeleteSampleBuilder(SampleBuilder); + +impl DeleteSampleBuilder { + pub fn new(key_expr: IntoKeyExpr) -> Self where IntoKeyExpr: Into>, { - Sample { + Self(SampleBuilder::new(Sample { key_expr: key_expr.into(), payload: Payload::empty(), - encoding: Encoding::default(), kind: SampleKind::Delete, + encoding: Encoding::default(), timestamp: None, qos: QoS::default(), #[cfg(feature = "unstable")] source_info: SourceInfo::empty(), #[cfg(feature = "unstable")] attachment: None, - } + })) } - - /// Attempts to create a "put" Sample - #[inline] - pub fn try_put( - key_expr: TryIntoKeyExpr, - payload: TryIntoPayload, - ) -> Result + pub fn with_keyexpr(mut self, key_expr: IntoKeyExpr) -> Self where - TryIntoKeyExpr: TryInto>, - >>::Error: Into, - TryIntoPayload: TryInto, - >::Error: Into, + IntoKeyExpr: Into>, { - let key_expr: KeyExpr<'static> = key_expr.try_into().map_err(Into::into)?; - let payload: Payload = payload.try_into().map_err(Into::into)?; - Ok(Self::put(key_expr, payload)) + self.0 = self.0.with_keyexpr(key_expr); + self + } + pub fn with_timestamp(mut self, timestamp: Timestamp) -> Self { + self.0 = self.0.with_timestamp(timestamp); + self + } + pub fn with_current_timestamp(mut self) -> Self { + self.0 = self.0.with_current_timestamp(); + self } + pub fn with_qos(mut self, qos: QoS) -> Self { + self.0 = self.0.with_qos(qos); + self + } + #[zenoh_macros::unstable] + pub fn with_source_info(mut self, source_info: SourceInfo) -> Self { + self.0 = self.0.with_source_info(source_info); + self + } + #[zenoh_macros::unstable] + pub fn with_attachment(mut self, attachment: Attachment) -> Self { + self.0 = self.0.with_attachment(attachment); + self + } +} - /// Attempts to create a "delete" Sample - #[inline] - pub fn try_delete( - key_expr: TryIntoKeyExpr, - ) -> Result - where - TryIntoKeyExpr: TryInto>, - >>::Error: Into, - { - let key_expr: KeyExpr<'static> = key_expr.try_into().map_err(Into::into)?; - Ok(Self::delete(key_expr)) +impl From for SampleBuilder { + fn from(sample: Sample) -> Self { + SampleBuilder(sample) } +} - /// Creates a new Sample with optional data info. - #[inline] - pub(crate) fn with_info(mut self, mut data_info: Option) -> Self { - if let Some(mut data_info) = data_info.take() { - self.kind = data_info.kind; - if let Some(encoding) = data_info.encoding.take() { - self.encoding = encoding; - } - self.qos = data_info.qos; - self.timestamp = data_info.timestamp; - #[cfg(feature = "unstable")] - { - self.source_info = SourceInfo { - source_id: data_info.source_id, - source_sn: data_info.source_sn, - }; - } +impl TryFrom for PutSampleBuilder { + type Error = zresult::Error; + fn try_from(sample: Sample) -> Result { + if sample.kind != SampleKind::Put { + bail!("Sample is not a put sample") } - self + Ok(Self(SampleBuilder(sample))) } +} - /// Sets the encoding of this Sample - #[inline] - pub fn with_encoding(mut self, encoding: Encoding) -> Self { - assert!(self.kind == SampleKind::Put, "Cannot set encoding on a delete sample"); - self.encoding = encoding; - self +impl TryFrom for DeleteSampleBuilder { + type Error = zresult::Error; + fn try_from(sample: Sample) -> Result { + if sample.kind != SampleKind::Delete { + bail!("Sample is not a delete sample") + } + Ok(Self(SampleBuilder(sample))) + } +} + +impl Resolvable for SampleBuilder { + type To = Sample; +} + +impl Resolvable for PutSampleBuilder { + type To = Sample; +} + +impl Resolvable for DeleteSampleBuilder { + type To = Sample; +} + +impl SyncResolve for SampleBuilder { + fn res_sync(self) -> Self::To { + self.0 } +} + +impl SyncResolve for PutSampleBuilder { + fn res_sync(self) -> Self::To { + self.0.res_sync() + } +} + +impl SyncResolve for DeleteSampleBuilder { + fn res_sync(self) -> Self::To { + self.0.res_sync() + } +} +impl AsyncResolve for SampleBuilder { + type Future = futures::future::Ready; + fn res_async(self) -> Self::Future { + futures::future::ready(self.0) + } +} + +impl AsyncResolve for PutSampleBuilder { + type Future = futures::future::Ready; + fn res_async(self) -> Self::Future { + self.0.res_async() + } +} + +impl AsyncResolve for DeleteSampleBuilder { + type Future = futures::future::Ready; + fn res_async(self) -> Self::Future { + self.0.res_async() + } +} + +/// A zenoh sample. +#[non_exhaustive] +#[derive(Clone, Debug)] +pub struct Sample { + pub(crate) key_expr: KeyExpr<'static>, + pub(crate) payload: Payload, + pub(crate) kind: SampleKind, + pub(crate) encoding: Encoding, + pub(crate) timestamp: Option, + pub(crate) qos: QoS, + + #[cfg(feature = "unstable")] + pub(crate) source_info: SourceInfo, + + #[cfg(feature = "unstable")] + pub(crate) attachment: Option, +} + +impl Sample { /// Gets the key expression on which this Sample was published. #[inline] pub fn key_expr(&self) -> &KeyExpr<'static> { @@ -508,15 +733,6 @@ impl Sample { self.timestamp.as_ref() } - /// Sets the timestamp of this Sample. - #[inline] - #[doc(hidden)] - #[zenoh_macros::unstable] - pub fn with_timestamp(mut self, timestamp: Timestamp) -> Self { - self.timestamp = Some(timestamp); - self - } - /// Gets the quality of service settings this Sample was sent with. #[inline] pub fn qos(&self) -> &QoS { @@ -530,52 +746,12 @@ impl Sample { &self.source_info } - /// Sets the source info of this Sample. - #[zenoh_macros::unstable] - #[inline] - pub fn with_source_info(mut self, source_info: SourceInfo) -> Self { - self.source_info = source_info; - self - } - - /// Ensure that an associated Timestamp is present in this Sample. - /// If not, a new one is created with the current system time and 0x00 as id. - /// Get the timestamp of this sample (either existing one or newly created) - #[inline] - #[doc(hidden)] - #[zenoh_macros::unstable] - pub fn ensure_timestamp(&mut self) -> &Timestamp { - if let Some(ref timestamp) = self.timestamp { - timestamp - } else { - let timestamp = new_reception_timestamp(); - self.timestamp = Some(timestamp); - self.timestamp.as_ref().unwrap() - } - } - /// Gets the sample attachment: a map of key-value pairs, where each key and value are byte-slices. #[zenoh_macros::unstable] #[inline] pub fn attachment(&self) -> Option<&Attachment> { self.attachment.as_ref() } - - /// Gets the mutable sample attachment: a map of key-value pairs, where each key and value are byte-slices. - #[inline] - #[doc(hidden)] - #[zenoh_macros::unstable] - pub fn attachment_mut(&mut self) -> &mut Option { - &mut self.attachment - } - - #[inline] - #[doc(hidden)] - #[zenoh_macros::unstable] - pub fn with_attachment(mut self, attachment: Attachment) -> Self { - self.attachment = Some(attachment); - self - } } impl From for Value { diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index 93d1e2fb9d..0a63d82354 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -32,6 +32,7 @@ use crate::queryable::*; #[cfg(feature = "unstable")] use crate::sample::Attachment; use crate::sample::DataInfo; +use crate::sample::DataInfoIntoSample; use crate::sample::QoS; use crate::selector::TIME_RANGE_KEY; use crate::subscriber::*; @@ -1537,21 +1538,21 @@ impl Session { drop(state); let zenoh_collections::single_or_vec::IntoIter { drain, last } = callbacks.into_iter(); for (cb, key_expr) in drain { - #[allow(unused_mut)] - let mut sample = Sample::put(key_expr, payload.clone()).with_info(info.clone()); - #[cfg(feature = "unstable")] - { - sample.attachment = attachment.clone(); - } + let sample = info.clone().into_sample( + key_expr, + payload.clone(), + #[cfg(feature = "unstable")] + attachment.clone(), + ); cb(sample); } if let Some((cb, key_expr)) = last { - #[allow(unused_mut)] - let mut sample = Sample::put(key_expr, payload).with_info(info); - #[cfg(feature = "unstable")] - { - sample.attachment = attachment; - } + let sample = info.into_sample( + key_expr, + payload, + #[cfg(feature = "unstable")] + attachment.clone(), + ); cb(sample); } } @@ -2254,14 +2255,12 @@ impl Primitives for Session { attachment: _attachment.map(Into::into), }, }; - - #[allow(unused_mut)] - let mut sample = - Sample::put(key_expr.into_owned(), payload).with_info(Some(info)); - #[cfg(feature = "unstable")] - { - sample.attachment = attachment; - } + let sample = info.into_sample( + key_expr.into_owned(), + payload, + #[cfg(feature = "unstable")] + attachment, + ); let new_reply = Reply { sample: Ok(sample), replier_id: ZenohId::rand(), // TODO From 4f1ba2f11fabc36a9c6900fee77107fd256fc14f Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Wed, 20 Mar 2024 19:32:38 +0100 Subject: [PATCH 08/63] compiles --- .../src/replica/storage.rs | 37 ++++++++++++------- zenoh/src/sample.rs | 29 +++++++++++++++ 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 5aa6b92a99..f90ea01754 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -28,9 +28,8 @@ use zenoh::sample::SampleBuilder; use zenoh::time::{new_reception_timestamp, Timestamp, NTP64}; use zenoh::{Result as ZResult, Session}; use zenoh_backend_traits::config::{GarbageCollectionConfig, StorageConfig}; -use zenoh_backend_traits::{ - Capability, History, Persistence, Storage, StorageInsertionResult, StoredData, -}; +use zenoh_backend_traits::{Capability, History, Persistence, StorageInsertionResult, StoredData}; +use zenoh_core::SyncResolve; use zenoh_keyexpr::key_expr::OwnedKeyExpr; use zenoh_keyexpr::keyexpr_tree::impls::KeyedSetProvider; use zenoh_keyexpr::keyexpr_tree::{support::NonWild, support::UnknownWildness, KeBoxTree}; @@ -274,7 +273,12 @@ impl StorageService { t.add_async(gc).await; // subscribe on key_expr - let storage_sub = match self.session.declare_subscriber(&self.key_expr).res().await { + let storage_sub = match self + .session + .declare_subscriber(&self.key_expr) + .res_async() + .await + { Ok(storage_sub) => storage_sub, Err(e) => { log::error!("Error starting storage '{}': {}", self.name, e); @@ -287,7 +291,7 @@ impl StorageService { .session .declare_queryable(&self.key_expr) .complete(self.complete) - .res() + .res_async() .await { Ok(storage_queryable) => storage_queryable, @@ -365,8 +369,6 @@ impl StorageService { }; let sample = if sample.timestamp().is_none() { SampleBuilder::new(sample).with_current_timestamp().res_sync() - - } else { sample }; @@ -622,8 +624,12 @@ impl StorageService { match storage.get(stripped_key, q.parameters()).await { Ok(stored_data) => { for entry in stored_data { - let sample = entry.into_sample(key.clone()); - if let Err(e) = q.reply_sample(sample).res().await { + if let Err(e) = q + .reply(key.clone(), entry.value.payload) + .with_timestamp(entry.timestamp) + .res_async() + .await + { log::warn!( "Storage '{}' raised an error replying a query: {}", self.name, @@ -652,10 +658,13 @@ impl StorageService { let Value { payload, encoding, .. } = entry.value; - let sample = Sample::put(q.key_expr().clone(), payload) + if let Err(e) = q + .reply(q.key_expr().clone(), payload) .with_encoding(encoding) - .with_timestamp(entry.timestamp); - if let Err(e) = q.reply_sample(sample).res().await { + .with_timestamp(entry.timestamp) + .res_async() + .await + { log::warn!( "Storage '{}' raised an error replying a query: {}", self.name, @@ -668,7 +677,7 @@ impl StorageService { let err_message = format!("Storage '{}' raised an error on query: {}", self.name, e); log::warn!("{}", err_message); - if let Err(e) = q.reply_err(err_message).res().await { + if let Err(e) = q.reply_err(err_message).res_async().await { log::warn!( "Storage '{}' raised an error replying a query: {}", self.name, @@ -750,7 +759,7 @@ impl StorageService { .get(KeyExpr::from(&self.key_expr).with_parameters("_time=[..]")) .target(QueryTarget::All) .consolidation(ConsolidationMode::None) - .res() + .res_async() .await { Ok(replies) => replies, diff --git a/zenoh/src/sample.rs b/zenoh/src/sample.rs index 395191a0d6..29d46cca3e 100644 --- a/zenoh/src/sample.rs +++ b/zenoh/src/sample.rs @@ -684,6 +684,19 @@ impl AsyncResolve for DeleteSampleBuilder { } } +pub struct SampleDecomposed { + pub key_expr: KeyExpr<'static>, + pub payload: Payload, + pub kind: SampleKind, + pub encoding: Encoding, + pub timestamp: Option, + pub qos: QoS, + #[cfg(feature = "unstable")] + pub source_info: SourceInfo, + #[cfg(feature = "unstable")] + pub attachment: Option, +} + /// A zenoh sample. #[non_exhaustive] #[derive(Clone, Debug)] @@ -752,6 +765,22 @@ impl Sample { pub fn attachment(&self) -> Option<&Attachment> { self.attachment.as_ref() } + + /// Decomposes the Sample into its components + pub fn decompose(self) -> SampleDecomposed { + SampleDecomposed { + key_expr: self.key_expr, + payload: self.payload, + kind: self.kind, + encoding: self.encoding, + timestamp: self.timestamp, + qos: self.qos, + #[cfg(feature = "unstable")] + source_info: self.source_info, + #[cfg(feature = "unstable")] + attachment: self.attachment, + } + } } impl From for Value { From d7cb97a3705b82364a2b48557d025aa3bff156da Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Sat, 23 Mar 2024 00:41:17 +0100 Subject: [PATCH 09/63] SampleBuilderTrait --- .../src/replica/storage.rs | 4 +- zenoh-ext/src/querying_subscriber.rs | 8 +- zenoh/src/lib.rs | 1 + zenoh/src/sample.rs | 282 +--------------- zenoh/src/sample_builder.rs | 306 ++++++++++++++++++ 5 files changed, 315 insertions(+), 286 deletions(-) create mode 100644 zenoh/src/sample_builder.rs diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index f90ea01754..576f6adec2 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -24,7 +24,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; use zenoh::buffers::ZBuf; use zenoh::prelude::r#async::*; use zenoh::query::ConsolidationMode; -use zenoh::sample::SampleBuilder; +use zenoh::sample_builder::{SampleBuilder, SampleBuilderTrait}; use zenoh::time::{new_reception_timestamp, Timestamp, NTP64}; use zenoh::{Result as ZResult, Session}; use zenoh_backend_traits::config::{GarbageCollectionConfig, StorageConfig}; @@ -368,7 +368,7 @@ impl StorageService { } }; let sample = if sample.timestamp().is_none() { - SampleBuilder::new(sample).with_current_timestamp().res_sync() + SampleBuilder::from(sample).with_timestamp(new_reception_timestamp()).res_sync() } else { sample }; diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index 7ca2730f57..eb6d6e9516 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -20,9 +20,9 @@ use std::time::Duration; use zenoh::handlers::{locked, DefaultHandler}; use zenoh::prelude::r#async::*; use zenoh::query::{QueryConsolidation, QueryTarget, ReplyKeyExpr}; -use zenoh::sample::SampleBuilder; +use zenoh::sample_builder::{SampleBuilder, SampleBuilderTrait}; use zenoh::subscriber::{Reliability, Subscriber}; -use zenoh::time::Timestamp; +use zenoh::time::{new_reception_timestamp, Timestamp}; use zenoh::Result as ZResult; use zenoh::SessionRef; use zenoh_core::{zlock, AsyncResolve, Resolvable, SyncResolve}; @@ -665,7 +665,9 @@ impl<'a, Receiver> FetchingSubscriber<'a, Receiver> { // ensure the sample has a timestamp, thus it will always be sorted into the MergeQueue // after any timestamped Sample possibly coming from a fetch reply. let s = if s.timestamp().is_none() { - SampleBuilder::new(s).with_current_timestamp().res_sync() + SampleBuilder::from(s) + .with_timestamp(new_reception_timestamp()) + .res_sync() } else { s }; diff --git a/zenoh/src/lib.rs b/zenoh/src/lib.rs index eb1ba1bcd1..8618cb9a88 100644 --- a/zenoh/src/lib.rs +++ b/zenoh/src/lib.rs @@ -146,6 +146,7 @@ pub mod publication; pub mod query; pub mod queryable; pub mod sample; +pub mod sample_builder; pub mod subscriber; pub mod value; #[cfg(feature = "shared-memory")] diff --git a/zenoh/src/sample.rs b/zenoh/src/sample.rs index 29d46cca3e..2c98d5ead1 100644 --- a/zenoh/src/sample.rs +++ b/zenoh/src/sample.rs @@ -16,12 +16,11 @@ use crate::encoding::Encoding; use crate::payload::Payload; use crate::prelude::{KeyExpr, Value}; -use crate::time::{new_reception_timestamp, Timestamp}; +use crate::time::Timestamp; use crate::Priority; #[zenoh_macros::unstable] use serde::Serialize; use std::{convert::TryFrom, fmt}; -use zenoh_core::{zresult, AsyncResolve, Resolvable, SyncResolve}; use zenoh_protocol::core::EntityGlobalId; use zenoh_protocol::{core::CongestionControl, network::push::ext::QoSType}; @@ -434,269 +433,6 @@ impl TryFrom for SampleKind { #[zenoh_macros::unstable] pub use attachment::{Attachment, AttachmentBuilder, AttachmentIterator}; -pub struct SampleBuilder(Sample); - -impl SampleBuilder { - pub fn new(sample: Sample) -> Self { - Self(sample) - } - - pub fn with_keyexpr(mut self, key_expr: IntoKeyExpr) -> Self - where - IntoKeyExpr: Into>, - { - self.0.key_expr = key_expr.into(); - self - } - - // pub(crate) fn with_kind(mut self, kind: SampleKind) -> Self { - // self.0.kind = kind; - // self - // } - - pub(crate) fn with_encoding(mut self, encoding: Encoding) -> Self { - self.0.encoding = encoding; - self - } - - pub(crate) fn with_payload(mut self, payload: IntoPayload) -> Self - where - IntoPayload: Into, - { - self.0.payload = payload.into(); - self - } - - pub fn with_timestamp(mut self, timestamp: Timestamp) -> Self { - self.0.timestamp = Some(timestamp); - self - } - - pub fn with_current_timestamp(mut self) -> Self { - self.0.timestamp = Some(new_reception_timestamp()); - self - } - - pub fn with_qos(mut self, qos: QoS) -> Self { - self.0.qos = qos; - self - } - - pub fn with_source_info(mut self, source_info: SourceInfo) -> Self { - self.0.source_info = source_info; - self - } - - pub fn with_attachment(mut self, attachment: Attachment) -> Self { - self.0.attachment = Some(attachment); - self - } -} - -pub struct PutSampleBuilder(SampleBuilder); - -impl PutSampleBuilder { - pub fn new(key_expr: IntoKeyExpr, payload: IntoPayload) -> Self - where - IntoKeyExpr: Into>, - IntoPayload: Into, - { - Self(SampleBuilder::new(Sample { - key_expr: key_expr.into(), - payload: payload.into(), - kind: SampleKind::Put, - encoding: Encoding::default(), - timestamp: None, - qos: QoS::default(), - #[cfg(feature = "unstable")] - source_info: SourceInfo::empty(), - #[cfg(feature = "unstable")] - attachment: None, - })) - } - - pub fn with_payload(mut self, payload: IntoPayload) -> Self - where - IntoPayload: Into, - { - self.0 = self.0.with_payload(payload); - self - } - - pub fn with_encoding(mut self, encoding: Encoding) -> Self { - self.0 = self.0.with_encoding(encoding); - self - } - - pub fn with_timestamp(mut self, timestamp: Timestamp) -> Self { - self.0 = self.0.with_timestamp(timestamp); - self - } - - pub fn with_current_timestamp(mut self) -> Self { - self.0 = self.0.with_current_timestamp(); - self - } - - pub fn with_qos(mut self, qos: QoS) -> Self { - self.0 = self.0.with_qos(qos); - self - } - - #[zenoh_macros::unstable] - pub fn with_source_info(mut self, source_info: SourceInfo) -> Self { - self.0 = self.0.with_source_info(source_info); - self - } - - #[zenoh_macros::unstable] - pub fn with_attachment(mut self, attachment: Attachment) -> Self { - self.0 = self.0.with_attachment(attachment); - self - } -} - -pub struct DeleteSampleBuilder(SampleBuilder); - -impl DeleteSampleBuilder { - pub fn new(key_expr: IntoKeyExpr) -> Self - where - IntoKeyExpr: Into>, - { - Self(SampleBuilder::new(Sample { - key_expr: key_expr.into(), - payload: Payload::empty(), - kind: SampleKind::Delete, - encoding: Encoding::default(), - timestamp: None, - qos: QoS::default(), - #[cfg(feature = "unstable")] - source_info: SourceInfo::empty(), - #[cfg(feature = "unstable")] - attachment: None, - })) - } - pub fn with_keyexpr(mut self, key_expr: IntoKeyExpr) -> Self - where - IntoKeyExpr: Into>, - { - self.0 = self.0.with_keyexpr(key_expr); - self - } - pub fn with_timestamp(mut self, timestamp: Timestamp) -> Self { - self.0 = self.0.with_timestamp(timestamp); - self - } - pub fn with_current_timestamp(mut self) -> Self { - self.0 = self.0.with_current_timestamp(); - self - } - pub fn with_qos(mut self, qos: QoS) -> Self { - self.0 = self.0.with_qos(qos); - self - } - #[zenoh_macros::unstable] - pub fn with_source_info(mut self, source_info: SourceInfo) -> Self { - self.0 = self.0.with_source_info(source_info); - self - } - #[zenoh_macros::unstable] - pub fn with_attachment(mut self, attachment: Attachment) -> Self { - self.0 = self.0.with_attachment(attachment); - self - } -} - -impl From for SampleBuilder { - fn from(sample: Sample) -> Self { - SampleBuilder(sample) - } -} - -impl TryFrom for PutSampleBuilder { - type Error = zresult::Error; - fn try_from(sample: Sample) -> Result { - if sample.kind != SampleKind::Put { - bail!("Sample is not a put sample") - } - Ok(Self(SampleBuilder(sample))) - } -} - -impl TryFrom for DeleteSampleBuilder { - type Error = zresult::Error; - fn try_from(sample: Sample) -> Result { - if sample.kind != SampleKind::Delete { - bail!("Sample is not a delete sample") - } - Ok(Self(SampleBuilder(sample))) - } -} - -impl Resolvable for SampleBuilder { - type To = Sample; -} - -impl Resolvable for PutSampleBuilder { - type To = Sample; -} - -impl Resolvable for DeleteSampleBuilder { - type To = Sample; -} - -impl SyncResolve for SampleBuilder { - fn res_sync(self) -> Self::To { - self.0 - } -} - -impl SyncResolve for PutSampleBuilder { - fn res_sync(self) -> Self::To { - self.0.res_sync() - } -} - -impl SyncResolve for DeleteSampleBuilder { - fn res_sync(self) -> Self::To { - self.0.res_sync() - } -} - -impl AsyncResolve for SampleBuilder { - type Future = futures::future::Ready; - fn res_async(self) -> Self::Future { - futures::future::ready(self.0) - } -} - -impl AsyncResolve for PutSampleBuilder { - type Future = futures::future::Ready; - fn res_async(self) -> Self::Future { - self.0.res_async() - } -} - -impl AsyncResolve for DeleteSampleBuilder { - type Future = futures::future::Ready; - fn res_async(self) -> Self::Future { - self.0.res_async() - } -} - -pub struct SampleDecomposed { - pub key_expr: KeyExpr<'static>, - pub payload: Payload, - pub kind: SampleKind, - pub encoding: Encoding, - pub timestamp: Option, - pub qos: QoS, - #[cfg(feature = "unstable")] - pub source_info: SourceInfo, - #[cfg(feature = "unstable")] - pub attachment: Option, -} - /// A zenoh sample. #[non_exhaustive] #[derive(Clone, Debug)] @@ -765,22 +501,6 @@ impl Sample { pub fn attachment(&self) -> Option<&Attachment> { self.attachment.as_ref() } - - /// Decomposes the Sample into its components - pub fn decompose(self) -> SampleDecomposed { - SampleDecomposed { - key_expr: self.key_expr, - payload: self.payload, - kind: self.kind, - encoding: self.encoding, - timestamp: self.timestamp, - qos: self.qos, - #[cfg(feature = "unstable")] - source_info: self.source_info, - #[cfg(feature = "unstable")] - attachment: self.attachment, - } - } } impl From for Value { diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs new file mode 100644 index 0000000000..a9cffb22d1 --- /dev/null +++ b/zenoh/src/sample_builder.rs @@ -0,0 +1,306 @@ +// +// Copyright (c) 2024 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +use crate::sample::Attachment; +use crate::sample::QoS; +use crate::sample::SourceInfo; +use crate::Encoding; +use crate::KeyExpr; +use crate::Payload; +use crate::Priority; +use crate::Sample; +use crate::SampleKind; +use uhlc::Timestamp; +use zenoh_core::zresult; +use zenoh_core::AsyncResolve; +use zenoh_core::Resolvable; +use zenoh_core::SyncResolve; +use zenoh_protocol::core::CongestionControl; + +pub trait SampleBuilderTrait { + fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self + where + IntoKeyExpr: Into>; + fn with_timestamp(self, timestamp: Timestamp) -> Self; + #[zenoh_macros::unstable] + fn with_source_info(self, source_info: SourceInfo) -> Self; + #[zenoh_macros::unstable] + fn with_attachment(self, attachment: Attachment) -> Self; + fn congestion_control(self, congestion_control: CongestionControl) -> Self; + fn priority(self, priority: Priority) -> Self; + fn express(self, is_express: bool) -> Self; +} + +pub trait PutSampleBuilderTrait: SampleBuilderTrait { + fn with_encoding(self, encoding: Encoding) -> Self; + fn with_payload(self, payload: IntoPayload) -> Self + where + IntoPayload: Into; +} + +pub trait DeleteSampleBuilderTrait: SampleBuilderTrait {} + +pub struct SampleBuilder(Sample); + +impl SampleBuilderTrait for SampleBuilder { + fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self + where + IntoKeyExpr: Into>, + { + let mut this = self; + this.0.key_expr = key_expr.into(); + this + } + + fn with_timestamp(self, timestamp: Timestamp) -> Self { + let mut this = self; + this.0.timestamp = Some(timestamp); + this + } + #[zenoh_macros::unstable] + fn with_source_info(self, source_info: SourceInfo) -> Self { + let mut this = self; + this.0.source_info = source_info; + this + } + #[zenoh_macros::unstable] + fn with_attachment(self, attachment: Attachment) -> Self { + let mut this = self; + this.0.attachment = Some(attachment); + this + } + fn congestion_control(self, congestion_control: CongestionControl) -> Self { + let mut this = self; + this.0.qos = this.0.qos.with_congestion_control(congestion_control); + this + } + fn priority(self, priority: Priority) -> Self { + let mut this = self; + this.0.qos = this.0.qos.with_priority(priority); + this + } + fn express(self, is_express: bool) -> Self { + let mut this = self; + this.0.qos = this.0.qos.with_express(is_express); + this + } +} + +pub struct PutSampleBuilder(SampleBuilder); + +impl PutSampleBuilder { + pub fn new(key_expr: IntoKeyExpr, payload: IntoPayload) -> Self + where + IntoKeyExpr: Into>, + IntoPayload: Into, + { + Self(SampleBuilder::from(Sample { + key_expr: key_expr.into(), + payload: payload.into(), + kind: SampleKind::Put, + encoding: Encoding::default(), + timestamp: None, + qos: QoS::default(), + #[cfg(feature = "unstable")] + source_info: SourceInfo::empty(), + #[cfg(feature = "unstable")] + attachment: None, + })) + } + pub fn without_timestamp(self) -> Self { + let mut this = self; + this.0 .0.timestamp = None; + this + } + pub fn without_attachment(self) -> Self { + let mut this = self; + this.0 .0.attachment = None; + this + } +} + +impl SampleBuilderTrait for PutSampleBuilder { + fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self + where + IntoKeyExpr: Into>, + { + Self(self.0.with_keyexpr(key_expr)) + } + fn with_timestamp(self, timestamp: Timestamp) -> Self { + Self(self.0.with_timestamp(timestamp)) + } + #[zenoh_macros::unstable] + fn with_source_info(self, source_info: SourceInfo) -> Self { + Self(self.0.with_source_info(source_info)) + } + #[zenoh_macros::unstable] + fn with_attachment(self, attachment: Attachment) -> Self { + Self(self.0.with_attachment(attachment)) + } + fn congestion_control(self, congestion_control: CongestionControl) -> Self { + Self(self.0.congestion_control(congestion_control)) + } + fn priority(self, priority: Priority) -> Self { + Self(self.0.priority(priority)) + } + fn express(self, is_express: bool) -> Self { + Self(self.0.express(is_express)) + } +} + +impl PutSampleBuilderTrait for PutSampleBuilder { + fn with_encoding(self, encoding: Encoding) -> Self { + let mut this = self; + this.0 .0.encoding = encoding; + this + } + fn with_payload(self, payload: IntoPayload) -> Self + where + IntoPayload: Into, + { + let mut this = self; + this.0 .0.payload = payload.into(); + this + } +} + +pub struct DeleteSampleBuilder(SampleBuilder); + +impl DeleteSampleBuilder { + pub fn new(key_expr: IntoKeyExpr) -> Self + where + IntoKeyExpr: Into>, + { + Self(SampleBuilder::from(Sample { + key_expr: key_expr.into(), + payload: Payload::empty(), + kind: SampleKind::Delete, + encoding: Encoding::default(), + timestamp: None, + qos: QoS::default(), + #[cfg(feature = "unstable")] + source_info: SourceInfo::empty(), + #[cfg(feature = "unstable")] + attachment: None, + })) + } +} + +impl SampleBuilderTrait for DeleteSampleBuilder { + fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self + where + IntoKeyExpr: Into>, + { + Self(self.0.with_keyexpr(key_expr)) + } + fn with_timestamp(self, timestamp: Timestamp) -> Self { + Self(self.0.with_timestamp(timestamp)) + } + #[zenoh_macros::unstable] + fn with_source_info(self, source_info: SourceInfo) -> Self { + Self(self.0.with_source_info(source_info)) + } + #[zenoh_macros::unstable] + fn with_attachment(self, attachment: Attachment) -> Self { + Self(self.0.with_attachment(attachment)) + } + fn congestion_control(self, congestion_control: CongestionControl) -> Self { + Self(self.0.congestion_control(congestion_control)) + } + fn priority(self, priority: Priority) -> Self { + Self(self.0.priority(priority)) + } + fn express(self, is_express: bool) -> Self { + Self(self.0.express(is_express)) + } +} + +impl DeleteSampleBuilderTrait for DeleteSampleBuilder {} + +impl From for SampleBuilder { + fn from(sample: Sample) -> Self { + SampleBuilder(sample) + } +} + +impl TryFrom for PutSampleBuilder { + type Error = zresult::Error; + fn try_from(sample: Sample) -> Result { + if sample.kind != SampleKind::Put { + bail!("Sample is not a put sample") + } + Ok(Self(SampleBuilder(sample))) + } +} + +impl TryFrom for DeleteSampleBuilder { + type Error = zresult::Error; + fn try_from(sample: Sample) -> Result { + if sample.kind != SampleKind::Delete { + bail!("Sample is not a delete sample") + } + Ok(Self(SampleBuilder(sample))) + } +} + +impl Resolvable for SampleBuilder { + type To = Sample; +} + +impl Resolvable for PutSampleBuilder { + type To = Sample; +} + +impl Resolvable for DeleteSampleBuilder { + type To = Sample; +} + +impl SyncResolve for SampleBuilder { + fn res_sync(self) -> Self::To { + self.0 + } +} + +impl SyncResolve for PutSampleBuilder { + fn res_sync(self) -> Self::To { + self.0.res_sync() + } +} + +impl SyncResolve for DeleteSampleBuilder { + fn res_sync(self) -> Self::To { + self.0.res_sync() + } +} + +impl AsyncResolve for SampleBuilder { + type Future = futures::future::Ready; + fn res_async(self) -> Self::Future { + futures::future::ready(self.0) + } +} + +impl AsyncResolve for PutSampleBuilder { + type Future = futures::future::Ready; + fn res_async(self) -> Self::Future { + self.0.res_async() + } +} + +impl AsyncResolve for DeleteSampleBuilder { + type Future = futures::future::Ready; + fn res_async(self) -> Self::Future { + self.0.res_async() + } +} From a05b93de8c9507e597d2f85bce88c9787241590b Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Sat, 23 Mar 2024 15:43:58 +0100 Subject: [PATCH 10/63] reply builder unfinished --- .../src/replica/storage.rs | 4 +- zenoh-ext/src/querying_subscriber.rs | 2 +- zenoh/src/queryable.rs | 268 +++++++++++------- zenoh/src/sample_builder.rs | 99 ++++--- 4 files changed, 238 insertions(+), 135 deletions(-) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 576f6adec2..1aadc88611 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -24,7 +24,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; use zenoh::buffers::ZBuf; use zenoh::prelude::r#async::*; use zenoh::query::ConsolidationMode; -use zenoh::sample_builder::{SampleBuilder, SampleBuilderTrait}; +use zenoh::sample_builder::{SampleBuilderTrait, SampleUpdater}; use zenoh::time::{new_reception_timestamp, Timestamp, NTP64}; use zenoh::{Result as ZResult, Session}; use zenoh_backend_traits::config::{GarbageCollectionConfig, StorageConfig}; @@ -368,7 +368,7 @@ impl StorageService { } }; let sample = if sample.timestamp().is_none() { - SampleBuilder::from(sample).with_timestamp(new_reception_timestamp()).res_sync() + SampleUpdater::from(sample).with_timestamp(new_reception_timestamp()).res_sync() } else { sample }; diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index eb6d6e9516..19388ea16f 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -20,7 +20,7 @@ use std::time::Duration; use zenoh::handlers::{locked, DefaultHandler}; use zenoh::prelude::r#async::*; use zenoh::query::{QueryConsolidation, QueryTarget, ReplyKeyExpr}; -use zenoh::sample_builder::{SampleBuilder, SampleBuilderTrait}; +use zenoh::sample_builder::{SampleBuilderTrait, SampleUpdater}; use zenoh::subscriber::{Reliability, Subscriber}; use zenoh::time::{new_reception_timestamp, Timestamp}; use zenoh::Result as ZResult; diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index d2eabcdc2a..eb6ef013c7 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -20,6 +20,10 @@ use crate::net::primitives::Primitives; use crate::prelude::*; use crate::sample::QoS; use crate::sample::SourceInfo; +use crate::sample_builder::{ + DeleteSampleBuilder, DeleteSampleBuilderTrait, PutSampleBuilder, PutSampleBuilderTrait, + SampleBuilder, SampleBuilderTrait, +}; use crate::Id; use crate::SessionRef; use crate::Undeclarable; @@ -102,43 +106,6 @@ impl Query { pub fn attachment(&self) -> Option<&Attachment> { self.inner.attachment.as_ref() } - /// Sends a reply in the form of [`Sample`] to this Query. - /// - /// By default, queries only accept replies whose key expression intersects with the query's. - /// Unless the query has enabled disjoint replies (you can check this through [`Query::accepts_replies`]), - /// replying on a disjoint key expression will result in an error when resolving the reply. - /// This api is for internal use only. - #[inline(always)] - #[cfg(feature = "unstable")] - #[doc(hidden)] - pub fn reply_sample(&self, sample: Sample) -> ReplyBuilder<'_> { - let Sample { - key_expr, - payload, - kind, - encoding, - timestamp, - qos, - #[cfg(feature = "unstable")] - source_info, - #[cfg(feature = "unstable")] - attachment, - } = sample; - ReplyBuilder { - query: self, - key_expr, - payload, - kind, - encoding, - timestamp, - qos, - #[cfg(feature = "unstable")] - source_info, - #[cfg(feature = "unstable")] - attachment, - } - } - /// Sends a reply to this Query. /// /// By default, queries only accept replies whose key expression intersects with the query's. @@ -154,18 +121,11 @@ impl Query { IntoKeyExpr: Into>, IntoPayload: Into, { + let sample_builder = PutSampleBuilder::new(key_expr, payload) + .with_qos(response::ext::QoSType::RESPONSE.into()); ReplyBuilder { query: self, - key_expr: key_expr.into(), - payload: payload.into(), - kind: SampleKind::Put, - timestamp: None, - encoding: Encoding::default(), - qos: response::ext::QoSType::RESPONSE.into(), - #[cfg(feature = "unstable")] - source_info: SourceInfo::empty(), - #[cfg(feature = "unstable")] - attachment: None, + sample_builder, } } /// Sends a error reply to this Query. @@ -187,22 +147,15 @@ impl Query { /// Unless the query has enabled disjoint replies (you can check this through [`Query::accepts_replies`]), /// replying on a disjoint key expression will result in an error when resolving the reply. #[inline(always)] - pub fn reply_del(&self, key_expr: IntoKeyExpr) -> ReplyBuilder<'_> + pub fn reply_del(&self, key_expr: IntoKeyExpr) -> ReplyDelBuilder<'_> where IntoKeyExpr: Into>, { - ReplyBuilder { + let sample_builder = + DeleteSampleBuilder::new(key_expr).with_qos(response::ext::QoSType::RESPONSE.into()); + ReplyDelBuilder { query: self, - key_expr: key_expr.into(), - payload: Payload::empty(), - kind: SampleKind::Delete, - timestamp: None, - encoding: Encoding::default(), - qos: response::ext::QoSType::RESPONSE.into(), - #[cfg(feature = "unstable")] - source_info: SourceInfo::empty(), - #[cfg(feature = "unstable")] - attachment: None, + sample_builder, } } @@ -250,45 +203,161 @@ impl fmt::Display for Query { #[derive(Debug)] pub struct ReplyBuilder<'a> { query: &'a Query, - key_expr: KeyExpr<'static>, - payload: Payload, - kind: SampleKind, - encoding: Encoding, - timestamp: Option, - qos: QoS, + sample_builder: PutSampleBuilder, +} + +impl SampleBuilderTrait for ReplyBuilder<'_> { + fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self + where + IntoKeyExpr: Into>, + { + Self { + sample_builder: self.sample_builder.with_keyexpr(key_expr), + ..self + } + } + + fn with_timestamp(self, timestamp: Timestamp) -> Self { + Self { + sample_builder: self.sample_builder.with_timestamp(timestamp), + ..self + } + } + #[cfg(feature = "unstable")] - source_info: SourceInfo, + fn with_source_info(self, source_info: SourceInfo) -> Self { + Self { + sample_builder: self.sample_builder.with_source_info(source_info), + ..self + } + } + #[cfg(feature = "unstable")] - attachment: Option, + fn with_attachment(self, attachment: Attachment) -> Self { + Self { + sample_builder: self.sample_builder.with_attachment(attachment), + ..self + } + } + + fn congestion_control(self, congestion_control: CongestionControl) -> Self { + Self { + sample_builder: self.sample_builder.congestion_control(congestion_control), + ..self + } + } + + fn priority(self, priority: Priority) -> Self { + Self { + sample_builder: self.sample_builder.priority(priority), + ..self + } + } + + fn express(self, is_express: bool) -> Self { + Self { + sample_builder: self.sample_builder.express(is_express), + ..self + } + } } -/// A builder returned by [`Query::reply_err()`](Query::reply_err). +impl PutSampleBuilderTrait for ReplyBuilder<'_> { + fn with_encoding(self, encoding: Encoding) -> Self { + Self { + sample_builder: self.sample_builder.with_encoding(encoding), + ..self + } + } + + fn with_payload(self, payload: IntoPayload) -> Self + where + IntoPayload: Into, + { + Self { + sample_builder: self.sample_builder.with_payload(payload), + ..self + } + } +} + +/// A builder returned by [`Query::reply_del()`](Query::reply) #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] #[derive(Debug)] -pub struct ReplyErrBuilder<'a> { +pub struct ReplyDelBuilder<'a> { query: &'a Query, - value: Value, + sample_builder: DeleteSampleBuilder, } -impl<'a> ReplyBuilder<'a> { - #[zenoh_macros::unstable] - pub fn with_attachment(mut self, attachment: Attachment) -> Self { - self.attachment = Some(attachment); - self +impl SampleBuilderTrait for ReplyDelBuilder<'_> { + fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self + where + IntoKeyExpr: Into>, + { + Self { + sample_builder: self.sample_builder.with_keyexpr(key_expr), + ..self + } } - #[zenoh_macros::unstable] - pub fn with_source_info(mut self, source_info: SourceInfo) -> Self { - self.source_info = source_info; - self + + fn with_timestamp(self, timestamp: Timestamp) -> Self { + Self { + sample_builder: self.sample_builder.with_timestamp(timestamp), + ..self + } } - pub fn with_timestamp(mut self, timestamp: Timestamp) -> Self { - self.timestamp = Some(timestamp); - self + + #[cfg(feature = "unstable")] + fn with_source_info(self, source_info: SourceInfo) -> Self { + Self { + sample_builder: self.sample_builder.with_source_info(source_info), + ..self + } } - pub fn with_encoding(mut self, encoding: Encoding) -> Self { - self.encoding = encoding; - self + #[cfg(feature = "unstable")] + fn with_attachment(self, attachment: Attachment) -> Self { + Self { + sample_builder: self.sample_builder.with_attachment(attachment), + ..self + } + } + + fn congestion_control(self, congestion_control: CongestionControl) -> Self { + Self { + sample_builder: self.sample_builder.congestion_control(congestion_control), + ..self + } + } + + fn priority(self, priority: Priority) -> Self { + Self { + sample_builder: self.sample_builder.priority(priority), + ..self + } + } + + fn express(self, is_express: bool) -> Self { + Self { + sample_builder: self.sample_builder.express(is_express), + ..self + } + } +} + +impl DeleteSampleBuilderTrait for ReplyDelBuilder<'_> {} + +/// A builder returned by [`Query::reply_err()`](Query::reply_err). +#[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] +#[derive(Debug)] +pub struct ReplyErrBuilder<'a> { + query: &'a Query, + value: Value, +} + +impl AsRef for ReplyBuilder<'_> { + fn as_ref(&self) -> &PutSampleBuilder { + &self.sample_builder } } @@ -298,19 +367,20 @@ impl<'a> Resolvable for ReplyBuilder<'a> { impl SyncResolve for ReplyBuilder<'_> { fn res_sync(self) -> ::To { + let sample = self.sample_builder.res_sync(); if !self.query._accepts_any_replies().unwrap_or(false) - && !self.query.key_expr().intersects(&self.key_expr) + && !self.query.key_expr().intersects(&sample.key_expr) { - bail!("Attempted to reply on `{}`, which does not intersect with query `{}`, despite query only allowing replies on matching key expressions", self.key_expr, self.query.key_expr()) + bail!("Attempted to reply on `{}`, which does not intersect with query `{}`, despite query only allowing replies on matching key expressions", sample.key_expr, self.query.key_expr()) } #[allow(unused_mut)] // will be unused if feature = "unstable" is not enabled let mut ext_sinfo = None; #[cfg(feature = "unstable")] { - if self.source_info.source_id.is_some() || self.source_info.source_sn.is_some() { + if sample.source_info.source_id.is_some() || sample.source_info.source_sn.is_some() { ext_sinfo = Some(zenoh::put::ext::SourceInfoType { - id: self.source_info.source_id.unwrap_or_default(), - sn: self.source_info.source_sn.unwrap_or_default() as u32, + id: sample.source_info.source_id.unwrap_or_default(), + sn: sample.source_info.source_sn.unwrap_or_default() as u32, }) } } @@ -318,38 +388,38 @@ impl SyncResolve for ReplyBuilder<'_> { rid: self.query.inner.qid, wire_expr: WireExpr { scope: 0, - suffix: std::borrow::Cow::Owned(self.key_expr.into()), + suffix: std::borrow::Cow::Owned(sample.key_expr.into()), mapping: Mapping::Sender, }, payload: ResponseBody::Reply(zenoh::Reply { consolidation: zenoh::Consolidation::DEFAULT, ext_unknown: vec![], - payload: match self.kind { + payload: match sample.kind { SampleKind::Put => ReplyBody::Put(Put { - timestamp: self.timestamp, - encoding: self.encoding.into(), + timestamp: sample.timestamp, + encoding: sample.encoding.into(), ext_sinfo, #[cfg(feature = "shared-memory")] ext_shm: None, #[cfg(feature = "unstable")] - ext_attachment: self.attachment.map(|a| a.into()), + ext_attachment: sample.attachment.map(|a| a.into()), #[cfg(not(feature = "unstable"))] ext_attachment: None, ext_unknown: vec![], - payload: self.payload.into(), + payload: sample.payload.into(), }), SampleKind::Delete => ReplyBody::Del(Del { - timestamp: self.timestamp, + timestamp: sample.timestamp, ext_sinfo, #[cfg(feature = "unstable")] - ext_attachment: self.attachment.map(|a| a.into()), + ext_attachment: sample.attachment.map(|a| a.into()), #[cfg(not(feature = "unstable"))] ext_attachment: None, ext_unknown: vec![], }), }, }), - ext_qos: self.qos.into(), + ext_qos: sample.qos.into(), ext_tstamp: None, ext_respid: Some(response::ext::ResponderIdType { zid: self.query.inner.zid, diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index a9cffb22d1..fcf3a64182 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -51,52 +51,76 @@ pub trait PutSampleBuilderTrait: SampleBuilderTrait { pub trait DeleteSampleBuilderTrait: SampleBuilderTrait {} +#[derive(Debug)] pub struct SampleBuilder(Sample); +impl SampleBuilder { + pub(crate) fn without_timestamp(self) -> Self { + Self(Sample { + timestamp: None, + ..self.0 + }) + } + pub(crate) fn without_attachment(self) -> Self { + Self(Sample { + attachment: None, + ..self.0 + }) + } +} + impl SampleBuilderTrait for SampleBuilder { fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self where IntoKeyExpr: Into>, { - let mut this = self; - this.0.key_expr = key_expr.into(); - this + Self(Sample { + key_expr: key_expr.into(), + ..self.0 + }) } fn with_timestamp(self, timestamp: Timestamp) -> Self { - let mut this = self; - this.0.timestamp = Some(timestamp); - this + Self(Sample { + timestamp: Some(timestamp), + ..self.0 + }) } #[zenoh_macros::unstable] fn with_source_info(self, source_info: SourceInfo) -> Self { - let mut this = self; - this.0.source_info = source_info; - this + Self(Sample { + source_info, + ..self.0 + }) } #[zenoh_macros::unstable] fn with_attachment(self, attachment: Attachment) -> Self { - let mut this = self; - this.0.attachment = Some(attachment); - this + Self(Sample { + attachment: Some(attachment), + ..self.0 + }) } fn congestion_control(self, congestion_control: CongestionControl) -> Self { - let mut this = self; - this.0.qos = this.0.qos.with_congestion_control(congestion_control); - this + Self(Sample { + qos: self.0.qos.with_congestion_control(congestion_control), + ..self.0 + }) } fn priority(self, priority: Priority) -> Self { - let mut this = self; - this.0.qos = this.0.qos.with_priority(priority); - this + Self(Sample { + qos: self.0.qos.with_priority(priority), + ..self.0 + }) } fn express(self, is_express: bool) -> Self { - let mut this = self; - this.0.qos = this.0.qos.with_express(is_express); - this + Self(Sample { + qos: self.0.qos.with_express(is_express), + ..self.0 + }) } } +#[derive(Debug)] pub struct PutSampleBuilder(SampleBuilder); impl PutSampleBuilder { @@ -118,15 +142,17 @@ impl PutSampleBuilder { attachment: None, })) } + #[zenoh_macros::unstable] pub fn without_timestamp(self) -> Self { - let mut this = self; - this.0 .0.timestamp = None; - this + Self(self.0.without_timestamp()) } + #[zenoh_macros::unstable] pub fn without_attachment(self) -> Self { - let mut this = self; - this.0 .0.attachment = None; - this + Self(self.0.without_attachment()) + } + // It's convenient to set QoS as a whole for internal usage. For user API there are `congestion_control`, `priority` and `express` methods. + pub(crate) fn with_qos(self, qos: QoS) -> Self { + Self(SampleBuilder(Sample { qos, ..self.0 .0 })) } } @@ -161,20 +187,23 @@ impl SampleBuilderTrait for PutSampleBuilder { impl PutSampleBuilderTrait for PutSampleBuilder { fn with_encoding(self, encoding: Encoding) -> Self { - let mut this = self; - this.0 .0.encoding = encoding; - this + Self(SampleBuilder(Sample { + encoding, + ..self.0 .0 + })) } fn with_payload(self, payload: IntoPayload) -> Self where IntoPayload: Into, { - let mut this = self; - this.0 .0.payload = payload.into(); - this + Self(SampleBuilder(Sample { + payload: payload.into(), + ..self.0 .0 + })) } } +#[derive(Debug)] pub struct DeleteSampleBuilder(SampleBuilder); impl DeleteSampleBuilder { @@ -195,6 +224,10 @@ impl DeleteSampleBuilder { attachment: None, })) } + // It's convenient to set QoS as a whole for internal usage. For user API there are `congestion_control`, `priority` and `express` methods. + pub(crate) fn with_qos(self, qos: QoS) -> Self { + Self(SampleBuilder(Sample { qos, ..self.0 .0 })) + } } impl SampleBuilderTrait for DeleteSampleBuilder { From 0992ff8812df04e4b0dc9acc01a45763739d0792 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Sat, 23 Mar 2024 22:44:36 +0100 Subject: [PATCH 11/63] replybuilder unfinished --- zenoh-ext/src/querying_subscriber.rs | 2 +- zenoh/src/net/runtime/adminspace.rs | 1 + zenoh/src/queryable.rs | 38 ++++++++++++++++++---------- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index 19388ea16f..eb6d6e9516 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -20,7 +20,7 @@ use std::time::Duration; use zenoh::handlers::{locked, DefaultHandler}; use zenoh::prelude::r#async::*; use zenoh::query::{QueryConsolidation, QueryTarget, ReplyKeyExpr}; -use zenoh::sample_builder::{SampleBuilderTrait, SampleUpdater}; +use zenoh::sample_builder::{SampleBuilder, SampleBuilderTrait}; use zenoh::subscriber::{Reliability, Subscriber}; use zenoh::time::{new_reception_timestamp, Timestamp}; use zenoh::Result as ZResult; diff --git a/zenoh/src/net/runtime/adminspace.rs b/zenoh/src/net/runtime/adminspace.rs index 29106cb89d..01f29ba19b 100644 --- a/zenoh/src/net/runtime/adminspace.rs +++ b/zenoh/src/net/runtime/adminspace.rs @@ -20,6 +20,7 @@ use crate::plugins::sealed::{self as plugins}; use crate::prelude::sync::SyncResolve; use crate::queryable::Query; use crate::queryable::QueryInner; +use crate::sample_builder::PutSampleBuilderTrait; use crate::value::Value; use async_std::task; use log::{error, trace}; diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index eb6ef013c7..a5b6deca4c 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -18,11 +18,10 @@ use crate::encoding::Encoding; use crate::handlers::{locked, DefaultHandler}; use crate::net::primitives::Primitives; use crate::prelude::*; -use crate::sample::QoS; use crate::sample::SourceInfo; use crate::sample_builder::{ DeleteSampleBuilder, DeleteSampleBuilderTrait, PutSampleBuilder, PutSampleBuilderTrait, - SampleBuilder, SampleBuilderTrait, + SampleBuilderTrait, }; use crate::Id; use crate::SessionRef; @@ -355,23 +354,34 @@ pub struct ReplyErrBuilder<'a> { value: Value, } -impl AsRef for ReplyBuilder<'_> { - fn as_ref(&self) -> &PutSampleBuilder { - &self.sample_builder +impl<'a> Resolvable for ReplyBuilder<'a> { + type To = ZResult<()>; +} + +impl SyncResolve for ReplyBuilder<'_> { + fn res_sync(self) -> ::To { + let sample = self.sample_builder.res_sync(); + self.query._reply_sample(sample) } } -impl<'a> Resolvable for ReplyBuilder<'a> { +impl<'a> Resolvable for ReplyDelBuilder<'a> { type To = ZResult<()>; } -impl SyncResolve for ReplyBuilder<'_> { +impl SyncResolve for ReplyDelBuilder<'_> { fn res_sync(self) -> ::To { let sample = self.sample_builder.res_sync(); - if !self.query._accepts_any_replies().unwrap_or(false) - && !self.query.key_expr().intersects(&sample.key_expr) + self.query._reply_sample(sample) + } +} + +impl Query { + fn _reply_sample(&self, sample: Sample) -> ZResult<()> { + if !self._accepts_any_replies().unwrap_or(false) + && !self.key_expr().intersects(&sample.key_expr) { - bail!("Attempted to reply on `{}`, which does not intersect with query `{}`, despite query only allowing replies on matching key expressions", sample.key_expr, self.query.key_expr()) + bail!("Attempted to reply on `{}`, which does not intersect with query `{}`, despite query only allowing replies on matching key expressions", sample.key_expr, self.key_expr()) } #[allow(unused_mut)] // will be unused if feature = "unstable" is not enabled let mut ext_sinfo = None; @@ -384,8 +394,8 @@ impl SyncResolve for ReplyBuilder<'_> { }) } } - self.query.inner.primitives.send_response(Response { - rid: self.query.inner.qid, + self.inner.primitives.send_response(Response { + rid: self.inner.qid, wire_expr: WireExpr { scope: 0, suffix: std::borrow::Cow::Owned(sample.key_expr.into()), @@ -422,8 +432,8 @@ impl SyncResolve for ReplyBuilder<'_> { ext_qos: sample.qos.into(), ext_tstamp: None, ext_respid: Some(response::ext::ResponderIdType { - zid: self.query.inner.zid, - eid: self.query.eid, + zid: self.inner.zid, + eid: self.eid, }), }); Ok(()) From 62378ad1805d3e13db06664f1176ca0f89393fe2 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Sun, 24 Mar 2024 11:21:32 +0100 Subject: [PATCH 12/63] new reply_sample --- zenoh/src/queryable.rs | 102 +++++++++++++++++++++++++++++++++++- zenoh/src/sample_builder.rs | 43 ++++++++++++++- 2 files changed, 141 insertions(+), 4 deletions(-) diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index a5b6deca4c..d0b80e9a11 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -21,7 +21,7 @@ use crate::prelude::*; use crate::sample::SourceInfo; use crate::sample_builder::{ DeleteSampleBuilder, DeleteSampleBuilderTrait, PutSampleBuilder, PutSampleBuilderTrait, - SampleBuilderTrait, + SampleBuilder, SampleBuilderTrait, }; use crate::Id; use crate::SessionRef; @@ -105,6 +105,24 @@ impl Query { pub fn attachment(&self) -> Option<&Attachment> { self.inner.attachment.as_ref() } + + /// Sends a reply or delete reply to this Query + /// + /// This function is useful when resending the samples which can be of [`SampleKind::Put`] or [`SampleKind::Delete`] + /// It allows to build the reply with same common parameters, like timestamp, attachment, source_info, etc. + /// and only on final step to choose the kind of reply by calling [`ReplySampleBuilder::put`] or [`ReplySampleBuilder::delete`] methods. + #[inline(always)] + pub fn reply_sample(&self, key_expr: IntoKeyExpr) -> ReplySampleBuilder + where + IntoKeyExpr: Into>, + { + let sample_builder = SampleBuilder::new(key_expr); + ReplySampleBuilder { + query: self, + sample_builder, + } + } + /// Sends a reply to this Query. /// /// By default, queries only accept replies whose key expression intersects with the query's. @@ -197,7 +215,87 @@ impl fmt::Display for Query { } } -/// A builder returned by [`Query::reply()`](Query::reply) or [`Query::reply()`](Query::reply). +pub struct ReplySampleBuilder<'a> { + query: &'a Query, + sample_builder: SampleBuilder, +} + +impl<'a> ReplySampleBuilder<'a> { + pub fn put(self, payload: IntoPayload) -> ReplyBuilder<'a> + where + IntoPayload: Into, + { + let builder = ReplyBuilder { + query: self.query, + sample_builder: self.sample_builder.into(), + }; + builder.with_payload(payload) + } + pub fn delete(self) -> ReplyDelBuilder<'a> { + ReplyDelBuilder { + query: self.query, + sample_builder: self.sample_builder.into(), + } + } +} + +impl SampleBuilderTrait for ReplySampleBuilder<'_> { + fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self + where + IntoKeyExpr: Into>, + { + Self { + sample_builder: self.sample_builder.with_keyexpr(key_expr), + ..self + } + } + + fn with_timestamp(self, timestamp: Timestamp) -> Self { + Self { + sample_builder: self.sample_builder.with_timestamp(timestamp), + ..self + } + } + + #[cfg(feature = "unstable")] + fn with_source_info(self, source_info: SourceInfo) -> Self { + Self { + sample_builder: self.sample_builder.with_source_info(source_info), + ..self + } + } + + #[cfg(feature = "unstable")] + fn with_attachment(self, attachment: Attachment) -> Self { + Self { + sample_builder: self.sample_builder.with_attachment(attachment), + ..self + } + } + + fn congestion_control(self, congestion_control: CongestionControl) -> Self { + Self { + sample_builder: self.sample_builder.congestion_control(congestion_control), + ..self + } + } + + fn priority(self, priority: Priority) -> Self { + Self { + sample_builder: self.sample_builder.priority(priority), + ..self + } + } + + fn express(self, is_express: bool) -> Self { + Self { + sample_builder: self.sample_builder.express(is_express), + ..self + } + } +} + +/// A builder returned by [`Query::reply()`](Query::reply) #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] #[derive(Debug)] pub struct ReplyBuilder<'a> { diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index fcf3a64182..61e4bf81fb 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -55,13 +55,30 @@ pub trait DeleteSampleBuilderTrait: SampleBuilderTrait {} pub struct SampleBuilder(Sample); impl SampleBuilder { - pub(crate) fn without_timestamp(self) -> Self { + pub fn new(key_expr: IntoKeyExpr) -> Self + where + IntoKeyExpr: Into>, + { + Self(Sample { + key_expr: key_expr.into(), + payload: Payload::empty(), + kind: SampleKind::default(), + encoding: Encoding::default(), + timestamp: None, + qos: QoS::default(), + #[cfg(feature = "unstable")] + source_info: SourceInfo::empty(), + #[cfg(feature = "unstable")] + attachment: None, + }) + } + pub fn without_timestamp(self) -> Self { Self(Sample { timestamp: None, ..self.0 }) } - pub(crate) fn without_attachment(self) -> Self { + pub fn without_attachment(self) -> Self { Self(Sample { attachment: None, ..self.0 @@ -123,6 +140,17 @@ impl SampleBuilderTrait for SampleBuilder { #[derive(Debug)] pub struct PutSampleBuilder(SampleBuilder); +impl From for PutSampleBuilder { + fn from(sample_builder: SampleBuilder) -> Self { + Self(SampleBuilder { + 0: Sample { + kind: SampleKind::Put, + ..sample_builder.0 + }, + }) + } +} + impl PutSampleBuilder { pub fn new(key_expr: IntoKeyExpr, payload: IntoPayload) -> Self where @@ -206,6 +234,17 @@ impl PutSampleBuilderTrait for PutSampleBuilder { #[derive(Debug)] pub struct DeleteSampleBuilder(SampleBuilder); +impl From for DeleteSampleBuilder { + fn from(sample_builder: SampleBuilder) -> Self { + Self(SampleBuilder { + 0: Sample { + kind: SampleKind::Delete, + ..sample_builder.0 + }, + }) + } +} + impl DeleteSampleBuilder { pub fn new(key_expr: IntoKeyExpr) -> Self where From cc580a5dd4a30409b12ab4ae7c5a81d0b9d5ab1d Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Sun, 24 Mar 2024 13:08:10 +0100 Subject: [PATCH 13/63] sample decompose, opt setters --- zenoh/src/queryable.rs | 45 +++++++++++++++++++++++++++++ zenoh/src/sample.rs | 35 +++++++++++++++++++++++ zenoh/src/sample_builder.rs | 56 +++++++++++++++++++++---------------- 3 files changed, 112 insertions(+), 24 deletions(-) diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index d0b80e9a11..7d4a0903c2 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -250,6 +250,13 @@ impl SampleBuilderTrait for ReplySampleBuilder<'_> { } } + fn with_timestamp_opt(self, timestamp: Option) -> Self { + Self { + sample_builder: self.sample_builder.with_timestamp_opt(timestamp), + ..self + } + } + fn with_timestamp(self, timestamp: Timestamp) -> Self { Self { sample_builder: self.sample_builder.with_timestamp(timestamp), @@ -265,6 +272,14 @@ impl SampleBuilderTrait for ReplySampleBuilder<'_> { } } + #[cfg(feature = "unstable")] + fn with_attachment_opt(self, attachment: Option) -> Self { + Self { + sample_builder: self.sample_builder.with_attachment_opt(attachment), + ..self + } + } + #[cfg(feature = "unstable")] fn with_attachment(self, attachment: Attachment) -> Self { Self { @@ -314,6 +329,13 @@ impl SampleBuilderTrait for ReplyBuilder<'_> { } } + fn with_timestamp_opt(self, timestamp: Option) -> Self { + Self { + sample_builder: self.sample_builder.with_timestamp_opt(timestamp), + ..self + } + } + fn with_timestamp(self, timestamp: Timestamp) -> Self { Self { sample_builder: self.sample_builder.with_timestamp(timestamp), @@ -329,6 +351,14 @@ impl SampleBuilderTrait for ReplyBuilder<'_> { } } + #[cfg(feature = "unstable")] + fn with_attachment_opt(self, attachment: Option) -> Self { + Self { + sample_builder: self.sample_builder.with_attachment_opt(attachment), + ..self + } + } + #[cfg(feature = "unstable")] fn with_attachment(self, attachment: Attachment) -> Self { Self { @@ -397,6 +427,13 @@ impl SampleBuilderTrait for ReplyDelBuilder<'_> { } } + fn with_timestamp_opt(self, timestamp: Option) -> Self { + Self { + sample_builder: self.sample_builder.with_timestamp_opt(timestamp), + ..self + } + } + fn with_timestamp(self, timestamp: Timestamp) -> Self { Self { sample_builder: self.sample_builder.with_timestamp(timestamp), @@ -412,6 +449,14 @@ impl SampleBuilderTrait for ReplyDelBuilder<'_> { } } + #[cfg(feature = "unstable")] + fn with_attachment_opt(self, attachment: Option) -> Self { + Self { + sample_builder: self.sample_builder.with_attachment_opt(attachment), + ..self + } + } + #[cfg(feature = "unstable")] fn with_attachment(self, attachment: Attachment) -> Self { Self { diff --git a/zenoh/src/sample.rs b/zenoh/src/sample.rs index 2c98d5ead1..3ac3087836 100644 --- a/zenoh/src/sample.rs +++ b/zenoh/src/sample.rs @@ -433,6 +433,41 @@ impl TryFrom for SampleKind { #[zenoh_macros::unstable] pub use attachment::{Attachment, AttachmentBuilder, AttachmentIterator}; +/// Structure with public fields for sample. It's convenient if it's necessary to decompose a sample into its fields. +pub struct SampleFields { + pub key_expr: KeyExpr<'static>, + pub payload: Payload, + pub kind: SampleKind, + pub encoding: Encoding, + pub timestamp: Option, + pub express: bool, + pub priority: Priority, + pub congestion_control: CongestionControl, + #[cfg(feature = "unstable")] + pub source_info: SourceInfo, + #[cfg(feature = "unstable")] + pub attachment: Option, +} + +impl From for SampleFields { + fn from(sample: Sample) -> Self { + SampleFields { + key_expr: sample.key_expr, + payload: sample.payload, + kind: sample.kind, + encoding: sample.encoding, + timestamp: sample.timestamp, + express: sample.qos.express(), + priority: sample.qos.priority(), + congestion_control: sample.qos.congestion_control(), + #[cfg(feature = "unstable")] + source_info: sample.source_info, + #[cfg(feature = "unstable")] + attachment: sample.attachment, + } + } +} + /// A zenoh sample. #[non_exhaustive] #[derive(Clone, Debug)] diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index 61e4bf81fb..c0ebf8c9d0 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -32,10 +32,13 @@ pub trait SampleBuilderTrait { fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self where IntoKeyExpr: Into>; + fn with_timestamp_opt(self, timestamp: Option) -> Self; fn with_timestamp(self, timestamp: Timestamp) -> Self; #[zenoh_macros::unstable] fn with_source_info(self, source_info: SourceInfo) -> Self; #[zenoh_macros::unstable] + fn with_attachment_opt(self, attachment: Option) -> Self; + #[zenoh_macros::unstable] fn with_attachment(self, attachment: Attachment) -> Self; fn congestion_control(self, congestion_control: CongestionControl) -> Self; fn priority(self, priority: Priority) -> Self; @@ -72,18 +75,6 @@ impl SampleBuilder { attachment: None, }) } - pub fn without_timestamp(self) -> Self { - Self(Sample { - timestamp: None, - ..self.0 - }) - } - pub fn without_attachment(self) -> Self { - Self(Sample { - attachment: None, - ..self.0 - }) - } } impl SampleBuilderTrait for SampleBuilder { @@ -97,12 +88,17 @@ impl SampleBuilderTrait for SampleBuilder { }) } - fn with_timestamp(self, timestamp: Timestamp) -> Self { + fn with_timestamp_opt(self, timestamp: Option) -> Self { Self(Sample { - timestamp: Some(timestamp), + timestamp, ..self.0 }) } + + fn with_timestamp(self, timestamp: Timestamp) -> Self { + self.with_timestamp_opt(Some(timestamp)) + } + #[zenoh_macros::unstable] fn with_source_info(self, source_info: SourceInfo) -> Self { Self(Sample { @@ -110,13 +106,19 @@ impl SampleBuilderTrait for SampleBuilder { ..self.0 }) } + #[zenoh_macros::unstable] - fn with_attachment(self, attachment: Attachment) -> Self { + fn with_attachment_opt(self, attachment: Option) -> Self { Self(Sample { - attachment: Some(attachment), + attachment, ..self.0 }) } + + #[zenoh_macros::unstable] + fn with_attachment(self, attachment: Attachment) -> Self { + self.with_attachment_opt(Some(attachment)) + } fn congestion_control(self, congestion_control: CongestionControl) -> Self { Self(Sample { qos: self.0.qos.with_congestion_control(congestion_control), @@ -170,14 +172,6 @@ impl PutSampleBuilder { attachment: None, })) } - #[zenoh_macros::unstable] - pub fn without_timestamp(self) -> Self { - Self(self.0.without_timestamp()) - } - #[zenoh_macros::unstable] - pub fn without_attachment(self) -> Self { - Self(self.0.without_attachment()) - } // It's convenient to set QoS as a whole for internal usage. For user API there are `congestion_control`, `priority` and `express` methods. pub(crate) fn with_qos(self, qos: QoS) -> Self { Self(SampleBuilder(Sample { qos, ..self.0 .0 })) @@ -194,6 +188,9 @@ impl SampleBuilderTrait for PutSampleBuilder { fn with_timestamp(self, timestamp: Timestamp) -> Self { Self(self.0.with_timestamp(timestamp)) } + fn with_timestamp_opt(self, timestamp: Option) -> Self { + Self(self.0.with_timestamp_opt(timestamp)) + } #[zenoh_macros::unstable] fn with_source_info(self, source_info: SourceInfo) -> Self { Self(self.0.with_source_info(source_info)) @@ -202,6 +199,10 @@ impl SampleBuilderTrait for PutSampleBuilder { fn with_attachment(self, attachment: Attachment) -> Self { Self(self.0.with_attachment(attachment)) } + #[zenoh_macros::unstable] + fn with_attachment_opt(self, attachment: Option) -> Self { + Self(self.0.with_attachment_opt(attachment)) + } fn congestion_control(self, congestion_control: CongestionControl) -> Self { Self(self.0.congestion_control(congestion_control)) } @@ -279,6 +280,9 @@ impl SampleBuilderTrait for DeleteSampleBuilder { fn with_timestamp(self, timestamp: Timestamp) -> Self { Self(self.0.with_timestamp(timestamp)) } + fn with_timestamp_opt(self, timestamp: Option) -> Self { + Self(self.0.with_timestamp_opt(timestamp)) + } #[zenoh_macros::unstable] fn with_source_info(self, source_info: SourceInfo) -> Self { Self(self.0.with_source_info(source_info)) @@ -287,6 +291,10 @@ impl SampleBuilderTrait for DeleteSampleBuilder { fn with_attachment(self, attachment: Attachment) -> Self { Self(self.0.with_attachment(attachment)) } + #[zenoh_macros::unstable] + fn with_attachment_opt(self, attachment: Option) -> Self { + Self(self.0.with_attachment_opt(attachment)) + } fn congestion_control(self, congestion_control: CongestionControl) -> Self { Self(self.0.congestion_control(congestion_control)) } From 270840247c72238654be20f611c4d4cb6338cfc4 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Sun, 24 Mar 2024 15:38:36 +0100 Subject: [PATCH 14/63] samples, plugins updated --- plugins/zenoh-plugin-example/src/lib.rs | 13 +++++++++- .../src/replica/align_queryable.rs | 2 ++ .../src/replica/storage.rs | 4 +-- zenoh-ext/src/publication_cache.rs | 25 ++++++++++++++----- zenoh/src/queryable.rs | 24 ++++++++++++------ 5 files changed, 51 insertions(+), 17 deletions(-) diff --git a/plugins/zenoh-plugin-example/src/lib.rs b/plugins/zenoh-plugin-example/src/lib.rs index 04f49b4739..9b9dda40de 100644 --- a/plugins/zenoh-plugin-example/src/lib.rs +++ b/plugins/zenoh-plugin-example/src/lib.rs @@ -24,6 +24,7 @@ use std::sync::{ use zenoh::plugins::{RunningPluginTrait, ZenohPlugin}; use zenoh::prelude::r#async::*; use zenoh::runtime::Runtime; +use zenoh::sample_builder::SampleBuilderTrait; use zenoh_core::zlock; use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginControl}; use zenoh_result::{bail, ZResult}; @@ -174,7 +175,17 @@ async fn run(runtime: Runtime, selector: KeyExpr<'_>, flag: Arc) { info!("Handling query '{}'", query.selector()); for (key_expr, sample) in stored.iter() { if query.selector().key_expr.intersects(unsafe{keyexpr::from_str_unchecked(key_expr)}) { - query.reply_sample(sample.clone()).res().await.unwrap(); + let reply = query + .reply_sample(sample.key_expr().clone().into_owned()) + .with_timestamp_opt(sample.timestamp().cloned()); + #[cfg(feature = "unstable")] + let reply = reply + .with_attachment_opt(sample.attachment()) + .with_source_info(sample.source_info()); + match sample.kind() { + SampleKind::Put => reply.put(sample.payload().clone()).res().await.unwrap(), + SampleKind::Delete => reply.delete().res().await.unwrap(), + } } } } diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs b/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs index 32be4a5534..691fabd7a7 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs @@ -20,6 +20,8 @@ use std::str; use std::str::FromStr; use zenoh::payload::StringOrBase64; use zenoh::prelude::r#async::*; +use zenoh::sample_builder::PutSampleBuilderTrait; +use zenoh::sample_builder::SampleBuilderTrait; use zenoh::time::Timestamp; use zenoh::Session; diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 1aadc88611..95af3c97a2 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -24,7 +24,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; use zenoh::buffers::ZBuf; use zenoh::prelude::r#async::*; use zenoh::query::ConsolidationMode; -use zenoh::sample_builder::{SampleBuilderTrait, SampleUpdater}; +use zenoh::sample_builder::{PutSampleBuilderTrait, SampleBuilder, SampleBuilderTrait}; use zenoh::time::{new_reception_timestamp, Timestamp, NTP64}; use zenoh::{Result as ZResult, Session}; use zenoh_backend_traits::config::{GarbageCollectionConfig, StorageConfig}; @@ -368,7 +368,7 @@ impl StorageService { } }; let sample = if sample.timestamp().is_none() { - SampleUpdater::from(sample).with_timestamp(new_reception_timestamp()).res_sync() + SampleBuilder::from(sample).with_timestamp(new_reception_timestamp()).res_sync() } else { sample }; diff --git a/zenoh-ext/src/publication_cache.rs b/zenoh-ext/src/publication_cache.rs index 85cb96cce2..78fff32014 100644 --- a/zenoh-ext/src/publication_cache.rs +++ b/zenoh-ext/src/publication_cache.rs @@ -20,6 +20,7 @@ use std::convert::TryInto; use std::future::Ready; use zenoh::prelude::r#async::*; use zenoh::queryable::{Query, Queryable}; +use zenoh::sample_builder::SampleBuilderTrait; use zenoh::subscriber::FlumeSubscriber; use zenoh::SessionRef; use zenoh_core::{AsyncResolve, Resolvable, SyncResolve}; @@ -116,6 +117,22 @@ pub struct PublicationCache<'a> { _stoptx: Sender, } +async fn reply_sample(query: &Query, sample: &Sample) { + let reply = query + .reply_sample(sample.key_expr().clone().into_owned()) + .with_timestamp_opt(sample.timestamp().cloned()); + #[cfg(feature = "unstable")] + let reply = reply + .with_attachment_opt(sample.attachment()) + .with_source_info(sample.source_info()); + if let Err(e) = match sample.kind() { + SampleKind::Put => reply.put(sample.payload().clone()).res_async().await, + SampleKind::Delete => reply.delete().res_async().await, + } { + log::warn!("Error replying to query: {}", e); + } +} + impl<'a> PublicationCache<'a> { fn new(conf: PublicationCacheBuilder<'a, '_, '_>) -> ZResult> { let key_expr = conf.pub_key_expr?; @@ -212,9 +229,7 @@ impl<'a> PublicationCache<'a> { continue; } } - if let Err(e) = query.reply_sample(sample.clone()).res_async().await { - log::warn!("Error replying to query: {}", e); - } + reply_sample(&query, sample).await; } } } else { @@ -226,9 +241,7 @@ impl<'a> PublicationCache<'a> { continue; } } - if let Err(e) = query.reply_sample(sample.clone()).res_async().await { - log::warn!("Error replying to query: {}", e); - } + reply_sample(&query, sample).await; } } } diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 7d4a0903c2..f2e00e47c6 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -519,6 +519,22 @@ impl SyncResolve for ReplyDelBuilder<'_> { } } +impl<'a> AsyncResolve for ReplyBuilder<'a> { + type Future = Ready; + + fn res_async(self) -> Self::Future { + std::future::ready(self.res_sync()) + } +} + +impl<'a> AsyncResolve for ReplyDelBuilder<'a> { + type Future = Ready; + + fn res_async(self) -> Self::Future { + std::future::ready(self.res_sync()) + } +} + impl Query { fn _reply_sample(&self, sample: Sample) -> ZResult<()> { if !self._accepts_any_replies().unwrap_or(false) @@ -583,14 +599,6 @@ impl Query { } } -impl<'a> AsyncResolve for ReplyBuilder<'a> { - type Future = Ready; - - fn res_async(self) -> Self::Future { - std::future::ready(self.res_sync()) - } -} - impl<'a> Resolvable for ReplyErrBuilder<'a> { type To = ZResult<()>; } From b80fd0aa30842e607ae661547368df7f818f3a29 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Sun, 24 Mar 2024 18:58:55 +0100 Subject: [PATCH 15/63] interceptors removed from plugin storage API --- plugins/zenoh-backend-example/src/lib.rs | 13 +--- plugins/zenoh-backend-traits/src/lib.rs | 68 +------------------ .../src/backends_mgt.rs | 7 -- .../zenoh-plugin-storage-manager/src/lib.rs | 4 -- .../src/memory_backend/mod.rs | 20 ------ .../src/replica/storage.rs | 23 ------- 6 files changed, 3 insertions(+), 132 deletions(-) diff --git a/plugins/zenoh-backend-example/src/lib.rs b/plugins/zenoh-backend-example/src/lib.rs index 602d29f375..f81231a498 100644 --- a/plugins/zenoh-backend-example/src/lib.rs +++ b/plugins/zenoh-backend-example/src/lib.rs @@ -13,11 +13,8 @@ // use async_std::sync::RwLock; use async_trait::async_trait; -use std::{ - collections::{hash_map::Entry, HashMap}, - sync::Arc, -}; -use zenoh::{prelude::OwnedKeyExpr, sample::Sample, time::Timestamp, value::Value}; +use std::collections::{hash_map::Entry, HashMap}; +use zenoh::{prelude::OwnedKeyExpr, time::Timestamp, value::Value}; use zenoh_backend_traits::{ config::{StorageConfig, VolumeConfig}, Capability, History, Persistence, Storage, StorageInsertionResult, StoredData, Volume, @@ -71,12 +68,6 @@ impl Volume for ExampleBackend { async fn create_storage(&self, _props: StorageConfig) -> ZResult> { Ok(Box::::default()) } - fn incoming_data_interceptor(&self) -> Option Sample + Send + Sync>> { - None - } - fn outgoing_data_interceptor(&self) -> Option Sample + Send + Sync>> { - None - } } #[async_trait] diff --git a/plugins/zenoh-backend-traits/src/lib.rs b/plugins/zenoh-backend-traits/src/lib.rs index d17e6dfd77..40d022f1ec 100644 --- a/plugins/zenoh-backend-traits/src/lib.rs +++ b/plugins/zenoh-backend-traits/src/lib.rs @@ -68,16 +68,6 @@ //! // The properties are the ones passed via a PUT in the admin space for Storage creation. //! Ok(Box::new(MyStorage::new(properties).await?)) //! } -//! -//! fn incoming_data_interceptor(&self) -> Option Sample + Send + Sync>> { -//! // No interception point for incoming data (on PUT operations) -//! None -//! } -//! -//! fn outgoing_data_interceptor(&self) -> Option Sample + Send + Sync>> { -//! // No interception point for outgoing data (on GET operations) -//! None -//! } //! } //! //! // Your Storage implementation @@ -135,9 +125,7 @@ use async_trait::async_trait; use const_format::concatcp; -use std::sync::Arc; -use zenoh::prelude::{KeyExpr, OwnedKeyExpr, Sample, Selector}; -use zenoh::queryable::ReplyBuilder; +use zenoh::prelude::OwnedKeyExpr; use zenoh::time::Timestamp; use zenoh::value::Value; pub use zenoh::Result as ZResult; @@ -210,14 +198,6 @@ pub trait Volume: Send + Sync { /// Creates a storage configured with some properties. async fn create_storage(&self, props: StorageConfig) -> ZResult>; - - /// Returns an interceptor that will be called before pushing any data - /// into a storage created by this backend. `None` can be returned for no interception point. - fn incoming_data_interceptor(&self) -> Option Sample + Send + Sync>>; - - /// Returns an interceptor that will be called before sending any reply - /// to a query from a storage created by this backend. `None` can be returned for no interception point. - fn outgoing_data_interceptor(&self) -> Option Sample + Send + Sync>>; } pub type VolumeInstance = Box; @@ -282,49 +262,3 @@ pub trait Storage: Send + Sync { /// Remember to fetch the entry corresponding to the `None` key async fn get_all_entries(&self) -> ZResult, Timestamp)>>; } - -/// A wrapper around the [`zenoh::queryable::Query`] allowing to call the -/// OutgoingDataInterceptor (if any) before to send the reply -pub struct Query { - q: zenoh::queryable::Query, - interceptor: Option Sample + Send + Sync>>, -} - -impl Query { - pub fn new( - q: zenoh::queryable::Query, - interceptor: Option Sample + Send + Sync>>, - ) -> Query { - Query { q, interceptor } - } - - /// The full [`Selector`] of this Query. - #[inline(always)] - pub fn selector(&self) -> Selector<'_> { - self.q.selector() - } - - /// The key selector part of this Query. - #[inline(always)] - pub fn key_expr(&self) -> &KeyExpr<'static> { - self.q.key_expr() - } - - /// This Query's selector parameters. - #[inline(always)] - pub fn parameters(&self) -> &str { - self.q.parameters() - } - - /// Sends a Sample as a reply to this Query - pub fn reply(&self, sample: Sample) -> ReplyBuilder<'_> { - // Call outgoing intercerceptor - let sample = if let Some(ref interceptor) = self.interceptor { - interceptor(sample) - } else { - sample - }; - // Send reply - self.q.reply_sample(sample) - } -} diff --git a/plugins/zenoh-plugin-storage-manager/src/backends_mgt.rs b/plugins/zenoh-plugin-storage-manager/src/backends_mgt.rs index aa7260e868..90a6ae6250 100644 --- a/plugins/zenoh-plugin-storage-manager/src/backends_mgt.rs +++ b/plugins/zenoh-plugin-storage-manager/src/backends_mgt.rs @@ -14,7 +14,6 @@ use super::storages_mgt::*; use flume::Sender; use std::sync::Arc; -use zenoh::prelude::r#async::*; use zenoh::Session; use zenoh_backend_traits::config::StorageConfig; use zenoh_backend_traits::{Capability, VolumeInstance}; @@ -23,16 +22,12 @@ use zenoh_result::ZResult; pub struct StoreIntercept { pub storage: Box, pub capability: Capability, - pub in_interceptor: Option Sample + Send + Sync>>, - pub out_interceptor: Option Sample + Send + Sync>>, } pub(crate) async fn create_and_start_storage( admin_key: String, config: StorageConfig, backend: &VolumeInstance, - in_interceptor: Option Sample + Send + Sync>>, - out_interceptor: Option Sample + Send + Sync>>, zenoh: Arc, ) -> ZResult> { log::trace!("Create storage '{}'", &admin_key); @@ -41,8 +36,6 @@ pub(crate) async fn create_and_start_storage( let store_intercept = StoreIntercept { storage, capability, - in_interceptor, - out_interceptor, }; start_storage(store_intercept, config, admin_key, zenoh).await diff --git a/plugins/zenoh-plugin-storage-manager/src/lib.rs b/plugins/zenoh-plugin-storage-manager/src/lib.rs index 0db30bbd6a..91df2f108d 100644 --- a/plugins/zenoh-plugin-storage-manager/src/lib.rs +++ b/plugins/zenoh-plugin-storage-manager/src/lib.rs @@ -239,14 +239,10 @@ impl StorageRuntimeInner { volume_id, backend.name() ); - let in_interceptor = backend.instance().incoming_data_interceptor(); - let out_interceptor = backend.instance().outgoing_data_interceptor(); let stopper = async_std::task::block_on(create_and_start_storage( admin_key, storage.clone(), backend.instance(), - in_interceptor, - out_interceptor, self.session.clone(), ))?; self.storages diff --git a/plugins/zenoh-plugin-storage-manager/src/memory_backend/mod.rs b/plugins/zenoh-plugin-storage-manager/src/memory_backend/mod.rs index ebb4922c9d..4e333b8592 100644 --- a/plugins/zenoh-plugin-storage-manager/src/memory_backend/mod.rs +++ b/plugins/zenoh-plugin-storage-manager/src/memory_backend/mod.rs @@ -61,26 +61,6 @@ impl Volume for MemoryBackend { log::debug!("Create Memory Storage with configuration: {:?}", properties); Ok(Box::new(MemoryStorage::new(properties).await?)) } - - fn incoming_data_interceptor(&self) -> Option Sample + Send + Sync>> { - // By default: no interception point - None - // To test interceptors, uncomment this line: - // Some(Arc::new(|sample| { - // trace!(">>>> IN INTERCEPTOR FOR {:?}", sample); - // sample - // })) - } - - fn outgoing_data_interceptor(&self) -> Option Sample + Send + Sync>> { - // By default: no interception point - None - // To test interceptors, uncomment this line: - // Some(Arc::new(|sample| { - // trace!("<<<< OUT INTERCEPTOR FOR {:?}", sample); - // sample - // })) - } } impl Drop for MemoryBackend { diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 0708dcabd9..35134dfe43 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -60,8 +60,6 @@ pub struct StorageService { capability: Capability, tombstones: Arc>>, wildcard_updates: Arc>>, - in_interceptor: Option Sample + Send + Sync>>, - out_interceptor: Option Sample + Send + Sync>>, replication: Option, } @@ -85,8 +83,6 @@ impl StorageService { capability: store_intercept.capability, tombstones: Arc::new(RwLock::new(KeBoxTree::default())), wildcard_updates: Arc::new(RwLock::new(KeBoxTree::default())), - in_interceptor: store_intercept.in_interceptor, - out_interceptor: store_intercept.out_interceptor, replication, }; if storage_service @@ -263,13 +259,6 @@ impl StorageService { // the trimming during PUT and GET should be handled by the plugin async fn process_sample(&self, sample: Sample) { log::trace!("[STORAGE] Processing sample: {:?}", sample); - // Call incoming data interceptor (if any) - let sample = if let Some(ref interceptor) = self.in_interceptor { - interceptor(sample) - } else { - sample - }; - // if wildcard, update wildcard_updates if sample.key_expr().is_wild() { self.register_wildcard_update(sample.clone()).await; @@ -523,12 +512,6 @@ impl StorageService { let sample = Sample::new(key.clone(), payload) .with_encoding(encoding) .with_timestamp(entry.timestamp); - // apply outgoing interceptor on results - let sample = if let Some(ref interceptor) = self.out_interceptor { - interceptor(sample) - } else { - sample - }; if let Err(e) = q.reply_sample(sample).res().await { log::warn!( "Storage '{}' raised an error replying a query: {}", @@ -561,12 +544,6 @@ impl StorageService { let sample = Sample::new(q.key_expr().clone(), payload) .with_encoding(encoding) .with_timestamp(entry.timestamp); - // apply outgoing interceptor on results - let sample = if let Some(ref interceptor) = self.out_interceptor { - interceptor(sample) - } else { - sample - }; if let Err(e) = q.reply_sample(sample).res().await { log::warn!( "Storage '{}' raised an error replying a query: {}", From 7d2abd44b19ed7ba86713f1752990ba344d07235 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Sun, 24 Mar 2024 19:20:11 +0100 Subject: [PATCH 16/63] deconstruct sample api used --- .../src/replica/aligner.rs | 3 +-- .../src/replica/storage.rs | 25 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs index 3f672382f1..f00029442f 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs @@ -12,11 +12,10 @@ // ZettaScale Zenoh Team, // -use crate::replica::storage::StorageSampleKind; - use super::storage::StorageSample; use super::{Digest, EraType, LogEntry, Snapshotter}; use super::{CONTENTS, ERA, INTERVALS, SUBINTERVALS}; +use crate::replica::storage::StorageSampleKind; use async_std::sync::{Arc, RwLock}; use flume::{Receiver, Sender}; use std::collections::{HashMap, HashSet}; diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 95af3c97a2..fbc734d716 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -24,6 +24,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; use zenoh::buffers::ZBuf; use zenoh::prelude::r#async::*; use zenoh::query::ConsolidationMode; +use zenoh::sample::SampleFields; use zenoh::sample_builder::{PutSampleBuilderTrait, SampleBuilder, SampleBuilderTrait}; use zenoh::time::{new_reception_timestamp, Timestamp, NTP64}; use zenoh::{Result as ZResult, Session}; @@ -55,19 +56,23 @@ pub struct StorageSample { impl From for StorageSample { fn from(sample: Sample) -> Self { - let timestamp = *sample.timestamp().unwrap_or(&new_reception_timestamp()); - // TODO: add API for disassembly of Sample - let key_expr = sample.key_expr().clone(); - let payload = sample.payload().clone(); - let encoding = sample.encoding().clone(); - let kind = match sample.kind() { - SampleKind::Put => StorageSampleKind::Put(Value::new(payload).with_encoding(encoding)), - SampleKind::Delete => StorageSampleKind::Delete, - }; - StorageSample { + let SampleFields { key_expr, timestamp, kind, + payload, + encoding, + .. + } = sample.into(); + StorageSample { + key_expr, + timestamp: timestamp.unwrap_or(new_reception_timestamp()), + kind: match kind { + SampleKind::Put => { + StorageSampleKind::Put(Value::new(payload).with_encoding(encoding)) + } + SampleKind::Delete => StorageSampleKind::Delete, + }, } } } From 2b1071f9b9b06dd10d401969ce5c8678560aea03 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Sun, 24 Mar 2024 19:52:30 +0100 Subject: [PATCH 17/63] comment, clippy fix --- zenoh/src/sample.rs | 4 ++-- zenoh/src/sample_builder.rs | 20 ++++++++------------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/zenoh/src/sample.rs b/zenoh/src/sample.rs index 3ac3087836..acf8536a0e 100644 --- a/zenoh/src/sample.rs +++ b/zenoh/src/sample.rs @@ -67,10 +67,10 @@ pub(crate) trait DataInfoIntoSample { } impl DataInfoIntoSample for DataInfo { - // TODO: this is internal function. + // This function is for internal use only. // Technically it may create invalid sample (e.g. a delete sample with a payload and encoding) // The test for it is intentionally not added to avoid inserting extra "if" into hot path. - // This need to be additionally investigated and measured. + // The correctness of the data should be ensured by the caller. #[inline] fn into_sample( self, diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index c0ebf8c9d0..c7ee6e8368 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -144,12 +144,10 @@ pub struct PutSampleBuilder(SampleBuilder); impl From for PutSampleBuilder { fn from(sample_builder: SampleBuilder) -> Self { - Self(SampleBuilder { - 0: Sample { - kind: SampleKind::Put, - ..sample_builder.0 - }, - }) + Self(SampleBuilder(Sample { + kind: SampleKind::Put, + ..sample_builder.0 + })) } } @@ -237,12 +235,10 @@ pub struct DeleteSampleBuilder(SampleBuilder); impl From for DeleteSampleBuilder { fn from(sample_builder: SampleBuilder) -> Self { - Self(SampleBuilder { - 0: Sample { - kind: SampleKind::Delete, - ..sample_builder.0 - }, - }) + Self(SampleBuilder(Sample { + kind: SampleKind::Delete, + ..sample_builder.0 + })) } } From 3386237bea3e10f80ddb5089617f723577cef5b5 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Sun, 24 Mar 2024 19:58:46 +0100 Subject: [PATCH 18/63] clippy fix --- plugins/zenoh-plugin-storage-manager/src/replica/storage.rs | 2 +- zenoh/tests/attachments.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index fbc734d716..f2fb0386c3 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -443,7 +443,7 @@ impl StorageService { match self.ovderriding_wild_update(&k, &sample.timestamp).await { Some(overriding_update) => overriding_update.into_sample(k.clone()), - None => sample.clone().into(), + None => sample.clone(), }; let stripped_key = match self.strip_prefix(&sample_to_store.key_expr) { diff --git a/zenoh/tests/attachments.rs b/zenoh/tests/attachments.rs index 38d03b0a84..8d26cc0344 100644 --- a/zenoh/tests/attachments.rs +++ b/zenoh/tests/attachments.rs @@ -51,7 +51,7 @@ fn pubsub() { #[cfg(feature = "unstable")] #[test] fn queries() { - use zenoh::{prelude::sync::*, sample::Attachment}; + use zenoh::{prelude::sync::*, sample::Attachment, sample_builder::SampleBuilderTrait}; let zenoh = zenoh::open(Config::default()).res().unwrap(); let _sub = zenoh From f52140aec5909389323cdad70d84b9fc4ba71395 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Sun, 24 Mar 2024 20:13:49 +0100 Subject: [PATCH 19/63] zenoh-ext links zenoh with unstable --- zenoh-ext/src/publication_cache.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/zenoh-ext/src/publication_cache.rs b/zenoh-ext/src/publication_cache.rs index 78fff32014..a4eff1e932 100644 --- a/zenoh-ext/src/publication_cache.rs +++ b/zenoh-ext/src/publication_cache.rs @@ -121,10 +121,9 @@ async fn reply_sample(query: &Query, sample: &Sample) { let reply = query .reply_sample(sample.key_expr().clone().into_owned()) .with_timestamp_opt(sample.timestamp().cloned()); - #[cfg(feature = "unstable")] let reply = reply - .with_attachment_opt(sample.attachment()) - .with_source_info(sample.source_info()); + .with_attachment_opt(sample.attachment().cloned()) + .with_source_info(sample.source_info().clone()); if let Err(e) = match sample.kind() { SampleKind::Put => reply.put(sample.payload().clone()).res_async().await, SampleKind::Delete => reply.delete().res_async().await, From a629c765fb86823d3f4fa57d979936c49915221a Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Sun, 24 Mar 2024 22:06:24 +0100 Subject: [PATCH 20/63] samplefields used --- plugins/zenoh-plugin-example/src/lib.rs | 16 ++++++++-------- zenoh-ext/src/publication_cache.rs | 23 ++++++++++++++++------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/plugins/zenoh-plugin-example/src/lib.rs b/plugins/zenoh-plugin-example/src/lib.rs index 9b9dda40de..40f8d69488 100644 --- a/plugins/zenoh-plugin-example/src/lib.rs +++ b/plugins/zenoh-plugin-example/src/lib.rs @@ -24,6 +24,7 @@ use std::sync::{ use zenoh::plugins::{RunningPluginTrait, ZenohPlugin}; use zenoh::prelude::r#async::*; use zenoh::runtime::Runtime; +use zenoh::sample::SampleFields; use zenoh::sample_builder::SampleBuilderTrait; use zenoh_core::zlock; use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginControl}; @@ -175,15 +176,14 @@ async fn run(runtime: Runtime, selector: KeyExpr<'_>, flag: Arc) { info!("Handling query '{}'", query.selector()); for (key_expr, sample) in stored.iter() { if query.selector().key_expr.intersects(unsafe{keyexpr::from_str_unchecked(key_expr)}) { + let SampleFields { key_expr, timestamp, attachment, source_info, payload, kind, .. } = sample.clone().into(); let reply = query - .reply_sample(sample.key_expr().clone().into_owned()) - .with_timestamp_opt(sample.timestamp().cloned()); - #[cfg(feature = "unstable")] - let reply = reply - .with_attachment_opt(sample.attachment()) - .with_source_info(sample.source_info()); - match sample.kind() { - SampleKind::Put => reply.put(sample.payload().clone()).res().await.unwrap(), + .reply_sample(key_expr) + .with_timestamp_opt(timestamp) + .with_attachment_opt(attachment) + .with_source_info(source_info); + match kind { + SampleKind::Put => reply.put(payload).res().await.unwrap(), SampleKind::Delete => reply.delete().res().await.unwrap(), } } diff --git a/zenoh-ext/src/publication_cache.rs b/zenoh-ext/src/publication_cache.rs index a4eff1e932..8a782a179e 100644 --- a/zenoh-ext/src/publication_cache.rs +++ b/zenoh-ext/src/publication_cache.rs @@ -20,6 +20,7 @@ use std::convert::TryInto; use std::future::Ready; use zenoh::prelude::r#async::*; use zenoh::queryable::{Query, Queryable}; +use zenoh::sample::SampleFields; use zenoh::sample_builder::SampleBuilderTrait; use zenoh::subscriber::FlumeSubscriber; use zenoh::SessionRef; @@ -118,14 +119,22 @@ pub struct PublicationCache<'a> { } async fn reply_sample(query: &Query, sample: &Sample) { + let SampleFields { + key_expr, + timestamp, + attachment, + source_info, + payload, + kind, + .. + } = sample.clone().into(); let reply = query - .reply_sample(sample.key_expr().clone().into_owned()) - .with_timestamp_opt(sample.timestamp().cloned()); - let reply = reply - .with_attachment_opt(sample.attachment().cloned()) - .with_source_info(sample.source_info().clone()); - if let Err(e) = match sample.kind() { - SampleKind::Put => reply.put(sample.payload().clone()).res_async().await, + .reply_sample(key_expr) + .with_timestamp_opt(timestamp) + .with_attachment_opt(attachment) + .with_source_info(source_info); + if let Err(e) = match kind { + SampleKind::Put => reply.put(payload).res_async().await, SampleKind::Delete => reply.delete().res_async().await, } { log::warn!("Error replying to query: {}", e); From 1945492ec9a27546e211e5bffac5bd5206cbdcd1 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Mon, 25 Mar 2024 10:41:14 +0100 Subject: [PATCH 21/63] restored old storage manager code --- .../src/replica/aligner.rs | 22 +- .../src/replica/storage.rs | 343 +++++++----------- 2 files changed, 146 insertions(+), 219 deletions(-) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs index f00029442f..a899196e7e 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs @@ -12,10 +12,8 @@ // ZettaScale Zenoh Team, // -use super::storage::StorageSample; use super::{Digest, EraType, LogEntry, Snapshotter}; use super::{CONTENTS, ERA, INTERVALS, SUBINTERVALS}; -use crate::replica::storage::StorageSampleKind; use async_std::sync::{Arc, RwLock}; use flume::{Receiver, Sender}; use std::collections::{HashMap, HashSet}; @@ -23,15 +21,17 @@ use std::str; use zenoh::key_expr::{KeyExpr, OwnedKeyExpr}; use zenoh::payload::StringOrBase64; use zenoh::prelude::r#async::*; +use zenoh::sample_builder::{PutSampleBuilder, PutSampleBuilderTrait, SampleBuilderTrait}; use zenoh::time::Timestamp; use zenoh::Session; +use zenoh_core::{AsyncResolve, SyncResolve}; pub struct Aligner { session: Arc, digest_key: OwnedKeyExpr, snapshotter: Arc, rx_digest: Receiver<(String, Digest)>, - tx_sample: Sender, + tx_sample: Sender, digests_processed: RwLock>, } @@ -40,7 +40,7 @@ impl Aligner { session: Arc, digest_key: OwnedKeyExpr, rx_digest: Receiver<(String, Digest)>, - tx_sample: Sender, + tx_sample: Sender, snapshotter: Arc, ) { let aligner = Aligner { @@ -107,11 +107,13 @@ impl Aligner { log::trace!("[ALIGNER] Received queried samples: {missing_data:?}"); for (key, (ts, value)) in missing_data { - let sample = StorageSample { - key_expr: key.into(), - timestamp: ts, - kind: StorageSampleKind::Put(value), - }; + let Value { + payload, encoding, .. + } = value; + let sample = PutSampleBuilder::new(key, payload) + .with_encoding(encoding) + .with_timestamp(ts) + .res_sync(); log::debug!("[ALIGNER] Adding {:?} to storage", sample); self.tx_sample.send_async(sample).await.unwrap_or_else(|e| { log::error!("[ALIGNER] Error adding sample to storage: {}", e) @@ -329,7 +331,7 @@ impl Aligner { .get(&selector) .consolidation(zenoh::query::ConsolidationMode::None) .accept_replies(zenoh::query::ReplyKeyExpr::Any) - .res() + .res_async() .await { Ok(replies) => { diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index f2fb0386c3..67ce871bb0 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -19,18 +19,19 @@ use async_trait::async_trait; use flume::{Receiver, Sender}; use futures::select; use std::collections::{HashMap, HashSet}; -use std::str::FromStr; +use std::str::{self, FromStr}; use std::time::{SystemTime, UNIX_EPOCH}; use zenoh::buffers::ZBuf; use zenoh::prelude::r#async::*; use zenoh::query::ConsolidationMode; -use zenoh::sample::SampleFields; -use zenoh::sample_builder::{PutSampleBuilderTrait, SampleBuilder, SampleBuilderTrait}; +use zenoh::sample_builder::{ + PutSampleBuilder, PutSampleBuilderTrait, SampleBuilder, SampleBuilderTrait, +}; use zenoh::time::{new_reception_timestamp, Timestamp, NTP64}; use zenoh::{Result as ZResult, Session}; use zenoh_backend_traits::config::{GarbageCollectionConfig, StorageConfig}; use zenoh_backend_traits::{Capability, History, Persistence, StorageInsertionResult, StoredData}; -use zenoh_core::SyncResolve; +use zenoh_core::{AsyncResolve, SyncResolve}; use zenoh_keyexpr::key_expr::OwnedKeyExpr; use zenoh_keyexpr::keyexpr_tree::impls::KeyedSetProvider; use zenoh_keyexpr::keyexpr_tree::{support::NonWild, support::UnknownWildness, KeBoxTree}; @@ -41,152 +42,15 @@ use zenoh_util::{zenoh_home, Timed, TimedEvent, Timer}; pub const WILDCARD_UPDATES_FILENAME: &str = "wildcard_updates"; pub const TOMBSTONE_FILENAME: &str = "tombstones"; -#[derive(Clone, Debug)] -pub enum StorageSampleKind { - Put(Value), - Delete, -} - -#[derive(Clone, Debug)] -pub struct StorageSample { - pub key_expr: KeyExpr<'static>, - pub timestamp: Timestamp, - pub kind: StorageSampleKind, -} - -impl From for StorageSample { - fn from(sample: Sample) -> Self { - let SampleFields { - key_expr, - timestamp, - kind, - payload, - encoding, - .. - } = sample.into(); - StorageSample { - key_expr, - timestamp: timestamp.unwrap_or(new_reception_timestamp()), - kind: match kind { - SampleKind::Put => { - StorageSampleKind::Put(Value::new(payload).with_encoding(encoding)) - } - SampleKind::Delete => StorageSampleKind::Delete, - }, - } - } -} - #[derive(Clone)] -enum Update { - Put(StoredData), - Delete(Timestamp), -} - -impl From for Update { - fn from(value: StorageSample) -> Self { - match value.kind { - StorageSampleKind::Put(data) => Update::Put(StoredData { - value: data, - timestamp: value.timestamp, - }), - StorageSampleKind::Delete => Update::Delete(value.timestamp), - } - } -} - -impl Update { - fn timestamp(&self) -> &Timestamp { - match self { - Update::Put(data) => &data.timestamp, - Update::Delete(ts) => ts, - } - } -} - -// implement from String for Update -impl TryFrom for Update { - type Error = zenoh::Error; - - fn try_from(value: String) -> Result { - let result: (String, String, String, Vec<&[u8]>) = serde_json::from_str(&value)?; - let mut payload = ZBuf::default(); - for slice in result.3 { - payload.push_zslice(slice.to_vec().into()); - } - let value = Value::new(payload).with_encoding(result.2); - let timestamp = Timestamp::from_str(&result.1).map_err(|_| "Error parsing timestamp")?; - if result.0.eq(&(SampleKind::Put).to_string()) { - Ok(Update::Put(StoredData { value, timestamp })) - } else { - Ok(Update::Delete(timestamp)) - } - } -} - -// implement to_string for Update -impl ToString for Update { - fn to_string(&self) -> String { - let result = match self { - Update::Put(data) => ( - SampleKind::Put.to_string(), - data.timestamp.to_string(), - data.value.encoding.to_string(), - data.value.payload.slices().collect::>(), - ), - Update::Delete(ts) => ( - SampleKind::Delete.to_string(), - ts.to_string(), - "".to_string(), - vec![], - ), - }; - serde_json::to_string_pretty(&result).unwrap() - } -} - -trait IntoStorageSample { - fn into_sample(self, key_expr: IntoKeyExpr) -> StorageSample - where - IntoKeyExpr: Into>; -} - -impl IntoStorageSample for StoredData { - fn into_sample(self, key_expr: IntoKeyExpr) -> StorageSample - where - IntoKeyExpr: Into>, - { - StorageSample { - key_expr: key_expr.into(), - timestamp: self.timestamp, - kind: StorageSampleKind::Put(self.value), - } - } -} - -impl IntoStorageSample for Update { - fn into_sample(self, key_expr: IntoKeyExpr) -> StorageSample - where - IntoKeyExpr: Into>, - { - match self { - Update::Put(data) => StorageSample { - key_expr: key_expr.into(), - timestamp: data.timestamp, - kind: StorageSampleKind::Put(data.value), - }, - Update::Delete(ts) => StorageSample { - key_expr: key_expr.into(), - timestamp: ts, - kind: StorageSampleKind::Delete, - }, - } - } +struct Update { + kind: SampleKind, + data: StoredData, } pub struct ReplicationService { pub empty_start: bool, - pub aligner_updates: Receiver, + pub aligner_updates: Receiver, pub log_propagation: Sender<(OwnedKeyExpr, Timestamp)>, } @@ -245,11 +109,10 @@ impl StorageService { let saved_wc = std::fs::read_to_string(zenoh_home().join(WILDCARD_UPDATES_FILENAME)).unwrap(); let saved_wc: HashMap = - serde_json::from_str(&saved_wc).unwrap(); // TODO: Remove unwrap + serde_json::from_str(&saved_wc).unwrap(); let mut wildcard_updates = storage_service.wildcard_updates.write().await; for (k, data) in saved_wc { - wildcard_updates.insert(&k, Update::try_from(data).unwrap()); - // TODO: Remove unwrap + wildcard_updates.insert(&k, construct_update(data)); } } } @@ -325,7 +188,7 @@ impl StorageService { log::error!("Sample {:?} is not timestamped. Please timestamp samples meant for replicated storage.", sample); } else { - self.process_sample(sample.into()).await; + self.process_sample(sample).await; } }, // on query on key_expr @@ -377,7 +240,7 @@ impl StorageService { } else { sample }; - self.process_sample(sample.into()).await; + self.process_sample(sample).await; }, // on query on key_expr query = storage_queryable.recv_async() => { @@ -407,46 +270,61 @@ impl StorageService { // The storage should only simply save the key, sample pair while put and retrieve the same during get // the trimming during PUT and GET should be handled by the plugin - async fn process_sample(&self, sample: StorageSample) { + async fn process_sample(&self, sample: Sample) { log::trace!("[STORAGE] Processing sample: {:?}", sample); - // if wildcard, update wildcard_updates - if sample.key_expr.is_wild() { + if sample.key_expr().is_wild() { self.register_wildcard_update(sample.clone()).await; } - let matching_keys = if sample.key_expr.is_wild() { - self.get_matching_keys(&sample.key_expr).await + let matching_keys = if sample.key_expr().is_wild() { + self.get_matching_keys(sample.key_expr()).await } else { - vec![sample.key_expr.clone().into()] + vec![sample.key_expr().clone().into()] }; log::trace!( "The list of keys matching `{}` is : {:?}", - sample.key_expr, + sample.key_expr(), matching_keys ); for k in matching_keys { - if !self.is_deleted(&k.clone(), &sample.timestamp).await + if !self + .is_deleted(&k.clone(), sample.timestamp().unwrap()) + .await && (self.capability.history.eq(&History::All) || (self.capability.history.eq(&History::Latest) - && self.is_latest(&k, &sample.timestamp).await)) + && self.is_latest(&k, sample.timestamp().unwrap()).await)) { log::trace!( "Sample `{:?}` identified as neded processing for key {}", sample, - &k + k ); // there might be the case that the actual update was outdated due to a wild card update, but not stored yet in the storage. // get the relevant wild card entry and use that value and timestamp to update the storage - let sample_to_store = - match self.ovderriding_wild_update(&k, &sample.timestamp).await { - Some(overriding_update) => overriding_update.into_sample(k.clone()), - - None => sample.clone(), - }; + let sample_to_store = match self + .ovderriding_wild_update(&k, sample.timestamp().unwrap()) + .await + { + Some(overriding_update) => { + let Value { + payload, encoding, .. + } = overriding_update.data.value; + PutSampleBuilder::new(KeyExpr::from(k.clone()), payload) + .with_encoding(encoding) + .with_timestamp(overriding_update.data.timestamp) + .res_sync() + } + None => { + PutSampleBuilder::new(KeyExpr::from(k.clone()), sample.payload().clone()) + .with_encoding(sample.encoding().clone()) + .with_timestamp(*sample.timestamp().unwrap()) + .res_sync() + } + }; - let stripped_key = match self.strip_prefix(&sample_to_store.key_expr) { + let stripped_key = match self.strip_prefix(sample_to_store.key_expr()) { Ok(stripped) => stripped, Err(e) => { log::error!("{}", e); @@ -454,17 +332,23 @@ impl StorageService { } }; let mut storage = self.storage.lock().await; - let result = match sample_to_store.kind { - StorageSampleKind::Put(data) => { + let result = match sample.kind() { + SampleKind::Put => { storage - .put(stripped_key, data, sample_to_store.timestamp) + .put( + stripped_key, + Value::new(sample_to_store.payload().clone()) + .with_encoding(sample_to_store.encoding().clone()), + *sample_to_store.timestamp().unwrap(), + ) .await } - StorageSampleKind::Delete => { + SampleKind::Delete => { // register a tombstone - self.mark_tombstone(&k, sample_to_store.timestamp).await; + self.mark_tombstone(&k, *sample_to_store.timestamp().unwrap()) + .await; storage - .delete(stripped_key, sample_to_store.timestamp) + .delete(stripped_key, *sample_to_store.timestamp().unwrap()) .await } }; @@ -478,7 +362,7 @@ impl StorageService { .as_ref() .unwrap() .log_propagation - .send((k.clone(), sample_to_store.timestamp)); + .send((k.clone(), *sample_to_store.timestamp().unwrap())); match sending { Ok(_) => (), Err(e) => { @@ -509,16 +393,26 @@ impl StorageService { } } - async fn register_wildcard_update(&self, sample: StorageSample) { + async fn register_wildcard_update(&self, sample: Sample) { // @TODO: change into a better store that does incremental writes - let key = sample.key_expr.clone(); + let key = sample.key_expr().clone(); let mut wildcards = self.wildcard_updates.write().await; - wildcards.insert(&key, sample.into()); + let timestamp = *sample.timestamp().unwrap(); + wildcards.insert( + &key, + Update { + kind: sample.kind(), + data: StoredData { + value: Value::from(sample), + timestamp, + }, + }, + ); if self.capability.persistence.eq(&Persistence::Durable) { // flush to disk to makeit durable let mut serialized_data = HashMap::new(); for (k, update) in wildcards.key_value_pairs() { - serialized_data.insert(k, update.to_string()); + serialized_data.insert(k, serialize_update(update)); } if let Err(e) = std::fs::write( zenoh_home().join(WILDCARD_UPDATES_FILENAME), @@ -547,36 +441,34 @@ impl StorageService { let mut update = None; for node in wildcards.intersecting_keys(key_expr) { let weight = wildcards.weight_at(&node); - if let Some(weight) = weight { - if weight.timestamp() > ts { - // if the key matches a wild card update, check whether it was saved in storage - // remember that wild card updates change only existing keys - let stripped_key = match self.strip_prefix(&key_expr.into()) { - Ok(stripped) => stripped, - Err(e) => { - log::error!("{}", e); - break; - } - }; - let mut storage = self.storage.lock().await; - match storage.get(stripped_key, "").await { - Ok(stored_data) => { - for entry in stored_data { - if entry.timestamp > *ts { - return None; - } + if weight.is_some() && weight.unwrap().data.timestamp > *ts { + // if the key matches a wild card update, check whether it was saved in storage + // remember that wild card updates change only existing keys + let stripped_key = match self.strip_prefix(&key_expr.into()) { + Ok(stripped) => stripped, + Err(e) => { + log::error!("{}", e); + break; + } + }; + let mut storage = self.storage.lock().await; + match storage.get(stripped_key, "").await { + Ok(stored_data) => { + for entry in stored_data { + if entry.timestamp > *ts { + return None; } } - Err(e) => { - log::warn!( - "Storage '{}' raised an error fetching a query on key {} : {}", - self.name, - key_expr, - e - ); - ts = weight.timestamp(); - update = Some(weight.clone()); - } + } + Err(e) => { + log::warn!( + "Storage '{}' raised an error fetching a query on key {} : {}", + self.name, + key_expr, + e + ); + ts = &weight.unwrap().data.timestamp; + update = Some(weight.unwrap().clone()); } } } @@ -629,8 +521,12 @@ impl StorageService { match storage.get(stripped_key, q.parameters()).await { Ok(stored_data) => { for entry in stored_data { + let Value { + payload, encoding, .. + } = entry.value; if let Err(e) = q - .reply(key.clone(), entry.value.payload) + .reply(key.clone(), payload) + .with_encoding(encoding) .with_timestamp(entry.timestamp) .res_async() .await @@ -776,7 +672,7 @@ impl StorageService { while let Ok(reply) = replies.recv_async().await { match reply.sample { Ok(sample) => { - self.process_sample(sample.into()).await; + self.process_sample(sample).await; } Err(e) => log::warn!( "Storage '{}' received an error to align query: {:?}", @@ -789,6 +685,35 @@ impl StorageService { } } +fn serialize_update(update: &Update) -> String { + let result = ( + update.kind.to_string(), + update.data.timestamp.to_string(), + update.data.value.encoding.to_string(), + update.data.value.payload.slices().collect::>(), + ); + serde_json::to_string_pretty(&result).unwrap() +} + +fn construct_update(data: String) -> Update { + let result: (String, String, String, Vec<&[u8]>) = serde_json::from_str(&data).unwrap(); // @TODO: remove the unwrap() + let mut payload = ZBuf::default(); + for slice in result.3 { + payload.push_zslice(slice.to_vec().into()); + } + let value = Value::new(payload).with_encoding(result.2); + let data = StoredData { + value, + timestamp: Timestamp::from_str(&result.1).unwrap(), // @TODO: remove the unwrap() + }; + let kind = if result.0.eq(&(SampleKind::Put).to_string()) { + SampleKind::Put + } else { + SampleKind::Delete + }; + Update { kind, data } +} + // Periodic event cleaning-up data info for old metadata struct GarbageCollectionEvent { config: GarbageCollectionConfig, @@ -820,7 +745,7 @@ impl Timed for GarbageCollectionEvent { let mut to_be_removed = HashSet::new(); for (k, update) in wildcard_updates.key_value_pairs() { - let ts = update.timestamp(); + let ts = update.data.timestamp; if ts.get_time() < &time_limit { // mark key to be removed to_be_removed.insert(k); From 48d8d776986ba31d0030b23250be00da93043b64 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Mon, 25 Mar 2024 11:49:52 +0100 Subject: [PATCH 22/63] separate qosbuilder trait --- zenoh/src/queryable.rs | 8 +++++++- zenoh/src/sample_builder.rs | 18 +++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index f2e00e47c6..68b27526ce 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -21,7 +21,7 @@ use crate::prelude::*; use crate::sample::SourceInfo; use crate::sample_builder::{ DeleteSampleBuilder, DeleteSampleBuilderTrait, PutSampleBuilder, PutSampleBuilderTrait, - SampleBuilder, SampleBuilderTrait, + QoSBuilderTrait, SampleBuilder, SampleBuilderTrait, }; use crate::Id; use crate::SessionRef; @@ -287,7 +287,9 @@ impl SampleBuilderTrait for ReplySampleBuilder<'_> { ..self } } +} +impl QoSBuilderTrait for ReplySampleBuilder<'_> { fn congestion_control(self, congestion_control: CongestionControl) -> Self { Self { sample_builder: self.sample_builder.congestion_control(congestion_control), @@ -366,7 +368,9 @@ impl SampleBuilderTrait for ReplyBuilder<'_> { ..self } } +} +impl QoSBuilderTrait for ReplyBuilder<'_> { fn congestion_control(self, congestion_control: CongestionControl) -> Self { Self { sample_builder: self.sample_builder.congestion_control(congestion_control), @@ -464,7 +468,9 @@ impl SampleBuilderTrait for ReplyDelBuilder<'_> { ..self } } +} +impl QoSBuilderTrait for ReplyDelBuilder<'_> { fn congestion_control(self, congestion_control: CongestionControl) -> Self { Self { sample_builder: self.sample_builder.congestion_control(congestion_control), diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index c7ee6e8368..7545646b91 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -28,6 +28,12 @@ use zenoh_core::Resolvable; use zenoh_core::SyncResolve; use zenoh_protocol::core::CongestionControl; +pub trait QoSBuilderTrait { + fn congestion_control(self, congestion_control: CongestionControl) -> Self; + fn priority(self, priority: Priority) -> Self; + fn express(self, is_express: bool) -> Self; +} + pub trait SampleBuilderTrait { fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self where @@ -40,9 +46,6 @@ pub trait SampleBuilderTrait { fn with_attachment_opt(self, attachment: Option) -> Self; #[zenoh_macros::unstable] fn with_attachment(self, attachment: Attachment) -> Self; - fn congestion_control(self, congestion_control: CongestionControl) -> Self; - fn priority(self, priority: Priority) -> Self; - fn express(self, is_express: bool) -> Self; } pub trait PutSampleBuilderTrait: SampleBuilderTrait { @@ -119,6 +122,9 @@ impl SampleBuilderTrait for SampleBuilder { fn with_attachment(self, attachment: Attachment) -> Self { self.with_attachment_opt(Some(attachment)) } +} + +impl QoSBuilderTrait for SampleBuilder { fn congestion_control(self, congestion_control: CongestionControl) -> Self { Self(Sample { qos: self.0.qos.with_congestion_control(congestion_control), @@ -201,6 +207,9 @@ impl SampleBuilderTrait for PutSampleBuilder { fn with_attachment_opt(self, attachment: Option) -> Self { Self(self.0.with_attachment_opt(attachment)) } +} + +impl QoSBuilderTrait for PutSampleBuilder { fn congestion_control(self, congestion_control: CongestionControl) -> Self { Self(self.0.congestion_control(congestion_control)) } @@ -291,6 +300,9 @@ impl SampleBuilderTrait for DeleteSampleBuilder { fn with_attachment_opt(self, attachment: Option) -> Self { Self(self.0.with_attachment_opt(attachment)) } +} + +impl QoSBuilderTrait for DeleteSampleBuilder { fn congestion_control(self, congestion_control: CongestionControl) -> Self { Self(self.0.congestion_control(congestion_control)) } From 322a4e06b0acdc5dc25be1b6e4abcd0a5c04bf82 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Mon, 25 Mar 2024 15:56:17 +0100 Subject: [PATCH 23/63] removed `with_keyexpr` from trait --- zenoh/src/queryable.rs | 30 -------------------------- zenoh/src/sample_builder.rs | 42 ++++++++++++++++++++----------------- 2 files changed, 23 insertions(+), 49 deletions(-) diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 68b27526ce..9edb9fb26c 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -240,16 +240,6 @@ impl<'a> ReplySampleBuilder<'a> { } impl SampleBuilderTrait for ReplySampleBuilder<'_> { - fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self - where - IntoKeyExpr: Into>, - { - Self { - sample_builder: self.sample_builder.with_keyexpr(key_expr), - ..self - } - } - fn with_timestamp_opt(self, timestamp: Option) -> Self { Self { sample_builder: self.sample_builder.with_timestamp_opt(timestamp), @@ -321,16 +311,6 @@ pub struct ReplyBuilder<'a> { } impl SampleBuilderTrait for ReplyBuilder<'_> { - fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self - where - IntoKeyExpr: Into>, - { - Self { - sample_builder: self.sample_builder.with_keyexpr(key_expr), - ..self - } - } - fn with_timestamp_opt(self, timestamp: Option) -> Self { Self { sample_builder: self.sample_builder.with_timestamp_opt(timestamp), @@ -421,16 +401,6 @@ pub struct ReplyDelBuilder<'a> { } impl SampleBuilderTrait for ReplyDelBuilder<'_> { - fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self - where - IntoKeyExpr: Into>, - { - Self { - sample_builder: self.sample_builder.with_keyexpr(key_expr), - ..self - } - } - fn with_timestamp_opt(self, timestamp: Option) -> Self { Self { sample_builder: self.sample_builder.with_timestamp_opt(timestamp), diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index 7545646b91..0df98773fc 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -29,15 +29,17 @@ use zenoh_core::SyncResolve; use zenoh_protocol::core::CongestionControl; pub trait QoSBuilderTrait { + /// Change the `congestion_control` to apply when routing the data. fn congestion_control(self, congestion_control: CongestionControl) -> Self; + /// Change the priority of the written data. fn priority(self, priority: Priority) -> Self; + /// Change the `express` policy to apply when routing the data. + /// When express is set to `true`, then the message will not be batched. + /// This usually has a positive impact on latency but negative impact on throughput. fn express(self, is_express: bool) -> Self; } pub trait SampleBuilderTrait { - fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self - where - IntoKeyExpr: Into>; fn with_timestamp_opt(self, timestamp: Option) -> Self; fn with_timestamp(self, timestamp: Timestamp) -> Self; #[zenoh_macros::unstable] @@ -78,10 +80,8 @@ impl SampleBuilder { attachment: None, }) } -} - -impl SampleBuilderTrait for SampleBuilder { - fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self + /// Allows to change keyexpr of [`Sample`] + pub fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self where IntoKeyExpr: Into>, { @@ -90,7 +90,9 @@ impl SampleBuilderTrait for SampleBuilder { ..self.0 }) } +} +impl SampleBuilderTrait for SampleBuilder { fn with_timestamp_opt(self, timestamp: Option) -> Self { Self(Sample { timestamp, @@ -176,6 +178,13 @@ impl PutSampleBuilder { attachment: None, })) } + /// Allows to change keyexpr of [`Sample`] + pub fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self + where + IntoKeyExpr: Into>, + { + Self(self.0.with_keyexpr(key_expr)) + } // It's convenient to set QoS as a whole for internal usage. For user API there are `congestion_control`, `priority` and `express` methods. pub(crate) fn with_qos(self, qos: QoS) -> Self { Self(SampleBuilder(Sample { qos, ..self.0 .0 })) @@ -183,12 +192,6 @@ impl PutSampleBuilder { } impl SampleBuilderTrait for PutSampleBuilder { - fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self - where - IntoKeyExpr: Into>, - { - Self(self.0.with_keyexpr(key_expr)) - } fn with_timestamp(self, timestamp: Timestamp) -> Self { Self(self.0.with_timestamp(timestamp)) } @@ -269,6 +272,13 @@ impl DeleteSampleBuilder { attachment: None, })) } + /// Allows to change keyexpr of [`Sample`] + pub fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self + where + IntoKeyExpr: Into>, + { + Self(self.0.with_keyexpr(key_expr)) + } // It's convenient to set QoS as a whole for internal usage. For user API there are `congestion_control`, `priority` and `express` methods. pub(crate) fn with_qos(self, qos: QoS) -> Self { Self(SampleBuilder(Sample { qos, ..self.0 .0 })) @@ -276,12 +286,6 @@ impl DeleteSampleBuilder { } impl SampleBuilderTrait for DeleteSampleBuilder { - fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self - where - IntoKeyExpr: Into>, - { - Self(self.0.with_keyexpr(key_expr)) - } fn with_timestamp(self, timestamp: Timestamp) -> Self { Self(self.0.with_timestamp(timestamp)) } From 9515c7d63bec0744d9a1bf2e86b7242ee9121480 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Mon, 25 Mar 2024 17:36:36 +0100 Subject: [PATCH 24/63] put, delete builder --- .../zenoh-plugin-rest/examples/z_serve_sse.rs | 1 + plugins/zenoh-plugin-rest/src/lib.rs | 1 + zenoh-ext/src/group.rs | 1 + zenoh/src/publication.rs | 284 +++++++++++++----- zenoh/src/sample_builder.rs | 6 + zenoh/src/session.rs | 12 +- zenoh/tests/qos.rs | 1 + zenoh/tests/routing.rs | 1 + zenoh/tests/session.rs | 1 + zenoh/tests/unicity.rs | 1 + 10 files changed, 233 insertions(+), 76 deletions(-) diff --git a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs index bb76005d6e..48f152e488 100644 --- a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs +++ b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs @@ -15,6 +15,7 @@ use clap::{arg, Command}; use std::time::Duration; use zenoh::prelude::r#async::*; use zenoh::publication::CongestionControl; +use zenoh::sample_builder::QoSBuilderTrait; use zenoh::{config::Config, key_expr::keyexpr}; const HTML: &str = r#" diff --git a/plugins/zenoh-plugin-rest/src/lib.rs b/plugins/zenoh-plugin-rest/src/lib.rs index e2718f6579..cc97590636 100644 --- a/plugins/zenoh-plugin-rest/src/lib.rs +++ b/plugins/zenoh-plugin-rest/src/lib.rs @@ -34,6 +34,7 @@ use zenoh::plugins::{RunningPluginTrait, ZenohPlugin}; use zenoh::prelude::r#async::*; use zenoh::query::{QueryConsolidation, Reply}; use zenoh::runtime::Runtime; +use zenoh::sample_builder::PutSampleBuilderTrait; use zenoh::selector::TIME_RANGE_KEY; use zenoh::Session; use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginControl}; diff --git a/zenoh-ext/src/group.rs b/zenoh-ext/src/group.rs index 41007d8b87..973baf271b 100644 --- a/zenoh-ext/src/group.rs +++ b/zenoh-ext/src/group.rs @@ -28,6 +28,7 @@ use std::time::{Duration, Instant}; use zenoh::prelude::r#async::*; use zenoh::publication::Publisher; use zenoh::query::ConsolidationMode; +use zenoh::sample_builder::QoSBuilderTrait; use zenoh::Error as ZError; use zenoh::Result as ZResult; use zenoh::Session; diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index 392c0bf8c1..97f485f1e3 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -18,6 +18,9 @@ use crate::prelude::*; #[zenoh_macros::unstable] use crate::sample::Attachment; use crate::sample::{DataInfo, QoS, Sample, SampleKind}; +use crate::sample_builder::{ + DeleteSampleBuilderTrait, PutSampleBuilderTrait, QoSBuilderTrait, SampleBuilderTrait, +}; use crate::SessionRef; use crate::Undeclarable; #[cfg(feature = "unstable")] @@ -56,7 +59,14 @@ pub use zenoh_protocol::core::CongestionControl; /// .unwrap(); /// # }) /// ``` -pub type DeleteBuilder<'a, 'b> = PutBuilder<'a, 'b>; +pub struct DeleteBuilder<'a, 'b> { + pub(crate) publisher: PublisherBuilder<'a, 'b>, + pub(crate) timestamp: Option, + #[cfg(feature = "unstable")] + pub(crate) source_info: Option, + #[cfg(feature = "unstable")] + pub(crate) attachment: Option, +} /// A builder for initializing a [`put`](crate::Session::put) operation. /// @@ -81,36 +91,141 @@ pub type DeleteBuilder<'a, 'b> = PutBuilder<'a, 'b>; pub struct PutBuilder<'a, 'b> { pub(crate) publisher: PublisherBuilder<'a, 'b>, pub(crate) payload: Payload, - pub(crate) kind: SampleKind, pub(crate) encoding: Encoding, + pub(crate) timestamp: Option, + #[cfg(feature = "unstable")] + pub(crate) source_info: Option, #[cfg(feature = "unstable")] pub(crate) attachment: Option, } -impl PutBuilder<'_, '_> { - /// Change the `congestion_control` to apply when routing the data. +impl QoSBuilderTrait for PutBuilder<'_, '_> { #[inline] - pub fn congestion_control(mut self, congestion_control: CongestionControl) -> Self { - self.publisher = self.publisher.congestion_control(congestion_control); - self + fn congestion_control(self, congestion_control: CongestionControl) -> Self { + Self { + publisher: self.publisher.congestion_control(congestion_control), + ..self + } } - - /// Change the priority of the written data. #[inline] - pub fn priority(mut self, priority: Priority) -> Self { - self.publisher = self.publisher.priority(priority); - self + fn priority(self, priority: Priority) -> Self { + Self { + publisher: self.publisher.priority(priority), + ..self + } } + #[inline] + fn express(self, is_express: bool) -> Self { + Self { + publisher: self.publisher.express(is_express), + ..self + } + } +} - /// Change the `express` policy to apply when routing the data. - /// When express is set to `true`, then the message will not be batched. - /// This usually has a positive impact on latency but negative impact on throughput. +impl QoSBuilderTrait for DeleteBuilder<'_, '_> { #[inline] - pub fn express(mut self, is_express: bool) -> Self { - self.publisher = self.publisher.express(is_express); - self + fn congestion_control(self, congestion_control: CongestionControl) -> Self { + Self { + publisher: self.publisher.congestion_control(congestion_control), + ..self + } + } + #[inline] + fn priority(self, priority: Priority) -> Self { + Self { + publisher: self.publisher.priority(priority), + ..self + } + } + #[inline] + fn express(self, is_express: bool) -> Self { + Self { + publisher: self.publisher.express(is_express), + ..self + } + } +} + +impl SampleBuilderTrait for PutBuilder<'_, '_> { + fn with_timestamp_opt(self, timestamp: Option) -> Self { + Self { timestamp, ..self } + } + fn with_timestamp(self, timestamp: uhlc::Timestamp) -> Self { + Self { + timestamp: Some(timestamp), + ..self + } + } + #[cfg(feature = "unstable")] + fn with_source_info(self, source_info: SourceInfo) -> Self { + Self { + source_info: Some(source_info), + ..self + } + } + #[cfg(feature = "unstable")] + fn with_attachment_opt(self, attachment: Option) -> Self { + Self { attachment, ..self } + } + #[cfg(feature = "unstable")] + fn with_attachment(self, attachment: Attachment) -> Self { + Self { + attachment: Some(attachment), + ..self + } + } +} + +impl SampleBuilderTrait for DeleteBuilder<'_, '_> { + fn with_timestamp_opt(self, timestamp: Option) -> Self { + Self { timestamp, ..self } + } + fn with_timestamp(self, timestamp: uhlc::Timestamp) -> Self { + Self { + timestamp: Some(timestamp), + ..self + } + } + #[cfg(feature = "unstable")] + fn with_source_info(self, source_info: SourceInfo) -> Self { + Self { + source_info: Some(source_info), + ..self + } + } + #[cfg(feature = "unstable")] + fn with_attachment_opt(self, attachment: Option) -> Self { + Self { attachment, ..self } + } + #[cfg(feature = "unstable")] + fn with_attachment(self, attachment: Attachment) -> Self { + Self { + attachment: Some(attachment), + ..self + } + } +} + +impl PutSampleBuilderTrait for PutBuilder<'_, '_> { + fn with_encoding(self, encoding: Encoding) -> Self { + Self { encoding, ..self } + } + + fn with_payload(self, payload: IntoPayload) -> Self + where + IntoPayload: Into, + { + Self { + payload: payload.into(), + ..self + } } +} +impl DeleteSampleBuilderTrait for DeleteBuilder<'_, '_> {} + +impl PutBuilder<'_, '_> { /// Restrict the matching subscribers that will receive the published data /// to the ones that have the given [`Locality`](crate::prelude::Locality). #[zenoh_macros::unstable] @@ -119,21 +234,15 @@ impl PutBuilder<'_, '_> { self.publisher = self.publisher.allowed_destination(destination); self } +} - /// Set the [`Encoding`] of the written data. - #[inline] - pub fn with_encoding(mut self, encoding: IntoEncoding) -> Self - where - IntoEncoding: Into, - { - self.encoding = encoding.into(); - self - } - +impl DeleteBuilder<'_, '_> { + /// Restrict the matching subscribers that will receive the published data + /// to the ones that have the given [`Locality`](crate::prelude::Locality). #[zenoh_macros::unstable] - /// Attach user-provided data to the written data. - pub fn with_attachment(mut self, attachment: Attachment) -> Self { - self.attachment = Some(attachment); + #[inline] + pub fn allowed_destination(mut self, destination: Locality) -> Self { + self.publisher = self.publisher.allowed_destination(destination); self } } @@ -142,36 +251,40 @@ impl Resolvable for PutBuilder<'_, '_> { type To = ZResult<()>; } +impl Resolvable for DeleteBuilder<'_, '_> { + type To = ZResult<()>; +} + impl SyncResolve for PutBuilder<'_, '_> { #[inline] fn res_sync(self) -> ::To { - let PublisherBuilder { - session, - key_expr, - congestion_control, - priority, - is_express, - destination, - } = self.publisher; - - let publisher = Publisher { - session, - #[cfg(feature = "unstable")] - eid: 0, // This is a one shot Publisher - key_expr: key_expr?, - congestion_control, - priority, - is_express, - destination, - }; - + let publisher = self.publisher.one_time_res_sync()?; resolve_put( &publisher, self.payload, - self.kind, + SampleKind::Put, self.encoding, + self.timestamp, + #[cfg(feature = "unstable")] + self.source_info, + #[cfg(feature = "unstable")] + self.attachment, + ) + } +} + +impl SyncResolve for DeleteBuilder<'_, '_> { + #[inline] + fn res_sync(self) -> ::To { + let publisher = self.publisher.one_time_res_sync()?; + resolve_put( + &publisher, + Payload::empty(), + SampleKind::Delete, + Encoding::ZENOH_BYTES, + self.timestamp, #[cfg(feature = "unstable")] - None, + self.source_info, #[cfg(feature = "unstable")] self.attachment, ) @@ -186,6 +299,14 @@ impl AsyncResolve for PutBuilder<'_, '_> { } } +impl AsyncResolve for DeleteBuilder<'_, '_> { + type Future = Ready; + + fn res_async(self) -> Self::Future { + std::future::ready(self.res_sync()) + } +} + use futures::Sink; use std::convert::TryFrom; use std::convert::TryInto; @@ -293,25 +414,22 @@ impl<'a> Publisher<'a> { /// Change the `congestion_control` to apply when routing the data. #[inline] - pub fn congestion_control(mut self, congestion_control: CongestionControl) -> Self { + pub fn set_congestion_control(&mut self, congestion_control: CongestionControl) { self.congestion_control = congestion_control; - self } /// Change the priority of the written data. #[inline] - pub fn priority(mut self, priority: Priority) -> Self { + pub fn set_priority(&mut self, priority: Priority) { self.priority = priority; - self } /// Restrict the matching subscribers that will receive the published data /// to the ones that have the given [`Locality`](crate::prelude::Locality). #[zenoh_macros::unstable] #[inline] - pub fn allowed_destination(mut self, destination: Locality) -> Self { + pub fn set_allowed_destination(&mut self, destination: Locality) { self.destination = destination; - self } /// Consumes the given `Publisher`, returning a thread-safe reference-counting @@ -355,6 +473,7 @@ impl<'a> Publisher<'a> { payload, kind, encoding: Encoding::ZENOH_BYTES, + timestamp: None, #[cfg(feature = "unstable")] source_info: None, #[cfg(feature = "unstable")] @@ -625,6 +744,7 @@ pub struct Publication<'a> { payload: Payload, kind: SampleKind, encoding: Encoding, + timestamp: Option, #[cfg(feature = "unstable")] pub(crate) source_info: Option, #[cfg(feature = "unstable")] @@ -676,6 +796,7 @@ impl SyncResolve for Publication<'_> { self.payload, self.kind, self.encoding, + self.timestamp, #[cfg(feature = "unstable")] self.source_info, #[cfg(feature = "unstable")] @@ -707,6 +828,7 @@ impl<'a> Sink for Publisher<'a> { payload: item.payload, kind: item.kind, encoding: item.encoding, + timestamp: None, #[cfg(feature = "unstable")] source_info: None, #[cfg(feature = "unstable")] @@ -770,30 +892,32 @@ impl<'a, 'b> Clone for PublisherBuilder<'a, 'b> { } } -impl<'a, 'b> PublisherBuilder<'a, 'b> { +impl QoSBuilderTrait for PublisherBuilder<'_, '_> { /// Change the `congestion_control` to apply when routing the data. #[inline] - pub fn congestion_control(mut self, congestion_control: CongestionControl) -> Self { - self.congestion_control = congestion_control; - self + fn congestion_control(self, congestion_control: CongestionControl) -> Self { + Self { + congestion_control, + ..self + } } /// Change the priority of the written data. #[inline] - pub fn priority(mut self, priority: Priority) -> Self { - self.priority = priority; - self + fn priority(self, priority: Priority) -> Self { + Self { priority, ..self } } /// Change the `express` policy to apply when routing the data. /// When express is set to `true`, then the message will not be batched. /// This usually has a positive impact on latency but negative impact on throughput. #[inline] - pub fn express(mut self, is_express: bool) -> Self { - self.is_express = is_express; - self + fn express(self, is_express: bool) -> Self { + Self { is_express, ..self } } +} +impl<'a, 'b> PublisherBuilder<'a, 'b> { /// Restrict the matching subscribers that will receive the published data /// to the ones that have the given [`Locality`](crate::prelude::Locality). #[zenoh_macros::unstable] @@ -802,6 +926,20 @@ impl<'a, 'b> PublisherBuilder<'a, 'b> { self.destination = destination; self } + + // internal function for `PutBuilder` and `DeleteBuilder` + fn one_time_res_sync(self) -> ZResult> { + Ok(Publisher { + session: self.session, + #[cfg(feature = "unstable")] + eid: 0, // This is a one shot Publisher + key_expr: self.key_expr?, + congestion_control: self.congestion_control, + priority: self.priority, + is_express: self.is_express, + destination: self.destination, + }) + } } impl<'a, 'b> Resolvable for PublisherBuilder<'a, 'b> { @@ -874,6 +1012,7 @@ fn resolve_put( payload: Payload, kind: SampleKind, encoding: Encoding, + timestamp: Option, #[cfg(feature = "unstable")] source_info: Option, #[cfg(feature = "unstable")] attachment: Option, ) -> ZResult<()> { @@ -883,8 +1022,11 @@ fn resolve_put( .as_ref() .unwrap() .clone(); - let timestamp = publisher.session.runtime.new_timestamp(); - + let timestamp = if timestamp.is_none() { + publisher.session.runtime.new_timestamp() + } else { + timestamp + }; if publisher.destination != Locality::SessionLocal { primitives.send_push(Push { wire_expr: publisher.key_expr.to_wire(&publisher.session).to_owned(), diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index 0df98773fc..1710cbc85b 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -40,17 +40,23 @@ pub trait QoSBuilderTrait { } pub trait SampleBuilderTrait { + /// Sets of clears timestamp fn with_timestamp_opt(self, timestamp: Option) -> Self; + /// Sets timestamp fn with_timestamp(self, timestamp: Timestamp) -> Self; + /// Attach source information #[zenoh_macros::unstable] fn with_source_info(self, source_info: SourceInfo) -> Self; + /// Attach or remove user-provided data in key-value format #[zenoh_macros::unstable] fn with_attachment_opt(self, attachment: Option) -> Self; + /// Attach user-provided data in key-value format #[zenoh_macros::unstable] fn with_attachment(self, attachment: Attachment) -> Self; } pub trait PutSampleBuilderTrait: SampleBuilderTrait { + /// Set the [`Encoding`] fn with_encoding(self, encoding: Encoding) -> Self; fn with_payload(self, payload: IntoPayload) -> Self where diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index 89c18ec4a8..e26bdeadaf 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -706,10 +706,12 @@ impl Session { PutBuilder { publisher: self.declare_publisher(key_expr), payload: payload.into(), - kind: SampleKind::Put, + timestamp: None, encoding: Encoding::default(), #[cfg(feature = "unstable")] attachment: None, + #[cfg(feature = "unstable")] + source_info: None, } } @@ -737,13 +739,13 @@ impl Session { TryIntoKeyExpr: TryInto>, >>::Error: Into, { - PutBuilder { + DeleteBuilder { publisher: self.declare_publisher(key_expr), - payload: Payload::empty(), - kind: SampleKind::Delete, - encoding: Encoding::default(), + timestamp: None, #[cfg(feature = "unstable")] attachment: None, + #[cfg(feature = "unstable")] + source_info: None, } } /// Query data from the matching queryables in the system. diff --git a/zenoh/tests/qos.rs b/zenoh/tests/qos.rs index 1a9df306b2..8dc39423cb 100644 --- a/zenoh/tests/qos.rs +++ b/zenoh/tests/qos.rs @@ -15,6 +15,7 @@ use async_std::prelude::FutureExt; use async_std::task; use std::time::Duration; use zenoh::prelude::r#async::*; +use zenoh::sample_builder::QoSBuilderTrait; use zenoh::{publication::Priority, SessionDeclarations}; use zenoh_core::zasync_executor_init; diff --git a/zenoh/tests/routing.rs b/zenoh/tests/routing.rs index 06a8f5da45..123550852e 100644 --- a/zenoh/tests/routing.rs +++ b/zenoh/tests/routing.rs @@ -20,6 +20,7 @@ use std::sync::{atomic::AtomicUsize, Arc}; use std::time::Duration; use zenoh::config::{Config, ModeDependentValue}; use zenoh::prelude::r#async::*; +use zenoh::sample_builder::QoSBuilderTrait; use zenoh::{value::Value, Result}; use zenoh_core::zasync_executor_init; use zenoh_protocol::core::{WhatAmI, WhatAmIMatcher}; diff --git a/zenoh/tests/session.rs b/zenoh/tests/session.rs index e3f5e2df63..955ec7a73f 100644 --- a/zenoh/tests/session.rs +++ b/zenoh/tests/session.rs @@ -17,6 +17,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use std::time::Duration; use zenoh::prelude::r#async::*; +use zenoh::sample_builder::QoSBuilderTrait; use zenoh_core::zasync_executor_init; const TIMEOUT: Duration = Duration::from_secs(60); diff --git a/zenoh/tests/unicity.rs b/zenoh/tests/unicity.rs index 8eb007b0c0..3d1327398d 100644 --- a/zenoh/tests/unicity.rs +++ b/zenoh/tests/unicity.rs @@ -17,6 +17,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use std::time::Duration; use zenoh::prelude::r#async::*; +use zenoh::sample_builder::QoSBuilderTrait; use zenoh_core::zasync_executor_init; const TIMEOUT: Duration = Duration::from_secs(60); From 4e14cf9e24f5bc7ba2cde3e1494f398d58ed1415 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Tue, 26 Mar 2024 01:49:14 +0100 Subject: [PATCH 25/63] build fixes --- examples/examples/z_ping.rs | 1 + examples/examples/z_pong.rs | 1 + examples/examples/z_pub_thr.rs | 1 + zenoh/tests/attachments.rs | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/examples/z_ping.rs b/examples/examples/z_ping.rs index a57c937e48..b40afc1f53 100644 --- a/examples/examples/z_ping.rs +++ b/examples/examples/z_ping.rs @@ -16,6 +16,7 @@ use std::time::{Duration, Instant}; use zenoh::config::Config; use zenoh::prelude::sync::*; use zenoh::publication::CongestionControl; +use zenoh::sample_builder::QoSBuilderTrait; use zenoh_examples::CommonArgs; fn main() { diff --git a/examples/examples/z_pong.rs b/examples/examples/z_pong.rs index baa5683f62..0003958b5d 100644 --- a/examples/examples/z_pong.rs +++ b/examples/examples/z_pong.rs @@ -15,6 +15,7 @@ use clap::Parser; use zenoh::config::Config; use zenoh::prelude::sync::*; use zenoh::publication::CongestionControl; +use zenoh::sample_builder::QoSBuilderTrait; use zenoh_examples::CommonArgs; fn main() { diff --git a/examples/examples/z_pub_thr.rs b/examples/examples/z_pub_thr.rs index 4354ad2e68..7e7c1ac9b5 100644 --- a/examples/examples/z_pub_thr.rs +++ b/examples/examples/z_pub_thr.rs @@ -16,6 +16,7 @@ use clap::Parser; use std::convert::TryInto; use zenoh::prelude::sync::*; use zenoh::publication::CongestionControl; +use zenoh::sample_builder::QoSBuilderTrait; use zenoh_examples::CommonArgs; fn main() { diff --git a/zenoh/tests/attachments.rs b/zenoh/tests/attachments.rs index 8d26cc0344..04ed28b761 100644 --- a/zenoh/tests/attachments.rs +++ b/zenoh/tests/attachments.rs @@ -1,7 +1,7 @@ #[cfg(feature = "unstable")] #[test] fn pubsub() { - use zenoh::prelude::sync::*; + use zenoh::{prelude::sync::*, sample_builder::SampleBuilderTrait}; let zenoh = zenoh::open(Config::default()).res().unwrap(); let _sub = zenoh From 8cd60d0afaeec5ab0468e899db300302f65c62e6 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Wed, 27 Mar 2024 00:47:48 +0100 Subject: [PATCH 26/63] Publication updated --- examples/examples/z_pub.rs | 1 + zenoh/src/publication.rs | 254 +++++++++++++++++++++++++------------ zenoh/src/queryable.rs | 13 +- zenoh/src/sample.rs | 18 ++- zenoh/src/session.rs | 5 +- 5 files changed, 196 insertions(+), 95 deletions(-) diff --git a/examples/examples/z_pub.rs b/examples/examples/z_pub.rs index 7ba17745b5..d22d4d55ee 100644 --- a/examples/examples/z_pub.rs +++ b/examples/examples/z_pub.rs @@ -16,6 +16,7 @@ use clap::Parser; use std::time::Duration; use zenoh::config::Config; use zenoh::prelude::r#async::*; +use zenoh::sample_builder::SampleBuilderTrait; use zenoh_examples::CommonArgs; #[async_std::main] diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index 97f485f1e3..1e1c0cb509 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -17,7 +17,7 @@ use crate::net::primitives::Primitives; use crate::prelude::*; #[zenoh_macros::unstable] use crate::sample::Attachment; -use crate::sample::{DataInfo, QoS, Sample, SampleKind}; +use crate::sample::{DataInfo, QoS, Sample, SampleFields, SampleKind}; use crate::sample_builder::{ DeleteSampleBuilderTrait, PutSampleBuilderTrait, QoSBuilderTrait, SampleBuilderTrait, }; @@ -33,8 +33,6 @@ use zenoh_core::{zread, AsyncResolve, Resolvable, Resolve, SyncResolve}; use zenoh_protocol::network::push::ext; use zenoh_protocol::network::Mapping; use zenoh_protocol::network::Push; -#[zenoh_macros::unstable] -use zenoh_protocol::zenoh::ext::SourceInfoType; use zenoh_protocol::zenoh::Del; use zenoh_protocol::zenoh::PushBody; use zenoh_protocol::zenoh::Put; @@ -63,7 +61,7 @@ pub struct DeleteBuilder<'a, 'b> { pub(crate) publisher: PublisherBuilder<'a, 'b>, pub(crate) timestamp: Option, #[cfg(feature = "unstable")] - pub(crate) source_info: Option, + pub(crate) source_info: SourceInfo, #[cfg(feature = "unstable")] pub(crate) attachment: Option, } @@ -94,7 +92,7 @@ pub struct PutBuilder<'a, 'b> { pub(crate) encoding: Encoding, pub(crate) timestamp: Option, #[cfg(feature = "unstable")] - pub(crate) source_info: Option, + pub(crate) source_info: SourceInfo, #[cfg(feature = "unstable")] pub(crate) attachment: Option, } @@ -160,7 +158,7 @@ impl SampleBuilderTrait for PutBuilder<'_, '_> { #[cfg(feature = "unstable")] fn with_source_info(self, source_info: SourceInfo) -> Self { Self { - source_info: Some(source_info), + source_info, ..self } } @@ -190,7 +188,7 @@ impl SampleBuilderTrait for DeleteBuilder<'_, '_> { #[cfg(feature = "unstable")] fn with_source_info(self, source_info: SourceInfo) -> Self { Self { - source_info: Some(source_info), + source_info, ..self } } @@ -258,7 +256,7 @@ impl Resolvable for DeleteBuilder<'_, '_> { impl SyncResolve for PutBuilder<'_, '_> { #[inline] fn res_sync(self) -> ::To { - let publisher = self.publisher.one_time_res_sync()?; + let publisher = self.publisher.create_one_shot_publisher()?; resolve_put( &publisher, self.payload, @@ -276,7 +274,7 @@ impl SyncResolve for PutBuilder<'_, '_> { impl SyncResolve for DeleteBuilder<'_, '_> { #[inline] fn res_sync(self) -> ::To { - let publisher = self.publisher.one_time_res_sync()?; + let publisher = self.publisher.create_one_shot_publisher()?; resolve_put( &publisher, Payload::empty(), @@ -467,20 +465,6 @@ impl<'a> Publisher<'a> { std::sync::Arc::new(self) } - fn _write(&self, kind: SampleKind, payload: Payload) -> Publication { - Publication { - publisher: self, - payload, - kind, - encoding: Encoding::ZENOH_BYTES, - timestamp: None, - #[cfg(feature = "unstable")] - source_info: None, - #[cfg(feature = "unstable")] - attachment: None, - } - } - /// Put data. /// /// # Examples @@ -494,11 +478,20 @@ impl<'a> Publisher<'a> { /// # }) /// ``` #[inline] - pub fn put(&self, payload: IntoPayload) -> Publication + pub fn put(&self, payload: IntoPayload) -> PutPublication where IntoPayload: Into, { - self._write(SampleKind::Put, payload.into()) + PutPublication { + publisher: self, + payload: payload.into(), + encoding: Encoding::ZENOH_BYTES, + timestamp: None, + #[cfg(feature = "unstable")] + source_info: SourceInfo::empty(), + #[cfg(feature = "unstable")] + attachment: None, + } } /// Delete data. @@ -513,8 +506,15 @@ impl<'a> Publisher<'a> { /// publisher.delete().res().await.unwrap(); /// # }) /// ``` - pub fn delete(&self) -> Publication { - self._write(SampleKind::Delete, Payload::empty()) + pub fn delete(&self) -> DeletePublication { + DeletePublication { + publisher: self, + timestamp: None, + #[cfg(feature = "unstable")] + source_info: SourceInfo::empty(), + #[cfg(feature = "unstable")] + attachment: None, + } } /// Return the [`MatchingStatus`] of the publisher. @@ -737,64 +737,129 @@ impl Drop for Publisher<'_> { } /// A [`Resolvable`] returned by [`Publisher::put()`](Publisher::put), -/// [`Publisher::delete()`](Publisher::delete) and [`Publisher::write()`](Publisher::write). #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] -pub struct Publication<'a> { +pub struct PutPublication<'a> { publisher: &'a Publisher<'a>, payload: Payload, - kind: SampleKind, encoding: Encoding, timestamp: Option, #[cfg(feature = "unstable")] - pub(crate) source_info: Option, + pub(crate) source_info: SourceInfo, #[cfg(feature = "unstable")] pub(crate) attachment: Option, } -impl<'a> Publication<'a> { - pub fn with_encoding(mut self, encoding: Encoding) -> Self { - self.encoding = encoding; - self +/// A [`Resolvable`] returned by [`Publisher::delete()`](Publisher::delete) +#[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] +pub struct DeletePublication<'a> { + publisher: &'a Publisher<'a>, + timestamp: Option, + #[cfg(feature = "unstable")] + pub(crate) source_info: SourceInfo, + #[cfg(feature = "unstable")] + pub(crate) attachment: Option, +} + +impl SampleBuilderTrait for PutPublication<'_> { + fn with_timestamp_opt(self, timestamp: Option) -> Self { + Self { timestamp, ..self } } - #[zenoh_macros::unstable] - pub fn with_attachment(mut self, attachment: Attachment) -> Self { - self.attachment = Some(attachment); - self + fn with_timestamp(self, timestamp: uhlc::Timestamp) -> Self { + Self { + timestamp: Some(timestamp), + ..self + } } - /// Send data with the given [`SourceInfo`]. - /// - /// # Examples - /// ``` - /// # async_std::task::block_on(async { - /// use zenoh::prelude::r#async::*; - /// - /// let session = zenoh::open(config::peer()).res().await.unwrap(); - /// let publisher = session.declare_publisher("key/expression").res().await.unwrap(); - /// publisher.put("Value").with_source_info(SourceInfo { - /// source_id: Some(publisher.id()), - /// source_sn: Some(0), - /// }).res().await.unwrap(); - /// # }) - /// ``` - #[zenoh_macros::unstable] - pub fn with_source_info(mut self, source_info: SourceInfo) -> Self { - self.source_info = Some(source_info); - self + #[cfg(feature = "unstable")] + fn with_source_info(self, source_info: SourceInfo) -> Self { + Self { + source_info, + ..self + } + } + + #[cfg(feature = "unstable")] + fn with_attachment_opt(self, attachment: Option) -> Self { + Self { attachment, ..self } + } + + #[cfg(feature = "unstable")] + fn with_attachment(self, attachment: Attachment) -> Self { + Self { + attachment: Some(attachment), + ..self + } + } +} + +impl PutSampleBuilderTrait for PutPublication<'_> { + fn with_encoding(self, encoding: Encoding) -> Self { + Self { encoding, ..self } } + + fn with_payload(self, payload: IntoPayload) -> Self + where + IntoPayload: Into, + { + Self { + payload: payload.into(), + ..self + } + } +} + +impl SampleBuilderTrait for DeletePublication<'_> { + fn with_timestamp_opt(self, timestamp: Option) -> Self { + Self { timestamp, ..self } + } + + fn with_timestamp(self, timestamp: uhlc::Timestamp) -> Self { + Self { + timestamp: Some(timestamp), + ..self + } + } + + #[cfg(feature = "unstable")] + fn with_source_info(self, source_info: SourceInfo) -> Self { + Self { + source_info, + ..self + } + } + + #[cfg(feature = "unstable")] + fn with_attachment_opt(self, attachment: Option) -> Self { + Self { attachment, ..self } + } + + #[cfg(feature = "unstable")] + fn with_attachment(self, attachment: Attachment) -> Self { + Self { + attachment: Some(attachment), + ..self + } + } +} + +impl DeleteSampleBuilderTrait for DeletePublication<'_> {} + +impl Resolvable for PutPublication<'_> { + type To = ZResult<()>; } -impl Resolvable for Publication<'_> { +impl Resolvable for DeletePublication<'_> { type To = ZResult<()>; } -impl SyncResolve for Publication<'_> { +impl SyncResolve for PutPublication<'_> { fn res_sync(self) -> ::To { resolve_put( self.publisher, self.payload, - self.kind, + SampleKind::Put, self.encoding, self.timestamp, #[cfg(feature = "unstable")] @@ -805,7 +870,31 @@ impl SyncResolve for Publication<'_> { } } -impl AsyncResolve for Publication<'_> { +impl SyncResolve for DeletePublication<'_> { + fn res_sync(self) -> ::To { + resolve_put( + self.publisher, + Payload::empty(), + SampleKind::Delete, + Encoding::ZENOH_BYTES, + self.timestamp, + #[cfg(feature = "unstable")] + self.source_info, + #[cfg(feature = "unstable")] + self.attachment, + ) + } +} + +impl AsyncResolve for PutPublication<'_> { + type Future = Ready; + + fn res_async(self) -> Self::Future { + std::future::ready(self.res_sync()) + } +} + +impl AsyncResolve for DeletePublication<'_> { type Future = Ready; fn res_async(self) -> Self::Future { @@ -823,18 +912,25 @@ impl<'a> Sink for Publisher<'a> { #[inline] fn start_send(self: Pin<&mut Self>, item: Sample) -> Result<(), Self::Error> { - Publication { - publisher: &self, - payload: item.payload, - kind: item.kind, - encoding: item.encoding, - timestamp: None, + let SampleFields { + payload, + kind, + encoding, + #[cfg(feature = "unstable")] + attachment, + .. + } = item.into(); + resolve_put( + &self, + payload, + kind, + encoding, + None, #[cfg(feature = "unstable")] - source_info: None, + SourceInfo::empty(), #[cfg(feature = "unstable")] - attachment: item.attachment, - } - .res_sync() + attachment, + ) } #[inline] @@ -928,7 +1024,7 @@ impl<'a, 'b> PublisherBuilder<'a, 'b> { } // internal function for `PutBuilder` and `DeleteBuilder` - fn one_time_res_sync(self) -> ZResult> { + fn create_one_shot_publisher(self) -> ZResult> { Ok(Publisher { session: self.session, #[cfg(feature = "unstable")] @@ -1013,7 +1109,7 @@ fn resolve_put( kind: SampleKind, encoding: Encoding, timestamp: Option, - #[cfg(feature = "unstable")] source_info: Option, + #[cfg(feature = "unstable")] source_info: SourceInfo, #[cfg(feature = "unstable")] attachment: Option, ) -> ZResult<()> { log::trace!("write({:?}, [...])", &publisher.key_expr); @@ -1051,10 +1147,7 @@ fn resolve_put( timestamp, encoding: encoding.clone().into(), #[cfg(feature = "unstable")] - ext_sinfo: source_info.map(|s| SourceInfoType { - id: s.source_id.unwrap_or_default(), - sn: s.source_sn.unwrap_or_default() as u32, - }), + ext_sinfo: source_info.into(), #[cfg(not(feature = "unstable"))] ext_sinfo: None, #[cfg(feature = "shared-memory")] @@ -1076,10 +1169,7 @@ fn resolve_put( PushBody::Del(Del { timestamp, #[cfg(feature = "unstable")] - ext_sinfo: source_info.map(|s| SourceInfoType { - id: s.source_id.unwrap_or_default(), - sn: s.source_sn.unwrap_or_default() as u32, - }), + ext_sinfo: source_info.into(), #[cfg(not(feature = "unstable"))] ext_sinfo: None, ext_attachment, diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 9edb9fb26c..6f71cd7fb7 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -518,17 +518,10 @@ impl Query { { bail!("Attempted to reply on `{}`, which does not intersect with query `{}`, despite query only allowing replies on matching key expressions", sample.key_expr, self.key_expr()) } - #[allow(unused_mut)] // will be unused if feature = "unstable" is not enabled - let mut ext_sinfo = None; + #[cfg(not(feature = "unstable"))] + let ext_sinfo = None; #[cfg(feature = "unstable")] - { - if sample.source_info.source_id.is_some() || sample.source_info.source_sn.is_some() { - ext_sinfo = Some(zenoh::put::ext::SourceInfoType { - id: sample.source_info.source_id.unwrap_or_default(), - sn: sample.source_info.source_sn.unwrap_or_default() as u32, - }) - } - } + let ext_sinfo = sample.source_info.into(); self.inner.primitives.send_response(Response { rid: self.inner.qid, wire_expr: WireExpr { diff --git a/zenoh/src/sample.rs b/zenoh/src/sample.rs index acf8536a0e..1998f3e844 100644 --- a/zenoh/src/sample.rs +++ b/zenoh/src/sample.rs @@ -22,7 +22,7 @@ use crate::Priority; use serde::Serialize; use std::{convert::TryFrom, fmt}; use zenoh_protocol::core::EntityGlobalId; -use zenoh_protocol::{core::CongestionControl, network::push::ext::QoSType}; +use zenoh_protocol::{core::CongestionControl, network::push::ext::QoSType, zenoh}; pub type SourceSn = u64; @@ -163,6 +163,22 @@ impl SourceInfo { source_sn: None, } } + pub(crate) fn is_empty(&self) -> bool { + self.source_id.is_none() && self.source_sn.is_none() + } +} + +impl From for Option { + fn from(source_info: SourceInfo) -> Option { + if source_info.is_empty() { + None + } else { + Some(zenoh::put::ext::SourceInfoType { + id: source_info.source_id.unwrap_or_default(), + sn: source_info.source_sn.unwrap_or_default() as u32, + }) + } + } } #[zenoh_macros::unstable] diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index db81888018..a2371d1bfa 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -41,6 +41,7 @@ use crate::Priority; use crate::Sample; use crate::SampleKind; use crate::Selector; +use crate::SourceInfo; use crate::Value; use async_std::task; use log::{error, trace, warn}; @@ -711,7 +712,7 @@ impl Session { #[cfg(feature = "unstable")] attachment: None, #[cfg(feature = "unstable")] - source_info: None, + source_info: SourceInfo::empty(), } } @@ -745,7 +746,7 @@ impl Session { #[cfg(feature = "unstable")] attachment: None, #[cfg(feature = "unstable")] - source_info: None, + source_info: SourceInfo::empty(), } } /// Query data from the matching queryables in the system. From 00e0a59a71804fa54e4e2cc6d92a35731a079654 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Wed, 27 Mar 2024 00:59:12 +0100 Subject: [PATCH 27/63] build fix --- examples/examples/z_pub_shm_thr.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/examples/z_pub_shm_thr.rs b/examples/examples/z_pub_shm_thr.rs index 7c6f3cbbd3..5230ea3ce6 100644 --- a/examples/examples/z_pub_shm_thr.rs +++ b/examples/examples/z_pub_shm_thr.rs @@ -15,6 +15,7 @@ use clap::Parser; use zenoh::config::Config; use zenoh::prelude::r#async::*; use zenoh::publication::CongestionControl; +use zenoh::sample_builder::QoSBuilderTrait; use zenoh::shm::SharedMemoryManager; use zenoh_examples::CommonArgs; From e601271c25becb47c0f14fbbf0dccce2dfdb81f5 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Wed, 27 Mar 2024 02:26:16 +0100 Subject: [PATCH 28/63] reply_sample restored --- plugins/zenoh-plugin-example/src/lib.rs | 13 +----- .../src/replica/storage.rs | 42 +++++++++++-------- zenoh-ext/src/publication_cache.rs | 33 +++------------ zenoh-ext/src/querying_subscriber.rs | 9 +--- zenoh/src/queryable.rs | 38 ++++++++++++----- zenoh/src/sample_builder.rs | 6 +-- 6 files changed, 64 insertions(+), 77 deletions(-) diff --git a/plugins/zenoh-plugin-example/src/lib.rs b/plugins/zenoh-plugin-example/src/lib.rs index 40f8d69488..04f49b4739 100644 --- a/plugins/zenoh-plugin-example/src/lib.rs +++ b/plugins/zenoh-plugin-example/src/lib.rs @@ -24,8 +24,6 @@ use std::sync::{ use zenoh::plugins::{RunningPluginTrait, ZenohPlugin}; use zenoh::prelude::r#async::*; use zenoh::runtime::Runtime; -use zenoh::sample::SampleFields; -use zenoh::sample_builder::SampleBuilderTrait; use zenoh_core::zlock; use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginControl}; use zenoh_result::{bail, ZResult}; @@ -176,16 +174,7 @@ async fn run(runtime: Runtime, selector: KeyExpr<'_>, flag: Arc) { info!("Handling query '{}'", query.selector()); for (key_expr, sample) in stored.iter() { if query.selector().key_expr.intersects(unsafe{keyexpr::from_str_unchecked(key_expr)}) { - let SampleFields { key_expr, timestamp, attachment, source_info, payload, kind, .. } = sample.clone().into(); - let reply = query - .reply_sample(key_expr) - .with_timestamp_opt(timestamp) - .with_attachment_opt(attachment) - .with_source_info(source_info); - match kind { - SampleKind::Put => reply.put(payload).res().await.unwrap(), - SampleKind::Delete => reply.delete().res().await.unwrap(), - } + query.reply_sample(sample.clone()).res().await.unwrap(); } } } diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 67ce871bb0..aed13bbbf1 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -21,14 +21,17 @@ use futures::select; use std::collections::{HashMap, HashSet}; use std::str::{self, FromStr}; use std::time::{SystemTime, UNIX_EPOCH}; +use zenoh::buffers::buffer::SplitBuffer; use zenoh::buffers::ZBuf; -use zenoh::prelude::r#async::*; -use zenoh::query::ConsolidationMode; +use zenoh::key_expr::KeyExpr; +use zenoh::query::{ConsolidationMode, QueryTarget}; +use zenoh::sample::{Sample, SampleKind}; use zenoh::sample_builder::{ - PutSampleBuilder, PutSampleBuilderTrait, SampleBuilder, SampleBuilderTrait, + DeleteSampleBuilder, PutSampleBuilder, PutSampleBuilderTrait, SampleBuilder, SampleBuilderTrait, }; use zenoh::time::{new_reception_timestamp, Timestamp, NTP64}; -use zenoh::{Result as ZResult, Session}; +use zenoh::value::Value; +use zenoh::{Result as ZResult, Session, SessionDeclarations}; use zenoh_backend_traits::config::{GarbageCollectionConfig, StorageConfig}; use zenoh_backend_traits::{Capability, History, Persistence, StorageInsertionResult, StoredData}; use zenoh_core::{AsyncResolve, SyncResolve}; @@ -235,11 +238,8 @@ impl StorageService { continue; } }; - let sample = if sample.timestamp().is_none() { - SampleBuilder::from(sample).with_timestamp(new_reception_timestamp()).res_sync() - } else { - sample - }; + let timestamp = sample.timestamp().cloned().unwrap_or(new_reception_timestamp()); + let sample = SampleBuilder::from(sample).with_timestamp(timestamp).res_sync(); self.process_sample(sample).await; }, // on query on key_expr @@ -307,21 +307,27 @@ impl StorageService { .ovderriding_wild_update(&k, sample.timestamp().unwrap()) .await { - Some(overriding_update) => { + Some(Update { + kind: SampleKind::Put, + data, + }) => { let Value { payload, encoding, .. - } = overriding_update.data.value; + } = data.value; PutSampleBuilder::new(KeyExpr::from(k.clone()), payload) .with_encoding(encoding) - .with_timestamp(overriding_update.data.timestamp) - .res_sync() - } - None => { - PutSampleBuilder::new(KeyExpr::from(k.clone()), sample.payload().clone()) - .with_encoding(sample.encoding().clone()) - .with_timestamp(*sample.timestamp().unwrap()) + .with_timestamp(data.timestamp) .res_sync() } + Some(Update { + kind: SampleKind::Delete, + data, + }) => DeleteSampleBuilder::new(KeyExpr::from(k.clone())) + .with_timestamp(data.timestamp) + .res_sync(), + None => SampleBuilder::from(sample.clone()) + .keyexpr(k.clone()) + .res_sync(), }; let stripped_key = match self.strip_prefix(sample_to_store.key_expr()) { diff --git a/zenoh-ext/src/publication_cache.rs b/zenoh-ext/src/publication_cache.rs index 8a782a179e..85cb96cce2 100644 --- a/zenoh-ext/src/publication_cache.rs +++ b/zenoh-ext/src/publication_cache.rs @@ -20,8 +20,6 @@ use std::convert::TryInto; use std::future::Ready; use zenoh::prelude::r#async::*; use zenoh::queryable::{Query, Queryable}; -use zenoh::sample::SampleFields; -use zenoh::sample_builder::SampleBuilderTrait; use zenoh::subscriber::FlumeSubscriber; use zenoh::SessionRef; use zenoh_core::{AsyncResolve, Resolvable, SyncResolve}; @@ -118,29 +116,6 @@ pub struct PublicationCache<'a> { _stoptx: Sender, } -async fn reply_sample(query: &Query, sample: &Sample) { - let SampleFields { - key_expr, - timestamp, - attachment, - source_info, - payload, - kind, - .. - } = sample.clone().into(); - let reply = query - .reply_sample(key_expr) - .with_timestamp_opt(timestamp) - .with_attachment_opt(attachment) - .with_source_info(source_info); - if let Err(e) = match kind { - SampleKind::Put => reply.put(payload).res_async().await, - SampleKind::Delete => reply.delete().res_async().await, - } { - log::warn!("Error replying to query: {}", e); - } -} - impl<'a> PublicationCache<'a> { fn new(conf: PublicationCacheBuilder<'a, '_, '_>) -> ZResult> { let key_expr = conf.pub_key_expr?; @@ -237,7 +212,9 @@ impl<'a> PublicationCache<'a> { continue; } } - reply_sample(&query, sample).await; + if let Err(e) = query.reply_sample(sample.clone()).res_async().await { + log::warn!("Error replying to query: {}", e); + } } } } else { @@ -249,7 +226,9 @@ impl<'a> PublicationCache<'a> { continue; } } - reply_sample(&query, sample).await; + if let Err(e) = query.reply_sample(sample.clone()).res_async().await { + log::warn!("Error replying to query: {}", e); + } } } } diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index eb6d6e9516..5c302840b8 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -664,13 +664,8 @@ impl<'a, Receiver> FetchingSubscriber<'a, Receiver> { log::trace!("Sample received while fetch in progress: push it to merge_queue"); // ensure the sample has a timestamp, thus it will always be sorted into the MergeQueue // after any timestamped Sample possibly coming from a fetch reply. - let s = if s.timestamp().is_none() { - SampleBuilder::from(s) - .with_timestamp(new_reception_timestamp()) - .res_sync() - } else { - s - }; + let timestamp = s.timestamp().cloned().unwrap_or(new_reception_timestamp()); + let s = SampleBuilder::from(s).with_timestamp(timestamp).res_sync(); state.merge_queue.push(s); } } diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 6f71cd7fb7..14e9d09068 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -106,20 +106,19 @@ impl Query { self.inner.attachment.as_ref() } - /// Sends a reply or delete reply to this Query + /// Sends a reply in the form of [`Sample`] to this Query. /// - /// This function is useful when resending the samples which can be of [`SampleKind::Put`] or [`SampleKind::Delete`] - /// It allows to build the reply with same common parameters, like timestamp, attachment, source_info, etc. - /// and only on final step to choose the kind of reply by calling [`ReplySampleBuilder::put`] or [`ReplySampleBuilder::delete`] methods. + /// By default, queries only accept replies whose key expression intersects with the query's. + /// Unless the query has enabled disjoint replies (you can check this through [`Query::accepts_replies`]), + /// replying on a disjoint key expression will result in an error when resolving the reply. + /// This api is for internal use only. #[inline(always)] - pub fn reply_sample(&self, key_expr: IntoKeyExpr) -> ReplySampleBuilder - where - IntoKeyExpr: Into>, - { - let sample_builder = SampleBuilder::new(key_expr); + #[cfg(feature = "unstable")] + #[doc(hidden)] + pub fn reply_sample(&self, sample: Sample) -> ReplySampleBuilder<'_> { ReplySampleBuilder { query: self, - sample_builder, + sample_builder: sample.into(), } } @@ -302,6 +301,25 @@ impl QoSBuilderTrait for ReplySampleBuilder<'_> { } } +impl Resolvable for ReplySampleBuilder<'_> { + type To = ZResult<()>; +} + +impl SyncResolve for ReplySampleBuilder<'_> { + fn res_sync(self) -> ::To { + let sample = self.sample_builder.res_sync(); + self.query._reply_sample(sample) + } +} + +impl AsyncResolve for ReplySampleBuilder<'_> { + type Future = Ready; + + fn res_async(self) -> Self::Future { + std::future::ready(self.res_sync()) + } +} + /// A builder returned by [`Query::reply()`](Query::reply) #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] #[derive(Debug)] diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index 1710cbc85b..7e38e84afd 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -87,7 +87,7 @@ impl SampleBuilder { }) } /// Allows to change keyexpr of [`Sample`] - pub fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self + pub fn keyexpr(self, key_expr: IntoKeyExpr) -> Self where IntoKeyExpr: Into>, { @@ -189,7 +189,7 @@ impl PutSampleBuilder { where IntoKeyExpr: Into>, { - Self(self.0.with_keyexpr(key_expr)) + Self(self.0.keyexpr(key_expr)) } // It's convenient to set QoS as a whole for internal usage. For user API there are `congestion_control`, `priority` and `express` methods. pub(crate) fn with_qos(self, qos: QoS) -> Self { @@ -283,7 +283,7 @@ impl DeleteSampleBuilder { where IntoKeyExpr: Into>, { - Self(self.0.with_keyexpr(key_expr)) + Self(self.0.keyexpr(key_expr)) } // It's convenient to set QoS as a whole for internal usage. For user API there are `congestion_control`, `priority` and `express` methods. pub(crate) fn with_qos(self, qos: QoS) -> Self { From ea4020ddd3bba3402bba7a4fe172cc2518333066 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Wed, 27 Mar 2024 11:29:05 +0100 Subject: [PATCH 29/63] build fixes --- zenoh/src/publication.rs | 2 ++ zenoh/src/session.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index 1e1c0cb509..8772319593 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -73,6 +73,7 @@ pub struct DeleteBuilder<'a, 'b> { /// # async_std::task::block_on(async { /// use zenoh::prelude::r#async::*; /// use zenoh::publication::CongestionControl; +/// use zenoh::sample_builder::{PutSampleBuilderTrait, QoSBuilderTrait}; /// /// let session = zenoh::open(config::peer()).res().await.unwrap(); /// session @@ -951,6 +952,7 @@ impl<'a> Sink for Publisher<'a> { /// # async_std::task::block_on(async { /// use zenoh::prelude::r#async::*; /// use zenoh::publication::CongestionControl; +/// use zenoh::sample_builder::{PutSampleBuilderTrait, QoSBuilderTrait}; /// /// let session = zenoh::open(config::peer()).res().await.unwrap(); /// let publisher = session diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index a2371d1bfa..ffe7036050 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -683,6 +683,7 @@ impl Session { /// ``` /// # async_std::task::block_on(async { /// use zenoh::prelude::r#async::*; + /// use zenoh::sample_builder::PutSampleBuilderTrait; /// /// let session = zenoh::open(config::peer()).res().await.unwrap(); /// session From 5f0b531041ace6a303533ac0fbc56227ba121617 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Wed, 27 Mar 2024 12:37:22 +0100 Subject: [PATCH 30/63] clippy warning fix --- commons/zenoh-macros/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/commons/zenoh-macros/build.rs b/commons/zenoh-macros/build.rs index 557593d00e..d3c6b4e55b 100644 --- a/commons/zenoh-macros/build.rs +++ b/commons/zenoh-macros/build.rs @@ -24,6 +24,7 @@ fn main() { let mut version_rs = OpenOptions::new() .create(true) .write(true) + .truncate(true) .open(version_rs) .unwrap(); version_rs.write_all(&output.stdout).unwrap(); From ce5b6108537599424f5ab0d6da9887b05f966e59 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 11:20:29 +0100 Subject: [PATCH 31/63] sample api for GetBuilder --- examples/examples/z_ping.rs | 2 +- examples/examples/z_pong.rs | 2 +- examples/examples/z_pub_thr.rs | 2 +- plugins/zenoh-plugin-rest/src/lib.rs | 2 +- .../src/replica/align_queryable.rs | 4 +- .../src/replica/aligner.rs | 2 +- .../src/replica/storage.rs | 4 +- zenoh-ext/src/querying_subscriber.rs | 2 +- zenoh/src/liveliness.rs | 5 +- zenoh/src/net/runtime/adminspace.rs | 4 +- zenoh/src/publication.rs | 38 ++++--- zenoh/src/query.rs | 100 ++++++++++++++---- zenoh/src/queryable.rs | 32 +++--- zenoh/src/sample.rs | 75 +++++++++---- zenoh/src/sample_builder.rs | 62 ++++++----- zenoh/src/session.rs | 9 +- zenoh/src/value.rs | 26 +++-- 17 files changed, 249 insertions(+), 122 deletions(-) diff --git a/examples/examples/z_ping.rs b/examples/examples/z_ping.rs index b40afc1f53..79a1e16514 100644 --- a/examples/examples/z_ping.rs +++ b/examples/examples/z_ping.rs @@ -36,7 +36,7 @@ fn main() { let publisher = session .declare_publisher(key_expr_ping) .congestion_control(CongestionControl::Block) - .express(express) + .is_express(express) .res() .unwrap(); diff --git a/examples/examples/z_pong.rs b/examples/examples/z_pong.rs index 0003958b5d..a629cce3cf 100644 --- a/examples/examples/z_pong.rs +++ b/examples/examples/z_pong.rs @@ -35,7 +35,7 @@ fn main() { let publisher = session .declare_publisher(key_expr_pong) .congestion_control(CongestionControl::Block) - .express(express) + .is_express(express) .res() .unwrap(); diff --git a/examples/examples/z_pub_thr.rs b/examples/examples/z_pub_thr.rs index 7e7c1ac9b5..c9b9fe64f3 100644 --- a/examples/examples/z_pub_thr.rs +++ b/examples/examples/z_pub_thr.rs @@ -42,7 +42,7 @@ fn main() { .declare_publisher("test/thr") .congestion_control(CongestionControl::Block) .priority(prio) - .express(args.express) + .is_express(args.express) .res() .unwrap(); diff --git a/plugins/zenoh-plugin-rest/src/lib.rs b/plugins/zenoh-plugin-rest/src/lib.rs index 8a85f14caa..74da23679f 100644 --- a/plugins/zenoh-plugin-rest/src/lib.rs +++ b/plugins/zenoh-plugin-rest/src/lib.rs @@ -34,7 +34,7 @@ use zenoh::plugins::{RunningPluginTrait, ZenohPlugin}; use zenoh::prelude::r#async::*; use zenoh::query::{QueryConsolidation, Reply}; use zenoh::runtime::Runtime; -use zenoh::sample_builder::PutSampleBuilderTrait; +use zenoh::sample_builder::ValueBuilderTrait; use zenoh::selector::TIME_RANGE_KEY; use zenoh::Session; use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginControl}; diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs b/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs index 691fabd7a7..e5c4840666 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs @@ -20,8 +20,8 @@ use std::str; use std::str::FromStr; use zenoh::payload::StringOrBase64; use zenoh::prelude::r#async::*; -use zenoh::sample_builder::PutSampleBuilderTrait; -use zenoh::sample_builder::SampleBuilderTrait; +use zenoh::sample_builder::TimestampBuilderTrait; +use zenoh::sample_builder::ValueBuilderTrait; use zenoh::time::Timestamp; use zenoh::Session; diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs index a899196e7e..4119a941e5 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs @@ -21,7 +21,7 @@ use std::str; use zenoh::key_expr::{KeyExpr, OwnedKeyExpr}; use zenoh::payload::StringOrBase64; use zenoh::prelude::r#async::*; -use zenoh::sample_builder::{PutSampleBuilder, PutSampleBuilderTrait, SampleBuilderTrait}; +use zenoh::sample_builder::{PutSampleBuilder, TimestampBuilderTrait, ValueBuilderTrait}; use zenoh::time::Timestamp; use zenoh::Session; use zenoh_core::{AsyncResolve, SyncResolve}; diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 04a707bfda..69c973de39 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -27,7 +27,7 @@ use zenoh::key_expr::KeyExpr; use zenoh::query::{ConsolidationMode, QueryTarget}; use zenoh::sample::{Sample, SampleKind}; use zenoh::sample_builder::{ - DeleteSampleBuilder, PutSampleBuilder, PutSampleBuilderTrait, SampleBuilder, SampleBuilderTrait, + DeleteSampleBuilder, PutSampleBuilder, SampleBuilder, TimestampBuilderTrait, ValueBuilderTrait, }; use zenoh::time::{new_reception_timestamp, Timestamp, NTP64}; use zenoh::value::Value; @@ -719,7 +719,7 @@ fn construct_update(data: String) -> Update { for slice in result.3 { payload.push_zslice(slice.to_vec().into()); } - let value = Value::new(payload).with_encoding(result.2); + let value = Value::new(payload).with_encoding(result.2.into()); let data = StoredData { value, timestamp: Timestamp::from_str(&result.1).unwrap(), // @TODO: remove the unwrap() diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index 5c302840b8..e6b269cfbd 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -20,7 +20,7 @@ use std::time::Duration; use zenoh::handlers::{locked, DefaultHandler}; use zenoh::prelude::r#async::*; use zenoh::query::{QueryConsolidation, QueryTarget, ReplyKeyExpr}; -use zenoh::sample_builder::{SampleBuilder, SampleBuilderTrait}; +use zenoh::sample_builder::{SampleBuilder, TimestampBuilderTrait}; use zenoh::subscriber::{Reliability, Subscriber}; use zenoh::time::{new_reception_timestamp, Timestamp}; use zenoh::Result as ZResult; diff --git a/zenoh/src/liveliness.rs b/zenoh/src/liveliness.rs index 425aa62592..6aac3d3908 100644 --- a/zenoh/src/liveliness.rs +++ b/zenoh/src/liveliness.rs @@ -15,6 +15,8 @@ //! Liveliness primitives. //! //! see [`Liveliness`] +use zenoh_protocol::network::request; + use crate::{query::Reply, Id}; #[zenoh_macros::unstable] @@ -740,18 +742,19 @@ where { fn res_sync(self) -> ::To { let (callback, receiver) = self.handler.into_handler(); - self.session .query( &self.key_expr?.into(), &Some(KeyExpr::from(*KE_PREFIX_LIVELINESS)), QueryTarget::DEFAULT, QueryConsolidation::DEFAULT, + request::ext::QoSType::REQUEST.into(), Locality::default(), self.timeout, None, #[cfg(feature = "unstable")] None, + SourceInfo::empty(), callback, ) .map(|_| receiver) diff --git a/zenoh/src/net/runtime/adminspace.rs b/zenoh/src/net/runtime/adminspace.rs index 2a2b318cde..9047e8b112 100644 --- a/zenoh/src/net/runtime/adminspace.rs +++ b/zenoh/src/net/runtime/adminspace.rs @@ -20,7 +20,7 @@ use crate::plugins::sealed::{self as plugins}; use crate::prelude::sync::SyncResolve; use crate::queryable::Query; use crate::queryable::QueryInner; -use crate::sample_builder::PutSampleBuilderTrait; +use crate::sample_builder::ValueBuilderTrait; use crate::value::Value; use async_std::task; use log::{error, trace}; @@ -426,7 +426,7 @@ impl Primitives for AdminSpace { parameters, value: query .ext_body - .map(|b| Value::from(b.payload).with_encoding(b.encoding)), + .map(|b| Value::from(b.payload).with_encoding(b.encoding.into())), qid: msg.id, zid, primitives, diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index 8772319593..81a12133ed 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -19,7 +19,7 @@ use crate::prelude::*; use crate::sample::Attachment; use crate::sample::{DataInfo, QoS, Sample, SampleFields, SampleKind}; use crate::sample_builder::{ - DeleteSampleBuilderTrait, PutSampleBuilderTrait, QoSBuilderTrait, SampleBuilderTrait, + QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, ValueBuilderTrait, }; use crate::SessionRef; use crate::Undeclarable; @@ -114,9 +114,9 @@ impl QoSBuilderTrait for PutBuilder<'_, '_> { } } #[inline] - fn express(self, is_express: bool) -> Self { + fn is_express(self, is_express: bool) -> Self { Self { - publisher: self.publisher.express(is_express), + publisher: self.publisher.is_express(is_express), ..self } } @@ -138,15 +138,15 @@ impl QoSBuilderTrait for DeleteBuilder<'_, '_> { } } #[inline] - fn express(self, is_express: bool) -> Self { + fn is_express(self, is_express: bool) -> Self { Self { - publisher: self.publisher.express(is_express), + publisher: self.publisher.is_express(is_express), ..self } } } -impl SampleBuilderTrait for PutBuilder<'_, '_> { +impl TimestampBuilderTrait for PutBuilder<'_, '_> { fn with_timestamp_opt(self, timestamp: Option) -> Self { Self { timestamp, ..self } } @@ -156,6 +156,9 @@ impl SampleBuilderTrait for PutBuilder<'_, '_> { ..self } } +} + +impl SampleBuilderTrait for PutBuilder<'_, '_> { #[cfg(feature = "unstable")] fn with_source_info(self, source_info: SourceInfo) -> Self { Self { @@ -176,7 +179,7 @@ impl SampleBuilderTrait for PutBuilder<'_, '_> { } } -impl SampleBuilderTrait for DeleteBuilder<'_, '_> { +impl TimestampBuilderTrait for DeleteBuilder<'_, '_> { fn with_timestamp_opt(self, timestamp: Option) -> Self { Self { timestamp, ..self } } @@ -186,6 +189,9 @@ impl SampleBuilderTrait for DeleteBuilder<'_, '_> { ..self } } +} + +impl SampleBuilderTrait for DeleteBuilder<'_, '_> { #[cfg(feature = "unstable")] fn with_source_info(self, source_info: SourceInfo) -> Self { Self { @@ -206,7 +212,7 @@ impl SampleBuilderTrait for DeleteBuilder<'_, '_> { } } -impl PutSampleBuilderTrait for PutBuilder<'_, '_> { +impl ValueBuilderTrait for PutBuilder<'_, '_> { fn with_encoding(self, encoding: Encoding) -> Self { Self { encoding, ..self } } @@ -222,8 +228,6 @@ impl PutSampleBuilderTrait for PutBuilder<'_, '_> { } } -impl DeleteSampleBuilderTrait for DeleteBuilder<'_, '_> {} - impl PutBuilder<'_, '_> { /// Restrict the matching subscribers that will receive the published data /// to the ones that have the given [`Locality`](crate::prelude::Locality). @@ -761,7 +765,7 @@ pub struct DeletePublication<'a> { pub(crate) attachment: Option, } -impl SampleBuilderTrait for PutPublication<'_> { +impl TimestampBuilderTrait for PutPublication<'_> { fn with_timestamp_opt(self, timestamp: Option) -> Self { Self { timestamp, ..self } } @@ -772,7 +776,9 @@ impl SampleBuilderTrait for PutPublication<'_> { ..self } } +} +impl SampleBuilderTrait for PutPublication<'_> { #[cfg(feature = "unstable")] fn with_source_info(self, source_info: SourceInfo) -> Self { Self { @@ -795,7 +801,7 @@ impl SampleBuilderTrait for PutPublication<'_> { } } -impl PutSampleBuilderTrait for PutPublication<'_> { +impl ValueBuilderTrait for PutPublication<'_> { fn with_encoding(self, encoding: Encoding) -> Self { Self { encoding, ..self } } @@ -811,7 +817,7 @@ impl PutSampleBuilderTrait for PutPublication<'_> { } } -impl SampleBuilderTrait for DeletePublication<'_> { +impl TimestampBuilderTrait for DeletePublication<'_> { fn with_timestamp_opt(self, timestamp: Option) -> Self { Self { timestamp, ..self } } @@ -822,7 +828,9 @@ impl SampleBuilderTrait for DeletePublication<'_> { ..self } } +} +impl SampleBuilderTrait for DeletePublication<'_> { #[cfg(feature = "unstable")] fn with_source_info(self, source_info: SourceInfo) -> Self { Self { @@ -845,8 +853,6 @@ impl SampleBuilderTrait for DeletePublication<'_> { } } -impl DeleteSampleBuilderTrait for DeletePublication<'_> {} - impl Resolvable for PutPublication<'_> { type To = ZResult<()>; } @@ -1010,7 +1016,7 @@ impl QoSBuilderTrait for PublisherBuilder<'_, '_> { /// When express is set to `true`, then the message will not be batched. /// This usually has a positive impact on latency but negative impact on throughput. #[inline] - fn express(self, is_express: bool) -> Self { + fn is_express(self, is_express: bool) -> Self { Self { is_express, ..self } } } diff --git a/zenoh/src/query.rs b/zenoh/src/query.rs index fe48748ad4..6a0c4b1933 100644 --- a/zenoh/src/query.rs +++ b/zenoh/src/query.rs @@ -17,6 +17,8 @@ use crate::handlers::{locked, Callback, DefaultHandler}; use crate::prelude::*; #[zenoh_macros::unstable] use crate::sample::Attachment; +use crate::sample::QoSBuilder; +use crate::sample_builder::{QoSBuilderTrait, SampleBuilderTrait, ValueBuilderTrait}; use crate::Session; use std::collections::HashMap; use std::future::Ready; @@ -120,12 +122,70 @@ pub struct GetBuilder<'a, 'b, Handler> { pub(crate) scope: ZResult>>, pub(crate) target: QueryTarget, pub(crate) consolidation: QueryConsolidation, + pub(crate) qos: QoSBuilder, pub(crate) destination: Locality, pub(crate) timeout: Duration, pub(crate) handler: Handler, pub(crate) value: Option, #[cfg(feature = "unstable")] pub(crate) attachment: Option, + #[cfg(feature = "unstable")] + pub(crate) source_info: SourceInfo, +} + +impl SampleBuilderTrait for GetBuilder<'_, '_, Handler> { + #[cfg(feature = "unstable")] + fn with_source_info(self, source_info: SourceInfo) -> Self { + Self { + source_info, + ..self + } + } + + #[cfg(feature = "unstable")] + fn with_attachment_opt(self, attachment: Option) -> Self { + Self { attachment, ..self } + } + + #[cfg(feature = "unstable")] + fn with_attachment(self, attachment: Attachment) -> Self { + Self { + attachment: Some(attachment), + ..self + } + } +} + +impl QoSBuilderTrait for GetBuilder<'_, '_, DefaultHandler> { + fn congestion_control(self, congestion_control: CongestionControl) -> Self { + let qos = self.qos.congestion_control(congestion_control); + Self { qos, ..self } + } + + fn priority(self, priority: Priority) -> Self { + let qos = self.qos.priority(priority); + Self { qos, ..self } + } + + fn is_express(self, is_express: bool) -> Self { + let qos = self.qos.is_express(is_express); + Self { qos, ..self } + } +} + +impl ValueBuilderTrait for GetBuilder<'_, '_, Handler> { + fn with_encoding(self, encoding: Encoding) -> Self { + let value = Some(self.value.unwrap_or_default().with_encoding(encoding)); + Self { value, ..self } + } + + fn with_payload(self, payload: IntoPayload) -> Self + where + IntoPayload: Into, + { + let value = Some(self.value.unwrap_or_default().with_payload(payload)); + Self { value, ..self } + } } impl<'a, 'b> GetBuilder<'a, 'b, DefaultHandler> { @@ -156,11 +216,14 @@ impl<'a, 'b> GetBuilder<'a, 'b, DefaultHandler> { scope, target, consolidation, + qos, destination, timeout, value, #[cfg(feature = "unstable")] attachment, + #[cfg(feature = "unstable")] + source_info, handler: _, } = self; GetBuilder { @@ -169,11 +232,14 @@ impl<'a, 'b> GetBuilder<'a, 'b, DefaultHandler> { scope, target, consolidation, + qos, destination, timeout, value, #[cfg(feature = "unstable")] attachment, + #[cfg(feature = "unstable")] + source_info, handler: callback, } } @@ -239,11 +305,14 @@ impl<'a, 'b> GetBuilder<'a, 'b, DefaultHandler> { scope, target, consolidation, + qos, destination, timeout, value, #[cfg(feature = "unstable")] attachment, + #[cfg(feature = "unstable")] + source_info, handler: _, } = self; GetBuilder { @@ -252,11 +321,14 @@ impl<'a, 'b> GetBuilder<'a, 'b, DefaultHandler> { scope, target, consolidation, + qos, destination, timeout, value, #[cfg(feature = "unstable")] attachment, + #[cfg(feature = "unstable")] + source_info, handler, } } @@ -315,29 +387,11 @@ impl<'a, 'b, Handler> GetBuilder<'a, 'b, Handler> { /// expressions that don't intersect with the query's. #[zenoh_macros::unstable] pub fn accept_replies(self, accept: ReplyKeyExpr) -> Self { - let Self { - session, - selector, - scope, - target, - consolidation, - destination, - timeout, - value, - attachment, - handler, - } = self; Self { - session, - selector: selector.and_then(|s| s.accept_any_keyexpr(accept == ReplyKeyExpr::Any)), - scope, - target, - consolidation, - destination, - timeout, - value, - attachment, - handler, + selector: self + .selector + .and_then(|s| s.accept_any_keyexpr(accept == ReplyKeyExpr::Any)), + ..self } } } @@ -382,11 +436,13 @@ where &self.scope?, self.target, self.consolidation, + self.qos.into(), self.destination, self.timeout, self.value, #[cfg(feature = "unstable")] self.attachment, + self.source_info, callback, ) .map(|_| receiver) diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 14e9d09068..a9b469a340 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -20,8 +20,8 @@ use crate::net::primitives::Primitives; use crate::prelude::*; use crate::sample::SourceInfo; use crate::sample_builder::{ - DeleteSampleBuilder, DeleteSampleBuilderTrait, PutSampleBuilder, PutSampleBuilderTrait, - QoSBuilderTrait, SampleBuilder, SampleBuilderTrait, + DeleteSampleBuilder, PutSampleBuilder, QoSBuilderTrait, SampleBuilder, SampleBuilderTrait, + TimestampBuilderTrait, ValueBuilderTrait, }; use crate::Id; use crate::SessionRef; @@ -238,7 +238,7 @@ impl<'a> ReplySampleBuilder<'a> { } } -impl SampleBuilderTrait for ReplySampleBuilder<'_> { +impl TimestampBuilderTrait for ReplySampleBuilder<'_> { fn with_timestamp_opt(self, timestamp: Option) -> Self { Self { sample_builder: self.sample_builder.with_timestamp_opt(timestamp), @@ -252,7 +252,9 @@ impl SampleBuilderTrait for ReplySampleBuilder<'_> { ..self } } +} +impl SampleBuilderTrait for ReplySampleBuilder<'_> { #[cfg(feature = "unstable")] fn with_source_info(self, source_info: SourceInfo) -> Self { Self { @@ -293,9 +295,9 @@ impl QoSBuilderTrait for ReplySampleBuilder<'_> { } } - fn express(self, is_express: bool) -> Self { + fn is_express(self, is_express: bool) -> Self { Self { - sample_builder: self.sample_builder.express(is_express), + sample_builder: self.sample_builder.is_express(is_express), ..self } } @@ -328,7 +330,7 @@ pub struct ReplyBuilder<'a> { sample_builder: PutSampleBuilder, } -impl SampleBuilderTrait for ReplyBuilder<'_> { +impl TimestampBuilderTrait for ReplyBuilder<'_> { fn with_timestamp_opt(self, timestamp: Option) -> Self { Self { sample_builder: self.sample_builder.with_timestamp_opt(timestamp), @@ -342,7 +344,9 @@ impl SampleBuilderTrait for ReplyBuilder<'_> { ..self } } +} +impl SampleBuilderTrait for ReplyBuilder<'_> { #[cfg(feature = "unstable")] fn with_source_info(self, source_info: SourceInfo) -> Self { Self { @@ -383,15 +387,15 @@ impl QoSBuilderTrait for ReplyBuilder<'_> { } } - fn express(self, is_express: bool) -> Self { + fn is_express(self, is_express: bool) -> Self { Self { - sample_builder: self.sample_builder.express(is_express), + sample_builder: self.sample_builder.is_express(is_express), ..self } } } -impl PutSampleBuilderTrait for ReplyBuilder<'_> { +impl ValueBuilderTrait for ReplyBuilder<'_> { fn with_encoding(self, encoding: Encoding) -> Self { Self { sample_builder: self.sample_builder.with_encoding(encoding), @@ -418,7 +422,7 @@ pub struct ReplyDelBuilder<'a> { sample_builder: DeleteSampleBuilder, } -impl SampleBuilderTrait for ReplyDelBuilder<'_> { +impl TimestampBuilderTrait for ReplyDelBuilder<'_> { fn with_timestamp_opt(self, timestamp: Option) -> Self { Self { sample_builder: self.sample_builder.with_timestamp_opt(timestamp), @@ -432,7 +436,9 @@ impl SampleBuilderTrait for ReplyDelBuilder<'_> { ..self } } +} +impl SampleBuilderTrait for ReplyDelBuilder<'_> { #[cfg(feature = "unstable")] fn with_source_info(self, source_info: SourceInfo) -> Self { Self { @@ -473,16 +479,14 @@ impl QoSBuilderTrait for ReplyDelBuilder<'_> { } } - fn express(self, is_express: bool) -> Self { + fn is_express(self, is_express: bool) -> Self { Self { - sample_builder: self.sample_builder.express(is_express), + sample_builder: self.sample_builder.is_express(is_express), ..self } } } -impl DeleteSampleBuilderTrait for ReplyDelBuilder<'_> {} - /// A builder returned by [`Query::reply_err()`](Query::reply_err). #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] #[derive(Debug)] diff --git a/zenoh/src/sample.rs b/zenoh/src/sample.rs index 1998f3e844..2dbeebe717 100644 --- a/zenoh/src/sample.rs +++ b/zenoh/src/sample.rs @@ -16,13 +16,16 @@ use crate::encoding::Encoding; use crate::payload::Payload; use crate::prelude::{KeyExpr, Value}; +use crate::sample_builder::{QoSBuilderTrait, ValueBuilderTrait}; use crate::time::Timestamp; use crate::Priority; #[zenoh_macros::unstable] use serde::Serialize; use std::{convert::TryFrom, fmt}; +use zenoh_core::{AsyncResolve, Resolvable, SyncResolve}; use zenoh_protocol::core::EntityGlobalId; -use zenoh_protocol::{core::CongestionControl, network::push::ext::QoSType, zenoh}; +use zenoh_protocol::network::declare::ext::QoSType; +use zenoh_protocol::{core::CongestionControl, zenoh}; pub type SourceSn = u64; @@ -566,6 +569,58 @@ pub struct QoS { inner: QoSType, } +#[derive(Debug)] +pub struct QoSBuilder(QoS); + +impl From for QoSBuilder { + fn from(qos: QoS) -> Self { + QoSBuilder(qos) + } +} + +impl From for QoS { + fn from(builder: QoSBuilder) -> Self { + builder.0 + } +} + +impl Resolvable for QoSBuilder { + type To = QoS; +} + +impl SyncResolve for QoSBuilder { + fn res_sync(self) -> ::To { + self.0 + } +} + +impl AsyncResolve for QoSBuilder { + type Future = futures::future::Ready; + fn res_async(self) -> Self::Future { + futures::future::ready(self.0) + } +} + +impl QoSBuilderTrait for QoSBuilder { + fn congestion_control(self, congestion_control: CongestionControl) -> Self { + let mut inner = self.0.inner; + inner.set_congestion_control(congestion_control); + Self(QoS { inner }) + } + + fn priority(self, priority: Priority) -> Self { + let mut inner = self.0.inner; + inner.set_priority(priority.into()); + Self(QoS { inner }) + } + + fn is_express(self, is_express: bool) -> Self { + let mut inner = self.0.inner; + inner.set_is_express(is_express); + Self(QoS { inner }) + } +} + impl QoS { /// Gets priority of the message. pub fn priority(&self) -> Priority { @@ -590,24 +645,6 @@ impl QoS { pub fn express(&self) -> bool { self.inner.is_express() } - - /// Sets priority value. - pub fn with_priority(mut self, priority: Priority) -> Self { - self.inner.set_priority(priority.into()); - self - } - - /// Sets congestion control value. - pub fn with_congestion_control(mut self, congestion_control: CongestionControl) -> Self { - self.inner.set_congestion_control(congestion_control); - self - } - - /// Sets express flag vlaue. - pub fn with_express(mut self, is_express: bool) -> Self { - self.inner.set_is_express(is_express); - self - } } impl From for QoS { diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index 7e38e84afd..5aca7ff1da 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -14,6 +14,7 @@ use crate::sample::Attachment; use crate::sample::QoS; +use crate::sample::QoSBuilder; use crate::sample::SourceInfo; use crate::Encoding; use crate::KeyExpr; @@ -36,14 +37,17 @@ pub trait QoSBuilderTrait { /// Change the `express` policy to apply when routing the data. /// When express is set to `true`, then the message will not be batched. /// This usually has a positive impact on latency but negative impact on throughput. - fn express(self, is_express: bool) -> Self; + fn is_express(self, is_express: bool) -> Self; } -pub trait SampleBuilderTrait { +pub trait TimestampBuilderTrait { /// Sets of clears timestamp fn with_timestamp_opt(self, timestamp: Option) -> Self; /// Sets timestamp fn with_timestamp(self, timestamp: Timestamp) -> Self; +} + +pub trait SampleBuilderTrait { /// Attach source information #[zenoh_macros::unstable] fn with_source_info(self, source_info: SourceInfo) -> Self; @@ -55,16 +59,15 @@ pub trait SampleBuilderTrait { fn with_attachment(self, attachment: Attachment) -> Self; } -pub trait PutSampleBuilderTrait: SampleBuilderTrait { +pub trait ValueBuilderTrait { /// Set the [`Encoding`] fn with_encoding(self, encoding: Encoding) -> Self; + /// Sets the payload fn with_payload(self, payload: IntoPayload) -> Self where IntoPayload: Into; } -pub trait DeleteSampleBuilderTrait: SampleBuilderTrait {} - #[derive(Debug)] pub struct SampleBuilder(Sample); @@ -98,7 +101,7 @@ impl SampleBuilder { } } -impl SampleBuilderTrait for SampleBuilder { +impl TimestampBuilderTrait for SampleBuilder { fn with_timestamp_opt(self, timestamp: Option) -> Self { Self(Sample { timestamp, @@ -109,7 +112,9 @@ impl SampleBuilderTrait for SampleBuilder { fn with_timestamp(self, timestamp: Timestamp) -> Self { self.with_timestamp_opt(Some(timestamp)) } +} +impl SampleBuilderTrait for SampleBuilder { #[zenoh_macros::unstable] fn with_source_info(self, source_info: SourceInfo) -> Self { Self(Sample { @@ -134,22 +139,19 @@ impl SampleBuilderTrait for SampleBuilder { impl QoSBuilderTrait for SampleBuilder { fn congestion_control(self, congestion_control: CongestionControl) -> Self { - Self(Sample { - qos: self.0.qos.with_congestion_control(congestion_control), - ..self.0 - }) + let qos: QoSBuilder = self.0.qos.into(); + let qos = qos.congestion_control(congestion_control).res_sync(); + Self(Sample { qos, ..self.0 }) } fn priority(self, priority: Priority) -> Self { - Self(Sample { - qos: self.0.qos.with_priority(priority), - ..self.0 - }) + let qos: QoSBuilder = self.0.qos.into(); + let qos = qos.priority(priority).res_sync(); + Self(Sample { qos, ..self.0 }) } - fn express(self, is_express: bool) -> Self { - Self(Sample { - qos: self.0.qos.with_express(is_express), - ..self.0 - }) + fn is_express(self, is_express: bool) -> Self { + let qos: QoSBuilder = self.0.qos.into(); + let qos = qos.is_express(is_express).res_sync(); + Self(Sample { qos, ..self.0 }) } } @@ -197,13 +199,16 @@ impl PutSampleBuilder { } } -impl SampleBuilderTrait for PutSampleBuilder { +impl TimestampBuilderTrait for PutSampleBuilder { fn with_timestamp(self, timestamp: Timestamp) -> Self { Self(self.0.with_timestamp(timestamp)) } fn with_timestamp_opt(self, timestamp: Option) -> Self { Self(self.0.with_timestamp_opt(timestamp)) } +} + +impl SampleBuilderTrait for PutSampleBuilder { #[zenoh_macros::unstable] fn with_source_info(self, source_info: SourceInfo) -> Self { Self(self.0.with_source_info(source_info)) @@ -225,12 +230,12 @@ impl QoSBuilderTrait for PutSampleBuilder { fn priority(self, priority: Priority) -> Self { Self(self.0.priority(priority)) } - fn express(self, is_express: bool) -> Self { - Self(self.0.express(is_express)) + fn is_express(self, is_express: bool) -> Self { + Self(self.0.is_express(is_express)) } } -impl PutSampleBuilderTrait for PutSampleBuilder { +impl ValueBuilderTrait for PutSampleBuilder { fn with_encoding(self, encoding: Encoding) -> Self { Self(SampleBuilder(Sample { encoding, @@ -291,13 +296,16 @@ impl DeleteSampleBuilder { } } -impl SampleBuilderTrait for DeleteSampleBuilder { +impl TimestampBuilderTrait for DeleteSampleBuilder { fn with_timestamp(self, timestamp: Timestamp) -> Self { Self(self.0.with_timestamp(timestamp)) } fn with_timestamp_opt(self, timestamp: Option) -> Self { Self(self.0.with_timestamp_opt(timestamp)) } +} + +impl SampleBuilderTrait for DeleteSampleBuilder { #[zenoh_macros::unstable] fn with_source_info(self, source_info: SourceInfo) -> Self { Self(self.0.with_source_info(source_info)) @@ -319,13 +327,11 @@ impl QoSBuilderTrait for DeleteSampleBuilder { fn priority(self, priority: Priority) -> Self { Self(self.0.priority(priority)) } - fn express(self, is_express: bool) -> Self { - Self(self.0.express(is_express)) + fn is_express(self, is_express: bool) -> Self { + Self(self.0.is_express(is_express)) } } -impl DeleteSampleBuilderTrait for DeleteSampleBuilder {} - impl From for SampleBuilder { fn from(sample: Sample) -> Self { SampleBuilder(sample) diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index ffe7036050..5b80adb0e5 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -784,18 +784,21 @@ impl Session { let conf = self.runtime.config().lock(); Duration::from_millis(unwrap_or_default!(conf.queries_default_timeout())) }; + let qos: QoS = request::ext::QoSType::REQUEST.into(); GetBuilder { session: self, selector, scope: Ok(None), target: QueryTarget::DEFAULT, consolidation: QueryConsolidation::DEFAULT, + qos: qos.into(), destination: Locality::default(), timeout, value: None, #[cfg(feature = "unstable")] attachment: None, handler: DefaultHandler, + source_info: SourceInfo::empty(), } } } @@ -1567,10 +1570,12 @@ impl Session { scope: &Option>, target: QueryTarget, consolidation: QueryConsolidation, + qos: QoS, destination: Locality, timeout: Duration, value: Option, #[cfg(feature = "unstable")] attachment: Option, + #[cfg(feature = "unstable")] source: SourceInfo, callback: Callback<'static, Reply>, ) -> ZResult<()> { log::trace!("get({}, {:?}, {:?})", selector, target, consolidation); @@ -1649,7 +1654,7 @@ impl Session { primitives.send_request(Request { id: qid, wire_expr: wexpr.clone(), - ext_qos: request::ext::QoSType::REQUEST, + ext_qos: qos.into(), ext_tstamp: None, ext_nodeid: request::ext::NodeIdType::DEFAULT, ext_target: target, @@ -1658,7 +1663,7 @@ impl Session { payload: RequestBody::Query(zenoh_protocol::zenoh::Query { consolidation, parameters: selector.parameters().to_string(), - ext_sinfo: None, + ext_sinfo: source.into(), ext_body: value.as_ref().map(|v| query::ext::QueryBodyType { #[cfg(feature = "shared-memory")] ext_shm: None, diff --git a/zenoh/src/value.rs b/zenoh/src/value.rs index 128f0ff605..2d98cbf398 100644 --- a/zenoh/src/value.rs +++ b/zenoh/src/value.rs @@ -13,7 +13,7 @@ // //! Value primitives. -use crate::{encoding::Encoding, payload::Payload}; +use crate::{encoding::Encoding, payload::Payload, sample_builder::ValueBuilderTrait}; /// A zenoh [`Value`] contains a `payload` and an [`Encoding`] that indicates how the [`Payload`] should be interpreted. #[non_exhaustive] @@ -36,7 +36,6 @@ impl Value { encoding: Encoding::default(), } } - /// Creates an empty [`Value`]. pub const fn empty() -> Self { Value { @@ -44,15 +43,20 @@ impl Value { encoding: Encoding::default(), } } +} - /// Sets the encoding of this [`Value`]`. - #[inline(always)] - pub fn with_encoding(mut self, encoding: IntoEncoding) -> Self +impl ValueBuilderTrait for Value { + fn with_encoding(self, encoding: Encoding) -> Self { + Self { encoding, ..self } + } + fn with_payload(self, payload: IntoPayload) -> Self where - IntoEncoding: Into, + IntoPayload: Into, { - self.encoding = encoding.into(); - self + Self { + payload: payload.into(), + ..self + } } } @@ -67,3 +71,9 @@ where } } } + +impl Default for Value { + fn default() -> Self { + Value::empty() + } +} From 0bce160e13947dacb6ed110b571578a93b70b8ae Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 11:23:52 +0100 Subject: [PATCH 32/63] restored "express" name --- examples/examples/z_ping.rs | 2 +- examples/examples/z_pong.rs | 2 +- examples/examples/z_pub_thr.rs | 2 +- zenoh/src/publication.rs | 10 +++++----- zenoh/src/query.rs | 4 ++-- zenoh/src/queryable.rs | 12 ++++++------ zenoh/src/sample.rs | 2 +- zenoh/src/sample_builder.rs | 14 +++++++------- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/examples/examples/z_ping.rs b/examples/examples/z_ping.rs index 79a1e16514..b40afc1f53 100644 --- a/examples/examples/z_ping.rs +++ b/examples/examples/z_ping.rs @@ -36,7 +36,7 @@ fn main() { let publisher = session .declare_publisher(key_expr_ping) .congestion_control(CongestionControl::Block) - .is_express(express) + .express(express) .res() .unwrap(); diff --git a/examples/examples/z_pong.rs b/examples/examples/z_pong.rs index a629cce3cf..0003958b5d 100644 --- a/examples/examples/z_pong.rs +++ b/examples/examples/z_pong.rs @@ -35,7 +35,7 @@ fn main() { let publisher = session .declare_publisher(key_expr_pong) .congestion_control(CongestionControl::Block) - .is_express(express) + .express(express) .res() .unwrap(); diff --git a/examples/examples/z_pub_thr.rs b/examples/examples/z_pub_thr.rs index c9b9fe64f3..7e7c1ac9b5 100644 --- a/examples/examples/z_pub_thr.rs +++ b/examples/examples/z_pub_thr.rs @@ -42,7 +42,7 @@ fn main() { .declare_publisher("test/thr") .congestion_control(CongestionControl::Block) .priority(prio) - .is_express(args.express) + .express(args.express) .res() .unwrap(); diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index 81a12133ed..e60e40d295 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -114,9 +114,9 @@ impl QoSBuilderTrait for PutBuilder<'_, '_> { } } #[inline] - fn is_express(self, is_express: bool) -> Self { + fn express(self, is_express: bool) -> Self { Self { - publisher: self.publisher.is_express(is_express), + publisher: self.publisher.express(is_express), ..self } } @@ -138,9 +138,9 @@ impl QoSBuilderTrait for DeleteBuilder<'_, '_> { } } #[inline] - fn is_express(self, is_express: bool) -> Self { + fn express(self, is_express: bool) -> Self { Self { - publisher: self.publisher.is_express(is_express), + publisher: self.publisher.express(is_express), ..self } } @@ -1016,7 +1016,7 @@ impl QoSBuilderTrait for PublisherBuilder<'_, '_> { /// When express is set to `true`, then the message will not be batched. /// This usually has a positive impact on latency but negative impact on throughput. #[inline] - fn is_express(self, is_express: bool) -> Self { + fn express(self, is_express: bool) -> Self { Self { is_express, ..self } } } diff --git a/zenoh/src/query.rs b/zenoh/src/query.rs index 6a0c4b1933..db17715a89 100644 --- a/zenoh/src/query.rs +++ b/zenoh/src/query.rs @@ -167,8 +167,8 @@ impl QoSBuilderTrait for GetBuilder<'_, '_, DefaultHandler> { Self { qos, ..self } } - fn is_express(self, is_express: bool) -> Self { - let qos = self.qos.is_express(is_express); + fn express(self, is_express: bool) -> Self { + let qos = self.qos.express(is_express); Self { qos, ..self } } } diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index a9b469a340..d9327415f5 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -295,9 +295,9 @@ impl QoSBuilderTrait for ReplySampleBuilder<'_> { } } - fn is_express(self, is_express: bool) -> Self { + fn express(self, is_express: bool) -> Self { Self { - sample_builder: self.sample_builder.is_express(is_express), + sample_builder: self.sample_builder.express(is_express), ..self } } @@ -387,9 +387,9 @@ impl QoSBuilderTrait for ReplyBuilder<'_> { } } - fn is_express(self, is_express: bool) -> Self { + fn express(self, is_express: bool) -> Self { Self { - sample_builder: self.sample_builder.is_express(is_express), + sample_builder: self.sample_builder.express(is_express), ..self } } @@ -479,9 +479,9 @@ impl QoSBuilderTrait for ReplyDelBuilder<'_> { } } - fn is_express(self, is_express: bool) -> Self { + fn express(self, is_express: bool) -> Self { Self { - sample_builder: self.sample_builder.is_express(is_express), + sample_builder: self.sample_builder.express(is_express), ..self } } diff --git a/zenoh/src/sample.rs b/zenoh/src/sample.rs index 2dbeebe717..d774e5e007 100644 --- a/zenoh/src/sample.rs +++ b/zenoh/src/sample.rs @@ -614,7 +614,7 @@ impl QoSBuilderTrait for QoSBuilder { Self(QoS { inner }) } - fn is_express(self, is_express: bool) -> Self { + fn express(self, is_express: bool) -> Self { let mut inner = self.0.inner; inner.set_is_express(is_express); Self(QoS { inner }) diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index 5aca7ff1da..b13bfce346 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -37,7 +37,7 @@ pub trait QoSBuilderTrait { /// Change the `express` policy to apply when routing the data. /// When express is set to `true`, then the message will not be batched. /// This usually has a positive impact on latency but negative impact on throughput. - fn is_express(self, is_express: bool) -> Self; + fn express(self, is_express: bool) -> Self; } pub trait TimestampBuilderTrait { @@ -148,9 +148,9 @@ impl QoSBuilderTrait for SampleBuilder { let qos = qos.priority(priority).res_sync(); Self(Sample { qos, ..self.0 }) } - fn is_express(self, is_express: bool) -> Self { + fn express(self, is_express: bool) -> Self { let qos: QoSBuilder = self.0.qos.into(); - let qos = qos.is_express(is_express).res_sync(); + let qos = qos.express(is_express).res_sync(); Self(Sample { qos, ..self.0 }) } } @@ -230,8 +230,8 @@ impl QoSBuilderTrait for PutSampleBuilder { fn priority(self, priority: Priority) -> Self { Self(self.0.priority(priority)) } - fn is_express(self, is_express: bool) -> Self { - Self(self.0.is_express(is_express)) + fn express(self, is_express: bool) -> Self { + Self(self.0.express(is_express)) } } @@ -327,8 +327,8 @@ impl QoSBuilderTrait for DeleteSampleBuilder { fn priority(self, priority: Priority) -> Self { Self(self.0.priority(priority)) } - fn is_express(self, is_express: bool) -> Self { - Self(self.0.is_express(is_express)) + fn express(self, is_express: bool) -> Self { + Self(self.0.express(is_express)) } } From 3620c3a7d057c312ff8354bffef40f79424aee80 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 11:32:11 +0100 Subject: [PATCH 33/63] removed 'timestamp_opt' --- zenoh/src/publication.rs | 34 ++++------------------------------ zenoh/src/queryable.rs | 27 +++------------------------ zenoh/src/sample_builder.rs | 20 ++++---------------- 3 files changed, 11 insertions(+), 70 deletions(-) diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index e60e40d295..f8a42077b9 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -147,15 +147,9 @@ impl QoSBuilderTrait for DeleteBuilder<'_, '_> { } impl TimestampBuilderTrait for PutBuilder<'_, '_> { - fn with_timestamp_opt(self, timestamp: Option) -> Self { + fn with_timestamp(self, timestamp: Option) -> Self { Self { timestamp, ..self } } - fn with_timestamp(self, timestamp: uhlc::Timestamp) -> Self { - Self { - timestamp: Some(timestamp), - ..self - } - } } impl SampleBuilderTrait for PutBuilder<'_, '_> { @@ -180,15 +174,9 @@ impl SampleBuilderTrait for PutBuilder<'_, '_> { } impl TimestampBuilderTrait for DeleteBuilder<'_, '_> { - fn with_timestamp_opt(self, timestamp: Option) -> Self { + fn with_timestamp(self, timestamp: Option) -> Self { Self { timestamp, ..self } } - fn with_timestamp(self, timestamp: uhlc::Timestamp) -> Self { - Self { - timestamp: Some(timestamp), - ..self - } - } } impl SampleBuilderTrait for DeleteBuilder<'_, '_> { @@ -766,16 +754,9 @@ pub struct DeletePublication<'a> { } impl TimestampBuilderTrait for PutPublication<'_> { - fn with_timestamp_opt(self, timestamp: Option) -> Self { + fn with_timestamp(self, timestamp: Option) -> Self { Self { timestamp, ..self } } - - fn with_timestamp(self, timestamp: uhlc::Timestamp) -> Self { - Self { - timestamp: Some(timestamp), - ..self - } - } } impl SampleBuilderTrait for PutPublication<'_> { @@ -818,16 +799,9 @@ impl ValueBuilderTrait for PutPublication<'_> { } impl TimestampBuilderTrait for DeletePublication<'_> { - fn with_timestamp_opt(self, timestamp: Option) -> Self { + fn with_timestamp(self, timestamp: Option) -> Self { Self { timestamp, ..self } } - - fn with_timestamp(self, timestamp: uhlc::Timestamp) -> Self { - Self { - timestamp: Some(timestamp), - ..self - } - } } impl SampleBuilderTrait for DeletePublication<'_> { diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index d9327415f5..625ae6f25f 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -239,14 +239,7 @@ impl<'a> ReplySampleBuilder<'a> { } impl TimestampBuilderTrait for ReplySampleBuilder<'_> { - fn with_timestamp_opt(self, timestamp: Option) -> Self { - Self { - sample_builder: self.sample_builder.with_timestamp_opt(timestamp), - ..self - } - } - - fn with_timestamp(self, timestamp: Timestamp) -> Self { + fn with_timestamp(self, timestamp: Option) -> Self { Self { sample_builder: self.sample_builder.with_timestamp(timestamp), ..self @@ -331,14 +324,7 @@ pub struct ReplyBuilder<'a> { } impl TimestampBuilderTrait for ReplyBuilder<'_> { - fn with_timestamp_opt(self, timestamp: Option) -> Self { - Self { - sample_builder: self.sample_builder.with_timestamp_opt(timestamp), - ..self - } - } - - fn with_timestamp(self, timestamp: Timestamp) -> Self { + fn with_timestamp(self, timestamp: Option) -> Self { Self { sample_builder: self.sample_builder.with_timestamp(timestamp), ..self @@ -423,14 +409,7 @@ pub struct ReplyDelBuilder<'a> { } impl TimestampBuilderTrait for ReplyDelBuilder<'_> { - fn with_timestamp_opt(self, timestamp: Option) -> Self { - Self { - sample_builder: self.sample_builder.with_timestamp_opt(timestamp), - ..self - } - } - - fn with_timestamp(self, timestamp: Timestamp) -> Self { + fn with_timestamp(self, timestamp: Option) -> Self { Self { sample_builder: self.sample_builder.with_timestamp(timestamp), ..self diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index b13bfce346..990586ca0f 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -42,9 +42,7 @@ pub trait QoSBuilderTrait { pub trait TimestampBuilderTrait { /// Sets of clears timestamp - fn with_timestamp_opt(self, timestamp: Option) -> Self; - /// Sets timestamp - fn with_timestamp(self, timestamp: Timestamp) -> Self; + fn with_timestamp(self, timestamp: Option) -> Self; } pub trait SampleBuilderTrait { @@ -102,16 +100,12 @@ impl SampleBuilder { } impl TimestampBuilderTrait for SampleBuilder { - fn with_timestamp_opt(self, timestamp: Option) -> Self { + fn with_timestamp(self, timestamp: Option) -> Self { Self(Sample { timestamp, ..self.0 }) } - - fn with_timestamp(self, timestamp: Timestamp) -> Self { - self.with_timestamp_opt(Some(timestamp)) - } } impl SampleBuilderTrait for SampleBuilder { @@ -200,12 +194,9 @@ impl PutSampleBuilder { } impl TimestampBuilderTrait for PutSampleBuilder { - fn with_timestamp(self, timestamp: Timestamp) -> Self { + fn with_timestamp(self, timestamp: Option) -> Self { Self(self.0.with_timestamp(timestamp)) } - fn with_timestamp_opt(self, timestamp: Option) -> Self { - Self(self.0.with_timestamp_opt(timestamp)) - } } impl SampleBuilderTrait for PutSampleBuilder { @@ -297,12 +288,9 @@ impl DeleteSampleBuilder { } impl TimestampBuilderTrait for DeleteSampleBuilder { - fn with_timestamp(self, timestamp: Timestamp) -> Self { + fn with_timestamp(self, timestamp: Option) -> Self { Self(self.0.with_timestamp(timestamp)) } - fn with_timestamp_opt(self, timestamp: Option) -> Self { - Self(self.0.with_timestamp_opt(timestamp)) - } } impl SampleBuilderTrait for DeleteSampleBuilder { From aafd2a4761b8b4df5089d19ef74f71bfe28aa644 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 13:10:32 +0100 Subject: [PATCH 34/63] with removed, into> added --- examples/examples/z_pub.rs | 2 +- .../src/replica/align_queryable.rs | 2 +- .../src/replica/aligner.rs | 2 +- .../src/replica/storage.rs | 10 +-- zenoh-ext/src/querying_subscriber.rs | 2 +- zenoh/src/publication.rs | 70 +++++++++---------- zenoh/src/query.rs | 11 +-- zenoh/src/queryable.rs | 60 +++++----------- zenoh/src/sample.rs | 11 +++ zenoh/src/sample_builder.rs | 58 ++++++--------- zenoh/tests/attachments.rs | 10 +-- 11 files changed, 99 insertions(+), 139 deletions(-) diff --git a/examples/examples/z_pub.rs b/examples/examples/z_pub.rs index d22d4d55ee..416ff31f46 100644 --- a/examples/examples/z_pub.rs +++ b/examples/examples/z_pub.rs @@ -39,7 +39,7 @@ async fn main() { println!("Putting Data ('{}': '{}')...", &key_expr, buf); let mut put = publisher.put(buf); if let Some(attachment) = &attachment { - put = put.with_attachment( + put = put.attachment( attachment .split('&') .map(|pair| split_once(pair, '=')) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs b/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs index e5c4840666..973fb89abe 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs @@ -130,7 +130,7 @@ impl AlignQueryable { query .reply(k, v.payload) .with_encoding(v.encoding) - .with_timestamp(ts) + .timestamp(ts) .res() .await .unwrap(); diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs index 4119a941e5..9d5257e53f 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs @@ -112,7 +112,7 @@ impl Aligner { } = value; let sample = PutSampleBuilder::new(key, payload) .with_encoding(encoding) - .with_timestamp(ts) + .timestamp(ts) .res_sync(); log::debug!("[ALIGNER] Adding {:?} to storage", sample); self.tx_sample.send_async(sample).await.unwrap_or_else(|e| { diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 69c973de39..de76ade51d 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -239,7 +239,7 @@ impl StorageService { } }; let timestamp = sample.timestamp().cloned().unwrap_or(new_reception_timestamp()); - let sample = SampleBuilder::from(sample).with_timestamp(timestamp).res_sync(); + let sample = SampleBuilder::from(sample).timestamp(timestamp).res_sync(); self.process_sample(sample).await; }, // on query on key_expr @@ -316,14 +316,14 @@ impl StorageService { } = data.value; PutSampleBuilder::new(KeyExpr::from(k.clone()), payload) .with_encoding(encoding) - .with_timestamp(data.timestamp) + .timestamp(data.timestamp) .res_sync() } Some(Update { kind: SampleKind::Delete, data, }) => DeleteSampleBuilder::new(KeyExpr::from(k.clone())) - .with_timestamp(data.timestamp) + .timestamp(data.timestamp) .res_sync(), None => SampleBuilder::from(sample.clone()) .keyexpr(k.clone()) @@ -533,7 +533,7 @@ impl StorageService { if let Err(e) = q .reply(key.clone(), payload) .with_encoding(encoding) - .with_timestamp(entry.timestamp) + .timestamp(entry.timestamp) .res_async() .await { @@ -568,7 +568,7 @@ impl StorageService { if let Err(e) = q .reply(q.key_expr().clone(), payload) .with_encoding(encoding) - .with_timestamp(entry.timestamp) + .timestamp(entry.timestamp) .res_async() .await { diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index e6b269cfbd..52a4263396 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -665,7 +665,7 @@ impl<'a, Receiver> FetchingSubscriber<'a, Receiver> { // ensure the sample has a timestamp, thus it will always be sorted into the MergeQueue // after any timestamped Sample possibly coming from a fetch reply. let timestamp = s.timestamp().cloned().unwrap_or(new_reception_timestamp()); - let s = SampleBuilder::from(s).with_timestamp(timestamp).res_sync(); + let s = SampleBuilder::from(s).timestamp(timestamp).res_sync(); state.merge_queue.push(s); } } diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index f8a42077b9..cd68530bf7 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -147,54 +147,52 @@ impl QoSBuilderTrait for DeleteBuilder<'_, '_> { } impl TimestampBuilderTrait for PutBuilder<'_, '_> { - fn with_timestamp(self, timestamp: Option) -> Self { - Self { timestamp, ..self } + fn timestamp>>(self, timestamp: T) -> Self { + Self { + timestamp: timestamp.into(), + ..self + } } } impl SampleBuilderTrait for PutBuilder<'_, '_> { #[cfg(feature = "unstable")] - fn with_source_info(self, source_info: SourceInfo) -> Self { + fn source_info(self, source_info: SourceInfo) -> Self { Self { source_info, ..self } } #[cfg(feature = "unstable")] - fn with_attachment_opt(self, attachment: Option) -> Self { - Self { attachment, ..self } - } - #[cfg(feature = "unstable")] - fn with_attachment(self, attachment: Attachment) -> Self { + fn attachment>>(self, attachment: T) -> Self { Self { - attachment: Some(attachment), + attachment: attachment.into(), ..self } } } impl TimestampBuilderTrait for DeleteBuilder<'_, '_> { - fn with_timestamp(self, timestamp: Option) -> Self { - Self { timestamp, ..self } + fn timestamp>>(self, timestamp: T) -> Self { + Self { + timestamp: timestamp.into(), + ..self + } } } impl SampleBuilderTrait for DeleteBuilder<'_, '_> { #[cfg(feature = "unstable")] - fn with_source_info(self, source_info: SourceInfo) -> Self { + fn source_info(self, source_info: SourceInfo) -> Self { Self { source_info, ..self } } #[cfg(feature = "unstable")] - fn with_attachment_opt(self, attachment: Option) -> Self { - Self { attachment, ..self } - } - #[cfg(feature = "unstable")] - fn with_attachment(self, attachment: Attachment) -> Self { + fn attachment>>(self, attachment: T) -> Self { Self { - attachment: Some(attachment), + attachment: attachment.into(), ..self } } @@ -754,14 +752,17 @@ pub struct DeletePublication<'a> { } impl TimestampBuilderTrait for PutPublication<'_> { - fn with_timestamp(self, timestamp: Option) -> Self { - Self { timestamp, ..self } + fn timestamp>>(self, timestamp: T) -> Self { + Self { + timestamp: timestamp.into(), + ..self + } } } impl SampleBuilderTrait for PutPublication<'_> { #[cfg(feature = "unstable")] - fn with_source_info(self, source_info: SourceInfo) -> Self { + fn source_info(self, source_info: SourceInfo) -> Self { Self { source_info, ..self @@ -769,14 +770,9 @@ impl SampleBuilderTrait for PutPublication<'_> { } #[cfg(feature = "unstable")] - fn with_attachment_opt(self, attachment: Option) -> Self { - Self { attachment, ..self } - } - - #[cfg(feature = "unstable")] - fn with_attachment(self, attachment: Attachment) -> Self { + fn attachment>>(self, attachment: T) -> Self { Self { - attachment: Some(attachment), + attachment: attachment.into(), ..self } } @@ -799,14 +795,17 @@ impl ValueBuilderTrait for PutPublication<'_> { } impl TimestampBuilderTrait for DeletePublication<'_> { - fn with_timestamp(self, timestamp: Option) -> Self { - Self { timestamp, ..self } + fn timestamp>>(self, timestamp: T) -> Self { + Self { + timestamp: timestamp.into(), + ..self + } } } impl SampleBuilderTrait for DeletePublication<'_> { #[cfg(feature = "unstable")] - fn with_source_info(self, source_info: SourceInfo) -> Self { + fn source_info(self, source_info: SourceInfo) -> Self { Self { source_info, ..self @@ -814,14 +813,9 @@ impl SampleBuilderTrait for DeletePublication<'_> { } #[cfg(feature = "unstable")] - fn with_attachment_opt(self, attachment: Option) -> Self { - Self { attachment, ..self } - } - - #[cfg(feature = "unstable")] - fn with_attachment(self, attachment: Attachment) -> Self { + fn attachment>>(self, attachment: T) -> Self { Self { - attachment: Some(attachment), + attachment: attachment.into(), ..self } } diff --git a/zenoh/src/query.rs b/zenoh/src/query.rs index db17715a89..2d4e5e1ee3 100644 --- a/zenoh/src/query.rs +++ b/zenoh/src/query.rs @@ -135,7 +135,7 @@ pub struct GetBuilder<'a, 'b, Handler> { impl SampleBuilderTrait for GetBuilder<'_, '_, Handler> { #[cfg(feature = "unstable")] - fn with_source_info(self, source_info: SourceInfo) -> Self { + fn source_info(self, source_info: SourceInfo) -> Self { Self { source_info, ..self @@ -143,14 +143,9 @@ impl SampleBuilderTrait for GetBuilder<'_, '_, Handler> { } #[cfg(feature = "unstable")] - fn with_attachment_opt(self, attachment: Option) -> Self { - Self { attachment, ..self } - } - - #[cfg(feature = "unstable")] - fn with_attachment(self, attachment: Attachment) -> Self { + fn attachment>>(self, attachment: T) -> Self { Self { - attachment: Some(attachment), + attachment: attachment.into(), ..self } } diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 625ae6f25f..66cb34459b 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -239,9 +239,9 @@ impl<'a> ReplySampleBuilder<'a> { } impl TimestampBuilderTrait for ReplySampleBuilder<'_> { - fn with_timestamp(self, timestamp: Option) -> Self { + fn timestamp>>(self, timestamp: T) -> Self { Self { - sample_builder: self.sample_builder.with_timestamp(timestamp), + sample_builder: self.sample_builder.timestamp(timestamp), ..self } } @@ -249,25 +249,17 @@ impl TimestampBuilderTrait for ReplySampleBuilder<'_> { impl SampleBuilderTrait for ReplySampleBuilder<'_> { #[cfg(feature = "unstable")] - fn with_source_info(self, source_info: SourceInfo) -> Self { + fn source_info(self, source_info: SourceInfo) -> Self { Self { - sample_builder: self.sample_builder.with_source_info(source_info), + sample_builder: self.sample_builder.source_info(source_info), ..self } } #[cfg(feature = "unstable")] - fn with_attachment_opt(self, attachment: Option) -> Self { + fn attachment>>(self, attachment: T) -> Self { Self { - sample_builder: self.sample_builder.with_attachment_opt(attachment), - ..self - } - } - - #[cfg(feature = "unstable")] - fn with_attachment(self, attachment: Attachment) -> Self { - Self { - sample_builder: self.sample_builder.with_attachment(attachment), + sample_builder: self.sample_builder.attachment(attachment), ..self } } @@ -324,9 +316,9 @@ pub struct ReplyBuilder<'a> { } impl TimestampBuilderTrait for ReplyBuilder<'_> { - fn with_timestamp(self, timestamp: Option) -> Self { + fn timestamp>>(self, timestamp: T) -> Self { Self { - sample_builder: self.sample_builder.with_timestamp(timestamp), + sample_builder: self.sample_builder.timestamp(timestamp), ..self } } @@ -334,25 +326,17 @@ impl TimestampBuilderTrait for ReplyBuilder<'_> { impl SampleBuilderTrait for ReplyBuilder<'_> { #[cfg(feature = "unstable")] - fn with_source_info(self, source_info: SourceInfo) -> Self { - Self { - sample_builder: self.sample_builder.with_source_info(source_info), - ..self - } - } - - #[cfg(feature = "unstable")] - fn with_attachment_opt(self, attachment: Option) -> Self { + fn source_info(self, source_info: SourceInfo) -> Self { Self { - sample_builder: self.sample_builder.with_attachment_opt(attachment), + sample_builder: self.sample_builder.source_info(source_info), ..self } } #[cfg(feature = "unstable")] - fn with_attachment(self, attachment: Attachment) -> Self { + fn attachment>>(self, attachment: T) -> Self { Self { - sample_builder: self.sample_builder.with_attachment(attachment), + sample_builder: self.sample_builder.attachment(attachment), ..self } } @@ -409,9 +393,9 @@ pub struct ReplyDelBuilder<'a> { } impl TimestampBuilderTrait for ReplyDelBuilder<'_> { - fn with_timestamp(self, timestamp: Option) -> Self { + fn timestamp>>(self, timestamp: T) -> Self { Self { - sample_builder: self.sample_builder.with_timestamp(timestamp), + sample_builder: self.sample_builder.timestamp(timestamp), ..self } } @@ -419,25 +403,17 @@ impl TimestampBuilderTrait for ReplyDelBuilder<'_> { impl SampleBuilderTrait for ReplyDelBuilder<'_> { #[cfg(feature = "unstable")] - fn with_source_info(self, source_info: SourceInfo) -> Self { - Self { - sample_builder: self.sample_builder.with_source_info(source_info), - ..self - } - } - - #[cfg(feature = "unstable")] - fn with_attachment_opt(self, attachment: Option) -> Self { + fn source_info(self, source_info: SourceInfo) -> Self { Self { - sample_builder: self.sample_builder.with_attachment_opt(attachment), + sample_builder: self.sample_builder.source_info(source_info), ..self } } #[cfg(feature = "unstable")] - fn with_attachment(self, attachment: Attachment) -> Self { + fn attachment>>(self, attachment: T) -> Self { Self { - sample_builder: self.sample_builder.with_attachment(attachment), + sample_builder: self.sample_builder.attachment(attachment), ..self } } diff --git a/zenoh/src/sample.rs b/zenoh/src/sample.rs index d774e5e007..163ae2090a 100644 --- a/zenoh/src/sample.rs +++ b/zenoh/src/sample.rs @@ -263,6 +263,17 @@ mod attachment { } } } + #[zenoh_macros::unstable] + impl From for Option { + fn from(value: AttachmentBuilder) -> Self { + if value.inner.is_empty() { + None + } else { + Some(value.into()) + } + } + } + #[zenoh_macros::unstable] #[derive(Clone)] pub struct Attachment { diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index 990586ca0f..2d7277506d 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -41,20 +41,17 @@ pub trait QoSBuilderTrait { } pub trait TimestampBuilderTrait { - /// Sets of clears timestamp - fn with_timestamp(self, timestamp: Option) -> Self; + /// Sets of clears timestamp + fn timestamp>>(self, timestamp: T) -> Self; } pub trait SampleBuilderTrait { /// Attach source information #[zenoh_macros::unstable] - fn with_source_info(self, source_info: SourceInfo) -> Self; - /// Attach or remove user-provided data in key-value format - #[zenoh_macros::unstable] - fn with_attachment_opt(self, attachment: Option) -> Self; + fn source_info(self, source_info: SourceInfo) -> Self; /// Attach user-provided data in key-value format #[zenoh_macros::unstable] - fn with_attachment(self, attachment: Attachment) -> Self; + fn attachment>>(self, attachment: T) -> Self; } pub trait ValueBuilderTrait { @@ -100,9 +97,9 @@ impl SampleBuilder { } impl TimestampBuilderTrait for SampleBuilder { - fn with_timestamp(self, timestamp: Option) -> Self { + fn timestamp>>(self, timestamp: T) -> Self { Self(Sample { - timestamp, + timestamp: timestamp.into(), ..self.0 }) } @@ -110,7 +107,7 @@ impl TimestampBuilderTrait for SampleBuilder { impl SampleBuilderTrait for SampleBuilder { #[zenoh_macros::unstable] - fn with_source_info(self, source_info: SourceInfo) -> Self { + fn source_info(self, source_info: SourceInfo) -> Self { Self(Sample { source_info, ..self.0 @@ -118,17 +115,12 @@ impl SampleBuilderTrait for SampleBuilder { } #[zenoh_macros::unstable] - fn with_attachment_opt(self, attachment: Option) -> Self { + fn attachment>>(self, attachment: T) -> Self { Self(Sample { - attachment, + attachment: attachment.into(), ..self.0 }) } - - #[zenoh_macros::unstable] - fn with_attachment(self, attachment: Attachment) -> Self { - self.with_attachment_opt(Some(attachment)) - } } impl QoSBuilderTrait for SampleBuilder { @@ -194,23 +186,19 @@ impl PutSampleBuilder { } impl TimestampBuilderTrait for PutSampleBuilder { - fn with_timestamp(self, timestamp: Option) -> Self { - Self(self.0.with_timestamp(timestamp)) + fn timestamp>>(self, timestamp: T) -> Self { + Self(self.0.timestamp(timestamp)) } } impl SampleBuilderTrait for PutSampleBuilder { #[zenoh_macros::unstable] - fn with_source_info(self, source_info: SourceInfo) -> Self { - Self(self.0.with_source_info(source_info)) + fn source_info(self, source_info: SourceInfo) -> Self { + Self(self.0.source_info(source_info)) } #[zenoh_macros::unstable] - fn with_attachment(self, attachment: Attachment) -> Self { - Self(self.0.with_attachment(attachment)) - } - #[zenoh_macros::unstable] - fn with_attachment_opt(self, attachment: Option) -> Self { - Self(self.0.with_attachment_opt(attachment)) + fn attachment>>(self, attachment: T) -> Self { + Self(self.0.attachment(attachment)) } } @@ -288,23 +276,19 @@ impl DeleteSampleBuilder { } impl TimestampBuilderTrait for DeleteSampleBuilder { - fn with_timestamp(self, timestamp: Option) -> Self { - Self(self.0.with_timestamp(timestamp)) + fn timestamp>>(self, timestamp: T) -> Self { + Self(self.0.timestamp(timestamp)) } } impl SampleBuilderTrait for DeleteSampleBuilder { #[zenoh_macros::unstable] - fn with_source_info(self, source_info: SourceInfo) -> Self { - Self(self.0.with_source_info(source_info)) - } - #[zenoh_macros::unstable] - fn with_attachment(self, attachment: Attachment) -> Self { - Self(self.0.with_attachment(attachment)) + fn source_info(self, source_info: SourceInfo) -> Self { + Self(self.0.source_info(source_info)) } #[zenoh_macros::unstable] - fn with_attachment_opt(self, attachment: Option) -> Self { - Self(self.0.with_attachment_opt(attachment)) + fn attachment>>(self, attachment: T) -> Self { + Self(self.0.attachment(attachment)) } } diff --git a/zenoh/tests/attachments.rs b/zenoh/tests/attachments.rs index ba4c8a7d7c..e87fc5243b 100644 --- a/zenoh/tests/attachments.rs +++ b/zenoh/tests/attachments.rs @@ -38,22 +38,22 @@ fn pubsub() { } zenoh .put("test/attachment", "put") - .with_attachment( + .attachment(Some( backer .iter() .map(|b| (b.0.as_slice(), b.1.as_slice())) .collect(), - ) + )) .res() .unwrap(); publisher .put("publisher") - .with_attachment( + .attachment(Some( backer .iter() .map(|b| (b.0.as_slice(), b.1.as_slice())) .collect(), - ) + )) .res() .unwrap(); } @@ -84,7 +84,7 @@ fn queries() { query.key_expr().clone(), query.value().unwrap().payload.clone(), ) - .with_attachment(attachment) + .attachment(attachment) .res() .unwrap(); }) From fb6509df61afccf4cd983e460553e9f07ce77d25 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 13:21:24 +0100 Subject: [PATCH 35/63] into to encoding returned --- .../src/replica/storage.rs | 2 +- zenoh/src/net/runtime/adminspace.rs | 2 +- zenoh/src/publication.rs | 14 ++++++++++---- zenoh/src/query.rs | 7 ++----- zenoh/src/queryable.rs | 7 ++----- zenoh/src/sample_builder.rs | 17 ++++++----------- zenoh/src/value.rs | 12 ++++++------ 7 files changed, 28 insertions(+), 33 deletions(-) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index de76ade51d..6d31c9710a 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -719,7 +719,7 @@ fn construct_update(data: String) -> Update { for slice in result.3 { payload.push_zslice(slice.to_vec().into()); } - let value = Value::new(payload).with_encoding(result.2.into()); + let value = Value::new(payload).with_encoding(result.2); let data = StoredData { value, timestamp: Timestamp::from_str(&result.1).unwrap(), // @TODO: remove the unwrap() diff --git a/zenoh/src/net/runtime/adminspace.rs b/zenoh/src/net/runtime/adminspace.rs index 9047e8b112..caeeb5c89b 100644 --- a/zenoh/src/net/runtime/adminspace.rs +++ b/zenoh/src/net/runtime/adminspace.rs @@ -426,7 +426,7 @@ impl Primitives for AdminSpace { parameters, value: query .ext_body - .map(|b| Value::from(b.payload).with_encoding(b.encoding.into())), + .map(|b| Value::from(b.payload).with_encoding(b.encoding)), qid: msg.id, zid, primitives, diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index cd68530bf7..0e93350222 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -199,8 +199,11 @@ impl SampleBuilderTrait for DeleteBuilder<'_, '_> { } impl ValueBuilderTrait for PutBuilder<'_, '_> { - fn with_encoding(self, encoding: Encoding) -> Self { - Self { encoding, ..self } + fn with_encoding>(self, encoding: T) -> Self { + Self { + encoding: encoding.into(), + ..self + } } fn with_payload(self, payload: IntoPayload) -> Self @@ -779,8 +782,11 @@ impl SampleBuilderTrait for PutPublication<'_> { } impl ValueBuilderTrait for PutPublication<'_> { - fn with_encoding(self, encoding: Encoding) -> Self { - Self { encoding, ..self } + fn with_encoding>(self, encoding: T) -> Self { + Self { + encoding: encoding.into(), + ..self + } } fn with_payload(self, payload: IntoPayload) -> Self diff --git a/zenoh/src/query.rs b/zenoh/src/query.rs index 2d4e5e1ee3..05f9a3557f 100644 --- a/zenoh/src/query.rs +++ b/zenoh/src/query.rs @@ -169,15 +169,12 @@ impl QoSBuilderTrait for GetBuilder<'_, '_, DefaultHandler> { } impl ValueBuilderTrait for GetBuilder<'_, '_, Handler> { - fn with_encoding(self, encoding: Encoding) -> Self { + fn with_encoding>(self, encoding: T) -> Self { let value = Some(self.value.unwrap_or_default().with_encoding(encoding)); Self { value, ..self } } - fn with_payload(self, payload: IntoPayload) -> Self - where - IntoPayload: Into, - { + fn with_payload>(self, payload: T) -> Self { let value = Some(self.value.unwrap_or_default().with_payload(payload)); Self { value, ..self } } diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 66cb34459b..4f478e1ce7 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -366,17 +366,14 @@ impl QoSBuilderTrait for ReplyBuilder<'_> { } impl ValueBuilderTrait for ReplyBuilder<'_> { - fn with_encoding(self, encoding: Encoding) -> Self { + fn with_encoding>(self, encoding: T) -> Self { Self { sample_builder: self.sample_builder.with_encoding(encoding), ..self } } - fn with_payload(self, payload: IntoPayload) -> Self - where - IntoPayload: Into, - { + fn with_payload>(self, payload: T) -> Self { Self { sample_builder: self.sample_builder.with_payload(payload), ..self diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index 2d7277506d..a113a9c953 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -41,7 +41,7 @@ pub trait QoSBuilderTrait { } pub trait TimestampBuilderTrait { - /// Sets of clears timestamp + /// Sets of clears timestamp fn timestamp>>(self, timestamp: T) -> Self; } @@ -56,11 +56,9 @@ pub trait SampleBuilderTrait { pub trait ValueBuilderTrait { /// Set the [`Encoding`] - fn with_encoding(self, encoding: Encoding) -> Self; + fn with_encoding>(self, encoding: T) -> Self; /// Sets the payload - fn with_payload(self, payload: IntoPayload) -> Self - where - IntoPayload: Into; + fn with_payload>(self, payload: T) -> Self; } #[derive(Debug)] @@ -215,16 +213,13 @@ impl QoSBuilderTrait for PutSampleBuilder { } impl ValueBuilderTrait for PutSampleBuilder { - fn with_encoding(self, encoding: Encoding) -> Self { + fn with_encoding>(self, encoding: T) -> Self { Self(SampleBuilder(Sample { - encoding, + encoding: encoding.into(), ..self.0 .0 })) } - fn with_payload(self, payload: IntoPayload) -> Self - where - IntoPayload: Into, - { + fn with_payload>(self, payload: T) -> Self { Self(SampleBuilder(Sample { payload: payload.into(), ..self.0 .0 diff --git a/zenoh/src/value.rs b/zenoh/src/value.rs index 2d98cbf398..2e288c64ad 100644 --- a/zenoh/src/value.rs +++ b/zenoh/src/value.rs @@ -46,13 +46,13 @@ impl Value { } impl ValueBuilderTrait for Value { - fn with_encoding(self, encoding: Encoding) -> Self { - Self { encoding, ..self } + fn with_encoding>(self, encoding: T) -> Self { + Self { + encoding: encoding.into(), + ..self + } } - fn with_payload(self, payload: IntoPayload) -> Self - where - IntoPayload: Into, - { + fn with_payload>(self, payload: T) -> Self { Self { payload: payload.into(), ..self From 2ff6bc22f79f5ab373e1073ae5be1744b646ab49 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 13:23:17 +0100 Subject: [PATCH 36/63] example build fix --- examples/examples/z_pub.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/examples/z_pub.rs b/examples/examples/z_pub.rs index 416ff31f46..7166981e72 100644 --- a/examples/examples/z_pub.rs +++ b/examples/examples/z_pub.rs @@ -39,12 +39,12 @@ async fn main() { println!("Putting Data ('{}': '{}')...", &key_expr, buf); let mut put = publisher.put(buf); if let Some(attachment) = &attachment { - put = put.attachment( + put = put.attachment(Some( attachment .split('&') .map(|pair| split_once(pair, '=')) .collect(), - ) + )) } put.res().await.unwrap(); } From 5bbef9c7d4643259a23cde58a20ea08f4a8a464f Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 13:24:50 +0100 Subject: [PATCH 37/63] with removed --- plugins/zenoh-plugin-rest/src/lib.rs | 10 ++-------- .../src/replica/align_queryable.rs | 2 +- .../src/replica/aligner.rs | 2 +- .../src/replica/storage.rs | 10 +++++----- zenoh/src/net/runtime/adminspace.rs | 4 ++-- zenoh/src/publication.rs | 8 ++++---- zenoh/src/query.rs | 8 ++++---- zenoh/src/queryable.rs | 10 +++++----- zenoh/src/sample.rs | 2 +- zenoh/src/sample_builder.rs | 8 ++++---- zenoh/src/value.rs | 4 ++-- 11 files changed, 31 insertions(+), 37 deletions(-) diff --git a/plugins/zenoh-plugin-rest/src/lib.rs b/plugins/zenoh-plugin-rest/src/lib.rs index 74da23679f..c90bbe5ac1 100644 --- a/plugins/zenoh-plugin-rest/src/lib.rs +++ b/plugins/zenoh-plugin-rest/src/lib.rs @@ -420,7 +420,7 @@ async fn query(mut req: Request<(Arc, String)>) -> tide::Result { @@ -464,13 +464,7 @@ async fn write(mut req: Request<(Arc, String)>) -> tide::Result { - session - .put(&key_expr, bytes) - .with_encoding(encoding) - .res() - .await - } + SampleKind::Put => session.put(&key_expr, bytes).encoding(encoding).res().await, SampleKind::Delete => session.delete(&key_expr).res().await, }; match res { diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs b/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs index 973fb89abe..b2d2bdc399 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs @@ -129,7 +129,7 @@ impl AlignQueryable { AlignData::Data(k, (v, ts)) => { query .reply(k, v.payload) - .with_encoding(v.encoding) + .encoding(v.encoding) .timestamp(ts) .res() .await diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs index 9d5257e53f..6527d54c66 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs @@ -111,7 +111,7 @@ impl Aligner { payload, encoding, .. } = value; let sample = PutSampleBuilder::new(key, payload) - .with_encoding(encoding) + .encoding(encoding) .timestamp(ts) .res_sync(); log::debug!("[ALIGNER] Adding {:?} to storage", sample); diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 6d31c9710a..8e60ee320e 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -315,7 +315,7 @@ impl StorageService { payload, encoding, .. } = data.value; PutSampleBuilder::new(KeyExpr::from(k.clone()), payload) - .with_encoding(encoding) + .encoding(encoding) .timestamp(data.timestamp) .res_sync() } @@ -344,7 +344,7 @@ impl StorageService { .put( stripped_key, Value::new(sample_to_store.payload().clone()) - .with_encoding(sample_to_store.encoding().clone()), + .encoding(sample_to_store.encoding().clone()), *sample_to_store.timestamp().unwrap(), ) .await @@ -532,7 +532,7 @@ impl StorageService { } = entry.value; if let Err(e) = q .reply(key.clone(), payload) - .with_encoding(encoding) + .encoding(encoding) .timestamp(entry.timestamp) .res_async() .await @@ -567,7 +567,7 @@ impl StorageService { } = entry.value; if let Err(e) = q .reply(q.key_expr().clone(), payload) - .with_encoding(encoding) + .encoding(encoding) .timestamp(entry.timestamp) .res_async() .await @@ -719,7 +719,7 @@ fn construct_update(data: String) -> Update { for slice in result.3 { payload.push_zslice(slice.to_vec().into()); } - let value = Value::new(payload).with_encoding(result.2); + let value = Value::new(payload).encoding(result.2); let data = StoredData { value, timestamp: Timestamp::from_str(&result.1).unwrap(), // @TODO: remove the unwrap() diff --git a/zenoh/src/net/runtime/adminspace.rs b/zenoh/src/net/runtime/adminspace.rs index caeeb5c89b..070b3bcd3a 100644 --- a/zenoh/src/net/runtime/adminspace.rs +++ b/zenoh/src/net/runtime/adminspace.rs @@ -426,7 +426,7 @@ impl Primitives for AdminSpace { parameters, value: query .ext_body - .map(|b| Value::from(b.payload).with_encoding(b.encoding)), + .map(|b| Value::from(b.payload).encoding(b.encoding)), qid: msg.id, zid, primitives, @@ -578,7 +578,7 @@ fn router_data(context: &AdminContext, query: Query) { }; if let Err(e) = query .reply(reply_key, payload) - .with_encoding(Encoding::APPLICATION_JSON) + .encoding(Encoding::APPLICATION_JSON) .res_sync() { log::error!("Error sending AdminSpace reply: {:?}", e); diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index 0e93350222..8f52d5e4fa 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -199,14 +199,14 @@ impl SampleBuilderTrait for DeleteBuilder<'_, '_> { } impl ValueBuilderTrait for PutBuilder<'_, '_> { - fn with_encoding>(self, encoding: T) -> Self { + fn encoding>(self, encoding: T) -> Self { Self { encoding: encoding.into(), ..self } } - fn with_payload(self, payload: IntoPayload) -> Self + fn payload(self, payload: IntoPayload) -> Self where IntoPayload: Into, { @@ -782,14 +782,14 @@ impl SampleBuilderTrait for PutPublication<'_> { } impl ValueBuilderTrait for PutPublication<'_> { - fn with_encoding>(self, encoding: T) -> Self { + fn encoding>(self, encoding: T) -> Self { Self { encoding: encoding.into(), ..self } } - fn with_payload(self, payload: IntoPayload) -> Self + fn payload(self, payload: IntoPayload) -> Self where IntoPayload: Into, { diff --git a/zenoh/src/query.rs b/zenoh/src/query.rs index 05f9a3557f..837ed69f22 100644 --- a/zenoh/src/query.rs +++ b/zenoh/src/query.rs @@ -169,13 +169,13 @@ impl QoSBuilderTrait for GetBuilder<'_, '_, DefaultHandler> { } impl ValueBuilderTrait for GetBuilder<'_, '_, Handler> { - fn with_encoding>(self, encoding: T) -> Self { - let value = Some(self.value.unwrap_or_default().with_encoding(encoding)); + fn encoding>(self, encoding: T) -> Self { + let value = Some(self.value.unwrap_or_default().encoding(encoding)); Self { value, ..self } } - fn with_payload>(self, payload: T) -> Self { - let value = Some(self.value.unwrap_or_default().with_payload(payload)); + fn payload>(self, payload: T) -> Self { + let value = Some(self.value.unwrap_or_default().payload(payload)); Self { value, ..self } } } diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 4f478e1ce7..37f914d0e0 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -228,7 +228,7 @@ impl<'a> ReplySampleBuilder<'a> { query: self.query, sample_builder: self.sample_builder.into(), }; - builder.with_payload(payload) + builder.payload(payload) } pub fn delete(self) -> ReplyDelBuilder<'a> { ReplyDelBuilder { @@ -366,16 +366,16 @@ impl QoSBuilderTrait for ReplyBuilder<'_> { } impl ValueBuilderTrait for ReplyBuilder<'_> { - fn with_encoding>(self, encoding: T) -> Self { + fn encoding>(self, encoding: T) -> Self { Self { - sample_builder: self.sample_builder.with_encoding(encoding), + sample_builder: self.sample_builder.encoding(encoding), ..self } } - fn with_payload>(self, payload: T) -> Self { + fn payload>(self, payload: T) -> Self { Self { - sample_builder: self.sample_builder.with_payload(payload), + sample_builder: self.sample_builder.payload(payload), ..self } } diff --git a/zenoh/src/sample.rs b/zenoh/src/sample.rs index 163ae2090a..813bc1c63e 100644 --- a/zenoh/src/sample.rs +++ b/zenoh/src/sample.rs @@ -570,7 +570,7 @@ impl Sample { impl From for Value { fn from(sample: Sample) -> Self { - Value::new(sample.payload).with_encoding(sample.encoding) + Value::new(sample.payload).encoding(sample.encoding) } } diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index a113a9c953..0996f17cf9 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -56,9 +56,9 @@ pub trait SampleBuilderTrait { pub trait ValueBuilderTrait { /// Set the [`Encoding`] - fn with_encoding>(self, encoding: T) -> Self; + fn encoding>(self, encoding: T) -> Self; /// Sets the payload - fn with_payload>(self, payload: T) -> Self; + fn payload>(self, payload: T) -> Self; } #[derive(Debug)] @@ -213,13 +213,13 @@ impl QoSBuilderTrait for PutSampleBuilder { } impl ValueBuilderTrait for PutSampleBuilder { - fn with_encoding>(self, encoding: T) -> Self { + fn encoding>(self, encoding: T) -> Self { Self(SampleBuilder(Sample { encoding: encoding.into(), ..self.0 .0 })) } - fn with_payload>(self, payload: T) -> Self { + fn payload>(self, payload: T) -> Self { Self(SampleBuilder(Sample { payload: payload.into(), ..self.0 .0 diff --git a/zenoh/src/value.rs b/zenoh/src/value.rs index 2e288c64ad..6d4de1366c 100644 --- a/zenoh/src/value.rs +++ b/zenoh/src/value.rs @@ -46,13 +46,13 @@ impl Value { } impl ValueBuilderTrait for Value { - fn with_encoding>(self, encoding: T) -> Self { + fn encoding>(self, encoding: T) -> Self { Self { encoding: encoding.into(), ..self } } - fn with_payload>(self, payload: T) -> Self { + fn payload>(self, payload: T) -> Self { Self { payload: payload.into(), ..self From c427ac732861fd775f1b275ca7948719f16fbad5 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 13:42:52 +0100 Subject: [PATCH 38/63] resolvable removed from simple builders --- .../src/replica/aligner.rs | 5 +- .../src/replica/storage.rs | 29 ++++----- zenoh-ext/src/querying_subscriber.rs | 5 +- zenoh/src/queryable.rs | 9 +-- zenoh/src/sample.rs | 18 ------ zenoh/src/sample_builder.rs | 60 ++++--------------- 6 files changed, 32 insertions(+), 94 deletions(-) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs index 6527d54c66..3a6cc0444d 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs @@ -24,7 +24,6 @@ use zenoh::prelude::r#async::*; use zenoh::sample_builder::{PutSampleBuilder, TimestampBuilderTrait, ValueBuilderTrait}; use zenoh::time::Timestamp; use zenoh::Session; -use zenoh_core::{AsyncResolve, SyncResolve}; pub struct Aligner { session: Arc, @@ -113,7 +112,7 @@ impl Aligner { let sample = PutSampleBuilder::new(key, payload) .encoding(encoding) .timestamp(ts) - .res_sync(); + .into(); log::debug!("[ALIGNER] Adding {:?} to storage", sample); self.tx_sample.send_async(sample).await.unwrap_or_else(|e| { log::error!("[ALIGNER] Error adding sample to storage: {}", e) @@ -331,7 +330,7 @@ impl Aligner { .get(&selector) .consolidation(zenoh::query::ConsolidationMode::None) .accept_replies(zenoh::query::ReplyKeyExpr::Any) - .res_async() + .res() .await { Ok(replies) => { diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 8e60ee320e..9e9f8914d0 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -24,6 +24,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; use zenoh::buffers::buffer::SplitBuffer; use zenoh::buffers::ZBuf; use zenoh::key_expr::KeyExpr; +use zenoh::prelude::r#async::*; use zenoh::query::{ConsolidationMode, QueryTarget}; use zenoh::sample::{Sample, SampleKind}; use zenoh::sample_builder::{ @@ -34,7 +35,6 @@ use zenoh::value::Value; use zenoh::{Result as ZResult, Session, SessionDeclarations}; use zenoh_backend_traits::config::{GarbageCollectionConfig, StorageConfig}; use zenoh_backend_traits::{Capability, History, Persistence, StorageInsertionResult, StoredData}; -use zenoh_core::{AsyncResolve, SyncResolve}; use zenoh_keyexpr::key_expr::OwnedKeyExpr; use zenoh_keyexpr::keyexpr_tree::impls::KeyedSetProvider; use zenoh_keyexpr::keyexpr_tree::{support::NonWild, support::UnknownWildness, KeBoxTree}; @@ -144,12 +144,7 @@ impl StorageService { t.add_async(gc).await; // subscribe on key_expr - let storage_sub = match self - .session - .declare_subscriber(&self.key_expr) - .res_async() - .await - { + let storage_sub = match self.session.declare_subscriber(&self.key_expr).res().await { Ok(storage_sub) => storage_sub, Err(e) => { log::error!("Error starting storage '{}': {}", self.name, e); @@ -162,7 +157,7 @@ impl StorageService { .session .declare_queryable(&self.key_expr) .complete(self.complete) - .res_async() + .res() .await { Ok(storage_queryable) => storage_queryable, @@ -239,7 +234,7 @@ impl StorageService { } }; let timestamp = sample.timestamp().cloned().unwrap_or(new_reception_timestamp()); - let sample = SampleBuilder::from(sample).timestamp(timestamp).res_sync(); + let sample = SampleBuilder::from(sample).timestamp(timestamp).into(); self.process_sample(sample).await; }, // on query on key_expr @@ -303,7 +298,7 @@ impl StorageService { ); // there might be the case that the actual update was outdated due to a wild card update, but not stored yet in the storage. // get the relevant wild card entry and use that value and timestamp to update the storage - let sample_to_store = match self + let sample_to_store: Sample = match self .ovderriding_wild_update(&k, sample.timestamp().unwrap()) .await { @@ -317,17 +312,17 @@ impl StorageService { PutSampleBuilder::new(KeyExpr::from(k.clone()), payload) .encoding(encoding) .timestamp(data.timestamp) - .res_sync() + .into() } Some(Update { kind: SampleKind::Delete, data, }) => DeleteSampleBuilder::new(KeyExpr::from(k.clone())) .timestamp(data.timestamp) - .res_sync(), + .into(), None => SampleBuilder::from(sample.clone()) .keyexpr(k.clone()) - .res_sync(), + .into(), }; let stripped_key = match self.strip_prefix(sample_to_store.key_expr()) { @@ -534,7 +529,7 @@ impl StorageService { .reply(key.clone(), payload) .encoding(encoding) .timestamp(entry.timestamp) - .res_async() + .res() .await { log::warn!( @@ -569,7 +564,7 @@ impl StorageService { .reply(q.key_expr().clone(), payload) .encoding(encoding) .timestamp(entry.timestamp) - .res_async() + .res() .await { log::warn!( @@ -584,7 +579,7 @@ impl StorageService { let err_message = format!("Storage '{}' raised an error on query: {}", self.name, e); log::warn!("{}", err_message); - if let Err(e) = q.reply_err(err_message).res_async().await { + if let Err(e) = q.reply_err(err_message).res().await { log::warn!( "Storage '{}' raised an error replying a query: {}", self.name, @@ -666,7 +661,7 @@ impl StorageService { .get(KeyExpr::from(&self.key_expr).with_parameters("_time=[..]")) .target(QueryTarget::All) .consolidation(ConsolidationMode::None) - .res_async() + .res() .await { Ok(replies) => replies, diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index 52a4263396..728e9cfa51 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -665,8 +665,9 @@ impl<'a, Receiver> FetchingSubscriber<'a, Receiver> { // ensure the sample has a timestamp, thus it will always be sorted into the MergeQueue // after any timestamped Sample possibly coming from a fetch reply. let timestamp = s.timestamp().cloned().unwrap_or(new_reception_timestamp()); - let s = SampleBuilder::from(s).timestamp(timestamp).res_sync(); - state.merge_queue.push(s); + state + .merge_queue + .push(SampleBuilder::from(s).timestamp(timestamp).into()); } } }; diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 37f914d0e0..a52c96c871 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -294,8 +294,7 @@ impl Resolvable for ReplySampleBuilder<'_> { impl SyncResolve for ReplySampleBuilder<'_> { fn res_sync(self) -> ::To { - let sample = self.sample_builder.res_sync(); - self.query._reply_sample(sample) + self.query._reply_sample(self.sample_builder.into()) } } @@ -453,8 +452,7 @@ impl<'a> Resolvable for ReplyBuilder<'a> { impl SyncResolve for ReplyBuilder<'_> { fn res_sync(self) -> ::To { - let sample = self.sample_builder.res_sync(); - self.query._reply_sample(sample) + self.query._reply_sample(self.sample_builder.into()) } } @@ -464,8 +462,7 @@ impl<'a> Resolvable for ReplyDelBuilder<'a> { impl SyncResolve for ReplyDelBuilder<'_> { fn res_sync(self) -> ::To { - let sample = self.sample_builder.res_sync(); - self.query._reply_sample(sample) + self.query._reply_sample(self.sample_builder.into()) } } diff --git a/zenoh/src/sample.rs b/zenoh/src/sample.rs index 813bc1c63e..870b25768e 100644 --- a/zenoh/src/sample.rs +++ b/zenoh/src/sample.rs @@ -22,7 +22,6 @@ use crate::Priority; #[zenoh_macros::unstable] use serde::Serialize; use std::{convert::TryFrom, fmt}; -use zenoh_core::{AsyncResolve, Resolvable, SyncResolve}; use zenoh_protocol::core::EntityGlobalId; use zenoh_protocol::network::declare::ext::QoSType; use zenoh_protocol::{core::CongestionControl, zenoh}; @@ -595,23 +594,6 @@ impl From for QoS { } } -impl Resolvable for QoSBuilder { - type To = QoS; -} - -impl SyncResolve for QoSBuilder { - fn res_sync(self) -> ::To { - self.0 - } -} - -impl AsyncResolve for QoSBuilder { - type Future = futures::future::Ready; - fn res_async(self) -> Self::Future { - futures::future::ready(self.0) - } -} - impl QoSBuilderTrait for QoSBuilder { fn congestion_control(self, congestion_control: CongestionControl) -> Self { let mut inner = self.0.inner; diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample_builder.rs index 0996f17cf9..f74afdf2b3 100644 --- a/zenoh/src/sample_builder.rs +++ b/zenoh/src/sample_builder.rs @@ -24,9 +24,6 @@ use crate::Sample; use crate::SampleKind; use uhlc::Timestamp; use zenoh_core::zresult; -use zenoh_core::AsyncResolve; -use zenoh_core::Resolvable; -use zenoh_core::SyncResolve; use zenoh_protocol::core::CongestionControl; pub trait QoSBuilderTrait { @@ -124,17 +121,17 @@ impl SampleBuilderTrait for SampleBuilder { impl QoSBuilderTrait for SampleBuilder { fn congestion_control(self, congestion_control: CongestionControl) -> Self { let qos: QoSBuilder = self.0.qos.into(); - let qos = qos.congestion_control(congestion_control).res_sync(); + let qos = qos.congestion_control(congestion_control).into(); Self(Sample { qos, ..self.0 }) } fn priority(self, priority: Priority) -> Self { let qos: QoSBuilder = self.0.qos.into(); - let qos = qos.priority(priority).res_sync(); + let qos = qos.priority(priority).into(); Self(Sample { qos, ..self.0 }) } fn express(self, is_express: bool) -> Self { let qos: QoSBuilder = self.0.qos.into(); - let qos = qos.express(is_express).res_sync(); + let qos = qos.express(is_express).into(); Self(Sample { qos, ..self.0 }) } } @@ -325,53 +322,20 @@ impl TryFrom for DeleteSampleBuilder { } } -impl Resolvable for SampleBuilder { - type To = Sample; -} - -impl Resolvable for PutSampleBuilder { - type To = Sample; -} - -impl Resolvable for DeleteSampleBuilder { - type To = Sample; -} - -impl SyncResolve for SampleBuilder { - fn res_sync(self) -> Self::To { - self.0 - } -} - -impl SyncResolve for PutSampleBuilder { - fn res_sync(self) -> Self::To { - self.0.res_sync() - } -} - -impl SyncResolve for DeleteSampleBuilder { - fn res_sync(self) -> Self::To { - self.0.res_sync() - } -} - -impl AsyncResolve for SampleBuilder { - type Future = futures::future::Ready; - fn res_async(self) -> Self::Future { - futures::future::ready(self.0) +impl From for Sample { + fn from(sample_builder: SampleBuilder) -> Self { + sample_builder.0 } } -impl AsyncResolve for PutSampleBuilder { - type Future = futures::future::Ready; - fn res_async(self) -> Self::Future { - self.0.res_async() +impl From for Sample { + fn from(put_sample_builder: PutSampleBuilder) -> Self { + put_sample_builder.0 .0 } } -impl AsyncResolve for DeleteSampleBuilder { - type Future = futures::future::Ready; - fn res_async(self) -> Self::Future { - self.0.res_async() +impl From for Sample { + fn from(delete_sample_builder: DeleteSampleBuilder) -> Self { + delete_sample_builder.0 .0 } } From 10baf8c9cf6050dc6c7f682a3d444710fdb93aea Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 16:04:11 +0100 Subject: [PATCH 39/63] doctests fixed --- zenoh/src/publication.rs | 6 +++--- zenoh/src/session.rs | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index 8f52d5e4fa..f8f15eca56 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -73,12 +73,12 @@ pub struct DeleteBuilder<'a, 'b> { /// # async_std::task::block_on(async { /// use zenoh::prelude::r#async::*; /// use zenoh::publication::CongestionControl; -/// use zenoh::sample_builder::{PutSampleBuilderTrait, QoSBuilderTrait}; +/// use zenoh::sample_builder::{ValueBuilderTrait, QoSBuilderTrait}; /// /// let session = zenoh::open(config::peer()).res().await.unwrap(); /// session /// .put("key/expression", "payload") -/// .with_encoding(Encoding::TEXT_PLAIN) +/// .encoding(Encoding::TEXT_PLAIN) /// .congestion_control(CongestionControl::Block) /// .res() /// .await @@ -932,7 +932,7 @@ impl<'a> Sink for Publisher<'a> { /// # async_std::task::block_on(async { /// use zenoh::prelude::r#async::*; /// use zenoh::publication::CongestionControl; -/// use zenoh::sample_builder::{PutSampleBuilderTrait, QoSBuilderTrait}; +/// use zenoh::sample_builder::QoSBuilderTrait; /// /// let session = zenoh::open(config::peer()).res().await.unwrap(); /// let publisher = session diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index 5b80adb0e5..cc30e12293 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -683,12 +683,13 @@ impl Session { /// ``` /// # async_std::task::block_on(async { /// use zenoh::prelude::r#async::*; - /// use zenoh::sample_builder::PutSampleBuilderTrait; + /// use zenoh::sample_builder::SampleBuilderTrait; + /// use zenoh::sample_builder::ValueBuilderTrait; /// /// let session = zenoh::open(config::peer()).res().await.unwrap(); /// session /// .put("key/expression", "payload") - /// .with_encoding(Encoding::TEXT_PLAIN) + /// .encoding(Encoding::TEXT_PLAIN) /// .res() /// .await /// .unwrap(); From 48cb96ba7ab43c13a212fe4bb5943edb38089b9b Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 16:41:55 +0100 Subject: [PATCH 40/63] sample bulider in separarte module --- zenoh/src/{sample_builder.rs => sample/builder.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename zenoh/src/{sample_builder.rs => sample/builder.rs} (100%) diff --git a/zenoh/src/sample_builder.rs b/zenoh/src/sample/builder.rs similarity index 100% rename from zenoh/src/sample_builder.rs rename to zenoh/src/sample/builder.rs From ddb93a2364bbe4db227d54b1107539b717fa0d83 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 16:42:05 +0100 Subject: [PATCH 41/63] separate module --- examples/examples/z_ping.rs | 2 +- examples/examples/z_pong.rs | 2 +- examples/examples/z_pub.rs | 2 +- examples/examples/z_pub_shm_thr.rs | 2 +- examples/examples/z_pub_thr.rs | 2 +- plugins/zenoh-plugin-rest/examples/z_serve_sse.rs | 2 +- plugins/zenoh-plugin-rest/src/lib.rs | 2 +- .../src/replica/align_queryable.rs | 4 ++-- .../src/replica/aligner.rs | 2 +- .../src/replica/storage.rs | 4 ++-- zenoh-ext/src/group.rs | 2 +- zenoh-ext/src/querying_subscriber.rs | 2 +- zenoh/src/lib.rs | 1 - zenoh/src/net/runtime/adminspace.rs | 2 +- zenoh/src/prelude.rs | 4 ++++ zenoh/src/publication.rs | 10 +++++----- zenoh/src/query.rs | 2 +- zenoh/src/queryable.rs | 4 ++-- zenoh/src/sample.rs | 4 +++- zenoh/src/session.rs | 3 +-- zenoh/src/value.rs | 2 +- zenoh/tests/attachments.rs | 4 ++-- zenoh/tests/qos.rs | 2 +- zenoh/tests/routing.rs | 2 +- zenoh/tests/session.rs | 2 +- zenoh/tests/unicity.rs | 2 +- 26 files changed, 38 insertions(+), 34 deletions(-) diff --git a/examples/examples/z_ping.rs b/examples/examples/z_ping.rs index b40afc1f53..59bcaddadc 100644 --- a/examples/examples/z_ping.rs +++ b/examples/examples/z_ping.rs @@ -16,7 +16,7 @@ use std::time::{Duration, Instant}; use zenoh::config::Config; use zenoh::prelude::sync::*; use zenoh::publication::CongestionControl; -use zenoh::sample_builder::QoSBuilderTrait; +use zenoh::sample::builder::QoSBuilderTrait; use zenoh_examples::CommonArgs; fn main() { diff --git a/examples/examples/z_pong.rs b/examples/examples/z_pong.rs index 0003958b5d..e0fa079629 100644 --- a/examples/examples/z_pong.rs +++ b/examples/examples/z_pong.rs @@ -15,7 +15,7 @@ use clap::Parser; use zenoh::config::Config; use zenoh::prelude::sync::*; use zenoh::publication::CongestionControl; -use zenoh::sample_builder::QoSBuilderTrait; +use zenoh::sample::builder::QoSBuilderTrait; use zenoh_examples::CommonArgs; fn main() { diff --git a/examples/examples/z_pub.rs b/examples/examples/z_pub.rs index 7166981e72..c4c592b47c 100644 --- a/examples/examples/z_pub.rs +++ b/examples/examples/z_pub.rs @@ -16,7 +16,7 @@ use clap::Parser; use std::time::Duration; use zenoh::config::Config; use zenoh::prelude::r#async::*; -use zenoh::sample_builder::SampleBuilderTrait; +use zenoh::sample::builder::SampleBuilderTrait; use zenoh_examples::CommonArgs; #[async_std::main] diff --git a/examples/examples/z_pub_shm_thr.rs b/examples/examples/z_pub_shm_thr.rs index 5230ea3ce6..a784429906 100644 --- a/examples/examples/z_pub_shm_thr.rs +++ b/examples/examples/z_pub_shm_thr.rs @@ -15,7 +15,7 @@ use clap::Parser; use zenoh::config::Config; use zenoh::prelude::r#async::*; use zenoh::publication::CongestionControl; -use zenoh::sample_builder::QoSBuilderTrait; +use zenoh::sample::builder::QoSBuilderTrait; use zenoh::shm::SharedMemoryManager; use zenoh_examples::CommonArgs; diff --git a/examples/examples/z_pub_thr.rs b/examples/examples/z_pub_thr.rs index 7e7c1ac9b5..78d54111a8 100644 --- a/examples/examples/z_pub_thr.rs +++ b/examples/examples/z_pub_thr.rs @@ -16,7 +16,7 @@ use clap::Parser; use std::convert::TryInto; use zenoh::prelude::sync::*; use zenoh::publication::CongestionControl; -use zenoh::sample_builder::QoSBuilderTrait; +use zenoh::sample::builder::QoSBuilderTrait; use zenoh_examples::CommonArgs; fn main() { diff --git a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs index 48f152e488..c353826fab 100644 --- a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs +++ b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs @@ -15,7 +15,7 @@ use clap::{arg, Command}; use std::time::Duration; use zenoh::prelude::r#async::*; use zenoh::publication::CongestionControl; -use zenoh::sample_builder::QoSBuilderTrait; +use zenoh::sample::builder::QoSBuilderTrait; use zenoh::{config::Config, key_expr::keyexpr}; const HTML: &str = r#" diff --git a/plugins/zenoh-plugin-rest/src/lib.rs b/plugins/zenoh-plugin-rest/src/lib.rs index c90bbe5ac1..94796c518d 100644 --- a/plugins/zenoh-plugin-rest/src/lib.rs +++ b/plugins/zenoh-plugin-rest/src/lib.rs @@ -34,7 +34,7 @@ use zenoh::plugins::{RunningPluginTrait, ZenohPlugin}; use zenoh::prelude::r#async::*; use zenoh::query::{QueryConsolidation, Reply}; use zenoh::runtime::Runtime; -use zenoh::sample_builder::ValueBuilderTrait; +use zenoh::sample::builder::ValueBuilderTrait; use zenoh::selector::TIME_RANGE_KEY; use zenoh::Session; use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginControl}; diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs b/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs index b2d2bdc399..729572601c 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs @@ -20,8 +20,8 @@ use std::str; use std::str::FromStr; use zenoh::payload::StringOrBase64; use zenoh::prelude::r#async::*; -use zenoh::sample_builder::TimestampBuilderTrait; -use zenoh::sample_builder::ValueBuilderTrait; +use zenoh::sample::builder::TimestampBuilderTrait; +use zenoh::sample::builder::ValueBuilderTrait; use zenoh::time::Timestamp; use zenoh::Session; diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs index 3a6cc0444d..1b7f945cee 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs @@ -21,7 +21,7 @@ use std::str; use zenoh::key_expr::{KeyExpr, OwnedKeyExpr}; use zenoh::payload::StringOrBase64; use zenoh::prelude::r#async::*; -use zenoh::sample_builder::{PutSampleBuilder, TimestampBuilderTrait, ValueBuilderTrait}; +use zenoh::sample::builder::{PutSampleBuilder, TimestampBuilderTrait, ValueBuilderTrait}; use zenoh::time::Timestamp; use zenoh::Session; diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 9e9f8914d0..62468ac6a1 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -26,10 +26,10 @@ use zenoh::buffers::ZBuf; use zenoh::key_expr::KeyExpr; use zenoh::prelude::r#async::*; use zenoh::query::{ConsolidationMode, QueryTarget}; -use zenoh::sample::{Sample, SampleKind}; -use zenoh::sample_builder::{ +use zenoh::sample::builder::{ DeleteSampleBuilder, PutSampleBuilder, SampleBuilder, TimestampBuilderTrait, ValueBuilderTrait, }; +use zenoh::sample::{Sample, SampleKind}; use zenoh::time::{new_reception_timestamp, Timestamp, NTP64}; use zenoh::value::Value; use zenoh::{Result as ZResult, Session, SessionDeclarations}; diff --git a/zenoh-ext/src/group.rs b/zenoh-ext/src/group.rs index 39cd982c41..4ae3c77c9f 100644 --- a/zenoh-ext/src/group.rs +++ b/zenoh-ext/src/group.rs @@ -29,7 +29,7 @@ use zenoh::payload::PayloadReader; use zenoh::prelude::r#async::*; use zenoh::publication::Publisher; use zenoh::query::ConsolidationMode; -use zenoh::sample_builder::QoSBuilderTrait; +use zenoh::sample::builder::QoSBuilderTrait; use zenoh::Error as ZError; use zenoh::Result as ZResult; use zenoh::Session; diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index 728e9cfa51..5e80cb704c 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -20,7 +20,7 @@ use std::time::Duration; use zenoh::handlers::{locked, DefaultHandler}; use zenoh::prelude::r#async::*; use zenoh::query::{QueryConsolidation, QueryTarget, ReplyKeyExpr}; -use zenoh::sample_builder::{SampleBuilder, TimestampBuilderTrait}; +use zenoh::sample::builder::{SampleBuilder, TimestampBuilderTrait}; use zenoh::subscriber::{Reliability, Subscriber}; use zenoh::time::{new_reception_timestamp, Timestamp}; use zenoh::Result as ZResult; diff --git a/zenoh/src/lib.rs b/zenoh/src/lib.rs index 24b21496ec..ed2f01f180 100644 --- a/zenoh/src/lib.rs +++ b/zenoh/src/lib.rs @@ -145,7 +145,6 @@ pub mod publication; pub mod query; pub mod queryable; pub mod sample; -pub mod sample_builder; pub mod subscriber; pub mod value; #[cfg(feature = "shared-memory")] diff --git a/zenoh/src/net/runtime/adminspace.rs b/zenoh/src/net/runtime/adminspace.rs index 070b3bcd3a..41295f6cd0 100644 --- a/zenoh/src/net/runtime/adminspace.rs +++ b/zenoh/src/net/runtime/adminspace.rs @@ -20,7 +20,7 @@ use crate::plugins::sealed::{self as plugins}; use crate::prelude::sync::SyncResolve; use crate::queryable::Query; use crate::queryable::QueryInner; -use crate::sample_builder::ValueBuilderTrait; +use crate::sample::builder::ValueBuilderTrait; use crate::value::Value; use async_std::task; use log::{error, trace}; diff --git a/zenoh/src/prelude.rs b/zenoh/src/prelude.rs index 26c93e1801..850148f506 100644 --- a/zenoh/src/prelude.rs +++ b/zenoh/src/prelude.rs @@ -60,6 +60,10 @@ pub(crate) mod common { #[zenoh_macros::unstable] pub use crate::publication::PublisherDeclarations; pub use zenoh_protocol::core::{CongestionControl, Reliability, WhatAmI}; + + pub use crate::sample::builder::{ + QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, ValueBuilderTrait, + }; } /// Prelude to import when using Zenoh's sync API. diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index f8f15eca56..d2463610fb 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -15,12 +15,12 @@ //! Publishing primitives. use crate::net::primitives::Primitives; use crate::prelude::*; +use crate::sample::builder::{ + QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, ValueBuilderTrait, +}; #[zenoh_macros::unstable] use crate::sample::Attachment; use crate::sample::{DataInfo, QoS, Sample, SampleFields, SampleKind}; -use crate::sample_builder::{ - QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, ValueBuilderTrait, -}; use crate::SessionRef; use crate::Undeclarable; #[cfg(feature = "unstable")] @@ -73,7 +73,7 @@ pub struct DeleteBuilder<'a, 'b> { /// # async_std::task::block_on(async { /// use zenoh::prelude::r#async::*; /// use zenoh::publication::CongestionControl; -/// use zenoh::sample_builder::{ValueBuilderTrait, QoSBuilderTrait}; +/// use zenoh::sample::builder::{ValueBuilderTrait, QoSBuilderTrait}; /// /// let session = zenoh::open(config::peer()).res().await.unwrap(); /// session @@ -932,7 +932,7 @@ impl<'a> Sink for Publisher<'a> { /// # async_std::task::block_on(async { /// use zenoh::prelude::r#async::*; /// use zenoh::publication::CongestionControl; -/// use zenoh::sample_builder::QoSBuilderTrait; +/// use zenoh::sample::builder::QoSBuilderTrait; /// /// let session = zenoh::open(config::peer()).res().await.unwrap(); /// let publisher = session diff --git a/zenoh/src/query.rs b/zenoh/src/query.rs index 837ed69f22..3a7ee771b3 100644 --- a/zenoh/src/query.rs +++ b/zenoh/src/query.rs @@ -15,10 +15,10 @@ //! Query primitives. use crate::handlers::{locked, Callback, DefaultHandler}; use crate::prelude::*; +use crate::sample::builder::{QoSBuilderTrait, SampleBuilderTrait, ValueBuilderTrait}; #[zenoh_macros::unstable] use crate::sample::Attachment; use crate::sample::QoSBuilder; -use crate::sample_builder::{QoSBuilderTrait, SampleBuilderTrait, ValueBuilderTrait}; use crate::Session; use std::collections::HashMap; use std::future::Ready; diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index a52c96c871..2e3a1f585a 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -18,11 +18,11 @@ use crate::encoding::Encoding; use crate::handlers::{locked, DefaultHandler}; use crate::net::primitives::Primitives; use crate::prelude::*; -use crate::sample::SourceInfo; -use crate::sample_builder::{ +use crate::sample::builder::{ DeleteSampleBuilder, PutSampleBuilder, QoSBuilderTrait, SampleBuilder, SampleBuilderTrait, TimestampBuilderTrait, ValueBuilderTrait, }; +use crate::sample::SourceInfo; use crate::Id; use crate::SessionRef; use crate::Undeclarable; diff --git a/zenoh/src/sample.rs b/zenoh/src/sample.rs index 870b25768e..455d54318b 100644 --- a/zenoh/src/sample.rs +++ b/zenoh/src/sample.rs @@ -16,7 +16,7 @@ use crate::encoding::Encoding; use crate::payload::Payload; use crate::prelude::{KeyExpr, Value}; -use crate::sample_builder::{QoSBuilderTrait, ValueBuilderTrait}; +use crate::sample::builder::{QoSBuilderTrait, ValueBuilderTrait}; use crate::time::Timestamp; use crate::Priority; #[zenoh_macros::unstable] @@ -26,6 +26,8 @@ use zenoh_protocol::core::EntityGlobalId; use zenoh_protocol::network::declare::ext::QoSType; use zenoh_protocol::{core::CongestionControl, zenoh}; +pub mod builder; + pub type SourceSn = u64; /// The locality of samples to be received by subscribers or targeted by publishers. diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index cc30e12293..2f24673b5e 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -683,8 +683,7 @@ impl Session { /// ``` /// # async_std::task::block_on(async { /// use zenoh::prelude::r#async::*; - /// use zenoh::sample_builder::SampleBuilderTrait; - /// use zenoh::sample_builder::ValueBuilderTrait; + /// use zenoh::prelude::*; /// /// let session = zenoh::open(config::peer()).res().await.unwrap(); /// session diff --git a/zenoh/src/value.rs b/zenoh/src/value.rs index 6d4de1366c..8ea5aef19f 100644 --- a/zenoh/src/value.rs +++ b/zenoh/src/value.rs @@ -13,7 +13,7 @@ // //! Value primitives. -use crate::{encoding::Encoding, payload::Payload, sample_builder::ValueBuilderTrait}; +use crate::{encoding::Encoding, payload::Payload, sample::builder::ValueBuilderTrait}; /// A zenoh [`Value`] contains a `payload` and an [`Encoding`] that indicates how the [`Payload`] should be interpreted. #[non_exhaustive] diff --git a/zenoh/tests/attachments.rs b/zenoh/tests/attachments.rs index e87fc5243b..f50e33cf6f 100644 --- a/zenoh/tests/attachments.rs +++ b/zenoh/tests/attachments.rs @@ -14,7 +14,7 @@ #[cfg(feature = "unstable")] #[test] fn pubsub() { - use zenoh::{prelude::sync::*, sample_builder::SampleBuilderTrait}; + use zenoh::{prelude::sync::*, sample::builder::SampleBuilderTrait}; let zenoh = zenoh::open(Config::default()).res().unwrap(); let _sub = zenoh @@ -61,7 +61,7 @@ fn pubsub() { #[cfg(feature = "unstable")] #[test] fn queries() { - use zenoh::{prelude::sync::*, sample::Attachment, sample_builder::SampleBuilderTrait}; + use zenoh::{prelude::sync::*, sample::builder::SampleBuilderTrait, sample::Attachment}; let zenoh = zenoh::open(Config::default()).res().unwrap(); let _sub = zenoh diff --git a/zenoh/tests/qos.rs b/zenoh/tests/qos.rs index 8dc39423cb..46896e5432 100644 --- a/zenoh/tests/qos.rs +++ b/zenoh/tests/qos.rs @@ -15,7 +15,7 @@ use async_std::prelude::FutureExt; use async_std::task; use std::time::Duration; use zenoh::prelude::r#async::*; -use zenoh::sample_builder::QoSBuilderTrait; +use zenoh::sample::builder::QoSBuilderTrait; use zenoh::{publication::Priority, SessionDeclarations}; use zenoh_core::zasync_executor_init; diff --git a/zenoh/tests/routing.rs b/zenoh/tests/routing.rs index 123550852e..6585f8aae4 100644 --- a/zenoh/tests/routing.rs +++ b/zenoh/tests/routing.rs @@ -20,7 +20,7 @@ use std::sync::{atomic::AtomicUsize, Arc}; use std::time::Duration; use zenoh::config::{Config, ModeDependentValue}; use zenoh::prelude::r#async::*; -use zenoh::sample_builder::QoSBuilderTrait; +use zenoh::sample::builder::QoSBuilderTrait; use zenoh::{value::Value, Result}; use zenoh_core::zasync_executor_init; use zenoh_protocol::core::{WhatAmI, WhatAmIMatcher}; diff --git a/zenoh/tests/session.rs b/zenoh/tests/session.rs index 955ec7a73f..436643ac25 100644 --- a/zenoh/tests/session.rs +++ b/zenoh/tests/session.rs @@ -17,7 +17,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use std::time::Duration; use zenoh::prelude::r#async::*; -use zenoh::sample_builder::QoSBuilderTrait; +use zenoh::sample::builder::QoSBuilderTrait; use zenoh_core::zasync_executor_init; const TIMEOUT: Duration = Duration::from_secs(60); diff --git a/zenoh/tests/unicity.rs b/zenoh/tests/unicity.rs index 3d1327398d..80f722205b 100644 --- a/zenoh/tests/unicity.rs +++ b/zenoh/tests/unicity.rs @@ -17,7 +17,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use std::time::Duration; use zenoh::prelude::r#async::*; -use zenoh::sample_builder::QoSBuilderTrait; +use zenoh::sample::builder::QoSBuilderTrait; use zenoh_core::zasync_executor_init; const TIMEOUT: Duration = Duration::from_secs(60); From ab96aab5345e7556c0c6ae1329c46efe45a31b63 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 16:53:43 +0100 Subject: [PATCH 42/63] SampleBuilder put/delete --- .../src/replica/aligner.rs | 4 +-- .../src/replica/storage.rs | 8 +++--- zenoh/src/queryable.rs | 4 +-- zenoh/src/sample/builder.rs | 27 +++++++++---------- 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs index 1b7f945cee..5121f0b445 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs @@ -21,7 +21,7 @@ use std::str; use zenoh::key_expr::{KeyExpr, OwnedKeyExpr}; use zenoh::payload::StringOrBase64; use zenoh::prelude::r#async::*; -use zenoh::sample::builder::{PutSampleBuilder, TimestampBuilderTrait, ValueBuilderTrait}; +use zenoh::sample::builder::{SampleBuilder, TimestampBuilderTrait, ValueBuilderTrait}; use zenoh::time::Timestamp; use zenoh::Session; @@ -109,7 +109,7 @@ impl Aligner { let Value { payload, encoding, .. } = value; - let sample = PutSampleBuilder::new(key, payload) + let sample = SampleBuilder::put(key, payload) .encoding(encoding) .timestamp(ts) .into(); diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 62468ac6a1..feebfb588a 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -26,9 +26,7 @@ use zenoh::buffers::ZBuf; use zenoh::key_expr::KeyExpr; use zenoh::prelude::r#async::*; use zenoh::query::{ConsolidationMode, QueryTarget}; -use zenoh::sample::builder::{ - DeleteSampleBuilder, PutSampleBuilder, SampleBuilder, TimestampBuilderTrait, ValueBuilderTrait, -}; +use zenoh::sample::builder::{SampleBuilder, TimestampBuilderTrait, ValueBuilderTrait}; use zenoh::sample::{Sample, SampleKind}; use zenoh::time::{new_reception_timestamp, Timestamp, NTP64}; use zenoh::value::Value; @@ -309,7 +307,7 @@ impl StorageService { let Value { payload, encoding, .. } = data.value; - PutSampleBuilder::new(KeyExpr::from(k.clone()), payload) + SampleBuilder::put(KeyExpr::from(k.clone()), payload) .encoding(encoding) .timestamp(data.timestamp) .into() @@ -317,7 +315,7 @@ impl StorageService { Some(Update { kind: SampleKind::Delete, data, - }) => DeleteSampleBuilder::new(KeyExpr::from(k.clone())) + }) => SampleBuilder::delete(KeyExpr::from(k.clone())) .timestamp(data.timestamp) .into(), None => SampleBuilder::from(sample.clone()) diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 2e3a1f585a..c9492394c4 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -137,8 +137,8 @@ impl Query { IntoKeyExpr: Into>, IntoPayload: Into, { - let sample_builder = PutSampleBuilder::new(key_expr, payload) - .with_qos(response::ext::QoSType::RESPONSE.into()); + let sample_builder = + SampleBuilder::put(key_expr, payload).with_qos(response::ext::QoSType::RESPONSE.into()); ReplyBuilder { query: self, sample_builder, diff --git a/zenoh/src/sample/builder.rs b/zenoh/src/sample/builder.rs index f74afdf2b3..8c507c8119 100644 --- a/zenoh/src/sample/builder.rs +++ b/zenoh/src/sample/builder.rs @@ -62,22 +62,21 @@ pub trait ValueBuilderTrait { pub struct SampleBuilder(Sample); impl SampleBuilder { - pub fn new(key_expr: IntoKeyExpr) -> Self + pub fn put( + key_expr: IntoKeyExpr, + payload: IntoPayload, + ) -> PutSampleBuilder where IntoKeyExpr: Into>, + IntoPayload: Into, { - Self(Sample { - key_expr: key_expr.into(), - payload: Payload::empty(), - kind: SampleKind::default(), - encoding: Encoding::default(), - timestamp: None, - qos: QoS::default(), - #[cfg(feature = "unstable")] - source_info: SourceInfo::empty(), - #[cfg(feature = "unstable")] - attachment: None, - }) + PutSampleBuilder::new(key_expr, payload) + } + pub fn delete(key_expr: IntoKeyExpr) -> DeleteSampleBuilder + where + IntoKeyExpr: Into>, + { + DeleteSampleBuilder::new(key_expr) } /// Allows to change keyexpr of [`Sample`] pub fn keyexpr(self, key_expr: IntoKeyExpr) -> Self @@ -149,7 +148,7 @@ impl From for PutSampleBuilder { } impl PutSampleBuilder { - pub fn new(key_expr: IntoKeyExpr, payload: IntoPayload) -> Self + fn new(key_expr: IntoKeyExpr, payload: IntoPayload) -> Self where IntoKeyExpr: Into>, IntoPayload: Into, From 82c1c999d0f73cc2cc09121e56067591971f5146 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 17:28:56 +0100 Subject: [PATCH 43/63] set value api --- examples/examples/z_get.rs | 21 +++++++----- plugins/zenoh-plugin-rest/src/lib.rs | 2 +- zenoh/src/publication.rs | 17 ++++++++++ zenoh/src/query.rs | 49 ++++++++++++---------------- zenoh/src/queryable.rs | 7 ++++ zenoh/src/sample/builder.rs | 12 +++++++ zenoh/src/value.rs | 18 ++++++++++ zenoh/tests/attachments.rs | 6 ++-- zenoh/tests/handler.rs | 4 +-- 9 files changed, 93 insertions(+), 43 deletions(-) diff --git a/examples/examples/z_get.rs b/examples/examples/z_get.rs index dce74d367b..074f931eff 100644 --- a/examples/examples/z_get.rs +++ b/examples/examples/z_get.rs @@ -28,15 +28,18 @@ async fn main() { let session = zenoh::open(config).res().await.unwrap(); println!("Sending Query '{selector}'..."); - let replies = match value { - Some(value) => session.get(&selector).with_value(value), - None => session.get(&selector), - } - .target(target) - .timeout(timeout) - .res() - .await - .unwrap(); + // let replies = match value { + // Some(value) => session.get(&selector).payload(value), + // None => session.get(&selector), + // } + let replies = session + .get(&selector) + .value(value.map(Value::from)) + .target(target) + .timeout(timeout) + .res() + .await + .unwrap(); while let Ok(reply) = replies.recv_async().await { match reply.sample { Ok(sample) => { diff --git a/plugins/zenoh-plugin-rest/src/lib.rs b/plugins/zenoh-plugin-rest/src/lib.rs index 94796c518d..f78c541eff 100644 --- a/plugins/zenoh-plugin-rest/src/lib.rs +++ b/plugins/zenoh-plugin-rest/src/lib.rs @@ -420,7 +420,7 @@ async fn query(mut req: Request<(Arc, String)>) -> tide::Result { diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index d2463610fb..103a65e782 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -215,6 +215,14 @@ impl ValueBuilderTrait for PutBuilder<'_, '_> { ..self } } + fn value>(self, value: T) -> Self { + let Value { payload, encoding } = value.into(); + Self { + payload, + encoding, + ..self + } + } } impl PutBuilder<'_, '_> { @@ -798,6 +806,15 @@ impl ValueBuilderTrait for PutPublication<'_> { ..self } } + + fn value>(self, value: T) -> Self { + let Value { payload, encoding } = value.into(); + Self { + payload, + encoding, + ..self + } + } } impl TimestampBuilderTrait for DeletePublication<'_> { diff --git a/zenoh/src/query.rs b/zenoh/src/query.rs index 3a7ee771b3..5a1d443463 100644 --- a/zenoh/src/query.rs +++ b/zenoh/src/query.rs @@ -178,6 +178,13 @@ impl ValueBuilderTrait for GetBuilder<'_, '_, Handler> { let value = Some(self.value.unwrap_or_default().payload(payload)); Self { value, ..self } } + fn value>(self, value: T) -> Self { + let value: Value = value.into(); + Self { + value: if value.is_empty() { None } else { Some(value) }, + ..self + } + } } impl<'a, 'b> GetBuilder<'a, 'b, DefaultHandler> { @@ -328,48 +335,34 @@ impl<'a, 'b> GetBuilder<'a, 'b, DefaultHandler> { impl<'a, 'b, Handler> GetBuilder<'a, 'b, Handler> { /// Change the target of the query. #[inline] - pub fn target(mut self, target: QueryTarget) -> Self { - self.target = target; - self + pub fn target(self, target: QueryTarget) -> Self { + Self { target, ..self } } /// Change the consolidation mode of the query. #[inline] - pub fn consolidation>(mut self, consolidation: QC) -> Self { - self.consolidation = consolidation.into(); - self + pub fn consolidation>(self, consolidation: QC) -> Self { + Self { + consolidation: consolidation.into(), + ..self + } } /// Restrict the matching queryables that will receive the query /// to the ones that have the given [`Locality`](crate::prelude::Locality). #[zenoh_macros::unstable] #[inline] - pub fn allowed_destination(mut self, destination: Locality) -> Self { - self.destination = destination; - self + pub fn allowed_destination(self, destination: Locality) -> Self { + Self { + destination, + ..self + } } /// Set query timeout. #[inline] - pub fn timeout(mut self, timeout: Duration) -> Self { - self.timeout = timeout; - self - } - - /// Set query value. - #[inline] - pub fn with_value(mut self, value: IntoValue) -> Self - where - IntoValue: Into, - { - self.value = Some(value.into()); - self - } - - #[zenoh_macros::unstable] - pub fn with_attachment(mut self, attachment: Attachment) -> Self { - self.attachment = Some(attachment); - self + pub fn timeout(self, timeout: Duration) -> Self { + Self { timeout, ..self } } /// By default, `get` guarantees that it will only receive replies whose key expressions intersect diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index c9492394c4..aa5f041a2b 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -378,6 +378,13 @@ impl ValueBuilderTrait for ReplyBuilder<'_> { ..self } } + fn value>(self, value: T) -> Self { + let Value { payload, encoding } = value.into(); + Self { + sample_builder: self.sample_builder.payload(payload).encoding(encoding), + ..self + } + } } /// A builder returned by [`Query::reply_del()`](Query::reply) diff --git a/zenoh/src/sample/builder.rs b/zenoh/src/sample/builder.rs index 8c507c8119..1bd50e7f69 100644 --- a/zenoh/src/sample/builder.rs +++ b/zenoh/src/sample/builder.rs @@ -22,6 +22,7 @@ use crate::Payload; use crate::Priority; use crate::Sample; use crate::SampleKind; +use crate::Value; use uhlc::Timestamp; use zenoh_core::zresult; use zenoh_protocol::core::CongestionControl; @@ -56,6 +57,9 @@ pub trait ValueBuilderTrait { fn encoding>(self, encoding: T) -> Self; /// Sets the payload fn payload>(self, payload: T) -> Self; + /// Sets both payload and encoding at once. + /// This is convenient for passing user type which supports `Into` when both payload and encoding depends on user type + fn value>(self, value: T) -> Self; } #[derive(Debug)] @@ -221,6 +225,14 @@ impl ValueBuilderTrait for PutSampleBuilder { ..self.0 .0 })) } + fn value>(self, value: T) -> Self { + let Value { payload, encoding } = value.into(); + Self(SampleBuilder(Sample { + payload, + encoding, + ..self.0 .0 + })) + } } #[derive(Debug)] diff --git a/zenoh/src/value.rs b/zenoh/src/value.rs index 8ea5aef19f..92a87cb6c5 100644 --- a/zenoh/src/value.rs +++ b/zenoh/src/value.rs @@ -43,6 +43,11 @@ impl Value { encoding: Encoding::default(), } } + /// Checks if the [`Value`] is empty. + /// Value is considered empty if its payload is empty and encoding is default. + pub fn is_empty(&self) -> bool { + self.payload.is_empty() && self.encoding == Encoding::default() + } } impl ValueBuilderTrait for Value { @@ -58,6 +63,10 @@ impl ValueBuilderTrait for Value { ..self } } + fn value>(self, value: T) -> Self { + let Value { payload, encoding } = value.into(); + Self { payload, encoding } + } } impl From for Value @@ -72,6 +81,15 @@ where } } +impl From> for Value +where + T: Into, +{ + fn from(t: Option) -> Self { + t.map_or_else(Value::empty, Into::into) + } +} + impl Default for Value { fn default() -> Self { Value::empty() diff --git a/zenoh/tests/attachments.rs b/zenoh/tests/attachments.rs index f50e33cf6f..2725351ab0 100644 --- a/zenoh/tests/attachments.rs +++ b/zenoh/tests/attachments.rs @@ -100,13 +100,13 @@ fn queries() { } let get = zenoh .get("test/attachment") - .with_value("query") - .with_attachment( + .payload("query") + .attachment(Some( backer .iter() .map(|b| (b.0.as_slice(), b.1.as_slice())) .collect(), - ) + )) .res() .unwrap(); while let Ok(reply) = get.recv() { diff --git a/zenoh/tests/handler.rs b/zenoh/tests/handler.rs index c1e912fc75..ceed15e2c3 100644 --- a/zenoh/tests/handler.rs +++ b/zenoh/tests/handler.rs @@ -57,12 +57,12 @@ fn query_with_ringbuffer() { let _reply1 = zenoh .get("test/ringbuffer_query") - .with_value("query1") + .payload("query1") .res() .unwrap(); let _reply2 = zenoh .get("test/ringbuffer_query") - .with_value("query2") + .payload("query2") .res() .unwrap(); From b5a1f6b1eb3fd3310f233d54abc9135449d4630a Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 17:32:48 +0100 Subject: [PATCH 44/63] with removed --- zenoh/src/queryable.rs | 2 +- zenoh/src/sample/builder.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index aa5f041a2b..aec45c46df 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -138,7 +138,7 @@ impl Query { IntoPayload: Into, { let sample_builder = - SampleBuilder::put(key_expr, payload).with_qos(response::ext::QoSType::RESPONSE.into()); + SampleBuilder::put(key_expr, payload).qos(response::ext::QoSType::RESPONSE.into()); ReplyBuilder { query: self, sample_builder, diff --git a/zenoh/src/sample/builder.rs b/zenoh/src/sample/builder.rs index 1bd50e7f69..920bd2b7b7 100644 --- a/zenoh/src/sample/builder.rs +++ b/zenoh/src/sample/builder.rs @@ -171,14 +171,14 @@ impl PutSampleBuilder { })) } /// Allows to change keyexpr of [`Sample`] - pub fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self + pub fn keyexpr(self, key_expr: IntoKeyExpr) -> Self where IntoKeyExpr: Into>, { Self(self.0.keyexpr(key_expr)) } // It's convenient to set QoS as a whole for internal usage. For user API there are `congestion_control`, `priority` and `express` methods. - pub(crate) fn with_qos(self, qos: QoS) -> Self { + pub(crate) fn qos(self, qos: QoS) -> Self { Self(SampleBuilder(Sample { qos, ..self.0 .0 })) } } From 1c9515704f25020468a22bf0dfe52d8cc0fb17cb Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 17:37:48 +0100 Subject: [PATCH 45/63] commented code removed --- examples/examples/z_get.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/examples/z_get.rs b/examples/examples/z_get.rs index 074f931eff..259137ee4a 100644 --- a/examples/examples/z_get.rs +++ b/examples/examples/z_get.rs @@ -28,10 +28,6 @@ async fn main() { let session = zenoh::open(config).res().await.unwrap(); println!("Sending Query '{selector}'..."); - // let replies = match value { - // Some(value) => session.get(&selector).payload(value), - // None => session.get(&selector), - // } let replies = session .get(&selector) .value(value.map(Value::from)) From d9eb96a8d86c232513f6c93b1d8a3d2f57ef9f1a Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 17:45:07 +0100 Subject: [PATCH 46/63] map-from removed --- examples/examples/z_get.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/examples/z_get.rs b/examples/examples/z_get.rs index 259137ee4a..542f94ba63 100644 --- a/examples/examples/z_get.rs +++ b/examples/examples/z_get.rs @@ -30,7 +30,7 @@ async fn main() { println!("Sending Query '{selector}'..."); let replies = session .get(&selector) - .value(value.map(Value::from)) + .value(value) .target(target) .timeout(timeout) .res() From e4501f403f11837a9d143dc9f3f91801498b33fa Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 18:01:14 +0100 Subject: [PATCH 47/63] build warnings fixed --- zenoh/tests/routing.rs | 16 +--------------- zenoh/tests/session.rs | 1 - zenoh/tests/unicity.rs | 1 - 3 files changed, 1 insertion(+), 17 deletions(-) diff --git a/zenoh/tests/routing.rs b/zenoh/tests/routing.rs index 056680ffd4..830f22a475 100644 --- a/zenoh/tests/routing.rs +++ b/zenoh/tests/routing.rs @@ -11,29 +11,15 @@ // Contributors: // ZettaScale Zenoh Team, // -use async_std::prelude::FutureExt; -use futures::future::try_join_all; -use futures::FutureExt as _; use std::str::FromStr; use std::sync::atomic::Ordering; use std::sync::{atomic::AtomicUsize, Arc}; use std::time::Duration; -use std::{ - str::FromStr, - sync::{atomic::AtomicUsize, atomic::Ordering, Arc}, - time::Duration, -}; use tokio_util::{sync::CancellationToken, task::TaskTracker}; use zenoh::config::{Config, ModeDependentValue}; use zenoh::prelude::r#async::*; use zenoh::sample::builder::QoSBuilderTrait; -use zenoh::{ - config::{Config, ModeDependentValue}, - prelude::r#async::*, - Result, -}; -use zenoh::{value::Value, Result}; -use zenoh_core::zasync_executor_init; +use zenoh::Result; use zenoh_core::ztimeout; use zenoh_protocol::core::{WhatAmI, WhatAmIMatcher}; use zenoh_result::bail; diff --git a/zenoh/tests/session.rs b/zenoh/tests/session.rs index 640f23da52..cd7335c28e 100644 --- a/zenoh/tests/session.rs +++ b/zenoh/tests/session.rs @@ -16,7 +16,6 @@ use std::sync::Arc; use std::time::Duration; use zenoh::prelude::r#async::*; use zenoh::sample::builder::QoSBuilderTrait; -use zenoh_core::zasync_executor_init; use zenoh_core::ztimeout; const TIMEOUT: Duration = Duration::from_secs(60); diff --git a/zenoh/tests/unicity.rs b/zenoh/tests/unicity.rs index f92a26d6c0..a71a0a8034 100644 --- a/zenoh/tests/unicity.rs +++ b/zenoh/tests/unicity.rs @@ -17,7 +17,6 @@ use std::time::Duration; use tokio::runtime::Handle; use zenoh::prelude::r#async::*; use zenoh::sample::builder::QoSBuilderTrait; -use zenoh_core::zasync_executor_init; use zenoh_core::ztimeout; const TIMEOUT: Duration = Duration::from_secs(60); From 43a49379c0f126032f89505789d158b908c62ad6 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Fri, 29 Mar 2024 18:18:28 +0100 Subject: [PATCH 48/63] SampleBuilder uses generics --- Cargo.lock | 50 ++--- zenoh/src/queryable.rs | 97 ++-------- zenoh/src/sample/builder.rs | 363 +++++++++++++++--------------------- 3 files changed, 189 insertions(+), 321 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d3ea8978b5..9dff82ad80 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -165,9 +165,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.12" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ "anstyle", "anstyle-parse", @@ -1103,9 +1103,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c012a26a7f605efc424dd53697843a72be7dc86ad2d01f7814337794a12231d" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" dependencies = [ "anstream", "anstyle", @@ -1122,9 +1122,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "erased-serde" -version = "0.3.31" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" +checksum = "2b73807008a3c7f171cc40312f37d95ef0396e048b5848d775f54b1a4dd4a0d3" dependencies = [ "serde", ] @@ -1541,9 +1541,9 @@ dependencies = [ [[package]] name = "http" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -1854,9 +1854,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" dependencies = [ "serde", "value-bag", @@ -2865,9 +2865,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.2" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c" dependencies = [ "log", "ring 0.17.6", @@ -2923,9 +2923,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" +checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" [[package]] name = "rustls-webpki" @@ -3701,9 +3701,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -3743,7 +3743,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls 0.22.2", + "rustls 0.22.3", "rustls-pki-types", "tokio", ] @@ -4030,9 +4030,9 @@ dependencies = [ [[package]] name = "value-bag" -version = "1.4.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3" +checksum = "74797339c3b98616c009c7c3eb53a0ce41e85c8ec66bd3db96ed132d20cfdee8" dependencies = [ "value-bag-serde1", "value-bag-sval2", @@ -4040,9 +4040,9 @@ dependencies = [ [[package]] name = "value-bag-serde1" -version = "1.4.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b9f3feef403a50d4d67e9741a6d8fc688bcbb4e4f31bd4aab72cc690284394" +checksum = "cc35703541cbccb5278ef7b589d79439fc808ff0b5867195a3230f9a47421d39" dependencies = [ "erased-serde", "serde", @@ -4051,9 +4051,9 @@ dependencies = [ [[package]] name = "value-bag-sval2" -version = "1.4.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b24f4146b6f3361e91cbf527d1fb35e9376c3c0cef72ca5ec5af6d640fad7d" +checksum = "285b43c29d0b4c0e65aad24561baee67a1b69dc9be9375d4a85138cbf556f7f8" dependencies = [ "sval", "sval_buffer", @@ -4676,7 +4676,7 @@ dependencies = [ "flume", "futures", "log", - "rustls 0.22.2", + "rustls 0.22.3", "rustls-webpki 0.102.2", "serde", "tokio", @@ -4763,7 +4763,7 @@ dependencies = [ "base64 0.21.4", "futures", "log", - "rustls 0.22.2", + "rustls 0.22.3", "rustls-pemfile 2.0.0", "rustls-pki-types", "rustls-webpki 0.102.2", diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 5df0d73d44..0e977f3def 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -19,8 +19,8 @@ use crate::handlers::{locked, DefaultHandler}; use crate::net::primitives::Primitives; use crate::prelude::*; use crate::sample::builder::{ - DeleteSampleBuilder, PutSampleBuilder, QoSBuilderTrait, SampleBuilder, SampleBuilderTrait, - TimestampBuilderTrait, ValueBuilderTrait, + OpDelete, OpPut, QoSBuilderTrait, SampleBuilder, SampleBuilderTrait, TimestampBuilderTrait, + ValueBuilderTrait, }; use crate::sample::SourceInfo; use crate::Id; @@ -115,10 +115,10 @@ impl Query { #[inline(always)] #[cfg(feature = "unstable")] #[doc(hidden)] - pub fn reply_sample(&self, sample: Sample) -> ReplySampleBuilder<'_> { - ReplySampleBuilder { + pub fn reply_sample(&self, sample: Sample) -> ReplySample<'_> { + ReplySample { query: self, - sample_builder: sample.into(), + sample, } } @@ -168,7 +168,7 @@ impl Query { IntoKeyExpr: Into>, { let sample_builder = - DeleteSampleBuilder::new(key_expr).with_qos(response::ext::QoSType::RESPONSE.into()); + SampleBuilder::delete(key_expr).qos(response::ext::QoSType::RESPONSE.into()); ReplyDelBuilder { query: self, sample_builder, @@ -214,91 +214,22 @@ impl fmt::Display for Query { } } -pub struct ReplySampleBuilder<'a> { +pub struct ReplySample<'a> { query: &'a Query, - sample_builder: SampleBuilder, + sample: Sample, } -impl<'a> ReplySampleBuilder<'a> { - pub fn put(self, payload: IntoPayload) -> ReplyBuilder<'a> - where - IntoPayload: Into, - { - let builder = ReplyBuilder { - query: self.query, - sample_builder: self.sample_builder.into(), - }; - builder.payload(payload) - } - pub fn delete(self) -> ReplyDelBuilder<'a> { - ReplyDelBuilder { - query: self.query, - sample_builder: self.sample_builder.into(), - } - } -} - -impl TimestampBuilderTrait for ReplySampleBuilder<'_> { - fn timestamp>>(self, timestamp: T) -> Self { - Self { - sample_builder: self.sample_builder.timestamp(timestamp), - ..self - } - } -} - -impl SampleBuilderTrait for ReplySampleBuilder<'_> { - #[cfg(feature = "unstable")] - fn source_info(self, source_info: SourceInfo) -> Self { - Self { - sample_builder: self.sample_builder.source_info(source_info), - ..self - } - } - - #[cfg(feature = "unstable")] - fn attachment>>(self, attachment: T) -> Self { - Self { - sample_builder: self.sample_builder.attachment(attachment), - ..self - } - } -} - -impl QoSBuilderTrait for ReplySampleBuilder<'_> { - fn congestion_control(self, congestion_control: CongestionControl) -> Self { - Self { - sample_builder: self.sample_builder.congestion_control(congestion_control), - ..self - } - } - - fn priority(self, priority: Priority) -> Self { - Self { - sample_builder: self.sample_builder.priority(priority), - ..self - } - } - - fn express(self, is_express: bool) -> Self { - Self { - sample_builder: self.sample_builder.express(is_express), - ..self - } - } -} - -impl Resolvable for ReplySampleBuilder<'_> { +impl Resolvable for ReplySample<'_> { type To = ZResult<()>; } -impl SyncResolve for ReplySampleBuilder<'_> { +impl SyncResolve for ReplySample<'_> { fn res_sync(self) -> ::To { - self.query._reply_sample(self.sample_builder.into()) + self.query._reply_sample(self.sample) } } -impl AsyncResolve for ReplySampleBuilder<'_> { +impl AsyncResolve for ReplySample<'_> { type Future = Ready; fn res_async(self) -> Self::Future { @@ -311,7 +242,7 @@ impl AsyncResolve for ReplySampleBuilder<'_> { #[derive(Debug)] pub struct ReplyBuilder<'a> { query: &'a Query, - sample_builder: PutSampleBuilder, + sample_builder: SampleBuilder, } impl TimestampBuilderTrait for ReplyBuilder<'_> { @@ -392,7 +323,7 @@ impl ValueBuilderTrait for ReplyBuilder<'_> { #[derive(Debug)] pub struct ReplyDelBuilder<'a> { query: &'a Query, - sample_builder: DeleteSampleBuilder, + sample_builder: SampleBuilder, } impl TimestampBuilderTrait for ReplyDelBuilder<'_> { diff --git a/zenoh/src/sample/builder.rs b/zenoh/src/sample/builder.rs index 920bd2b7b7..cae58514ff 100644 --- a/zenoh/src/sample/builder.rs +++ b/zenoh/src/sample/builder.rs @@ -12,6 +12,8 @@ // ZettaScale Zenoh Team, // +use std::marker::PhantomData; + use crate::sample::Attachment; use crate::sample::QoS; use crate::sample::QoSBuilder; @@ -63,290 +65,225 @@ pub trait ValueBuilderTrait { } #[derive(Debug)] -pub struct SampleBuilder(Sample); +pub struct OpPut; +#[derive(Debug)] +pub struct OpDelete; +#[derive(Debug)] +pub struct OpAny; -impl SampleBuilder { +#[derive(Debug)] +pub struct SampleBuilder { + sample: Sample, + _t: PhantomData, +} + +impl SampleBuilder { pub fn put( key_expr: IntoKeyExpr, payload: IntoPayload, - ) -> PutSampleBuilder + ) -> SampleBuilder where IntoKeyExpr: Into>, IntoPayload: Into, { - PutSampleBuilder::new(key_expr, payload) + Self { + sample: Sample { + key_expr: key_expr.into(), + payload: payload.into(), + kind: SampleKind::Put, + encoding: Encoding::default(), + timestamp: None, + qos: QoS::default(), + #[cfg(feature = "unstable")] + source_info: SourceInfo::empty(), + #[cfg(feature = "unstable")] + attachment: None, + }, + _t: PhantomData::, + } } - pub fn delete(key_expr: IntoKeyExpr) -> DeleteSampleBuilder +} + +impl SampleBuilder { + pub fn delete(key_expr: IntoKeyExpr) -> SampleBuilder where IntoKeyExpr: Into>, { - DeleteSampleBuilder::new(key_expr) + Self { + sample: Sample { + key_expr: key_expr.into(), + payload: Payload::empty(), + kind: SampleKind::Delete, + encoding: Encoding::default(), + timestamp: None, + qos: QoS::default(), + #[cfg(feature = "unstable")] + source_info: SourceInfo::empty(), + #[cfg(feature = "unstable")] + attachment: None, + }, + _t: PhantomData::, + } } +} + +impl SampleBuilder { /// Allows to change keyexpr of [`Sample`] pub fn keyexpr(self, key_expr: IntoKeyExpr) -> Self where IntoKeyExpr: Into>, { - Self(Sample { - key_expr: key_expr.into(), - ..self.0 - }) + Self { + sample: Sample { + key_expr: key_expr.into(), + ..self.sample + }, + _t: PhantomData::, + } } } -impl TimestampBuilderTrait for SampleBuilder { - fn timestamp>>(self, timestamp: T) -> Self { - Self(Sample { - timestamp: timestamp.into(), - ..self.0 - }) +impl TimestampBuilderTrait for SampleBuilder { + fn timestamp>>(self, timestamp: U) -> Self { + Self { + sample: Sample { + timestamp: timestamp.into(), + ..self.sample + }, + _t: PhantomData::, + } } } -impl SampleBuilderTrait for SampleBuilder { +impl SampleBuilderTrait for SampleBuilder { #[zenoh_macros::unstable] fn source_info(self, source_info: SourceInfo) -> Self { - Self(Sample { - source_info, - ..self.0 - }) + Self { + sample: Sample { + source_info, + ..self.sample + }, + _t: PhantomData::, + } } #[zenoh_macros::unstable] - fn attachment>>(self, attachment: T) -> Self { - Self(Sample { - attachment: attachment.into(), - ..self.0 - }) - } -} - -impl QoSBuilderTrait for SampleBuilder { - fn congestion_control(self, congestion_control: CongestionControl) -> Self { - let qos: QoSBuilder = self.0.qos.into(); - let qos = qos.congestion_control(congestion_control).into(); - Self(Sample { qos, ..self.0 }) - } - fn priority(self, priority: Priority) -> Self { - let qos: QoSBuilder = self.0.qos.into(); - let qos = qos.priority(priority).into(); - Self(Sample { qos, ..self.0 }) - } - fn express(self, is_express: bool) -> Self { - let qos: QoSBuilder = self.0.qos.into(); - let qos = qos.express(is_express).into(); - Self(Sample { qos, ..self.0 }) - } -} - -#[derive(Debug)] -pub struct PutSampleBuilder(SampleBuilder); - -impl From for PutSampleBuilder { - fn from(sample_builder: SampleBuilder) -> Self { - Self(SampleBuilder(Sample { - kind: SampleKind::Put, - ..sample_builder.0 - })) - } -} - -impl PutSampleBuilder { - fn new(key_expr: IntoKeyExpr, payload: IntoPayload) -> Self - where - IntoKeyExpr: Into>, - IntoPayload: Into, - { - Self(SampleBuilder::from(Sample { - key_expr: key_expr.into(), - payload: payload.into(), - kind: SampleKind::Put, - encoding: Encoding::default(), - timestamp: None, - qos: QoS::default(), - #[cfg(feature = "unstable")] - source_info: SourceInfo::empty(), - #[cfg(feature = "unstable")] - attachment: None, - })) - } - /// Allows to change keyexpr of [`Sample`] - pub fn keyexpr(self, key_expr: IntoKeyExpr) -> Self - where - IntoKeyExpr: Into>, - { - Self(self.0.keyexpr(key_expr)) - } - // It's convenient to set QoS as a whole for internal usage. For user API there are `congestion_control`, `priority` and `express` methods. - pub(crate) fn qos(self, qos: QoS) -> Self { - Self(SampleBuilder(Sample { qos, ..self.0 .0 })) - } -} - -impl TimestampBuilderTrait for PutSampleBuilder { - fn timestamp>>(self, timestamp: T) -> Self { - Self(self.0.timestamp(timestamp)) + fn attachment>>(self, attachment: U) -> Self { + Self { + sample: Sample { + attachment: attachment.into(), + ..self.sample + }, + _t: PhantomData::, + } } } -impl SampleBuilderTrait for PutSampleBuilder { - #[zenoh_macros::unstable] - fn source_info(self, source_info: SourceInfo) -> Self { - Self(self.0.source_info(source_info)) - } - #[zenoh_macros::unstable] - fn attachment>>(self, attachment: T) -> Self { - Self(self.0.attachment(attachment)) +impl SampleBuilder { + pub fn qos(self, qos: QoS) -> Self { + Self { + sample: Sample { qos, ..self.sample }, + _t: PhantomData::, + } } } -impl QoSBuilderTrait for PutSampleBuilder { +impl QoSBuilderTrait for SampleBuilder { fn congestion_control(self, congestion_control: CongestionControl) -> Self { - Self(self.0.congestion_control(congestion_control)) + let qos: QoSBuilder = self.sample.qos.into(); + let qos = qos.congestion_control(congestion_control).into(); + Self { + sample: Sample { qos, ..self.sample }, + _t: PhantomData::, + } } fn priority(self, priority: Priority) -> Self { - Self(self.0.priority(priority)) + let qos: QoSBuilder = self.sample.qos.into(); + let qos = qos.priority(priority).into(); + Self { + sample: Sample { qos, ..self.sample }, + _t: PhantomData::, + } } fn express(self, is_express: bool) -> Self { - Self(self.0.express(is_express)) + let qos: QoSBuilder = self.sample.qos.into(); + let qos = qos.express(is_express).into(); + Self { + sample: Sample { qos, ..self.sample }, + _t: PhantomData::, + } } } -impl ValueBuilderTrait for PutSampleBuilder { +impl ValueBuilderTrait for SampleBuilder { fn encoding>(self, encoding: T) -> Self { - Self(SampleBuilder(Sample { - encoding: encoding.into(), - ..self.0 .0 - })) + Self { + sample: Sample { + encoding: encoding.into(), + ..self.sample + }, + _t: PhantomData::, + } } fn payload>(self, payload: T) -> Self { - Self(SampleBuilder(Sample { - payload: payload.into(), - ..self.0 .0 - })) + Self { + sample: Sample { + payload: payload.into(), + ..self.sample + }, + _t: PhantomData::, + } } fn value>(self, value: T) -> Self { let Value { payload, encoding } = value.into(); - Self(SampleBuilder(Sample { - payload, - encoding, - ..self.0 .0 - })) - } -} - -#[derive(Debug)] -pub struct DeleteSampleBuilder(SampleBuilder); - -impl From for DeleteSampleBuilder { - fn from(sample_builder: SampleBuilder) -> Self { - Self(SampleBuilder(Sample { - kind: SampleKind::Delete, - ..sample_builder.0 - })) - } -} - -impl DeleteSampleBuilder { - pub fn new(key_expr: IntoKeyExpr) -> Self - where - IntoKeyExpr: Into>, - { - Self(SampleBuilder::from(Sample { - key_expr: key_expr.into(), - payload: Payload::empty(), - kind: SampleKind::Delete, - encoding: Encoding::default(), - timestamp: None, - qos: QoS::default(), - #[cfg(feature = "unstable")] - source_info: SourceInfo::empty(), - #[cfg(feature = "unstable")] - attachment: None, - })) - } - /// Allows to change keyexpr of [`Sample`] - pub fn with_keyexpr(self, key_expr: IntoKeyExpr) -> Self - where - IntoKeyExpr: Into>, - { - Self(self.0.keyexpr(key_expr)) - } - // It's convenient to set QoS as a whole for internal usage. For user API there are `congestion_control`, `priority` and `express` methods. - pub(crate) fn with_qos(self, qos: QoS) -> Self { - Self(SampleBuilder(Sample { qos, ..self.0 .0 })) - } -} - -impl TimestampBuilderTrait for DeleteSampleBuilder { - fn timestamp>>(self, timestamp: T) -> Self { - Self(self.0.timestamp(timestamp)) - } -} - -impl SampleBuilderTrait for DeleteSampleBuilder { - #[zenoh_macros::unstable] - fn source_info(self, source_info: SourceInfo) -> Self { - Self(self.0.source_info(source_info)) - } - #[zenoh_macros::unstable] - fn attachment>>(self, attachment: T) -> Self { - Self(self.0.attachment(attachment)) - } -} - -impl QoSBuilderTrait for DeleteSampleBuilder { - fn congestion_control(self, congestion_control: CongestionControl) -> Self { - Self(self.0.congestion_control(congestion_control)) - } - fn priority(self, priority: Priority) -> Self { - Self(self.0.priority(priority)) - } - fn express(self, is_express: bool) -> Self { - Self(self.0.express(is_express)) + Self { + sample: Sample { + payload, + encoding, + ..self.sample + }, + _t: PhantomData::, + } } } -impl From for SampleBuilder { +impl From for SampleBuilder { fn from(sample: Sample) -> Self { - SampleBuilder(sample) + SampleBuilder { + sample, + _t: PhantomData::, + } } } -impl TryFrom for PutSampleBuilder { +impl TryFrom for SampleBuilder { type Error = zresult::Error; fn try_from(sample: Sample) -> Result { if sample.kind != SampleKind::Put { bail!("Sample is not a put sample") } - Ok(Self(SampleBuilder(sample))) + Ok(SampleBuilder { + sample, + _t: PhantomData::, + }) } } -impl TryFrom for DeleteSampleBuilder { +impl TryFrom for SampleBuilder { type Error = zresult::Error; fn try_from(sample: Sample) -> Result { if sample.kind != SampleKind::Delete { bail!("Sample is not a delete sample") } - Ok(Self(SampleBuilder(sample))) - } -} - -impl From for Sample { - fn from(sample_builder: SampleBuilder) -> Self { - sample_builder.0 - } -} - -impl From for Sample { - fn from(put_sample_builder: PutSampleBuilder) -> Self { - put_sample_builder.0 .0 + Ok(SampleBuilder { + sample, + _t: PhantomData::, + }) } } -impl From for Sample { - fn from(delete_sample_builder: DeleteSampleBuilder) -> Self { - delete_sample_builder.0 .0 +impl From> for Sample { + fn from(sample_builder: SampleBuilder) -> Self { + sample_builder.sample } } From 6c305a130043a66ee58f3985eb4f71eb708ff5dc Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Fri, 29 Mar 2024 18:35:40 +0100 Subject: [PATCH 49/63] Improve Query builders with generics --- zenoh/src/queryable.rs | 178 +++++++++++++----------------------- zenoh/src/sample/builder.rs | 65 ++++++------- 2 files changed, 99 insertions(+), 144 deletions(-) diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 0e977f3def..fea148e6e6 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -19,7 +19,7 @@ use crate::handlers::{locked, DefaultHandler}; use crate::net::primitives::Primitives; use crate::prelude::*; use crate::sample::builder::{ - OpDelete, OpPut, QoSBuilderTrait, SampleBuilder, SampleBuilderTrait, TimestampBuilderTrait, + op, QoSBuilderTrait, SampleBuilder, SampleBuilderTrait, TimestampBuilderTrait, ValueBuilderTrait, }; use crate::sample::SourceInfo; @@ -132,18 +132,19 @@ impl Query { &self, key_expr: IntoKeyExpr, payload: IntoPayload, - ) -> ReplyBuilder<'_> + ) -> ReplySampleBuilder<'_, op::Put> where IntoKeyExpr: Into>, IntoPayload: Into, { let sample_builder = SampleBuilder::put(key_expr, payload).qos(response::ext::QoSType::RESPONSE.into()); - ReplyBuilder { + ReplySampleBuilder { query: self, sample_builder, } } + /// Sends a error reply to this Query. /// #[inline(always)] @@ -163,13 +164,16 @@ impl Query { /// Unless the query has enabled disjoint replies (you can check this through [`Query::accepts_replies`]), /// replying on a disjoint key expression will result in an error when resolving the reply. #[inline(always)] - pub fn reply_del(&self, key_expr: IntoKeyExpr) -> ReplyDelBuilder<'_> + pub fn reply_del( + &self, + key_expr: IntoKeyExpr, + ) -> ReplySampleBuilder<'_, op::Delete> where IntoKeyExpr: Into>, { let sample_builder = SampleBuilder::delete(key_expr).qos(response::ext::QoSType::RESPONSE.into()); - ReplyDelBuilder { + ReplySampleBuilder { query: self, sample_builder, } @@ -240,13 +244,13 @@ impl AsyncResolve for ReplySample<'_> { /// A builder returned by [`Query::reply()`](Query::reply) #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] #[derive(Debug)] -pub struct ReplyBuilder<'a> { +pub struct ReplySampleBuilder<'a, T> { query: &'a Query, - sample_builder: SampleBuilder, + sample_builder: SampleBuilder, } -impl TimestampBuilderTrait for ReplyBuilder<'_> { - fn timestamp>>(self, timestamp: T) -> Self { +impl TimestampBuilderTrait for ReplySampleBuilder<'_, T> { + fn timestamp>>(self, timestamp: U) -> Self { Self { sample_builder: self.sample_builder.timestamp(timestamp), ..self @@ -254,7 +258,7 @@ impl TimestampBuilderTrait for ReplyBuilder<'_> { } } -impl SampleBuilderTrait for ReplyBuilder<'_> { +impl SampleBuilderTrait for ReplySampleBuilder<'_, T> { #[cfg(feature = "unstable")] fn source_info(self, source_info: SourceInfo) -> Self { Self { @@ -264,7 +268,7 @@ impl SampleBuilderTrait for ReplyBuilder<'_> { } #[cfg(feature = "unstable")] - fn attachment>>(self, attachment: T) -> Self { + fn attachment>>(self, attachment: U) -> Self { Self { sample_builder: self.sample_builder.attachment(attachment), ..self @@ -272,7 +276,7 @@ impl SampleBuilderTrait for ReplyBuilder<'_> { } } -impl QoSBuilderTrait for ReplyBuilder<'_> { +impl QoSBuilderTrait for ReplySampleBuilder<'_, T> { fn congestion_control(self, congestion_control: CongestionControl) -> Self { Self { sample_builder: self.sample_builder.congestion_control(congestion_control), @@ -295,7 +299,7 @@ impl QoSBuilderTrait for ReplyBuilder<'_> { } } -impl ValueBuilderTrait for ReplyBuilder<'_> { +impl ValueBuilderTrait for ReplySampleBuilder<'_, op::Put> { fn encoding>(self, encoding: T) -> Self { Self { sample_builder: self.sample_builder.encoding(encoding), @@ -318,101 +322,86 @@ impl ValueBuilderTrait for ReplyBuilder<'_> { } } -/// A builder returned by [`Query::reply_del()`](Query::reply) -#[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] -#[derive(Debug)] -pub struct ReplyDelBuilder<'a> { - query: &'a Query, - sample_builder: SampleBuilder, +impl<'a, T> Resolvable for ReplySampleBuilder<'a, T> { + type To = ZResult<()>; } -impl TimestampBuilderTrait for ReplyDelBuilder<'_> { - fn timestamp>>(self, timestamp: T) -> Self { - Self { - sample_builder: self.sample_builder.timestamp(timestamp), - ..self - } +impl SyncResolve for ReplySampleBuilder<'_, T> { + fn res_sync(self) -> ::To { + self.query._reply_sample(self.sample_builder.into()) } } -impl SampleBuilderTrait for ReplyDelBuilder<'_> { - #[cfg(feature = "unstable")] - fn source_info(self, source_info: SourceInfo) -> Self { - Self { - sample_builder: self.sample_builder.source_info(source_info), - ..self - } - } +impl<'a, T> AsyncResolve for ReplySampleBuilder<'a, T> { + type Future = Ready; - #[cfg(feature = "unstable")] - fn attachment>>(self, attachment: T) -> Self { - Self { - sample_builder: self.sample_builder.attachment(attachment), - ..self - } + fn res_async(self) -> Self::Future { + std::future::ready(self.res_sync()) } } -impl QoSBuilderTrait for ReplyDelBuilder<'_> { - fn congestion_control(self, congestion_control: CongestionControl) -> Self { +/// A builder returned by [`Query::reply_err()`](Query::reply_err). +#[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] +#[derive(Debug)] +pub struct ReplyErrBuilder<'a> { + query: &'a Query, + value: Value, +} + +impl ValueBuilderTrait for ReplyErrBuilder<'_> { + fn encoding>(self, encoding: T) -> Self { Self { - sample_builder: self.sample_builder.congestion_control(congestion_control), + value: self.value.encoding(encoding), ..self } } - fn priority(self, priority: Priority) -> Self { + fn payload>(self, payload: T) -> Self { Self { - sample_builder: self.sample_builder.priority(priority), + value: self.value.payload(payload), ..self } } - fn express(self, is_express: bool) -> Self { + fn value>(self, value: T) -> Self { Self { - sample_builder: self.sample_builder.express(is_express), + value: value.into(), ..self } } } -/// A builder returned by [`Query::reply_err()`](Query::reply_err). -#[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] -#[derive(Debug)] -pub struct ReplyErrBuilder<'a> { - query: &'a Query, - value: Value, -} - -impl<'a> Resolvable for ReplyBuilder<'a> { - type To = ZResult<()>; -} - -impl SyncResolve for ReplyBuilder<'_> { - fn res_sync(self) -> ::To { - self.query._reply_sample(self.sample_builder.into()) - } -} - -impl<'a> Resolvable for ReplyDelBuilder<'a> { +impl<'a> Resolvable for ReplyErrBuilder<'a> { type To = ZResult<()>; } -impl SyncResolve for ReplyDelBuilder<'_> { +impl SyncResolve for ReplyErrBuilder<'_> { fn res_sync(self) -> ::To { - self.query._reply_sample(self.sample_builder.into()) - } -} - -impl<'a> AsyncResolve for ReplyBuilder<'a> { - type Future = Ready; - - fn res_async(self) -> Self::Future { - std::future::ready(self.res_sync()) + self.query.inner.primitives.send_response(Response { + rid: self.query.inner.qid, + wire_expr: WireExpr { + scope: 0, + suffix: std::borrow::Cow::Owned(self.query.key_expr().as_str().to_owned()), + mapping: Mapping::Sender, + }, + payload: ResponseBody::Err(zenoh::Err { + encoding: self.value.encoding.into(), + ext_sinfo: None, + ext_unknown: vec![], + payload: self.value.payload.into(), + }), + ext_qos: response::ext::QoSType::RESPONSE, + ext_tstamp: None, + ext_respid: Some(response::ext::ResponderIdType { + zid: self.query.inner.zid, + eid: self.query.eid, + }), + }); + Ok(()) } } -impl<'a> AsyncResolve for ReplyDelBuilder<'a> { +impl<'a> AsyncResolve for ReplyErrBuilder<'a> { type Future = Ready; fn res_async(self) -> Self::Future { @@ -477,43 +466,6 @@ impl Query { } } -impl<'a> Resolvable for ReplyErrBuilder<'a> { - type To = ZResult<()>; -} - -impl SyncResolve for ReplyErrBuilder<'_> { - fn res_sync(self) -> ::To { - self.query.inner.primitives.send_response(Response { - rid: self.query.inner.qid, - wire_expr: WireExpr { - scope: 0, - suffix: std::borrow::Cow::Owned(self.query.key_expr().as_str().to_owned()), - mapping: Mapping::Sender, - }, - payload: ResponseBody::Err(zenoh::Err { - encoding: self.value.encoding.into(), - ext_sinfo: None, - ext_unknown: vec![], - payload: self.value.payload.into(), - }), - ext_qos: response::ext::QoSType::RESPONSE, - ext_tstamp: None, - ext_respid: Some(response::ext::ResponderIdType { - zid: self.query.inner.zid, - eid: self.query.eid, - }), - }); - Ok(()) - } -} -impl<'a> AsyncResolve for ReplyErrBuilder<'a> { - type Future = Ready; - - fn res_async(self) -> Self::Future { - std::future::ready(self.res_sync()) - } -} - pub(crate) struct QueryableState { pub(crate) id: Id, pub(crate) key_expr: WireExpr<'static>, diff --git a/zenoh/src/sample/builder.rs b/zenoh/src/sample/builder.rs index cae58514ff..1ec20209aa 100644 --- a/zenoh/src/sample/builder.rs +++ b/zenoh/src/sample/builder.rs @@ -64,12 +64,16 @@ pub trait ValueBuilderTrait { fn value>(self, value: T) -> Self; } -#[derive(Debug)] -pub struct OpPut; -#[derive(Debug)] -pub struct OpDelete; -#[derive(Debug)] -pub struct OpAny; +pub mod op { + #[derive(Debug)] + pub struct Put; + #[derive(Debug)] + pub struct Delete; + #[derive(Debug)] + pub struct Error; + #[derive(Debug)] + pub struct Any; +} #[derive(Debug)] pub struct SampleBuilder { @@ -77,11 +81,11 @@ pub struct SampleBuilder { _t: PhantomData, } -impl SampleBuilder { +impl SampleBuilder { pub fn put( key_expr: IntoKeyExpr, payload: IntoPayload, - ) -> SampleBuilder + ) -> SampleBuilder where IntoKeyExpr: Into>, IntoPayload: Into, @@ -99,13 +103,13 @@ impl SampleBuilder { #[cfg(feature = "unstable")] attachment: None, }, - _t: PhantomData::, + _t: PhantomData::, } } } -impl SampleBuilder { - pub fn delete(key_expr: IntoKeyExpr) -> SampleBuilder +impl SampleBuilder { + pub fn delete(key_expr: IntoKeyExpr) -> SampleBuilder where IntoKeyExpr: Into>, { @@ -122,7 +126,7 @@ impl SampleBuilder { #[cfg(feature = "unstable")] attachment: None, }, - _t: PhantomData::, + _t: PhantomData::, } } } @@ -141,6 +145,14 @@ impl SampleBuilder { _t: PhantomData::, } } + + // Allows to change qos as a whole of [`Sample`] + pub fn qos(self, qos: QoS) -> Self { + Self { + sample: Sample { qos, ..self.sample }, + _t: PhantomData::, + } + } } impl TimestampBuilderTrait for SampleBuilder { @@ -179,15 +191,6 @@ impl SampleBuilderTrait for SampleBuilder { } } -impl SampleBuilder { - pub fn qos(self, qos: QoS) -> Self { - Self { - sample: Sample { qos, ..self.sample }, - _t: PhantomData::, - } - } -} - impl QoSBuilderTrait for SampleBuilder { fn congestion_control(self, congestion_control: CongestionControl) -> Self { let qos: QoSBuilder = self.sample.qos.into(); @@ -215,14 +218,14 @@ impl QoSBuilderTrait for SampleBuilder { } } -impl ValueBuilderTrait for SampleBuilder { +impl ValueBuilderTrait for SampleBuilder { fn encoding>(self, encoding: T) -> Self { Self { sample: Sample { encoding: encoding.into(), ..self.sample }, - _t: PhantomData::, + _t: PhantomData::, } } fn payload>(self, payload: T) -> Self { @@ -231,7 +234,7 @@ impl ValueBuilderTrait for SampleBuilder { payload: payload.into(), ..self.sample }, - _t: PhantomData::, + _t: PhantomData::, } } fn value>(self, value: T) -> Self { @@ -242,21 +245,21 @@ impl ValueBuilderTrait for SampleBuilder { encoding, ..self.sample }, - _t: PhantomData::, + _t: PhantomData::, } } } -impl From for SampleBuilder { +impl From for SampleBuilder { fn from(sample: Sample) -> Self { SampleBuilder { sample, - _t: PhantomData::, + _t: PhantomData::, } } } -impl TryFrom for SampleBuilder { +impl TryFrom for SampleBuilder { type Error = zresult::Error; fn try_from(sample: Sample) -> Result { if sample.kind != SampleKind::Put { @@ -264,12 +267,12 @@ impl TryFrom for SampleBuilder { } Ok(SampleBuilder { sample, - _t: PhantomData::, + _t: PhantomData::, }) } } -impl TryFrom for SampleBuilder { +impl TryFrom for SampleBuilder { type Error = zresult::Error; fn try_from(sample: Sample) -> Result { if sample.kind != SampleKind::Delete { @@ -277,7 +280,7 @@ impl TryFrom for SampleBuilder { } Ok(SampleBuilder { sample, - _t: PhantomData::, + _t: PhantomData::, }) } } From bca953da3de684228241cbd1c8bc8641945b2b84 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Fri, 29 Mar 2024 18:36:58 +0100 Subject: [PATCH 50/63] Reorg sample files --- zenoh/src/sample.rs | 655 -------------------------------------------- 1 file changed, 655 deletions(-) delete mode 100644 zenoh/src/sample.rs diff --git a/zenoh/src/sample.rs b/zenoh/src/sample.rs deleted file mode 100644 index 2b71105d5e..0000000000 --- a/zenoh/src/sample.rs +++ /dev/null @@ -1,655 +0,0 @@ -// -// Copyright (c) 2023 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - -//! Sample primitives -use crate::encoding::Encoding; -use crate::payload::Payload; -use crate::prelude::{KeyExpr, Value}; -use crate::sample::builder::{QoSBuilderTrait, ValueBuilderTrait}; -use crate::time::Timestamp; -use crate::Priority; -#[zenoh_macros::unstable] -use serde::Serialize; -use std::{convert::TryFrom, fmt}; -use zenoh_protocol::core::EntityGlobalId; -use zenoh_protocol::network::declare::ext::QoSType; -use zenoh_protocol::{core::CongestionControl, zenoh}; - -pub mod builder; - -pub type SourceSn = u64; - -/// The locality of samples to be received by subscribers or targeted by publishers. -#[zenoh_macros::unstable] -#[derive(Clone, Copy, Debug, Default, Serialize, PartialEq, Eq)] -pub enum Locality { - SessionLocal, - Remote, - #[default] - Any, -} -#[cfg(not(feature = "unstable"))] -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -pub(crate) enum Locality { - SessionLocal, - Remote, - #[default] - Any, -} - -#[derive(Debug, Clone, PartialEq, Eq, Default)] -pub(crate) struct DataInfo { - pub kind: SampleKind, - pub encoding: Option, - pub timestamp: Option, - pub source_id: Option, - pub source_sn: Option, - pub qos: QoS, -} - -pub(crate) trait DataInfoIntoSample { - fn into_sample( - self, - key_expr: IntoKeyExpr, - payload: IntoPayload, - #[cfg(feature = "unstable")] attachment: Option, - ) -> Sample - where - IntoKeyExpr: Into>, - IntoPayload: Into; -} - -impl DataInfoIntoSample for DataInfo { - // This function is for internal use only. - // Technically it may create invalid sample (e.g. a delete sample with a payload and encoding) - // The test for it is intentionally not added to avoid inserting extra "if" into hot path. - // The correctness of the data should be ensured by the caller. - #[inline] - fn into_sample( - self, - key_expr: IntoKeyExpr, - payload: IntoPayload, - #[cfg(feature = "unstable")] attachment: Option, - ) -> Sample - where - IntoKeyExpr: Into>, - IntoPayload: Into, - { - Sample { - key_expr: key_expr.into(), - payload: payload.into(), - kind: self.kind, - encoding: self.encoding.unwrap_or_default(), - timestamp: self.timestamp, - qos: self.qos, - #[cfg(feature = "unstable")] - source_info: SourceInfo { - source_id: self.source_id, - source_sn: self.source_sn, - }, - #[cfg(feature = "unstable")] - attachment, - } - } -} - -impl DataInfoIntoSample for Option { - #[inline] - fn into_sample( - self, - key_expr: IntoKeyExpr, - payload: IntoPayload, - #[cfg(feature = "unstable")] attachment: Option, - ) -> Sample - where - IntoKeyExpr: Into>, - IntoPayload: Into, - { - if let Some(data_info) = self { - data_info.into_sample(key_expr, payload, attachment) - } else { - Sample { - key_expr: key_expr.into(), - payload: payload.into(), - kind: SampleKind::Put, - encoding: Encoding::default(), - timestamp: None, - qos: QoS::default(), - #[cfg(feature = "unstable")] - source_info: SourceInfo::empty(), - #[cfg(feature = "unstable")] - attachment, - } - } - } -} - -/// Informations on the source of a zenoh [`Sample`]. -#[zenoh_macros::unstable] -#[derive(Debug, Clone)] -pub struct SourceInfo { - /// The [`EntityGlobalId`] of the zenoh entity that published the concerned [`Sample`]. - pub source_id: Option, - /// The sequence number of the [`Sample`] from the source. - pub source_sn: Option, -} - -#[test] -#[cfg(feature = "unstable")] -fn source_info_stack_size() { - use crate::{ - sample::{SourceInfo, SourceSn}, - ZenohId, - }; - - assert_eq!(std::mem::size_of::(), 16); - assert_eq!(std::mem::size_of::>(), 17); - assert_eq!(std::mem::size_of::>(), 16); - assert_eq!(std::mem::size_of::(), 17 + 16 + 7); -} - -#[zenoh_macros::unstable] -impl SourceInfo { - pub(crate) fn empty() -> Self { - SourceInfo { - source_id: None, - source_sn: None, - } - } - pub(crate) fn is_empty(&self) -> bool { - self.source_id.is_none() && self.source_sn.is_none() - } -} - -impl From for Option { - fn from(source_info: SourceInfo) -> Option { - if source_info.is_empty() { - None - } else { - Some(zenoh::put::ext::SourceInfoType { - id: source_info.source_id.unwrap_or_default(), - sn: source_info.source_sn.unwrap_or_default() as u32, - }) - } - } -} - -#[zenoh_macros::unstable] -impl From for SourceInfo { - fn from(data_info: DataInfo) -> Self { - SourceInfo { - source_id: data_info.source_id, - source_sn: data_info.source_sn, - } - } -} - -#[zenoh_macros::unstable] -impl From> for SourceInfo { - fn from(data_info: Option) -> Self { - match data_info { - Some(data_info) => data_info.into(), - None => SourceInfo::empty(), - } - } -} - -mod attachment { - #[zenoh_macros::unstable] - use zenoh_buffers::{ - reader::{HasReader, Reader}, - writer::HasWriter, - ZBuf, ZBufReader, ZSlice, - }; - #[zenoh_macros::unstable] - use zenoh_codec::{RCodec, WCodec, Zenoh080}; - #[zenoh_macros::unstable] - use zenoh_protocol::zenoh::ext::AttachmentType; - - /// A builder for [`Attachment`] - #[zenoh_macros::unstable] - #[derive(Debug)] - pub struct AttachmentBuilder { - pub(crate) inner: Vec, - } - #[zenoh_macros::unstable] - impl Default for AttachmentBuilder { - fn default() -> Self { - Self::new() - } - } - #[zenoh_macros::unstable] - impl AttachmentBuilder { - pub fn new() -> Self { - Self { inner: Vec::new() } - } - fn _insert(&mut self, key: &[u8], value: &[u8]) { - let codec = Zenoh080; - let mut writer = self.inner.writer(); - codec.write(&mut writer, key).unwrap(); // Infallible, barring alloc failure - codec.write(&mut writer, value).unwrap(); // Infallible, barring alloc failure - } - /// Inserts a key-value pair to the attachment. - /// - /// Note that [`Attachment`] is a list of non-unique key-value pairs: inserting at the same key multiple times leads to both values being transmitted for that key. - pub fn insert + ?Sized, Value: AsRef<[u8]> + ?Sized>( - &mut self, - key: &Key, - value: &Value, - ) { - self._insert(key.as_ref(), value.as_ref()) - } - pub fn build(self) -> Attachment { - Attachment { - inner: self.inner.into(), - } - } - } - #[zenoh_macros::unstable] - impl From for Attachment { - fn from(value: AttachmentBuilder) -> Self { - Attachment { - inner: value.inner.into(), - } - } - } - #[zenoh_macros::unstable] - impl From for Option { - fn from(value: AttachmentBuilder) -> Self { - if value.inner.is_empty() { - None - } else { - Some(value.into()) - } - } - } - - #[zenoh_macros::unstable] - #[derive(Clone)] - pub struct Attachment { - pub(crate) inner: ZBuf, - } - #[zenoh_macros::unstable] - impl Default for Attachment { - fn default() -> Self { - Self::new() - } - } - #[zenoh_macros::unstable] - impl From for AttachmentType { - fn from(this: Attachment) -> Self { - AttachmentType { buffer: this.inner } - } - } - #[zenoh_macros::unstable] - impl From> for Attachment { - fn from(this: AttachmentType) -> Self { - Attachment { inner: this.buffer } - } - } - #[zenoh_macros::unstable] - impl Attachment { - pub fn new() -> Self { - Self { - inner: ZBuf::empty(), - } - } - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - pub fn len(&self) -> usize { - self.iter().count() - } - pub fn iter(&self) -> AttachmentIterator { - self.into_iter() - } - fn _get(&self, key: &[u8]) -> Option { - self.iter() - .find_map(|(k, v)| (k.as_slice() == key).then_some(v)) - } - pub fn get>(&self, key: &Key) -> Option { - self._get(key.as_ref()) - } - fn _insert(&mut self, key: &[u8], value: &[u8]) { - let codec = Zenoh080; - let mut writer = self.inner.writer(); - codec.write(&mut writer, key).unwrap(); // Infallible, barring alloc failure - codec.write(&mut writer, value).unwrap(); // Infallible, barring alloc failure - } - /// Inserts a key-value pair to the attachment. - /// - /// Note that [`Attachment`] is a list of non-unique key-value pairs: inserting at the same key multiple times leads to both values being transmitted for that key. - /// - /// [`Attachment`] is not very efficient at inserting, so if you wish to perform multiple inserts, it's generally better to [`Attachment::extend`] after performing the inserts on an [`AttachmentBuilder`] - pub fn insert + ?Sized, Value: AsRef<[u8]> + ?Sized>( - &mut self, - key: &Key, - value: &Value, - ) { - self._insert(key.as_ref(), value.as_ref()) - } - fn _extend(&mut self, with: Self) -> &mut Self { - for slice in with.inner.zslices().cloned() { - self.inner.push_zslice(slice); - } - self - } - pub fn extend(&mut self, with: impl Into) -> &mut Self { - let with = with.into(); - self._extend(with) - } - } - #[zenoh_macros::unstable] - pub struct AttachmentIterator<'a> { - reader: ZBufReader<'a>, - } - #[zenoh_macros::unstable] - impl<'a> core::iter::IntoIterator for &'a Attachment { - type Item = (ZSlice, ZSlice); - type IntoIter = AttachmentIterator<'a>; - fn into_iter(self) -> Self::IntoIter { - AttachmentIterator { - reader: self.inner.reader(), - } - } - } - #[zenoh_macros::unstable] - impl core::fmt::Debug for Attachment { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{{")?; - for (key, value) in self { - let key = key.as_slice(); - let value = value.as_slice(); - match core::str::from_utf8(key) { - Ok(key) => write!(f, "\"{key}\": ")?, - Err(_) => { - write!(f, "0x")?; - for byte in key { - write!(f, "{byte:02X}")? - } - } - } - match core::str::from_utf8(value) { - Ok(value) => write!(f, "\"{value}\", ")?, - Err(_) => { - write!(f, "0x")?; - for byte in value { - write!(f, "{byte:02X}")? - } - write!(f, ", ")? - } - } - } - write!(f, "}}") - } - } - #[zenoh_macros::unstable] - impl<'a> core::iter::Iterator for AttachmentIterator<'a> { - type Item = (ZSlice, ZSlice); - fn next(&mut self) -> Option { - let key = Zenoh080.read(&mut self.reader).ok()?; - let value = Zenoh080.read(&mut self.reader).ok()?; - Some((key, value)) - } - fn size_hint(&self) -> (usize, Option) { - ( - (self.reader.remaining() != 0) as usize, - Some(self.reader.remaining() / 2), - ) - } - } - #[zenoh_macros::unstable] - impl<'a> core::iter::FromIterator<(&'a [u8], &'a [u8])> for AttachmentBuilder { - fn from_iter>(iter: T) -> Self { - let codec = Zenoh080; - let mut buffer: Vec = Vec::new(); - let mut writer = buffer.writer(); - for (key, value) in iter { - codec.write(&mut writer, key).unwrap(); // Infallible, barring allocation failures - codec.write(&mut writer, value).unwrap(); // Infallible, barring allocation failures - } - Self { inner: buffer } - } - } - #[zenoh_macros::unstable] - impl<'a> core::iter::FromIterator<(&'a [u8], &'a [u8])> for Attachment { - fn from_iter>(iter: T) -> Self { - AttachmentBuilder::from_iter(iter).into() - } - } -} - -/// The kind of a `Sample`. -#[repr(u8)] -#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] -pub enum SampleKind { - /// if the `Sample` was issued by a `put` operation. - #[default] - Put = 0, - /// if the `Sample` was issued by a `delete` operation. - Delete = 1, -} - -impl fmt::Display for SampleKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - SampleKind::Put => write!(f, "PUT"), - SampleKind::Delete => write!(f, "DELETE"), - } - } -} - -impl TryFrom for SampleKind { - type Error = u64; - fn try_from(kind: u64) -> Result { - match kind { - 0 => Ok(SampleKind::Put), - 1 => Ok(SampleKind::Delete), - _ => Err(kind), - } - } -} - -#[zenoh_macros::unstable] -pub use attachment::{Attachment, AttachmentBuilder, AttachmentIterator}; - -/// Structure with public fields for sample. It's convenient if it's necessary to decompose a sample into its fields. -pub struct SampleFields { - pub key_expr: KeyExpr<'static>, - pub payload: Payload, - pub kind: SampleKind, - pub encoding: Encoding, - pub timestamp: Option, - pub express: bool, - pub priority: Priority, - pub congestion_control: CongestionControl, - #[cfg(feature = "unstable")] - pub source_info: SourceInfo, - #[cfg(feature = "unstable")] - pub attachment: Option, -} - -impl From for SampleFields { - fn from(sample: Sample) -> Self { - SampleFields { - key_expr: sample.key_expr, - payload: sample.payload, - kind: sample.kind, - encoding: sample.encoding, - timestamp: sample.timestamp, - express: sample.qos.express(), - priority: sample.qos.priority(), - congestion_control: sample.qos.congestion_control(), - #[cfg(feature = "unstable")] - source_info: sample.source_info, - #[cfg(feature = "unstable")] - attachment: sample.attachment, - } - } -} - -/// A zenoh sample. -#[non_exhaustive] -#[derive(Clone, Debug)] -pub struct Sample { - pub(crate) key_expr: KeyExpr<'static>, - pub(crate) payload: Payload, - pub(crate) kind: SampleKind, - pub(crate) encoding: Encoding, - pub(crate) timestamp: Option, - pub(crate) qos: QoS, - - #[cfg(feature = "unstable")] - pub(crate) source_info: SourceInfo, - - #[cfg(feature = "unstable")] - pub(crate) attachment: Option, -} - -impl Sample { - /// Gets the key expression on which this Sample was published. - #[inline] - pub fn key_expr(&self) -> &KeyExpr<'static> { - &self.key_expr - } - - /// Gets the payload of this Sample. - #[inline] - pub fn payload(&self) -> &Payload { - &self.payload - } - - /// Gets the kind of this Sample. - #[inline] - pub fn kind(&self) -> SampleKind { - self.kind - } - - /// Gets the encoding of this sample - #[inline] - pub fn encoding(&self) -> &Encoding { - &self.encoding - } - - /// Gets the timestamp of this Sample. - #[inline] - pub fn timestamp(&self) -> Option<&Timestamp> { - self.timestamp.as_ref() - } - - /// Gets the quality of service settings this Sample was sent with. - #[inline] - pub fn qos(&self) -> &QoS { - &self.qos - } - - /// Gets infos on the source of this Sample. - #[zenoh_macros::unstable] - #[inline] - pub fn source_info(&self) -> &SourceInfo { - &self.source_info - } - - /// Gets the sample attachment: a map of key-value pairs, where each key and value are byte-slices. - #[zenoh_macros::unstable] - #[inline] - pub fn attachment(&self) -> Option<&Attachment> { - self.attachment.as_ref() - } -} - -impl From for Value { - fn from(sample: Sample) -> Self { - Value::new(sample.payload).encoding(sample.encoding) - } -} - -/// Structure containing quality of service data -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)] -pub struct QoS { - inner: QoSType, -} - -#[derive(Debug)] -pub struct QoSBuilder(QoS); - -impl From for QoSBuilder { - fn from(qos: QoS) -> Self { - QoSBuilder(qos) - } -} - -impl From for QoS { - fn from(builder: QoSBuilder) -> Self { - builder.0 - } -} - -impl QoSBuilderTrait for QoSBuilder { - fn congestion_control(self, congestion_control: CongestionControl) -> Self { - let mut inner = self.0.inner; - inner.set_congestion_control(congestion_control); - Self(QoS { inner }) - } - - fn priority(self, priority: Priority) -> Self { - let mut inner = self.0.inner; - inner.set_priority(priority.into()); - Self(QoS { inner }) - } - - fn express(self, is_express: bool) -> Self { - let mut inner = self.0.inner; - inner.set_is_express(is_express); - Self(QoS { inner }) - } -} - -impl QoS { - /// Gets priority of the message. - pub fn priority(&self) -> Priority { - match Priority::try_from(self.inner.get_priority()) { - Ok(p) => p, - Err(e) => { - log::trace!( - "Failed to convert priority: {}; replacing with default value", - e.to_string() - ); - Priority::default() - } - } - } - - /// Gets congestion control of the message. - pub fn congestion_control(&self) -> CongestionControl { - self.inner.get_congestion_control() - } - - /// Gets express flag value. If `true`, the message is not batched during transmission, in order to reduce latency. - pub fn express(&self) -> bool { - self.inner.is_express() - } -} - -impl From for QoS { - fn from(qos: QoSType) -> Self { - QoS { inner: qos } - } -} - -impl From for QoSType { - fn from(qos: QoS) -> Self { - qos.inner - } -} From 9d1a5409541831926e70420fdf89006a67b1020c Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Fri, 29 Mar 2024 18:37:23 +0100 Subject: [PATCH 51/63] Remove error op struct in SampleBuilder --- zenoh/src/sample/builder.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/zenoh/src/sample/builder.rs b/zenoh/src/sample/builder.rs index 1ec20209aa..7f438d1381 100644 --- a/zenoh/src/sample/builder.rs +++ b/zenoh/src/sample/builder.rs @@ -70,8 +70,6 @@ pub mod op { #[derive(Debug)] pub struct Delete; #[derive(Debug)] - pub struct Error; - #[derive(Debug)] pub struct Any; } From 7904d099ba3d069ecc51b76241ef136678a5e005 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Fri, 29 Mar 2024 20:29:43 +0100 Subject: [PATCH 52/63] Add forgotten file --- zenoh/src/sample/mod.rs | 655 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 655 insertions(+) create mode 100644 zenoh/src/sample/mod.rs diff --git a/zenoh/src/sample/mod.rs b/zenoh/src/sample/mod.rs new file mode 100644 index 0000000000..2b71105d5e --- /dev/null +++ b/zenoh/src/sample/mod.rs @@ -0,0 +1,655 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +//! Sample primitives +use crate::encoding::Encoding; +use crate::payload::Payload; +use crate::prelude::{KeyExpr, Value}; +use crate::sample::builder::{QoSBuilderTrait, ValueBuilderTrait}; +use crate::time::Timestamp; +use crate::Priority; +#[zenoh_macros::unstable] +use serde::Serialize; +use std::{convert::TryFrom, fmt}; +use zenoh_protocol::core::EntityGlobalId; +use zenoh_protocol::network::declare::ext::QoSType; +use zenoh_protocol::{core::CongestionControl, zenoh}; + +pub mod builder; + +pub type SourceSn = u64; + +/// The locality of samples to be received by subscribers or targeted by publishers. +#[zenoh_macros::unstable] +#[derive(Clone, Copy, Debug, Default, Serialize, PartialEq, Eq)] +pub enum Locality { + SessionLocal, + Remote, + #[default] + Any, +} +#[cfg(not(feature = "unstable"))] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub(crate) enum Locality { + SessionLocal, + Remote, + #[default] + Any, +} + +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub(crate) struct DataInfo { + pub kind: SampleKind, + pub encoding: Option, + pub timestamp: Option, + pub source_id: Option, + pub source_sn: Option, + pub qos: QoS, +} + +pub(crate) trait DataInfoIntoSample { + fn into_sample( + self, + key_expr: IntoKeyExpr, + payload: IntoPayload, + #[cfg(feature = "unstable")] attachment: Option, + ) -> Sample + where + IntoKeyExpr: Into>, + IntoPayload: Into; +} + +impl DataInfoIntoSample for DataInfo { + // This function is for internal use only. + // Technically it may create invalid sample (e.g. a delete sample with a payload and encoding) + // The test for it is intentionally not added to avoid inserting extra "if" into hot path. + // The correctness of the data should be ensured by the caller. + #[inline] + fn into_sample( + self, + key_expr: IntoKeyExpr, + payload: IntoPayload, + #[cfg(feature = "unstable")] attachment: Option, + ) -> Sample + where + IntoKeyExpr: Into>, + IntoPayload: Into, + { + Sample { + key_expr: key_expr.into(), + payload: payload.into(), + kind: self.kind, + encoding: self.encoding.unwrap_or_default(), + timestamp: self.timestamp, + qos: self.qos, + #[cfg(feature = "unstable")] + source_info: SourceInfo { + source_id: self.source_id, + source_sn: self.source_sn, + }, + #[cfg(feature = "unstable")] + attachment, + } + } +} + +impl DataInfoIntoSample for Option { + #[inline] + fn into_sample( + self, + key_expr: IntoKeyExpr, + payload: IntoPayload, + #[cfg(feature = "unstable")] attachment: Option, + ) -> Sample + where + IntoKeyExpr: Into>, + IntoPayload: Into, + { + if let Some(data_info) = self { + data_info.into_sample(key_expr, payload, attachment) + } else { + Sample { + key_expr: key_expr.into(), + payload: payload.into(), + kind: SampleKind::Put, + encoding: Encoding::default(), + timestamp: None, + qos: QoS::default(), + #[cfg(feature = "unstable")] + source_info: SourceInfo::empty(), + #[cfg(feature = "unstable")] + attachment, + } + } + } +} + +/// Informations on the source of a zenoh [`Sample`]. +#[zenoh_macros::unstable] +#[derive(Debug, Clone)] +pub struct SourceInfo { + /// The [`EntityGlobalId`] of the zenoh entity that published the concerned [`Sample`]. + pub source_id: Option, + /// The sequence number of the [`Sample`] from the source. + pub source_sn: Option, +} + +#[test] +#[cfg(feature = "unstable")] +fn source_info_stack_size() { + use crate::{ + sample::{SourceInfo, SourceSn}, + ZenohId, + }; + + assert_eq!(std::mem::size_of::(), 16); + assert_eq!(std::mem::size_of::>(), 17); + assert_eq!(std::mem::size_of::>(), 16); + assert_eq!(std::mem::size_of::(), 17 + 16 + 7); +} + +#[zenoh_macros::unstable] +impl SourceInfo { + pub(crate) fn empty() -> Self { + SourceInfo { + source_id: None, + source_sn: None, + } + } + pub(crate) fn is_empty(&self) -> bool { + self.source_id.is_none() && self.source_sn.is_none() + } +} + +impl From for Option { + fn from(source_info: SourceInfo) -> Option { + if source_info.is_empty() { + None + } else { + Some(zenoh::put::ext::SourceInfoType { + id: source_info.source_id.unwrap_or_default(), + sn: source_info.source_sn.unwrap_or_default() as u32, + }) + } + } +} + +#[zenoh_macros::unstable] +impl From for SourceInfo { + fn from(data_info: DataInfo) -> Self { + SourceInfo { + source_id: data_info.source_id, + source_sn: data_info.source_sn, + } + } +} + +#[zenoh_macros::unstable] +impl From> for SourceInfo { + fn from(data_info: Option) -> Self { + match data_info { + Some(data_info) => data_info.into(), + None => SourceInfo::empty(), + } + } +} + +mod attachment { + #[zenoh_macros::unstable] + use zenoh_buffers::{ + reader::{HasReader, Reader}, + writer::HasWriter, + ZBuf, ZBufReader, ZSlice, + }; + #[zenoh_macros::unstable] + use zenoh_codec::{RCodec, WCodec, Zenoh080}; + #[zenoh_macros::unstable] + use zenoh_protocol::zenoh::ext::AttachmentType; + + /// A builder for [`Attachment`] + #[zenoh_macros::unstable] + #[derive(Debug)] + pub struct AttachmentBuilder { + pub(crate) inner: Vec, + } + #[zenoh_macros::unstable] + impl Default for AttachmentBuilder { + fn default() -> Self { + Self::new() + } + } + #[zenoh_macros::unstable] + impl AttachmentBuilder { + pub fn new() -> Self { + Self { inner: Vec::new() } + } + fn _insert(&mut self, key: &[u8], value: &[u8]) { + let codec = Zenoh080; + let mut writer = self.inner.writer(); + codec.write(&mut writer, key).unwrap(); // Infallible, barring alloc failure + codec.write(&mut writer, value).unwrap(); // Infallible, barring alloc failure + } + /// Inserts a key-value pair to the attachment. + /// + /// Note that [`Attachment`] is a list of non-unique key-value pairs: inserting at the same key multiple times leads to both values being transmitted for that key. + pub fn insert + ?Sized, Value: AsRef<[u8]> + ?Sized>( + &mut self, + key: &Key, + value: &Value, + ) { + self._insert(key.as_ref(), value.as_ref()) + } + pub fn build(self) -> Attachment { + Attachment { + inner: self.inner.into(), + } + } + } + #[zenoh_macros::unstable] + impl From for Attachment { + fn from(value: AttachmentBuilder) -> Self { + Attachment { + inner: value.inner.into(), + } + } + } + #[zenoh_macros::unstable] + impl From for Option { + fn from(value: AttachmentBuilder) -> Self { + if value.inner.is_empty() { + None + } else { + Some(value.into()) + } + } + } + + #[zenoh_macros::unstable] + #[derive(Clone)] + pub struct Attachment { + pub(crate) inner: ZBuf, + } + #[zenoh_macros::unstable] + impl Default for Attachment { + fn default() -> Self { + Self::new() + } + } + #[zenoh_macros::unstable] + impl From for AttachmentType { + fn from(this: Attachment) -> Self { + AttachmentType { buffer: this.inner } + } + } + #[zenoh_macros::unstable] + impl From> for Attachment { + fn from(this: AttachmentType) -> Self { + Attachment { inner: this.buffer } + } + } + #[zenoh_macros::unstable] + impl Attachment { + pub fn new() -> Self { + Self { + inner: ZBuf::empty(), + } + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn len(&self) -> usize { + self.iter().count() + } + pub fn iter(&self) -> AttachmentIterator { + self.into_iter() + } + fn _get(&self, key: &[u8]) -> Option { + self.iter() + .find_map(|(k, v)| (k.as_slice() == key).then_some(v)) + } + pub fn get>(&self, key: &Key) -> Option { + self._get(key.as_ref()) + } + fn _insert(&mut self, key: &[u8], value: &[u8]) { + let codec = Zenoh080; + let mut writer = self.inner.writer(); + codec.write(&mut writer, key).unwrap(); // Infallible, barring alloc failure + codec.write(&mut writer, value).unwrap(); // Infallible, barring alloc failure + } + /// Inserts a key-value pair to the attachment. + /// + /// Note that [`Attachment`] is a list of non-unique key-value pairs: inserting at the same key multiple times leads to both values being transmitted for that key. + /// + /// [`Attachment`] is not very efficient at inserting, so if you wish to perform multiple inserts, it's generally better to [`Attachment::extend`] after performing the inserts on an [`AttachmentBuilder`] + pub fn insert + ?Sized, Value: AsRef<[u8]> + ?Sized>( + &mut self, + key: &Key, + value: &Value, + ) { + self._insert(key.as_ref(), value.as_ref()) + } + fn _extend(&mut self, with: Self) -> &mut Self { + for slice in with.inner.zslices().cloned() { + self.inner.push_zslice(slice); + } + self + } + pub fn extend(&mut self, with: impl Into) -> &mut Self { + let with = with.into(); + self._extend(with) + } + } + #[zenoh_macros::unstable] + pub struct AttachmentIterator<'a> { + reader: ZBufReader<'a>, + } + #[zenoh_macros::unstable] + impl<'a> core::iter::IntoIterator for &'a Attachment { + type Item = (ZSlice, ZSlice); + type IntoIter = AttachmentIterator<'a>; + fn into_iter(self) -> Self::IntoIter { + AttachmentIterator { + reader: self.inner.reader(), + } + } + } + #[zenoh_macros::unstable] + impl core::fmt::Debug for Attachment { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{{")?; + for (key, value) in self { + let key = key.as_slice(); + let value = value.as_slice(); + match core::str::from_utf8(key) { + Ok(key) => write!(f, "\"{key}\": ")?, + Err(_) => { + write!(f, "0x")?; + for byte in key { + write!(f, "{byte:02X}")? + } + } + } + match core::str::from_utf8(value) { + Ok(value) => write!(f, "\"{value}\", ")?, + Err(_) => { + write!(f, "0x")?; + for byte in value { + write!(f, "{byte:02X}")? + } + write!(f, ", ")? + } + } + } + write!(f, "}}") + } + } + #[zenoh_macros::unstable] + impl<'a> core::iter::Iterator for AttachmentIterator<'a> { + type Item = (ZSlice, ZSlice); + fn next(&mut self) -> Option { + let key = Zenoh080.read(&mut self.reader).ok()?; + let value = Zenoh080.read(&mut self.reader).ok()?; + Some((key, value)) + } + fn size_hint(&self) -> (usize, Option) { + ( + (self.reader.remaining() != 0) as usize, + Some(self.reader.remaining() / 2), + ) + } + } + #[zenoh_macros::unstable] + impl<'a> core::iter::FromIterator<(&'a [u8], &'a [u8])> for AttachmentBuilder { + fn from_iter>(iter: T) -> Self { + let codec = Zenoh080; + let mut buffer: Vec = Vec::new(); + let mut writer = buffer.writer(); + for (key, value) in iter { + codec.write(&mut writer, key).unwrap(); // Infallible, barring allocation failures + codec.write(&mut writer, value).unwrap(); // Infallible, barring allocation failures + } + Self { inner: buffer } + } + } + #[zenoh_macros::unstable] + impl<'a> core::iter::FromIterator<(&'a [u8], &'a [u8])> for Attachment { + fn from_iter>(iter: T) -> Self { + AttachmentBuilder::from_iter(iter).into() + } + } +} + +/// The kind of a `Sample`. +#[repr(u8)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] +pub enum SampleKind { + /// if the `Sample` was issued by a `put` operation. + #[default] + Put = 0, + /// if the `Sample` was issued by a `delete` operation. + Delete = 1, +} + +impl fmt::Display for SampleKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + SampleKind::Put => write!(f, "PUT"), + SampleKind::Delete => write!(f, "DELETE"), + } + } +} + +impl TryFrom for SampleKind { + type Error = u64; + fn try_from(kind: u64) -> Result { + match kind { + 0 => Ok(SampleKind::Put), + 1 => Ok(SampleKind::Delete), + _ => Err(kind), + } + } +} + +#[zenoh_macros::unstable] +pub use attachment::{Attachment, AttachmentBuilder, AttachmentIterator}; + +/// Structure with public fields for sample. It's convenient if it's necessary to decompose a sample into its fields. +pub struct SampleFields { + pub key_expr: KeyExpr<'static>, + pub payload: Payload, + pub kind: SampleKind, + pub encoding: Encoding, + pub timestamp: Option, + pub express: bool, + pub priority: Priority, + pub congestion_control: CongestionControl, + #[cfg(feature = "unstable")] + pub source_info: SourceInfo, + #[cfg(feature = "unstable")] + pub attachment: Option, +} + +impl From for SampleFields { + fn from(sample: Sample) -> Self { + SampleFields { + key_expr: sample.key_expr, + payload: sample.payload, + kind: sample.kind, + encoding: sample.encoding, + timestamp: sample.timestamp, + express: sample.qos.express(), + priority: sample.qos.priority(), + congestion_control: sample.qos.congestion_control(), + #[cfg(feature = "unstable")] + source_info: sample.source_info, + #[cfg(feature = "unstable")] + attachment: sample.attachment, + } + } +} + +/// A zenoh sample. +#[non_exhaustive] +#[derive(Clone, Debug)] +pub struct Sample { + pub(crate) key_expr: KeyExpr<'static>, + pub(crate) payload: Payload, + pub(crate) kind: SampleKind, + pub(crate) encoding: Encoding, + pub(crate) timestamp: Option, + pub(crate) qos: QoS, + + #[cfg(feature = "unstable")] + pub(crate) source_info: SourceInfo, + + #[cfg(feature = "unstable")] + pub(crate) attachment: Option, +} + +impl Sample { + /// Gets the key expression on which this Sample was published. + #[inline] + pub fn key_expr(&self) -> &KeyExpr<'static> { + &self.key_expr + } + + /// Gets the payload of this Sample. + #[inline] + pub fn payload(&self) -> &Payload { + &self.payload + } + + /// Gets the kind of this Sample. + #[inline] + pub fn kind(&self) -> SampleKind { + self.kind + } + + /// Gets the encoding of this sample + #[inline] + pub fn encoding(&self) -> &Encoding { + &self.encoding + } + + /// Gets the timestamp of this Sample. + #[inline] + pub fn timestamp(&self) -> Option<&Timestamp> { + self.timestamp.as_ref() + } + + /// Gets the quality of service settings this Sample was sent with. + #[inline] + pub fn qos(&self) -> &QoS { + &self.qos + } + + /// Gets infos on the source of this Sample. + #[zenoh_macros::unstable] + #[inline] + pub fn source_info(&self) -> &SourceInfo { + &self.source_info + } + + /// Gets the sample attachment: a map of key-value pairs, where each key and value are byte-slices. + #[zenoh_macros::unstable] + #[inline] + pub fn attachment(&self) -> Option<&Attachment> { + self.attachment.as_ref() + } +} + +impl From for Value { + fn from(sample: Sample) -> Self { + Value::new(sample.payload).encoding(sample.encoding) + } +} + +/// Structure containing quality of service data +#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)] +pub struct QoS { + inner: QoSType, +} + +#[derive(Debug)] +pub struct QoSBuilder(QoS); + +impl From for QoSBuilder { + fn from(qos: QoS) -> Self { + QoSBuilder(qos) + } +} + +impl From for QoS { + fn from(builder: QoSBuilder) -> Self { + builder.0 + } +} + +impl QoSBuilderTrait for QoSBuilder { + fn congestion_control(self, congestion_control: CongestionControl) -> Self { + let mut inner = self.0.inner; + inner.set_congestion_control(congestion_control); + Self(QoS { inner }) + } + + fn priority(self, priority: Priority) -> Self { + let mut inner = self.0.inner; + inner.set_priority(priority.into()); + Self(QoS { inner }) + } + + fn express(self, is_express: bool) -> Self { + let mut inner = self.0.inner; + inner.set_is_express(is_express); + Self(QoS { inner }) + } +} + +impl QoS { + /// Gets priority of the message. + pub fn priority(&self) -> Priority { + match Priority::try_from(self.inner.get_priority()) { + Ok(p) => p, + Err(e) => { + log::trace!( + "Failed to convert priority: {}; replacing with default value", + e.to_string() + ); + Priority::default() + } + } + } + + /// Gets congestion control of the message. + pub fn congestion_control(&self) -> CongestionControl { + self.inner.get_congestion_control() + } + + /// Gets express flag value. If `true`, the message is not batched during transmission, in order to reduce latency. + pub fn express(&self) -> bool { + self.inner.is_express() + } +} + +impl From for QoS { + fn from(qos: QoSType) -> Self { + QoS { inner: qos } + } +} + +impl From for QoSType { + fn from(qos: QoS) -> Self { + qos.inner + } +} From ab349b2e91ee2fce1b0776526f6bb26af26a3b76 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Mon, 1 Apr 2024 11:46:29 +0200 Subject: [PATCH 53/63] support of TryIntoKeyexpr --- zenoh/src/key_expr.rs | 2 +- zenoh/src/queryable.rs | 144 ++++++++++++++++++++++++++++------------ zenoh/src/sample/mod.rs | 6 ++ 3 files changed, 107 insertions(+), 45 deletions(-) diff --git a/zenoh/src/key_expr.rs b/zenoh/src/key_expr.rs index aaa1d13724..d2bfb5bcfe 100644 --- a/zenoh/src/key_expr.rs +++ b/zenoh/src/key_expr.rs @@ -185,7 +185,7 @@ impl<'a> KeyExpr<'a> { /// # Safety /// Key Expressions must follow some rules to be accepted by a Zenoh network. /// Messages addressed with invalid key expressions will be dropped. - pub unsafe fn from_str_uncheckend(s: &'a str) -> Self { + pub unsafe fn from_str_unchecked(s: &'a str) -> Self { keyexpr::from_str_unchecked(s).into() } diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index c2a5557440..37c3a2303a 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -19,10 +19,9 @@ use crate::handlers::{locked, DefaultHandler}; use crate::net::primitives::Primitives; use crate::prelude::*; use crate::sample::builder::{ - op, QoSBuilderTrait, SampleBuilder, SampleBuilderTrait, TimestampBuilderTrait, - ValueBuilderTrait, + QoSBuilderTrait, SampleBuilder, SampleBuilderTrait, TimestampBuilderTrait, ValueBuilderTrait, }; -use crate::sample::SourceInfo; +use crate::sample::{QoSBuilder, SourceInfo}; use crate::Id; use crate::SessionRef; use crate::Undeclarable; @@ -132,17 +131,23 @@ impl Query { &self, key_expr: TryIntoKeyExpr, payload: IntoPayload, - ) -> ReplySampleBuilder<'_, op::Put> + ) -> ReplyBuilder<'_, 'b, ReplyBuilderPut> where TryIntoKeyExpr: TryInto>, >>::Error: Into, IntoPayload: Into, { - let sample_builder = - SampleBuilder::put(key_expr, payload).qos(response::ext::QoSType::RESPONSE.into()); - ReplySampleBuilder { + ReplyBuilder { query: self, - sample_builder, + key_expr: key_expr.try_into().map_err(Into::into), + qos: response::ext::QoSType::RESPONSE.into(), + kind: ReplyBuilderPut { + payload: payload.into(), + encoding: Encoding::default(), + }, + timestamp: None, + source_info: SourceInfo::empty(), + attachment: None, } } @@ -165,19 +170,22 @@ impl Query { /// Unless the query has enabled disjoint replies (you can check this through [`Query::accepts_replies`]), /// replying on a disjoint key expression will result in an error when resolving the reply. #[inline(always)] - pub fn reply_del( + pub fn reply_del<'b, TryIntoKeyExpr>( &self, - key_expr: IntoKeyExpr, - ) -> ReplySampleBuilder<'_, op::Delete> + key_expr: TryIntoKeyExpr, + ) -> ReplyBuilder<'_, 'b, ReplyBuilderDelete> where TryIntoKeyExpr: TryInto>, >>::Error: Into, { - let sample_builder = - SampleBuilder::delete(key_expr).qos(response::ext::QoSType::RESPONSE.into()); - ReplySampleBuilder { + ReplyBuilder { query: self, - sample_builder, + key_expr: key_expr.try_into().map_err(Into::into), + qos: response::ext::QoSType::RESPONSE.into(), + kind: ReplyBuilderDelete, + timestamp: None, + source_info: SourceInfo::empty(), + attachment: None, } } @@ -243,28 +251,45 @@ impl AsyncResolve for ReplySample<'_> { } } -/// A builder returned by [`Query::reply()`](Query::reply) +#[derive(Debug)] +pub struct ReplyBuilderPut { + payload: super::Payload, + encoding: super::Encoding, +} +#[derive(Debug)] +pub struct ReplyBuilderDelete; + +/// A builder returned by [`Query::reply()`](Query::reply) and [`Query::reply_del()`](Query::reply_del) #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] #[derive(Debug)] -pub struct ReplySampleBuilder<'a, T> { +pub struct ReplyBuilder<'a, 'b, T> { query: &'a Query, - sample_builder: SampleBuilder, + key_expr: ZResult>, + kind: T, + timestamp: Option, + qos: QoSBuilder, + + #[cfg(feature = "unstable")] + source_info: SourceInfo, + + #[cfg(feature = "unstable")] + attachment: Option, } -impl TimestampBuilderTrait for ReplySampleBuilder<'_, T> { +impl TimestampBuilderTrait for ReplyBuilder<'_, '_, T> { fn timestamp>>(self, timestamp: U) -> Self { Self { - sample_builder: self.sample_builder.timestamp(timestamp), + timestamp: timestamp.into(), ..self } } } -impl SampleBuilderTrait for ReplySampleBuilder<'_, T> { +impl SampleBuilderTrait for ReplyBuilder<'_, '_, T> { #[cfg(feature = "unstable")] fn source_info(self, source_info: SourceInfo) -> Self { Self { - sample_builder: self.sample_builder.source_info(source_info), + source_info, ..self } } @@ -272,69 +297,100 @@ impl SampleBuilderTrait for ReplySampleBuilder<'_, T> { #[cfg(feature = "unstable")] fn attachment>>(self, attachment: U) -> Self { Self { - sample_builder: self.sample_builder.attachment(attachment), + attachment: attachment.into(), ..self } } } -impl QoSBuilderTrait for ReplySampleBuilder<'_, T> { +impl QoSBuilderTrait for ReplyBuilder<'_, '_, T> { fn congestion_control(self, congestion_control: CongestionControl) -> Self { - Self { - sample_builder: self.sample_builder.congestion_control(congestion_control), - ..self - } + let qos = self.qos.congestion_control(congestion_control); + Self { qos, ..self } } fn priority(self, priority: Priority) -> Self { - Self { - sample_builder: self.sample_builder.priority(priority), - ..self - } + let qos = self.qos.priority(priority); + Self { qos, ..self } } fn express(self, is_express: bool) -> Self { - Self { - sample_builder: self.sample_builder.express(is_express), - ..self - } + let qos = self.qos.express(is_express); + Self { qos, ..self } } } -impl ValueBuilderTrait for ReplySampleBuilder<'_, op::Put> { +impl ValueBuilderTrait for ReplyBuilder<'_, '_, ReplyBuilderPut> { fn encoding>(self, encoding: T) -> Self { Self { - sample_builder: self.sample_builder.encoding(encoding), + kind: ReplyBuilderPut { + encoding: encoding.into(), + ..self.kind + }, ..self } } fn payload>(self, payload: T) -> Self { Self { - sample_builder: self.sample_builder.payload(payload), + kind: ReplyBuilderPut { + payload: payload.into(), + ..self.kind + }, ..self } } fn value>(self, value: T) -> Self { let Value { payload, encoding } = value.into(); Self { - sample_builder: self.sample_builder.payload(payload).encoding(encoding), + kind: ReplyBuilderPut { payload, encoding }, ..self } } } -impl<'a, T> Resolvable for ReplySampleBuilder<'a, T> { +impl Resolvable for ReplyBuilder<'_, '_, T> { type To = ZResult<()>; } -impl SyncResolve for ReplySampleBuilder<'_, T> { +impl SyncResolve for ReplyBuilder<'_, '_, ReplyBuilderPut> { + fn res_sync(self) -> ::To { + let key_expr = self.key_expr?.into_owned(); + let sample = SampleBuilder::put(key_expr, self.kind.payload) + .encoding(self.kind.encoding) + .timestamp(self.timestamp) + .qos(self.qos.into()); + #[cfg(feature = "unstable")] + let sample = sample.source_info(self.source_info); + #[cfg(feature = "unstable")] + let sample = sample.attachment(self.attachment); + self.query._reply_sample(sample.into()) + } +} + +impl SyncResolve for ReplyBuilder<'_, '_, ReplyBuilderDelete> { fn res_sync(self) -> ::To { - self.query._reply_sample(self.sample_builder.into()) + let key_expr = self.key_expr?.into_owned(); + let sample = SampleBuilder::delete(key_expr) + .timestamp(self.timestamp) + .qos(self.qos.into()); + #[cfg(feature = "unstable")] + let sample = sample.source_info(self.source_info); + #[cfg(feature = "unstable")] + let sample = sample.attachment(self.attachment); + self.query._reply_sample(sample.into()) + } +} + +impl AsyncResolve for ReplyBuilder<'_, '_, ReplyBuilderPut> { + type Future = Ready; + + fn res_async(self) -> Self::Future { + std::future::ready(self.res_sync()) } } -impl<'a, T> AsyncResolve for ReplySampleBuilder<'a, T> { +impl AsyncResolve for ReplyBuilder<'_, '_, ReplyBuilderDelete> { type Future = Ready; fn res_async(self) -> Self::Future { diff --git a/zenoh/src/sample/mod.rs b/zenoh/src/sample/mod.rs index 2b71105d5e..be80f8277e 100644 --- a/zenoh/src/sample/mod.rs +++ b/zenoh/src/sample/mod.rs @@ -590,6 +590,12 @@ impl From for QoSBuilder { } } +impl From for QoSBuilder { + fn from(qos: QoSType) -> Self { + QoSBuilder(QoS { inner: qos }) + } +} + impl From for QoS { fn from(builder: QoSBuilder) -> Self { builder.0 From e4c4be1d4c5dd5b02ed539a57eba324c6e5b2a07 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Mon, 1 Apr 2024 11:53:44 +0200 Subject: [PATCH 54/63] removed "op" namespace to align naming with ReplyBuilder --- zenoh/src/sample/builder.rs | 46 ++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/zenoh/src/sample/builder.rs b/zenoh/src/sample/builder.rs index 7f438d1381..fd697e942a 100644 --- a/zenoh/src/sample/builder.rs +++ b/zenoh/src/sample/builder.rs @@ -64,14 +64,12 @@ pub trait ValueBuilderTrait { fn value>(self, value: T) -> Self; } -pub mod op { - #[derive(Debug)] - pub struct Put; - #[derive(Debug)] - pub struct Delete; - #[derive(Debug)] - pub struct Any; -} +#[derive(Debug)] +pub struct SampleBuilderPut; +#[derive(Debug)] +pub struct SampleBuilderDelete; +#[derive(Debug)] +pub struct SampleBuilderAny; #[derive(Debug)] pub struct SampleBuilder { @@ -79,11 +77,11 @@ pub struct SampleBuilder { _t: PhantomData, } -impl SampleBuilder { +impl SampleBuilder { pub fn put( key_expr: IntoKeyExpr, payload: IntoPayload, - ) -> SampleBuilder + ) -> SampleBuilder where IntoKeyExpr: Into>, IntoPayload: Into, @@ -101,13 +99,13 @@ impl SampleBuilder { #[cfg(feature = "unstable")] attachment: None, }, - _t: PhantomData::, + _t: PhantomData::, } } } -impl SampleBuilder { - pub fn delete(key_expr: IntoKeyExpr) -> SampleBuilder +impl SampleBuilder { + pub fn delete(key_expr: IntoKeyExpr) -> SampleBuilder where IntoKeyExpr: Into>, { @@ -124,7 +122,7 @@ impl SampleBuilder { #[cfg(feature = "unstable")] attachment: None, }, - _t: PhantomData::, + _t: PhantomData::, } } } @@ -216,14 +214,14 @@ impl QoSBuilderTrait for SampleBuilder { } } -impl ValueBuilderTrait for SampleBuilder { +impl ValueBuilderTrait for SampleBuilder { fn encoding>(self, encoding: T) -> Self { Self { sample: Sample { encoding: encoding.into(), ..self.sample }, - _t: PhantomData::, + _t: PhantomData::, } } fn payload>(self, payload: T) -> Self { @@ -232,7 +230,7 @@ impl ValueBuilderTrait for SampleBuilder { payload: payload.into(), ..self.sample }, - _t: PhantomData::, + _t: PhantomData::, } } fn value>(self, value: T) -> Self { @@ -243,21 +241,21 @@ impl ValueBuilderTrait for SampleBuilder { encoding, ..self.sample }, - _t: PhantomData::, + _t: PhantomData::, } } } -impl From for SampleBuilder { +impl From for SampleBuilder { fn from(sample: Sample) -> Self { SampleBuilder { sample, - _t: PhantomData::, + _t: PhantomData::, } } } -impl TryFrom for SampleBuilder { +impl TryFrom for SampleBuilder { type Error = zresult::Error; fn try_from(sample: Sample) -> Result { if sample.kind != SampleKind::Put { @@ -265,12 +263,12 @@ impl TryFrom for SampleBuilder { } Ok(SampleBuilder { sample, - _t: PhantomData::, + _t: PhantomData::, }) } } -impl TryFrom for SampleBuilder { +impl TryFrom for SampleBuilder { type Error = zresult::Error; fn try_from(sample: Sample) -> Result { if sample.kind != SampleKind::Delete { @@ -278,7 +276,7 @@ impl TryFrom for SampleBuilder { } Ok(SampleBuilder { sample, - _t: PhantomData::, + _t: PhantomData::, }) } } From d631f761620b377cd9460f275c4f6deeef61e996 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Mon, 1 Apr 2024 13:25:59 +0200 Subject: [PATCH 55/63] publication builder shortened --- zenoh/src/publication.rs | 145 ++++++++---------------------------- zenoh/src/sample/builder.rs | 8 +- zenoh/src/session.rs | 15 ++-- 3 files changed, 46 insertions(+), 122 deletions(-) diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index 1d62375cdd..69715a0867 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -41,33 +41,15 @@ use zenoh_result::ZResult; /// The kind of congestion control. pub use zenoh_protocol::core::CongestionControl; -/// A builder for initializing a [`delete`](crate::Session::delete) operation. -/// -/// # Examples -/// ``` -/// # #[tokio::main] -/// # async fn main() { -/// use zenoh::prelude::r#async::*; -/// use zenoh::publication::CongestionControl; -/// -/// let session = zenoh::open(config::peer()).res().await.unwrap(); -/// session -/// .delete("key/expression") -/// .res() -/// .await -/// .unwrap(); -/// # } -/// ``` -pub struct DeleteBuilder<'a, 'b> { - pub(crate) publisher: PublisherBuilder<'a, 'b>, - pub(crate) timestamp: Option, - #[cfg(feature = "unstable")] - pub(crate) source_info: SourceInfo, - #[cfg(feature = "unstable")] - pub(crate) attachment: Option, +#[derive(Debug, Clone)] +pub struct PublicationBuilderPut { + pub(crate) payload: Payload, + pub(crate) encoding: Encoding, } +#[derive(Debug, Clone)] +pub struct PublicationBuilderDelete; -/// A builder for initializing a [`put`](crate::Session::put) operation. +/// A builder for initializing a [`put`](crate::Session::put) and [`delete`](crate::Session::delete) operations /// /// # Examples /// ``` @@ -89,10 +71,9 @@ pub struct DeleteBuilder<'a, 'b> { /// ``` #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] #[derive(Debug, Clone)] -pub struct PutBuilder<'a, 'b> { +pub struct PublicationBuilder<'a, 'b, T> { pub(crate) publisher: PublisherBuilder<'a, 'b>, - pub(crate) payload: Payload, - pub(crate) encoding: Encoding, + pub(crate) kind: T, pub(crate) timestamp: Option, #[cfg(feature = "unstable")] pub(crate) source_info: SourceInfo, @@ -100,7 +81,7 @@ pub struct PutBuilder<'a, 'b> { pub(crate) attachment: Option, } -impl QoSBuilderTrait for PutBuilder<'_, '_> { +impl QoSBuilderTrait for PublicationBuilder<'_, '_, T> { #[inline] fn congestion_control(self, congestion_control: CongestionControl) -> Self { Self { @@ -124,58 +105,8 @@ impl QoSBuilderTrait for PutBuilder<'_, '_> { } } -impl QoSBuilderTrait for DeleteBuilder<'_, '_> { - #[inline] - fn congestion_control(self, congestion_control: CongestionControl) -> Self { - Self { - publisher: self.publisher.congestion_control(congestion_control), - ..self - } - } - #[inline] - fn priority(self, priority: Priority) -> Self { - Self { - publisher: self.publisher.priority(priority), - ..self - } - } - #[inline] - fn express(self, is_express: bool) -> Self { - Self { - publisher: self.publisher.express(is_express), - ..self - } - } -} - -impl TimestampBuilderTrait for PutBuilder<'_, '_> { - fn timestamp>>(self, timestamp: T) -> Self { - Self { - timestamp: timestamp.into(), - ..self - } - } -} - -impl SampleBuilderTrait for PutBuilder<'_, '_> { - #[cfg(feature = "unstable")] - fn source_info(self, source_info: SourceInfo) -> Self { - Self { - source_info, - ..self - } - } - #[cfg(feature = "unstable")] - fn attachment>>(self, attachment: T) -> Self { - Self { - attachment: attachment.into(), - ..self - } - } -} - -impl TimestampBuilderTrait for DeleteBuilder<'_, '_> { - fn timestamp>>(self, timestamp: T) -> Self { +impl TimestampBuilderTrait for PublicationBuilder<'_, '_, T> { + fn timestamp>>(self, timestamp: TS) -> Self { Self { timestamp: timestamp.into(), ..self @@ -183,7 +114,7 @@ impl TimestampBuilderTrait for DeleteBuilder<'_, '_> { } } -impl SampleBuilderTrait for DeleteBuilder<'_, '_> { +impl SampleBuilderTrait for PublicationBuilder<'_, '_, T> { #[cfg(feature = "unstable")] fn source_info(self, source_info: SourceInfo) -> Self { Self { @@ -192,7 +123,7 @@ impl SampleBuilderTrait for DeleteBuilder<'_, '_> { } } #[cfg(feature = "unstable")] - fn attachment>>(self, attachment: T) -> Self { + fn attachment>>(self, attachment: TA) -> Self { Self { attachment: attachment.into(), ..self @@ -200,10 +131,13 @@ impl SampleBuilderTrait for DeleteBuilder<'_, '_> { } } -impl ValueBuilderTrait for PutBuilder<'_, '_> { +impl ValueBuilderTrait for PublicationBuilder<'_, '_, PublicationBuilderPut> { fn encoding>(self, encoding: T) -> Self { Self { - encoding: encoding.into(), + kind: PublicationBuilderPut { + encoding: encoding.into(), + ..self.kind + }, ..self } } @@ -213,32 +147,23 @@ impl ValueBuilderTrait for PutBuilder<'_, '_> { IntoPayload: Into, { Self { - payload: payload.into(), + kind: PublicationBuilderPut { + payload: payload.into(), + ..self.kind + }, ..self } } fn value>(self, value: T) -> Self { let Value { payload, encoding } = value.into(); Self { - payload, - encoding, + kind: PublicationBuilderPut { payload, encoding }, ..self } } } -impl PutBuilder<'_, '_> { - /// Restrict the matching subscribers that will receive the published data - /// to the ones that have the given [`Locality`](crate::prelude::Locality). - #[zenoh_macros::unstable] - #[inline] - pub fn allowed_destination(mut self, destination: Locality) -> Self { - self.publisher = self.publisher.allowed_destination(destination); - self - } -} - -impl DeleteBuilder<'_, '_> { +impl PublicationBuilder<'_, '_, T> { /// Restrict the matching subscribers that will receive the published data /// to the ones that have the given [`Locality`](crate::prelude::Locality). #[zenoh_macros::unstable] @@ -249,23 +174,19 @@ impl DeleteBuilder<'_, '_> { } } -impl Resolvable for PutBuilder<'_, '_> { - type To = ZResult<()>; -} - -impl Resolvable for DeleteBuilder<'_, '_> { +impl Resolvable for PublicationBuilder<'_, '_, T> { type To = ZResult<()>; } -impl SyncResolve for PutBuilder<'_, '_> { +impl SyncResolve for PublicationBuilder<'_, '_, PublicationBuilderPut> { #[inline] fn res_sync(self) -> ::To { let publisher = self.publisher.create_one_shot_publisher()?; resolve_put( &publisher, - self.payload, + self.kind.payload, SampleKind::Put, - self.encoding, + self.kind.encoding, self.timestamp, #[cfg(feature = "unstable")] self.source_info, @@ -275,7 +196,7 @@ impl SyncResolve for PutBuilder<'_, '_> { } } -impl SyncResolve for DeleteBuilder<'_, '_> { +impl SyncResolve for PublicationBuilder<'_, '_, PublicationBuilderDelete> { #[inline] fn res_sync(self) -> ::To { let publisher = self.publisher.create_one_shot_publisher()?; @@ -293,7 +214,7 @@ impl SyncResolve for DeleteBuilder<'_, '_> { } } -impl AsyncResolve for PutBuilder<'_, '_> { +impl AsyncResolve for PublicationBuilder<'_, '_, PublicationBuilderPut> { type Future = Ready; fn res_async(self) -> Self::Future { @@ -301,7 +222,7 @@ impl AsyncResolve for PutBuilder<'_, '_> { } } -impl AsyncResolve for DeleteBuilder<'_, '_> { +impl AsyncResolve for PublicationBuilder<'_, '_, PublicationBuilderDelete> { type Future = Ready; fn res_async(self) -> Self::Future { @@ -1038,7 +959,7 @@ impl<'a, 'b> PublisherBuilder<'a, 'b> { self } - // internal function for `PutBuilder` and `DeleteBuilder` + // internal function for perfroming the publication fn create_one_shot_publisher(self) -> ZResult> { Ok(Publisher { session: self.session, diff --git a/zenoh/src/sample/builder.rs b/zenoh/src/sample/builder.rs index fd697e942a..295451abc1 100644 --- a/zenoh/src/sample/builder.rs +++ b/zenoh/src/sample/builder.rs @@ -64,14 +64,14 @@ pub trait ValueBuilderTrait { fn value>(self, value: T) -> Self; } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct SampleBuilderPut; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct SampleBuilderDelete; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct SampleBuilderAny; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct SampleBuilder { sample: Sample, _t: PhantomData, diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index 4d71f58ffa..b1b059d163 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -705,17 +705,19 @@ impl Session { &'a self, key_expr: TryIntoKeyExpr, payload: IntoPayload, - ) -> PutBuilder<'a, 'b> + ) -> PublicationBuilder<'a, 'b, PublicationBuilderPut> where TryIntoKeyExpr: TryInto>, >>::Error: Into, IntoPayload: Into, { - PutBuilder { + PublicationBuilder { publisher: self.declare_publisher(key_expr), - payload: payload.into(), + kind: PublicationBuilderPut { + payload: payload.into(), + encoding: Encoding::default(), + }, timestamp: None, - encoding: Encoding::default(), #[cfg(feature = "unstable")] attachment: None, #[cfg(feature = "unstable")] @@ -743,13 +745,14 @@ impl Session { pub fn delete<'a, 'b: 'a, TryIntoKeyExpr>( &'a self, key_expr: TryIntoKeyExpr, - ) -> DeleteBuilder<'a, 'b> + ) -> PublicationBuilder<'a, 'b, PublicationBuilderDelete> where TryIntoKeyExpr: TryInto>, >>::Error: Into, { - DeleteBuilder { + PublicationBuilder { publisher: self.declare_publisher(key_expr), + kind: PublicationBuilderDelete, timestamp: None, #[cfg(feature = "unstable")] attachment: None, From 9b8aaa69d190547a65084cb5c0be605aa706b67f Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Mon, 1 Apr 2024 13:45:01 +0200 Subject: [PATCH 56/63] parametrized publication builder --- zenoh/src/publication.rs | 24 ++++++++++++------------ zenoh/src/session.rs | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index 69715a0867..dd1818d842 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -71,8 +71,8 @@ pub struct PublicationBuilderDelete; /// ``` #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] #[derive(Debug, Clone)] -pub struct PublicationBuilder<'a, 'b, T> { - pub(crate) publisher: PublisherBuilder<'a, 'b>, +pub struct PublicationBuilder { + pub(crate) publisher: P, pub(crate) kind: T, pub(crate) timestamp: Option, #[cfg(feature = "unstable")] @@ -81,7 +81,7 @@ pub struct PublicationBuilder<'a, 'b, T> { pub(crate) attachment: Option, } -impl QoSBuilderTrait for PublicationBuilder<'_, '_, T> { +impl QoSBuilderTrait for PublicationBuilder, T> { #[inline] fn congestion_control(self, congestion_control: CongestionControl) -> Self { Self { @@ -105,7 +105,7 @@ impl QoSBuilderTrait for PublicationBuilder<'_, '_, T> { } } -impl TimestampBuilderTrait for PublicationBuilder<'_, '_, T> { +impl TimestampBuilderTrait for PublicationBuilder { fn timestamp>>(self, timestamp: TS) -> Self { Self { timestamp: timestamp.into(), @@ -114,7 +114,7 @@ impl TimestampBuilderTrait for PublicationBuilder<'_, '_, T> { } } -impl SampleBuilderTrait for PublicationBuilder<'_, '_, T> { +impl SampleBuilderTrait for PublicationBuilder { #[cfg(feature = "unstable")] fn source_info(self, source_info: SourceInfo) -> Self { Self { @@ -131,7 +131,7 @@ impl SampleBuilderTrait for PublicationBuilder<'_, '_, T> { } } -impl ValueBuilderTrait for PublicationBuilder<'_, '_, PublicationBuilderPut> { +impl

ValueBuilderTrait for PublicationBuilder { fn encoding>(self, encoding: T) -> Self { Self { kind: PublicationBuilderPut { @@ -163,7 +163,7 @@ impl ValueBuilderTrait for PublicationBuilder<'_, '_, PublicationBuilderPut> { } } -impl PublicationBuilder<'_, '_, T> { +impl PublicationBuilder, T> { /// Restrict the matching subscribers that will receive the published data /// to the ones that have the given [`Locality`](crate::prelude::Locality). #[zenoh_macros::unstable] @@ -174,11 +174,11 @@ impl PublicationBuilder<'_, '_, T> { } } -impl Resolvable for PublicationBuilder<'_, '_, T> { +impl Resolvable for PublicationBuilder { type To = ZResult<()>; } -impl SyncResolve for PublicationBuilder<'_, '_, PublicationBuilderPut> { +impl SyncResolve for PublicationBuilder, PublicationBuilderPut> { #[inline] fn res_sync(self) -> ::To { let publisher = self.publisher.create_one_shot_publisher()?; @@ -196,7 +196,7 @@ impl SyncResolve for PublicationBuilder<'_, '_, PublicationBuilderPut> { } } -impl SyncResolve for PublicationBuilder<'_, '_, PublicationBuilderDelete> { +impl SyncResolve for PublicationBuilder, PublicationBuilderDelete> { #[inline] fn res_sync(self) -> ::To { let publisher = self.publisher.create_one_shot_publisher()?; @@ -214,7 +214,7 @@ impl SyncResolve for PublicationBuilder<'_, '_, PublicationBuilderDelete> { } } -impl AsyncResolve for PublicationBuilder<'_, '_, PublicationBuilderPut> { +impl AsyncResolve for PublicationBuilder, PublicationBuilderPut> { type Future = Ready; fn res_async(self) -> Self::Future { @@ -222,7 +222,7 @@ impl AsyncResolve for PublicationBuilder<'_, '_, PublicationBuilderPut> { } } -impl AsyncResolve for PublicationBuilder<'_, '_, PublicationBuilderDelete> { +impl AsyncResolve for PublicationBuilder, PublicationBuilderDelete> { type Future = Ready; fn res_async(self) -> Self::Future { diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index b1b059d163..63cc0bb7fa 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -705,7 +705,7 @@ impl Session { &'a self, key_expr: TryIntoKeyExpr, payload: IntoPayload, - ) -> PublicationBuilder<'a, 'b, PublicationBuilderPut> + ) -> PublicationBuilder, PublicationBuilderPut> where TryIntoKeyExpr: TryInto>, >>::Error: Into, @@ -745,7 +745,7 @@ impl Session { pub fn delete<'a, 'b: 'a, TryIntoKeyExpr>( &'a self, key_expr: TryIntoKeyExpr, - ) -> PublicationBuilder<'a, 'b, PublicationBuilderDelete> + ) -> PublicationBuilder, PublicationBuilderDelete> where TryIntoKeyExpr: TryInto>, >>::Error: Into, From bbe07f78294418e5f1d2aa95499987f827e3510c Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Mon, 1 Apr 2024 14:03:02 +0200 Subject: [PATCH 57/63] removed PutPublication, DeletePublication --- zenoh/src/publication.rs | 144 +++++---------------------------------- 1 file changed, 18 insertions(+), 126 deletions(-) diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index dd1818d842..41e2b0fa04 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -408,14 +408,19 @@ impl<'a> Publisher<'a> { /// # } /// ``` #[inline] - pub fn put(&self, payload: IntoPayload) -> PutPublication + pub fn put( + &self, + payload: IntoPayload, + ) -> PublicationBuilder<&Publisher<'_>, PublicationBuilderPut> where IntoPayload: Into, { - PutPublication { + PublicationBuilder { publisher: self, - payload: payload.into(), - encoding: Encoding::ZENOH_BYTES, + kind: PublicationBuilderPut { + payload: payload.into(), + encoding: Encoding::ZENOH_BYTES, + }, timestamp: None, #[cfg(feature = "unstable")] source_info: SourceInfo::empty(), @@ -437,9 +442,10 @@ impl<'a> Publisher<'a> { /// publisher.delete().res().await.unwrap(); /// # } /// ``` - pub fn delete(&self) -> DeletePublication { - DeletePublication { + pub fn delete(&self) -> PublicationBuilder<&Publisher<'_>, PublicationBuilderDelete> { + PublicationBuilder { publisher: self, + kind: PublicationBuilderDelete, timestamp: None, #[cfg(feature = "unstable")] source_info: SourceInfo::empty(), @@ -674,127 +680,13 @@ impl Drop for Publisher<'_> { } } -/// A [`Resolvable`] returned by [`Publisher::put()`](Publisher::put), -#[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] -pub struct PutPublication<'a> { - publisher: &'a Publisher<'a>, - payload: Payload, - encoding: Encoding, - timestamp: Option, - #[cfg(feature = "unstable")] - pub(crate) source_info: SourceInfo, - #[cfg(feature = "unstable")] - pub(crate) attachment: Option, -} - -/// A [`Resolvable`] returned by [`Publisher::delete()`](Publisher::delete) -#[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] -pub struct DeletePublication<'a> { - publisher: &'a Publisher<'a>, - timestamp: Option, - #[cfg(feature = "unstable")] - pub(crate) source_info: SourceInfo, - #[cfg(feature = "unstable")] - pub(crate) attachment: Option, -} - -impl TimestampBuilderTrait for PutPublication<'_> { - fn timestamp>>(self, timestamp: T) -> Self { - Self { - timestamp: timestamp.into(), - ..self - } - } -} - -impl SampleBuilderTrait for PutPublication<'_> { - #[cfg(feature = "unstable")] - fn source_info(self, source_info: SourceInfo) -> Self { - Self { - source_info, - ..self - } - } - - #[cfg(feature = "unstable")] - fn attachment>>(self, attachment: T) -> Self { - Self { - attachment: attachment.into(), - ..self - } - } -} - -impl ValueBuilderTrait for PutPublication<'_> { - fn encoding>(self, encoding: T) -> Self { - Self { - encoding: encoding.into(), - ..self - } - } - - fn payload(self, payload: IntoPayload) -> Self - where - IntoPayload: Into, - { - Self { - payload: payload.into(), - ..self - } - } - - fn value>(self, value: T) -> Self { - let Value { payload, encoding } = value.into(); - Self { - payload, - encoding, - ..self - } - } -} - -impl TimestampBuilderTrait for DeletePublication<'_> { - fn timestamp>>(self, timestamp: T) -> Self { - Self { - timestamp: timestamp.into(), - ..self - } - } -} - -impl SampleBuilderTrait for DeletePublication<'_> { - #[cfg(feature = "unstable")] - fn source_info(self, source_info: SourceInfo) -> Self { - Self { - source_info, - ..self - } - } - - #[cfg(feature = "unstable")] - fn attachment>>(self, attachment: T) -> Self { - Self { - attachment: attachment.into(), - ..self - } - } -} - -impl Resolvable for PutPublication<'_> { - type To = ZResult<()>; -} - -impl Resolvable for DeletePublication<'_> { - type To = ZResult<()>; -} - -impl SyncResolve for PutPublication<'_> { +impl SyncResolve for PublicationBuilder<&Publisher<'_>, PublicationBuilderPut> { fn res_sync(self) -> ::To { resolve_put( self.publisher, - self.payload, + self.kind.payload, SampleKind::Put, - self.encoding, + self.kind.encoding, self.timestamp, #[cfg(feature = "unstable")] self.source_info, @@ -804,7 +696,7 @@ impl SyncResolve for PutPublication<'_> { } } -impl SyncResolve for DeletePublication<'_> { +impl SyncResolve for PublicationBuilder<&Publisher<'_>, PublicationBuilderDelete> { fn res_sync(self) -> ::To { resolve_put( self.publisher, @@ -820,7 +712,7 @@ impl SyncResolve for DeletePublication<'_> { } } -impl AsyncResolve for PutPublication<'_> { +impl AsyncResolve for PublicationBuilder<&Publisher<'_>, PublicationBuilderPut> { type Future = Ready; fn res_async(self) -> Self::Future { @@ -828,7 +720,7 @@ impl AsyncResolve for PutPublication<'_> { } } -impl AsyncResolve for DeletePublication<'_> { +impl AsyncResolve for PublicationBuilder<&Publisher<'_>, PublicationBuilderDelete> { type Future = Ready; fn res_async(self) -> Self::Future { From 4d0f6e52d07c9c0208430b454f8982044f2e0409 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Mon, 1 Apr 2024 15:32:30 +0200 Subject: [PATCH 58/63] removed extra uses --- examples/examples/z_ping.rs | 1 - examples/examples/z_pong.rs | 1 - examples/examples/z_pub.rs | 1 - examples/examples/z_pub_shm_thr.rs | 1 - examples/examples/z_pub_thr.rs | 1 - .../zenoh-plugin-rest/examples/z_serve_sse.rs | 1 - .../src/replica/align_queryable.rs | 2 - .../src/replica/aligner.rs | 2 +- .../src/replica/storage.rs | 53 +++----- zenoh-ext/src/group.rs | 1 - zenoh-ext/src/querying_subscriber.rs | 2 +- zenoh/src/publication.rs | 65 +++++---- zenoh/src/queryable.rs | 126 +++++++++--------- zenoh/tests/session.rs | 1 - zenoh/tests/unicity.rs | 1 - 15 files changed, 115 insertions(+), 144 deletions(-) diff --git a/examples/examples/z_ping.rs b/examples/examples/z_ping.rs index 59bcaddadc..a57c937e48 100644 --- a/examples/examples/z_ping.rs +++ b/examples/examples/z_ping.rs @@ -16,7 +16,6 @@ use std::time::{Duration, Instant}; use zenoh::config::Config; use zenoh::prelude::sync::*; use zenoh::publication::CongestionControl; -use zenoh::sample::builder::QoSBuilderTrait; use zenoh_examples::CommonArgs; fn main() { diff --git a/examples/examples/z_pong.rs b/examples/examples/z_pong.rs index e0fa079629..baa5683f62 100644 --- a/examples/examples/z_pong.rs +++ b/examples/examples/z_pong.rs @@ -15,7 +15,6 @@ use clap::Parser; use zenoh::config::Config; use zenoh::prelude::sync::*; use zenoh::publication::CongestionControl; -use zenoh::sample::builder::QoSBuilderTrait; use zenoh_examples::CommonArgs; fn main() { diff --git a/examples/examples/z_pub.rs b/examples/examples/z_pub.rs index b6a1ddc0d8..8cd3c4edba 100644 --- a/examples/examples/z_pub.rs +++ b/examples/examples/z_pub.rs @@ -15,7 +15,6 @@ use clap::Parser; use std::time::Duration; use zenoh::config::Config; use zenoh::prelude::r#async::*; -use zenoh::sample::builder::SampleBuilderTrait; use zenoh_examples::CommonArgs; #[tokio::main] diff --git a/examples/examples/z_pub_shm_thr.rs b/examples/examples/z_pub_shm_thr.rs index 86429e8ab7..c8a33f98fa 100644 --- a/examples/examples/z_pub_shm_thr.rs +++ b/examples/examples/z_pub_shm_thr.rs @@ -15,7 +15,6 @@ use clap::Parser; use zenoh::config::Config; use zenoh::prelude::r#async::*; use zenoh::publication::CongestionControl; -use zenoh::sample::builder::QoSBuilderTrait; use zenoh::shm::SharedMemoryManager; use zenoh_examples::CommonArgs; diff --git a/examples/examples/z_pub_thr.rs b/examples/examples/z_pub_thr.rs index 78d54111a8..4354ad2e68 100644 --- a/examples/examples/z_pub_thr.rs +++ b/examples/examples/z_pub_thr.rs @@ -16,7 +16,6 @@ use clap::Parser; use std::convert::TryInto; use zenoh::prelude::sync::*; use zenoh::publication::CongestionControl; -use zenoh::sample::builder::QoSBuilderTrait; use zenoh_examples::CommonArgs; fn main() { diff --git a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs index c353826fab..bb76005d6e 100644 --- a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs +++ b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs @@ -15,7 +15,6 @@ use clap::{arg, Command}; use std::time::Duration; use zenoh::prelude::r#async::*; use zenoh::publication::CongestionControl; -use zenoh::sample::builder::QoSBuilderTrait; use zenoh::{config::Config, key_expr::keyexpr}; const HTML: &str = r#" diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs b/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs index 729572601c..1ce6a1cb16 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs @@ -20,8 +20,6 @@ use std::str; use std::str::FromStr; use zenoh::payload::StringOrBase64; use zenoh::prelude::r#async::*; -use zenoh::sample::builder::TimestampBuilderTrait; -use zenoh::sample::builder::ValueBuilderTrait; use zenoh::time::Timestamp; use zenoh::Session; diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs index 5121f0b445..64d5cfa1cd 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs @@ -21,7 +21,7 @@ use std::str; use zenoh::key_expr::{KeyExpr, OwnedKeyExpr}; use zenoh::payload::StringOrBase64; use zenoh::prelude::r#async::*; -use zenoh::sample::builder::{SampleBuilder, TimestampBuilderTrait, ValueBuilderTrait}; +use zenoh::sample::builder::SampleBuilder; use zenoh::time::Timestamp; use zenoh::Session; diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index feebfb588a..06c5882408 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -23,14 +23,13 @@ use std::str::{self, FromStr}; use std::time::{SystemTime, UNIX_EPOCH}; use zenoh::buffers::buffer::SplitBuffer; use zenoh::buffers::ZBuf; -use zenoh::key_expr::KeyExpr; use zenoh::prelude::r#async::*; use zenoh::query::{ConsolidationMode, QueryTarget}; -use zenoh::sample::builder::{SampleBuilder, TimestampBuilderTrait, ValueBuilderTrait}; +use zenoh::sample::builder::SampleBuilder; use zenoh::sample::{Sample, SampleKind}; use zenoh::time::{new_reception_timestamp, Timestamp, NTP64}; use zenoh::value::Value; -use zenoh::{Result as ZResult, Session, SessionDeclarations}; +use zenoh::{Result as ZResult, Session}; use zenoh_backend_traits::config::{GarbageCollectionConfig, StorageConfig}; use zenoh_backend_traits::{Capability, History, Persistence, StorageInsertionResult, StoredData}; use zenoh_keyexpr::key_expr::OwnedKeyExpr; @@ -296,31 +295,25 @@ impl StorageService { ); // there might be the case that the actual update was outdated due to a wild card update, but not stored yet in the storage. // get the relevant wild card entry and use that value and timestamp to update the storage - let sample_to_store: Sample = match self + let sample_to_store: Sample = if let Some(update) = self .ovderriding_wild_update(&k, sample.timestamp().unwrap()) .await { - Some(Update { - kind: SampleKind::Put, - data, - }) => { - let Value { - payload, encoding, .. - } = data.value; - SampleBuilder::put(KeyExpr::from(k.clone()), payload) - .encoding(encoding) - .timestamp(data.timestamp) - .into() + match update.kind { + SampleKind::Put => { + SampleBuilder::put(KeyExpr::from(k.clone()), update.data.value.payload) + .encoding(update.data.value.encoding) + .timestamp(update.data.timestamp) + .into() + } + SampleKind::Delete => SampleBuilder::delete(KeyExpr::from(k.clone())) + .timestamp(update.data.timestamp) + .into(), } - Some(Update { - kind: SampleKind::Delete, - data, - }) => SampleBuilder::delete(KeyExpr::from(k.clone())) - .timestamp(data.timestamp) - .into(), - None => SampleBuilder::from(sample.clone()) + } else { + SampleBuilder::from(sample.clone()) .keyexpr(k.clone()) - .into(), + .into() }; let stripped_key = match self.strip_prefix(sample_to_store.key_expr()) { @@ -520,12 +513,9 @@ impl StorageService { match storage.get(stripped_key, q.parameters()).await { Ok(stored_data) => { for entry in stored_data { - let Value { - payload, encoding, .. - } = entry.value; if let Err(e) = q - .reply(key.clone(), payload) - .encoding(encoding) + .reply(key.clone(), entry.value.payload) + .encoding(entry.value.encoding) .timestamp(entry.timestamp) .res() .await @@ -555,12 +545,9 @@ impl StorageService { match storage.get(stripped_key, q.parameters()).await { Ok(stored_data) => { for entry in stored_data { - let Value { - payload, encoding, .. - } = entry.value; if let Err(e) = q - .reply(q.key_expr().clone(), payload) - .encoding(encoding) + .reply(q.key_expr().clone(), entry.value.payload) + .encoding(entry.value.encoding) .timestamp(entry.timestamp) .res() .await diff --git a/zenoh-ext/src/group.rs b/zenoh-ext/src/group.rs index 2075ea9472..8a7823ed72 100644 --- a/zenoh-ext/src/group.rs +++ b/zenoh-ext/src/group.rs @@ -29,7 +29,6 @@ use zenoh::payload::PayloadReader; use zenoh::prelude::r#async::*; use zenoh::publication::Publisher; use zenoh::query::ConsolidationMode; -use zenoh::sample::builder::QoSBuilderTrait; use zenoh::Error as ZError; use zenoh::Result as ZResult; use zenoh::Session; diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index 4e9b46854d..d749a94ed9 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -20,7 +20,7 @@ use std::time::Duration; use zenoh::handlers::{locked, DefaultHandler}; use zenoh::prelude::r#async::*; use zenoh::query::{QueryConsolidation, QueryTarget, ReplyKeyExpr}; -use zenoh::sample::builder::{SampleBuilder, TimestampBuilderTrait}; +use zenoh::sample::builder::SampleBuilder; use zenoh::subscriber::{Reliability, Subscriber}; use zenoh::time::{new_reception_timestamp, Timestamp}; use zenoh::Result as ZResult; diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index 41e2b0fa04..64fa5b49c6 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -15,9 +15,6 @@ //! Publishing primitives. use crate::net::primitives::Primitives; use crate::prelude::*; -use crate::sample::builder::{ - QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, ValueBuilderTrait, -}; #[zenoh_macros::unstable] use crate::sample::Attachment; use crate::sample::{DataInfo, QoS, Sample, SampleFields, SampleKind}; @@ -105,29 +102,14 @@ impl QoSBuilderTrait for PublicationBuilder, T> { } } -impl TimestampBuilderTrait for PublicationBuilder { - fn timestamp>>(self, timestamp: TS) -> Self { - Self { - timestamp: timestamp.into(), - ..self - } - } -} - -impl SampleBuilderTrait for PublicationBuilder { - #[cfg(feature = "unstable")] - fn source_info(self, source_info: SourceInfo) -> Self { - Self { - source_info, - ..self - } - } - #[cfg(feature = "unstable")] - fn attachment>>(self, attachment: TA) -> Self { - Self { - attachment: attachment.into(), - ..self - } +impl PublicationBuilder, T> { + /// Restrict the matching subscribers that will receive the published data + /// to the ones that have the given [`Locality`](crate::prelude::Locality). + #[zenoh_macros::unstable] + #[inline] + pub fn allowed_destination(mut self, destination: Locality) -> Self { + self.publisher = self.publisher.allowed_destination(destination); + self } } @@ -163,14 +145,29 @@ impl

ValueBuilderTrait for PublicationBuilder { } } -impl PublicationBuilder, T> { - /// Restrict the matching subscribers that will receive the published data - /// to the ones that have the given [`Locality`](crate::prelude::Locality). - #[zenoh_macros::unstable] - #[inline] - pub fn allowed_destination(mut self, destination: Locality) -> Self { - self.publisher = self.publisher.allowed_destination(destination); - self +impl SampleBuilderTrait for PublicationBuilder { + #[cfg(feature = "unstable")] + fn source_info(self, source_info: SourceInfo) -> Self { + Self { + source_info, + ..self + } + } + #[cfg(feature = "unstable")] + fn attachment>>(self, attachment: TA) -> Self { + Self { + attachment: attachment.into(), + ..self + } + } +} + +impl TimestampBuilderTrait for PublicationBuilder { + fn timestamp>>(self, timestamp: TS) -> Self { + Self { + timestamp: timestamp.into(), + ..self + } } } diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 37c3a2303a..0696fcbe33 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -18,9 +18,7 @@ use crate::encoding::Encoding; use crate::handlers::{locked, DefaultHandler}; use crate::net::primitives::Primitives; use crate::prelude::*; -use crate::sample::builder::{ - QoSBuilderTrait, SampleBuilder, SampleBuilderTrait, TimestampBuilderTrait, ValueBuilderTrait, -}; +use crate::sample::builder::SampleBuilder; use crate::sample::{QoSBuilder, SourceInfo}; use crate::Id; use crate::SessionRef; @@ -287,17 +285,17 @@ impl TimestampBuilderTrait for ReplyBuilder<'_, '_, T> { impl SampleBuilderTrait for ReplyBuilder<'_, '_, T> { #[cfg(feature = "unstable")] - fn source_info(self, source_info: SourceInfo) -> Self { + fn attachment>>(self, attachment: U) -> Self { Self { - source_info, + attachment: attachment.into(), ..self } } #[cfg(feature = "unstable")] - fn attachment>>(self, attachment: U) -> Self { + fn source_info(self, source_info: SourceInfo) -> Self { Self { - attachment: attachment.into(), + source_info, ..self } } @@ -382,6 +380,63 @@ impl SyncResolve for ReplyBuilder<'_, '_, ReplyBuilderDelete> { } } +impl Query { + fn _reply_sample(&self, sample: Sample) -> ZResult<()> { + if !self._accepts_any_replies().unwrap_or(false) + && !self.key_expr().intersects(&sample.key_expr) + { + bail!("Attempted to reply on `{}`, which does not intersect with query `{}`, despite query only allowing replies on matching key expressions", sample.key_expr, self.key_expr()) + } + #[cfg(not(feature = "unstable"))] + let ext_sinfo = None; + #[cfg(feature = "unstable")] + let ext_sinfo = sample.source_info.into(); + self.inner.primitives.send_response(Response { + rid: self.inner.qid, + wire_expr: WireExpr { + scope: 0, + suffix: std::borrow::Cow::Owned(sample.key_expr.into()), + mapping: Mapping::Sender, + }, + payload: ResponseBody::Reply(zenoh::Reply { + consolidation: zenoh::Consolidation::DEFAULT, + ext_unknown: vec![], + payload: match sample.kind { + SampleKind::Put => ReplyBody::Put(Put { + timestamp: sample.timestamp, + encoding: sample.encoding.into(), + ext_sinfo, + #[cfg(feature = "shared-memory")] + ext_shm: None, + #[cfg(feature = "unstable")] + ext_attachment: sample.attachment.map(|a| a.into()), + #[cfg(not(feature = "unstable"))] + ext_attachment: None, + ext_unknown: vec![], + payload: sample.payload.into(), + }), + SampleKind::Delete => ReplyBody::Del(Del { + timestamp: sample.timestamp, + ext_sinfo, + #[cfg(feature = "unstable")] + ext_attachment: sample.attachment.map(|a| a.into()), + #[cfg(not(feature = "unstable"))] + ext_attachment: None, + ext_unknown: vec![], + }), + }, + }), + ext_qos: sample.qos.into(), + ext_tstamp: None, + ext_respid: Some(response::ext::ResponderIdType { + zid: self.inner.zid, + eid: self.eid, + }), + }); + Ok(()) + } +} + impl AsyncResolve for ReplyBuilder<'_, '_, ReplyBuilderPut> { type Future = Ready; @@ -467,63 +522,6 @@ impl<'a> AsyncResolve for ReplyErrBuilder<'a> { } } -impl Query { - fn _reply_sample(&self, sample: Sample) -> ZResult<()> { - if !self._accepts_any_replies().unwrap_or(false) - && !self.key_expr().intersects(&sample.key_expr) - { - bail!("Attempted to reply on `{}`, which does not intersect with query `{}`, despite query only allowing replies on matching key expressions", sample.key_expr, self.key_expr()) - } - #[cfg(not(feature = "unstable"))] - let ext_sinfo = None; - #[cfg(feature = "unstable")] - let ext_sinfo = sample.source_info.into(); - self.inner.primitives.send_response(Response { - rid: self.inner.qid, - wire_expr: WireExpr { - scope: 0, - suffix: std::borrow::Cow::Owned(sample.key_expr.into()), - mapping: Mapping::Sender, - }, - payload: ResponseBody::Reply(zenoh::Reply { - consolidation: zenoh::Consolidation::DEFAULT, - ext_unknown: vec![], - payload: match sample.kind { - SampleKind::Put => ReplyBody::Put(Put { - timestamp: sample.timestamp, - encoding: sample.encoding.into(), - ext_sinfo, - #[cfg(feature = "shared-memory")] - ext_shm: None, - #[cfg(feature = "unstable")] - ext_attachment: sample.attachment.map(|a| a.into()), - #[cfg(not(feature = "unstable"))] - ext_attachment: None, - ext_unknown: vec![], - payload: sample.payload.into(), - }), - SampleKind::Delete => ReplyBody::Del(Del { - timestamp: sample.timestamp, - ext_sinfo, - #[cfg(feature = "unstable")] - ext_attachment: sample.attachment.map(|a| a.into()), - #[cfg(not(feature = "unstable"))] - ext_attachment: None, - ext_unknown: vec![], - }), - }, - }), - ext_qos: sample.qos.into(), - ext_tstamp: None, - ext_respid: Some(response::ext::ResponderIdType { - zid: self.inner.zid, - eid: self.eid, - }), - }); - Ok(()) - } -} - pub(crate) struct QueryableState { pub(crate) id: Id, pub(crate) key_expr: WireExpr<'static>, diff --git a/zenoh/tests/session.rs b/zenoh/tests/session.rs index 0518316be9..8c2d2e9937 100644 --- a/zenoh/tests/session.rs +++ b/zenoh/tests/session.rs @@ -15,7 +15,6 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use std::time::Duration; use zenoh::prelude::r#async::*; -use zenoh::sample::builder::QoSBuilderTrait; use zenoh_core::ztimeout; const TIMEOUT: Duration = Duration::from_secs(60); diff --git a/zenoh/tests/unicity.rs b/zenoh/tests/unicity.rs index a71a0a8034..f34704fb7e 100644 --- a/zenoh/tests/unicity.rs +++ b/zenoh/tests/unicity.rs @@ -16,7 +16,6 @@ use std::sync::Arc; use std::time::Duration; use tokio::runtime::Handle; use zenoh::prelude::r#async::*; -use zenoh::sample::builder::QoSBuilderTrait; use zenoh_core::ztimeout; const TIMEOUT: Duration = Duration::from_secs(60); From 23931f92d5f9c321d8a0247a1379cc76b0275def Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Mon, 1 Apr 2024 15:48:02 +0200 Subject: [PATCH 59/63] more cleanup --- plugins/zenoh-plugin-rest/src/lib.rs | 1 - zenoh/src/query.rs | 1 - zenoh/src/sample/builder.rs | 2 ++ zenoh/src/sample/mod.rs | 8 +++++++- zenoh/src/session.rs | 1 + zenoh/tests/attachments.rs | 2 +- 6 files changed, 11 insertions(+), 4 deletions(-) diff --git a/plugins/zenoh-plugin-rest/src/lib.rs b/plugins/zenoh-plugin-rest/src/lib.rs index f78c541eff..43c3f33776 100644 --- a/plugins/zenoh-plugin-rest/src/lib.rs +++ b/plugins/zenoh-plugin-rest/src/lib.rs @@ -34,7 +34,6 @@ use zenoh::plugins::{RunningPluginTrait, ZenohPlugin}; use zenoh::prelude::r#async::*; use zenoh::query::{QueryConsolidation, Reply}; use zenoh::runtime::Runtime; -use zenoh::sample::builder::ValueBuilderTrait; use zenoh::selector::TIME_RANGE_KEY; use zenoh::Session; use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginControl}; diff --git a/zenoh/src/query.rs b/zenoh/src/query.rs index 9f96db4f4b..cb1116130d 100644 --- a/zenoh/src/query.rs +++ b/zenoh/src/query.rs @@ -15,7 +15,6 @@ //! Query primitives. use crate::handlers::{locked, Callback, DefaultHandler}; use crate::prelude::*; -use crate::sample::builder::{QoSBuilderTrait, SampleBuilderTrait, ValueBuilderTrait}; #[zenoh_macros::unstable] use crate::sample::Attachment; use crate::sample::QoSBuilder; diff --git a/zenoh/src/sample/builder.rs b/zenoh/src/sample/builder.rs index 295451abc1..5fab36617d 100644 --- a/zenoh/src/sample/builder.rs +++ b/zenoh/src/sample/builder.rs @@ -14,9 +14,11 @@ use std::marker::PhantomData; +#[cfg(feature = "unstable")] use crate::sample::Attachment; use crate::sample::QoS; use crate::sample::QoSBuilder; +#[cfg(feature = "unstable")] use crate::sample::SourceInfo; use crate::Encoding; use crate::KeyExpr; diff --git a/zenoh/src/sample/mod.rs b/zenoh/src/sample/mod.rs index be80f8277e..6e457578a3 100644 --- a/zenoh/src/sample/mod.rs +++ b/zenoh/src/sample/mod.rs @@ -117,7 +117,12 @@ impl DataInfoIntoSample for Option { IntoPayload: Into, { if let Some(data_info) = self { - data_info.into_sample(key_expr, payload, attachment) + data_info.into_sample( + key_expr, + payload, + #[cfg(feature = "unstable")] + attachment, + ) } else { Sample { key_expr: key_expr.into(), @@ -172,6 +177,7 @@ impl SourceInfo { } } +#[zenoh_macros::unstable] impl From for Option { fn from(source_info: SourceInfo) -> Option { if source_info.is_empty() { diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index 63cc0bb7fa..c44cb4f817 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -809,6 +809,7 @@ impl Session { #[cfg(feature = "unstable")] attachment: None, handler: DefaultHandler, + #[cfg(feature = "unstable")] source_info: SourceInfo::empty(), } } diff --git a/zenoh/tests/attachments.rs b/zenoh/tests/attachments.rs index 2725351ab0..9fb99b7cc0 100644 --- a/zenoh/tests/attachments.rs +++ b/zenoh/tests/attachments.rs @@ -14,7 +14,7 @@ #[cfg(feature = "unstable")] #[test] fn pubsub() { - use zenoh::{prelude::sync::*, sample::builder::SampleBuilderTrait}; + use zenoh::prelude::sync::*; let zenoh = zenoh::open(Config::default()).res().unwrap(); let _sub = zenoh From 8f8eb2589a57c1074622c125f5111c4afde9a1e7 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Fri, 5 Apr 2024 11:19:56 +0200 Subject: [PATCH 60/63] typedefs for complex builder types (#890) --- zenoh/src/publication.rs | 21 +++++++++++++++------ zenoh/src/queryable.rs | 8 ++++++-- zenoh/src/session.rs | 4 ++-- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index 64fa5b49c6..c176ad32e0 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -46,7 +46,8 @@ pub struct PublicationBuilderPut { #[derive(Debug, Clone)] pub struct PublicationBuilderDelete; -/// A builder for initializing a [`put`](crate::Session::put) and [`delete`](crate::Session::delete) operations +/// A builder for initializing [`Session::put`](crate::Session::put), [`Session::delete`](crate::Session::delete), +/// [`Publisher::put`](crate::Publisher::put), and [`Publisher::delete`](crate::Publisher::delete) operations. /// /// # Examples /// ``` @@ -78,6 +79,17 @@ pub struct PublicationBuilder { pub(crate) attachment: Option, } +pub type SessionPutBuilder<'a, 'b> = + PublicationBuilder, PublicationBuilderPut>; + +pub type SessionDeleteBuilder<'a, 'b> = + PublicationBuilder, PublicationBuilderDelete>; + +pub type PublisherPutBuilder<'a> = PublicationBuilder<&'a Publisher<'a>, PublicationBuilderPut>; + +pub type PublisherDeleteBuilder<'a> = + PublicationBuilder<&'a Publisher<'a>, PublicationBuilderDelete>; + impl QoSBuilderTrait for PublicationBuilder, T> { #[inline] fn congestion_control(self, congestion_control: CongestionControl) -> Self { @@ -405,10 +417,7 @@ impl<'a> Publisher<'a> { /// # } /// ``` #[inline] - pub fn put( - &self, - payload: IntoPayload, - ) -> PublicationBuilder<&Publisher<'_>, PublicationBuilderPut> + pub fn put(&self, payload: IntoPayload) -> PublisherPutBuilder<'_> where IntoPayload: Into, { @@ -439,7 +448,7 @@ impl<'a> Publisher<'a> { /// publisher.delete().res().await.unwrap(); /// # } /// ``` - pub fn delete(&self) -> PublicationBuilder<&Publisher<'_>, PublicationBuilderDelete> { + pub fn delete(&self) -> PublisherDeleteBuilder<'_> { PublicationBuilder { publisher: self, kind: PublicationBuilderDelete, diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 0696fcbe33..c2fd67fcf4 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -129,7 +129,7 @@ impl Query { &self, key_expr: TryIntoKeyExpr, payload: IntoPayload, - ) -> ReplyBuilder<'_, 'b, ReplyBuilderPut> + ) -> ReplyPutBuilder<'_, 'b> where TryIntoKeyExpr: TryInto>, >>::Error: Into, @@ -171,7 +171,7 @@ impl Query { pub fn reply_del<'b, TryIntoKeyExpr>( &self, key_expr: TryIntoKeyExpr, - ) -> ReplyBuilder<'_, 'b, ReplyBuilderDelete> + ) -> ReplyDeleteBuilder<'_, 'b> where TryIntoKeyExpr: TryInto>, >>::Error: Into, @@ -274,6 +274,10 @@ pub struct ReplyBuilder<'a, 'b, T> { attachment: Option, } +pub type ReplyPutBuilder<'a, 'b> = ReplyBuilder<'a, 'b, ReplyBuilderPut>; + +pub type ReplyDeleteBuilder<'a, 'b> = ReplyBuilder<'a, 'b, ReplyBuilderDelete>; + impl TimestampBuilderTrait for ReplyBuilder<'_, '_, T> { fn timestamp>>(self, timestamp: U) -> Self { Self { diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index c44cb4f817..d9427f270c 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -705,7 +705,7 @@ impl Session { &'a self, key_expr: TryIntoKeyExpr, payload: IntoPayload, - ) -> PublicationBuilder, PublicationBuilderPut> + ) -> SessionPutBuilder<'a, 'b> where TryIntoKeyExpr: TryInto>, >>::Error: Into, @@ -745,7 +745,7 @@ impl Session { pub fn delete<'a, 'b: 'a, TryIntoKeyExpr>( &'a self, key_expr: TryIntoKeyExpr, - ) -> PublicationBuilder, PublicationBuilderDelete> + ) -> SessionDeleteBuilder<'a, 'b> where TryIntoKeyExpr: TryInto>, >>::Error: Into, From eb1a80ac9ddc7c15942238e477993825f559cd17 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Fri, 5 Apr 2024 14:47:11 +0200 Subject: [PATCH 61/63] Fix use and unstable visibility --- zenoh/src/prelude.rs | 5 ++++- zenoh/src/queryable.rs | 3 +-- zenoh/src/sample/builder.rs | 8 +++----- zenoh/src/session.rs | 1 + zenoh/tests/qos.rs | 1 - zenoh/tests/routing.rs | 1 - 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/zenoh/src/prelude.rs b/zenoh/src/prelude.rs index 850148f506..2e95e8d908 100644 --- a/zenoh/src/prelude.rs +++ b/zenoh/src/prelude.rs @@ -62,8 +62,11 @@ pub(crate) mod common { pub use zenoh_protocol::core::{CongestionControl, Reliability, WhatAmI}; pub use crate::sample::builder::{ - QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, ValueBuilderTrait, + QoSBuilderTrait, TimestampBuilderTrait, ValueBuilderTrait, }; + + #[zenoh_macros::unstable] + pub use crate::sample::builder::SampleBuilderTrait; } /// Prelude to import when using Zenoh's sync API. diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index c2fd67fcf4..794ff3a504 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -18,13 +18,12 @@ use crate::encoding::Encoding; use crate::handlers::{locked, DefaultHandler}; use crate::net::primitives::Primitives; use crate::prelude::*; -use crate::sample::builder::SampleBuilder; use crate::sample::{QoSBuilder, SourceInfo}; use crate::Id; use crate::SessionRef; use crate::Undeclarable; #[cfg(feature = "unstable")] -use crate::{query::ReplyKeyExpr, sample::Attachment}; +use crate::{query::ReplyKeyExpr, sample::Attachment, sample::builder::SampleBuilder}; use std::fmt; use std::future::Ready; use std::ops::Deref; diff --git a/zenoh/src/sample/builder.rs b/zenoh/src/sample/builder.rs index 5fab36617d..fca55edd09 100644 --- a/zenoh/src/sample/builder.rs +++ b/zenoh/src/sample/builder.rs @@ -15,11 +15,8 @@ use std::marker::PhantomData; #[cfg(feature = "unstable")] -use crate::sample::Attachment; -use crate::sample::QoS; -use crate::sample::QoSBuilder; -#[cfg(feature = "unstable")] -use crate::sample::SourceInfo; +use crate::sample::{Attachment, SourceInfo}; +use crate::sample::{QoS, QoSBuilder}; use crate::Encoding; use crate::KeyExpr; use crate::Payload; @@ -47,6 +44,7 @@ pub trait TimestampBuilderTrait { fn timestamp>>(self, timestamp: T) -> Self; } +#[zenoh_macros::unstable] pub trait SampleBuilderTrait { /// Attach source information #[zenoh_macros::unstable] diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index d9427f270c..67bec5f488 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -41,6 +41,7 @@ use crate::Priority; use crate::Sample; use crate::SampleKind; use crate::Selector; +#[cfg(feature = "unstable")] use crate::SourceInfo; use crate::Value; use log::{error, trace, warn}; diff --git a/zenoh/tests/qos.rs b/zenoh/tests/qos.rs index 5fd3edd985..1885c316ea 100644 --- a/zenoh/tests/qos.rs +++ b/zenoh/tests/qos.rs @@ -13,7 +13,6 @@ // use std::time::Duration; use zenoh::prelude::r#async::*; -use zenoh::sample::builder::QoSBuilderTrait; use zenoh::{publication::Priority, SessionDeclarations}; use zenoh_core::ztimeout; diff --git a/zenoh/tests/routing.rs b/zenoh/tests/routing.rs index 1031630a68..56bacd7fdd 100644 --- a/zenoh/tests/routing.rs +++ b/zenoh/tests/routing.rs @@ -18,7 +18,6 @@ use std::time::Duration; use tokio_util::{sync::CancellationToken, task::TaskTracker}; use zenoh::config::{Config, ModeDependentValue}; use zenoh::prelude::r#async::*; -use zenoh::sample::builder::QoSBuilderTrait; use zenoh::Result; use zenoh_core::ztimeout; use zenoh_protocol::core::{WhatAmI, WhatAmIMatcher}; From a43e4518875f1c4be314943e78fdc483ae6f9844 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Fri, 5 Apr 2024 14:50:16 +0200 Subject: [PATCH 62/63] Add payload and encoding accessors for Query --- zenoh/src/queryable.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/zenoh/src/queryable.rs b/zenoh/src/queryable.rs index 794ff3a504..6fbb4e9090 100644 --- a/zenoh/src/queryable.rs +++ b/zenoh/src/queryable.rs @@ -23,7 +23,7 @@ use crate::Id; use crate::SessionRef; use crate::Undeclarable; #[cfg(feature = "unstable")] -use crate::{query::ReplyKeyExpr, sample::Attachment, sample::builder::SampleBuilder}; +use crate::{query::ReplyKeyExpr, sample::builder::SampleBuilder, sample::Attachment}; use std::fmt; use std::future::Ready; use std::ops::Deref; @@ -97,6 +97,18 @@ impl Query { self.inner.value.as_ref() } + /// This Query's payload. + #[inline(always)] + pub fn payload(&self) -> Option<&Payload> { + self.inner.value.as_ref().map(|v| &v.payload) + } + + /// This Query's encoding. + #[inline(always)] + pub fn encoding(&self) -> Option<&Encoding> { + self.inner.value.as_ref().map(|v| &v.encoding) + } + #[zenoh_macros::unstable] pub fn attachment(&self) -> Option<&Attachment> { self.inner.attachment.as_ref() From 1ad8c84c8b3f2f0f93f5dadb3a190af198e4e289 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Fri, 5 Apr 2024 14:52:08 +0200 Subject: [PATCH 63/63] cargo fmt --all --- zenoh/src/prelude.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zenoh/src/prelude.rs b/zenoh/src/prelude.rs index 2e95e8d908..e2327c0dcc 100644 --- a/zenoh/src/prelude.rs +++ b/zenoh/src/prelude.rs @@ -61,9 +61,7 @@ pub(crate) mod common { pub use crate::publication::PublisherDeclarations; pub use zenoh_protocol::core::{CongestionControl, Reliability, WhatAmI}; - pub use crate::sample::builder::{ - QoSBuilderTrait, TimestampBuilderTrait, ValueBuilderTrait, - }; + pub use crate::sample::builder::{QoSBuilderTrait, TimestampBuilderTrait, ValueBuilderTrait}; #[zenoh_macros::unstable] pub use crate::sample::builder::SampleBuilderTrait;