From 2318e869a5fadb650059cebd15b918ae29553883 Mon Sep 17 00:00:00 2001 From: Mallets Date: Mon, 14 Oct 2024 13:23:13 +0000 Subject: [PATCH] deploy: 26c5e75ec5094c90d38a8c565f8c51c65e0eefc7 --- docs/migration_1.0/python/index.html | 12 +++++++----- docs/migration_1.0/rust/index.html | 26 +++++++++----------------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/docs/migration_1.0/python/index.html b/docs/migration_1.0/python/index.html index 20b68155..c99b3d6b 100644 --- a/docs/migration_1.0/python/index.html +++ b/docs/migration_1.0/python/index.html @@ -1,15 +1,17 @@ Python · Zenoh - pub/sub, geo distributed storage, query

Python

Highlights

The library has been fully rewritten to use only Rust. It should make no difference for users, except for a significant performance improvement.

The API has also been reworked to feel more pythonic, using notably context managers.

Context managers and background callbacks

You should close the zenoh session after use and the recommended way is through context manager:

import zenoh
+

Python

Highlights

The library has been fully rewritten to use only Rust. It should make no difference for users, except for a significant performance improvement.

The API has also been reworked to feel more pythonic, using notably context managers.

Context managers and background callbacks

You should close the zenoh session after use and the recommended way is through context manager:

import zenoh
 with zenoh.open(zenoh.Config()) as session:
     # `session.close()` will be called at the end of the block
 

Session-managed objects like subscribers or queryables can also be managed using context managers:

with session.declare_subscriber("my/keyexpr") as subscriber:
     # `subscriber.undeclare()` will be called at the end of the block`
-

In previous version, it was necessary to keep a variable in the scope for a subscriber/queryable declared with a callback. This constraint has been lifted, and it’s now possible to declare and forget an entity with a callback; in that case, the entity will keep living in background, until the session is closed.

import zenoh
+

In previous version, it was necessary to keep a variable in the scope for a subscriber/queryable declared with a callback. This constraint has been lifted, and it’s now possible to declare a “background” entity; this entity will keep living in background, having its callback executed until the session is closed.

import zenoh
 with zenoh.open(zenoh.Config()) as session:
-    session.declare_subscriber("my/keyepxr", lambda s: print(s))
+    # no need to declare a variable
+    session.declare_subscriber("my/keyepxr", lambda s: print(s), background=True)
     sleep(10) # subscriber stays in background and its callback can be called
-    # `session.close()` will be called at the end of the block, and it will undeclare the subscriber
+    # `session.close()` will be called at the end of the block,
+    # and it will undeclare the subscriber
 

Value is gone, long live ZBytes

Value has been split into ZBytes and Encoding. put and other operations now require a ZBytes payload, and builders accept an optional Encoding parameter.

ZBytes is a raw bytes container. It can be created directly from raw bytes/strings using ZBytes constructor. Then bytes can be retrieved using ZBytes.to_bytes or ZBytes.to_string. Sample payload is now a ZBytes instead of bytes.

  • Zenoh 0.11.x
sample = subscriber.recv()
 my_string = sample.payload.decode("utf-8")
 
  • Zenoh 1.0.0
sample = subscriber.recv()
@@ -19,7 +21,7 @@
 output = payload.to_bytes()
 

zenoh.ext serialization doesn’t pretend to cover all use cases, as it is just one available choice among other serialization formats like JSON, Protobuf, CBOR, etc. In the end, Zenoh will just send and receive payload raw bytes independently of the serialization used.

NOTE: ⚠️ Serialization of bytes is not the same as passing bytes to ZBytes constructor.

Encoding

Encoding has been reworked. Zenoh does not impose any encoding requirement on the user, nor does it operate on it. -It can be thought of as optional metadata, carried over by Zenoh in such a way that the end user’s application may perform different operations based on encoding.

NOTE: ⚠️ The encoding is no longer automatically deduced from the payload type.

session.put(json.dumps({"key", "value"}), encoding=Encoding.APPLICATION_JSON)
+It can be thought of as optional metadata, carried over by Zenoh in such a way that the end user’s application may perform different operations based on encoding.

