Skip to content

Commit dab433d

Browse files
Fix cursor reset issue and cancelled effects spawning (#184)
feat(subscription): add more types to create `SubscriptionCursor` from Make it possible to create `SubscriptionCursor` from the string slice. feat(subscription): add methods to manipulate subscriptions in set Add `add_subscriptions(..)` and `sub_subscriptions(..)` to `SubscriptionSet` to make it possible in addition to sets manipulation, use a list of subscriptions. feat(subscribe): add subscription list changed status fix(subscribe): fix `cursor` reset issue Fix issue because of which `cursor` is not reset on `Subscription` and `SubscriptionSet` on unsubscribe. fix(subscription): fix issue with cancelled effects Fix issue because of which cancelled effects still asynchronously spawned for processing. refactor(examples): refactor `subscribe` example Separate `subscribe` example into two to show separately `subscribe` feature and `presence state` maintenance with subscribe. refactor(subscribe): add subscription token validation Added a method to validate the provided subscription token to conform to PubNub time token requirements with precision. refactor(subscription): split `subscribe` method Split the `subscribe` method into two: `subscribe` and `subscribe_with_timetoken`. docs(inline): change `client` to `pubnub` in inline docs --------- Co-authored-by: Mateusz Wiktor <[email protected]>
1 parent c3b921f commit dab433d

28 files changed

+1162
-332
lines changed

.pubnub.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,28 @@
11
name: rust
2-
version: 0.5.0
2+
version: 0.6.0
33
schema: 1
44
scm: github.com/pubnub/rust
55
files: []
66
changelog:
7+
- date: 2024-02-07
8+
version: 0.6.0
9+
changes:
10+
- type: feature
11+
text: "Make it possible to create `SubscriptionCursor` from the string slice."
12+
- type: feature
13+
text: "Add `add_subscriptions(..)` and `sub_subscriptions(..)` to `SubscriptionSet` to make it possible in addition to sets manipulation use list of subscriptions."
14+
- type: bug
15+
text: "Fix issue because of which `cursor` is not reset on `Subscription` and `SubscriptionSet` on unsubscribe."
16+
- type: bug
17+
text: "Fix issue because of which cancelled effects still asynchronously spawned for processing."
18+
- type: improvement
19+
text: "Change `client` to `pubnub` in inline docs."
20+
- type: improvement
21+
text: "Add subscription token validation."
22+
- type: improvement
23+
text: "Added a method to validate the provided subscription token to conform to PubNub time token requirements with precision."
24+
- type: improvement
25+
text: "Separate `subscribe` example into two to show separately `subscribe` feature and `presence state` maintenance with subscribe."
726
- date: 2024-01-25
827
version: 0.5.0
928
changes:

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pubnub"
3-
version = "0.5.0"
3+
version = "0.6.0"
44
edition = "2021"
55
license-file = "LICENSE"
66
authors = ["PubNub <[email protected]>"]
@@ -165,6 +165,10 @@ required-features = ["default"]
165165

166166
[[example]]
167167
name = "subscribe"
168+
required-features = ["default", "subscribe"]
169+
170+
[[example]]
171+
name = "subscribe_with_presence_state"
168172
required-features = ["default", "subscribe", "presence"]
169173

170174
[[example]]

README.md

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,29 +36,32 @@ Add `pubnub` to your Rust project in the `Cargo.toml` file:
3636
```toml
3737
# default features
3838
[dependencies]
39-
pubnub = "0.5.0"
39+
pubnub = "0.6.0"
4040

4141
# all features
4242
[dependencies]
43-
pubnub = { version = "0.5.0", features = ["full"] }
43+
pubnub = { version = "0.6.0", features = ["full"] }
4444
```
4545

4646
### Example
4747

4848
Try the following sample code to get up and running quickly!
4949

5050
```rust
51-
use pubnub::{Keyset, PubNubClientBuilder};
52-
use pubnub::dx::subscribe::{SubscribeStreamEvent, Update};
51+
use pubnub::subscribe::Subscriber;
5352
use futures::StreamExt;
5453
use tokio::time::sleep;
5554
use std::time::Duration;
5655
use serde_json;
57-
56+
use pubnub::{
57+
dx::subscribe::Update,
58+
subscribe::EventSubscriber,
59+
Keyset, PubNubClientBuilder,
60+
};
5861
#[tokio::main]
5962
async fn main() -> Result<(), Box<dyn std::error::Error>> {
6063
use pubnub::subscribe::{EventEmitter, SubscriptionParams};
61-
let publish_key = "my_publish_key";
64+
let publish_key = "my_publish_key";
6265
let subscribe_key = "my_subscribe_key";
6366
let client = PubNubClientBuilder::with_reqwest_transport()
6467
.with_keyset(Keyset {
@@ -68,6 +71,7 @@ let publish_key = "my_publish_key";
6871
})
6972
.with_user_id("user_id")
7073
.build()?;
74+
7175
println!("PubNub instance created");
7276

7377
let subscription = client.subscription(SubscriptionParams {
@@ -76,7 +80,13 @@ let publish_key = "my_publish_key";
7680
options: None
7781
});
7882

79-
println!("Subscribed to channel");
83+
let channel_entity = client.channel("my_channel_2");
84+
let channel_entity_subscription = channel_entity.subscription(None);
85+
86+
subscription.subscribe();
87+
channel_entity_subscription.subscribe();
88+
89+
println!("Subscribed to channels");
8090

8191
// Launch a new task to print out each received message
8292
tokio::spawn(client.status_stream().for_each(|status| async move {
@@ -107,7 +117,21 @@ let publish_key = "my_publish_key";
107117
}
108118
}));
109119

110-
sleep(Duration::from_secs(1)).await;
120+
// Explicitly listen only for real-time `message` updates.
121+
tokio::spawn(
122+
channel_entity_subscription
123+
.messages_stream()
124+
.for_each(|message| async move {
125+
if let Ok(utf8_message) = String::from_utf8(message.data.clone()) {
126+
if let Ok(cleaned) = serde_json::from_str::<String>(&utf8_message) {
127+
println!("message: {}", cleaned);
128+
}
129+
}
130+
}),
131+
);
132+
133+
sleep(Duration::from_secs(2)).await;
134+
111135
// Send a message to the channel
112136
client
113137
.publish_message("hello world!")
@@ -116,7 +140,15 @@ let publish_key = "my_publish_key";
116140
.execute()
117141
.await?;
118142

119-
sleep(Duration::from_secs(10)).await;
143+
// Send a message to another channel
144+
client
145+
.publish_message("hello world on the other channel!")
146+
.channel("my_channel_2")
147+
.r#type("text-message")
148+
.execute()
149+
.await?;
150+
151+
sleep(Duration::from_secs(15)).await;
120152

121153
Ok(())
122154
}
@@ -132,11 +164,11 @@ disable them in the `Cargo.toml` file, like so:
132164
```toml
133165
# only blocking and access + default features
134166
[dependencies]
135-
pubnub = { version = "0.5.0", features = ["blocking", "access"] }
167+
pubnub = { version = "0.6.0", features = ["blocking", "access"] }
136168

137169
# only parse_token + default features
138170
[dependencies]
139-
pubnub = { version = "0.5.0", features = ["parse_token"] }
171+
pubnub = { version = "0.6.0", features = ["parse_token"] }
140172
```
141173

142174
### Available features
@@ -175,7 +207,7 @@ you need, for example:
175207

176208
```toml
177209
[dependencies]
178-
pubnub = { version = "0.5.0", default-features = false, features = ["serde", "publish",
210+
pubnub = { version = "0.6.0", default-features = false, features = ["serde", "publish",
179211
"blocking"] }
180212
```
181213

examples/subscribe.rs

Lines changed: 27 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::collections::HashMap;
2-
31
use futures::StreamExt;
42
use serde::Deserialize;
53
use std::env;
@@ -26,7 +24,7 @@ async fn main() -> Result<(), Box<dyn snafu::Error>> {
2624
let publish_key = env::var("SDK_PUB_KEY")?;
2725
let subscribe_key = env::var("SDK_SUB_KEY")?;
2826

29-
let client = PubNubClientBuilder::with_reqwest_transport()
27+
let pubnub = PubNubClientBuilder::with_reqwest_transport()
3028
.with_keyset(Keyset {
3129
subscribe_key,
3230
publish_key: Some(publish_key),
@@ -40,36 +38,25 @@ async fn main() -> Result<(), Box<dyn snafu::Error>> {
4038

4139
println!("running!");
4240

43-
client
44-
.set_presence_state(HashMap::<String, String>::from([
45-
(
46-
"is_doing".to_string(),
47-
"Nothing... Just hanging around...".to_string(),
48-
),
49-
("flag".to_string(), "false".to_string()),
50-
]))
51-
.channels(["my_channel".into(), "other_channel".into()].to_vec())
52-
.user_id("user_id")
53-
.execute()
54-
.await?;
55-
5641
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
5742

58-
let subscription = client.subscription(SubscriptionParams {
43+
let subscription = pubnub.subscription(SubscriptionParams {
5944
channels: Some(&["my_channel", "other_channel"]),
6045
channel_groups: None,
6146
options: Some(vec![SubscriptionOptions::ReceivePresenceEvents]),
6247
});
63-
subscription.subscribe(None);
48+
subscription.subscribe();
6449
let subscription_clone = subscription.clone_empty();
6550

6651
// Attach connection status to the PubNub client instance.
6752
tokio::spawn(
68-
client
53+
pubnub
6954
.status_stream()
7055
.for_each(|status| async move { println!("\nstatus: {:?}", status) }),
7156
);
7257

58+
// Example of the "global" listener for multiplexed subscription object from
59+
// PubNub client.
7360
tokio::spawn(subscription.stream().for_each(|event| async move {
7461
match event {
7562
Update::Message(message) | Update::Signal(message) => {
@@ -96,48 +83,44 @@ async fn main() -> Result<(), Box<dyn snafu::Error>> {
9683
}
9784
}));
9885

99-
tokio::spawn(subscription_clone.stream().for_each(|event| async move {
100-
match event {
101-
Update::Message(message) | Update::Signal(message) => {
86+
// Explicitly listen only for real-time `message` updates.
87+
tokio::spawn(
88+
subscription_clone
89+
.messages_stream()
90+
.for_each(|message| async move {
10291
// Deserialize the message payload as you wish
10392
match serde_json::from_slice::<Message>(&message.data) {
10493
Ok(message) => println!("(b) defined message: {:?}", message),
10594
Err(_) => {
10695
println!("(b) other message: {:?}", String::from_utf8(message.data))
10796
}
10897
}
109-
}
110-
Update::Presence(presence) => {
111-
println!("(b) presence: {:?}", presence)
112-
}
113-
Update::AppContext(object) => {
114-
println!("(b) object: {:?}", object)
115-
}
116-
Update::MessageAction(action) => {
117-
println!("(b) message action: {:?}", action)
118-
}
119-
Update::File(file) => {
120-
println!("(b) file: {:?}", file)
121-
}
122-
}
123-
}));
98+
}),
99+
);
100+
101+
// Explicitly listen only for real-time `file` updates.
102+
tokio::spawn(
103+
subscription_clone
104+
.files_stream()
105+
.for_each(|file| async move { println!("(b) file: {:?}", file) }),
106+
);
124107

125108
// Sleep for a minute. Now you can send messages to the channels
126109
// "my_channel" and "other_channel" and see them printed in the console.
127-
// You can use the publish example or [PubNub console](https://www.pubnub.com/docs/console/)
110+
// You can use the publishing example or [PubNub console](https://www.pubnub.com/docs/console/)
128111
// to send messages.
129112
tokio::time::sleep(tokio::time::Duration::from_secs(15)).await;
130113

131114
// You can also cancel the subscription at any time.
132115
// subscription.unsubscribe();
133116

134117
println!("\nDisconnect from the real-time data stream");
135-
client.disconnect();
118+
pubnub.disconnect();
136119

137120
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
138121

139122
println!("\nReconnect to the real-time data stream");
140-
client.reconnect(None);
123+
pubnub.reconnect(None);
141124

142125
// Let event engine process unsubscribe request
143126
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
@@ -147,9 +130,11 @@ async fn main() -> Result<(), Box<dyn snafu::Error>> {
147130
// drop(subscription_clone);
148131

149132
println!(
150-
"\nUnsubscribe from all data streams. To restore requires `subscription.subscribe(None)` call." );
133+
"\nUnsubscribe from all data streams. To restore call `subscription.subscribe()` or \
134+
`subscription.subscribe_with_timetoken(Some(<timetoken>)) call."
135+
);
151136
// Clean up before complete work with PubNub client instance.
152-
client.unsubscribe_all();
137+
pubnub.unsubscribe_all();
153138
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
154139

155140
Ok(())

0 commit comments

Comments
 (0)