NOTE: ⚠️ The encoding is no longer automatically inferred from the payload type.

session.put(json.dumps({"key", "value"}), encoding=Encoding.APPLICATION_JSON)
 

Users can also define their own encoding scheme that does not need to be based on the pre-defined variants.

encoding = Encoding("pointcloud/LAS")
 

Because encoding is now optional for put, Publisher can be declared with a default encoding, which will be used in every Publisher.put.

publisher = session.declare_publisher("my/keyepxr", encoding=Encoding.APPLICATION_JSON)
 // default encoding from publisher `application/json`
diff --git a/docs/migration_1.0/rust/index.html b/docs/migration_1.0/rust/index.html
index b67b73e4..a8335e5f 100644
--- a/docs/migration_1.0/rust/index.html
+++ b/docs/migration_1.0/rust/index.html
@@ -1,6 +1,6 @@
 Rust · Zenoh - pub/sub, geo distributed storage, query

Rust

Module reorganization

We reorganized the module tree, so import paths are not the same as before. The main difference is that everything should be imported via the root path zenoh::. Here are some examples, but you can look into zenoh/src/lib.rs for the complete list of changes.

// common use
+

Rust

Module reorganization

We reorganized the module tree, so import paths are not the same as before. The main difference is that everything should be imported via the root path zenoh::. Here are some examples, but you can look into zenoh/src/lib.rs for the complete list of changes.

// common use
 use zenoh::config::*;
 use zenoh::{Config, Error, Result};
 
@@ -55,7 +55,7 @@
 publisher.put(buf).wait().unwrap();
 

Session is now clonable and can be closed easily

Session implements Clone now, so there is no more need to wrap it into an Arc<Session>, and Session::into_arc has been deprecated. All the session methods, except Session::close, works like before, so only the session type need to be changed. As a side effect, Subscriber and Queryable no longer have a generic lifetime parameter. Publisher also looses one of its lifetime parameters, to keep only the one of its key expression.

The session is now closed automatically when the last Session instance is dropped, even if publishers/subscribers/etc. are still alive. Session can also be manually closed using Session::close, which now takes an immutable reference, so it can be called anytime, even if publishers/subscribers/etc. are still alive. -Subscriber and queryable of a closed session will no longer receive data; trying to call Session::get, Session::put or Publisher::put will result in an error. Closing session on the fly may save bandwidth on the wire, as it avoids propagating the undeclaration of remaining entities like subscribers/queryables/etc.

let session = zenoh::open(zenoh::config::peer()).await.unwrap();
+Subscriber and queryable of a closed session will no longer receive data; trying to call Session::get, Session::put or Publisher::put will result in an error. Closing session on the fly may save bandwidth on the wire, as it avoids propagating the undeclaration of remaining entities like subscribers/queryables/etc.

let session = zenoh::open(config).await.unwrap();
 let subscriber = session
     .declare_subscriber("key/expression")
     .await
@@ -72,24 +72,16 @@
 // **when all remaining data has been processed**.
 // subscriber undeclaration has not been sent on the wire
 subscriber_task.await.unwrap()
-

Callbacks run in background until session is closed

Session entities, e.g. subscribers, declared with callbacks are no longer undeclared when they are dropped; there is no longer need to keep a reference to an entity when the intent is to have it run until the session is closed.

let session = zenoh::open(zenoh::config::default()).await.unwrap();
+

Callbacks run in background until session is closed

It is now possible to declare “background” entities, e.g. subscribers, which have their callback called until the session is closed. So it is no longer needed to keep a dummy variable in scope when the intent is to have an entity living for the rest of the program.

let session = zenoh::open(config).await.unwrap();
 session
     .declare_subscriber("key/ expression")
     .callback(|sample| { println!("Received: {} {:?}", sample. key_expr(), sample. payload()) })
-    .await
+    .background() // declare the subscriber in background
+    .await
     .unwrap();
-// subscriber run in background until the session is closed
+// subscriber runs in background until the session is closed
 // no need to keep a variable around
-

If you still want the entity to be undeclared when dropped, you can simply use with instead of callback; it may just require you to annotate the callback, as type inference is not as good as with callback method.

let session = zenoh::open(zenoh::config::default()).await.unwrap();
-let subscriber = session
-    .declare_subscriber("key/ expression")
-    // annotation needed
-    .with(|sample: Sample| { println!("Received: {} {:?}", sample. key_expr(), sample. payload()) })
-    .await
-    .unwrap();
-// subscriber is undeclared when dropped
-

Going into details, a new method undeclare_on_drop(bool) – default to true, has been added to the builders, and callback(cb) is now simply a shortcut to with(cb).undeclare_on_drop(false). -However, the normal user would rarely need to call this method directly.

Value is gone, long live ZBytes

Value has been split into ZBytes and Encoding. put and other operations now require a ZBytes payload, and builders accept an optional Encoding parameter. The encoding is no longer automatically deduced from the payload type.

ZBytes is a raw bytes container, which can also contain non-contiguous regions of memory. It can be created directly from raw bytes/strings using ZBytes::from. The bytes can be retrieved using ZBytes::to_bytes, which returns a Cow<[u8]>, as a copy may have to be done if the underlying bytes are not contiguous.

  • Zenoh 0.11.x
let sample = subscriber.recv_async().await.unwrap();
+

Value is gone, long live ZBytes

Value has been split into ZBytes and Encoding. put and other operations now require a ZBytes payload, and builders accept an optional Encoding parameter. The encoding is no longer automatically inferred from the payload type.

ZBytes is a raw bytes container, which can also contain non-contiguous regions of memory. It can be created directly from raw bytes/strings using ZBytes::from. The bytes can be retrieved using ZBytes::to_bytes, which returns a Cow<[u8]>, as a copy may have to be done if the underlying bytes are not contiguous.

  • Zenoh 0.11.x
let sample = subscriber.recv_async().await.unwrap();
 let value: Value = sample.value;
 let raw_bytes: Vec<u8> = value.try_into().unwrap();
 
  • Zenoh 1.0.0
let sample = subscriber.recv_async().await.unwrap();
@@ -217,8 +209,8 @@
     .with(RingChannel::new(size))
     .await
     .unwrap();
-

⚠️ Note: We no longer support Pull mode in Zenoh

To get the same behavior of a Zenoh 0.11.0 PullSubscriber, please make use of a RingChannel an example of this is illustrated in z_pull.rs.

Timestamps

We now tie generating a timestamp to a Zenoh session, with the timestamp inheriting the ZenohID of the session.

Note that a Zenoh session will only be able to generate a timestamp if the timestamping configuration option is enabled.

  • Zenoh 0.11.x
let timestamp : Timestamp =  zenoh::time::new_reception_timestamp();
-
  • Zenoh 1.0.0
let session: Session = zenoh::open();
+

⚠️ Note: We no longer support Pull mode in Zenoh

To get the same behavior of a Zenoh 0.11.0 PullSubscriber, please make use of a RingChannel an example of this is illustrated in z_pull.rs.

Timestamps

We now tie generating a timestamp to a Zenoh session, with the timestamp inheriting the ZenohID of the session.

Note that a Zenoh session will only be able to generate a timestamp if the timestamping configuration option is enabled.

  • Zenoh 0.11.x
let timestamp : Timestamp =  zenoh::time::new_reception_timestamp();
+
  • Zenoh 1.0.0
let session: Session = zenoh::open(config);
 // If the `timestamping` configuration is disabled, this call will return `None`.
 let timestamp: Option<Timestamp> = session::new_timestamp();
 

This will affect user-created plugins and applications that need to generate timestamps.

Feature Flags

Removed:

  • complete_n: due to a Legacy code cleanup

Storages

Zenoh 1.0.0 introduced the possibility for Zenoh nodes configured in a mode other than router to load plugins.

A, somehow, implicit assumption that dictated the behaviour of storages is that the Zenoh node loading them has to add a timestamp to any received publication that did not have one. This functionality is controlled by the timestamping configuration option.

Until Zenoh 1.0.0 this assumption held true as only a router could load storage and the default configuration for a router enables timestamping. However, in Zenoh 1.0.0 nodes configured in client & peer mode can load storage and their default configuration disables timestamping.

⚠️ The storage-manager will fail to launch if the timestamping configuration option is disabled.

Next up: C++