Skip to content

Commit 335b6b1

Browse files
authored
refactor(iroh-docs): Replace flume with async_channel in docs (#2540)
## Description This is mostly a 1:1 replacement, except for the fact that the same_channel api is missing from async_channel. So I replaced it with some ugly code that uses the fact that a async_channel Sender or Receiver is just an Arc<Channel>. To be removed if/when smol-rs/async-channel#98 is merged, but until then I think it is fine. ## Breaking Changes None ## Notes & open questions Note: we can not use tokio::sync::mpsc::Channel for the actor because we can't control from which thread Drop is called. Note: some streams were Unpin before, but it was not explicit. Now I added Unpin explicitly (and boxed the stream to make it true). Not sure if the version check would catch this, pretty sure that not. But taking away Unpin would have been a breaking change. ## Change checklist - [ ] Self-review. - [ ] Documentation updates following the [style guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text), if relevant. - [ ] Tests if relevant. - [ ] All breaking changes documented.
1 parent 956c51a commit 335b6b1

File tree

5 files changed

+81
-56
lines changed

5 files changed

+81
-56
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ workspace = true
1616

1717
[dependencies]
1818
anyhow = "1"
19+
async-channel = "2.3.1"
1920
blake3 = { package = "iroh-blake3", version = "1.4.5"}
2021
bytes = { version = "1.4", features = ["serde"] }
2122
derive_more = { version = "1.0.0-beta.6", features = ["debug", "deref", "display", "from", "try_into", "into", "as_ref"] }
2223
ed25519-dalek = { version = "2.0.0", features = ["serde", "rand_core"] }
23-
flume = "0.11"
2424
futures-buffered = "0.2.4"
2525
futures-lite = "2.3.0"
2626
futures-util = { version = "0.3.25" }

src/actor.rs

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ enum Action {
6161
#[display("ListAuthors")]
6262
ListAuthors {
6363
#[debug("reply")]
64-
reply: flume::Sender<Result<AuthorId>>,
64+
reply: async_channel::Sender<Result<AuthorId>>,
6565
},
6666
#[display("ListReplicas")]
6767
ListReplicas {
6868
#[debug("reply")]
69-
reply: flume::Sender<Result<(NamespaceId, CapabilityKind)>>,
69+
reply: async_channel::Sender<Result<(NamespaceId, CapabilityKind)>>,
7070
},
7171
#[display("ContentHashes")]
7272
ContentHashes {
@@ -108,12 +108,12 @@ enum ReplicaAction {
108108
reply: oneshot::Sender<Result<()>>,
109109
},
110110
Subscribe {
111-
sender: flume::Sender<Event>,
111+
sender: async_channel::Sender<Event>,
112112
#[debug("reply")]
113113
reply: oneshot::Sender<Result<()>>,
114114
},
115115
Unsubscribe {
116-
sender: flume::Sender<Event>,
116+
sender: async_channel::Sender<Event>,
117117
#[debug("reply")]
118118
reply: oneshot::Sender<Result<()>>,
119119
},
@@ -166,7 +166,7 @@ enum ReplicaAction {
166166
},
167167
GetMany {
168168
query: Query,
169-
reply: flume::Sender<Result<SignedEntry>>,
169+
reply: async_channel::Sender<Result<SignedEntry>>,
170170
},
171171
DropReplica {
172172
reply: oneshot::Sender<Result<()>>,
@@ -222,7 +222,7 @@ struct OpenReplica {
222222
/// [`SyncHandle::drop`] will not block.
223223
#[derive(Debug, Clone)]
224224
pub struct SyncHandle {
225-
tx: flume::Sender<Action>,
225+
tx: async_channel::Sender<Action>,
226226
join_handle: Arc<Option<JoinHandle<()>>>,
227227
}
228228

@@ -232,7 +232,7 @@ pub struct OpenOpts {
232232
/// Set to true to set sync state to true.
233233
pub sync: bool,
234234
/// Optionally subscribe to replica events.
235-
pub subscribe: Option<flume::Sender<Event>>,
235+
pub subscribe: Option<async_channel::Sender<Event>>,
236236
}
237237
impl OpenOpts {
238238
/// Set sync state to true.
@@ -241,7 +241,7 @@ impl OpenOpts {
241241
self
242242
}
243243
/// Subscribe to replica events.
244-
pub fn subscribe(mut self, subscribe: flume::Sender<Event>) -> Self {
244+
pub fn subscribe(mut self, subscribe: async_channel::Sender<Event>) -> Self {
245245
self.subscribe = Some(subscribe);
246246
self
247247
}
@@ -255,7 +255,7 @@ impl SyncHandle {
255255
content_status_callback: Option<ContentStatusCallback>,
256256
me: String,
257257
) -> SyncHandle {
258-
let (action_tx, action_rx) = flume::bounded(ACTION_CAP);
258+
let (action_tx, action_rx) = async_channel::bounded(ACTION_CAP);
259259
let actor = Actor {
260260
store,
261261
states: Default::default(),
@@ -298,7 +298,7 @@ impl SyncHandle {
298298
pub async fn subscribe(
299299
&self,
300300
namespace: NamespaceId,
301-
sender: flume::Sender<Event>,
301+
sender: async_channel::Sender<Event>,
302302
) -> Result<()> {
303303
let (reply, rx) = oneshot::channel();
304304
self.send_replica(namespace, ReplicaAction::Subscribe { sender, reply })
@@ -309,7 +309,7 @@ impl SyncHandle {
309309
pub async fn unsubscribe(
310310
&self,
311311
namespace: NamespaceId,
312-
sender: flume::Sender<Event>,
312+
sender: async_channel::Sender<Event>,
313313
) -> Result<()> {
314314
let (reply, rx) = oneshot::channel();
315315
self.send_replica(namespace, ReplicaAction::Unsubscribe { sender, reply })
@@ -435,7 +435,7 @@ impl SyncHandle {
435435
&self,
436436
namespace: NamespaceId,
437437
query: Query,
438-
reply: flume::Sender<Result<SignedEntry>>,
438+
reply: async_channel::Sender<Result<SignedEntry>>,
439439
) -> Result<()> {
440440
let action = ReplicaAction::GetMany { query, reply };
441441
self.send_replica(namespace, action).await?;
@@ -489,13 +489,13 @@ impl SyncHandle {
489489
Ok(store)
490490
}
491491

492-
pub async fn list_authors(&self, reply: flume::Sender<Result<AuthorId>>) -> Result<()> {
492+
pub async fn list_authors(&self, reply: async_channel::Sender<Result<AuthorId>>) -> Result<()> {
493493
self.send(Action::ListAuthors { reply }).await
494494
}
495495

496496
pub async fn list_replicas(
497497
&self,
498-
reply: flume::Sender<Result<(NamespaceId, CapabilityKind)>>,
498+
reply: async_channel::Sender<Result<(NamespaceId, CapabilityKind)>>,
499499
) -> Result<()> {
500500
self.send(Action::ListReplicas { reply }).await
501501
}
@@ -566,7 +566,7 @@ impl SyncHandle {
566566

567567
async fn send(&self, action: Action) -> Result<()> {
568568
self.tx
569-
.send_async(action)
569+
.send(action)
570570
.await
571571
.context("sending to iroh_docs actor failed")?;
572572
Ok(())
@@ -581,7 +581,10 @@ impl Drop for SyncHandle {
581581
fn drop(&mut self) {
582582
// this means we're dropping the last reference
583583
if let Some(handle) = Arc::get_mut(&mut self.join_handle) {
584-
self.tx.send(Action::Shutdown { reply: None }).ok();
584+
// this call is the reason tx can not be a tokio mpsc channel.
585+
// we have no control about where drop is called, yet tokio send_blocking panics
586+
// when called from inside a tokio runtime.
587+
self.tx.send_blocking(Action::Shutdown { reply: None }).ok();
585588
let handle = handle.take().expect("this can only run once");
586589
if let Err(err) = handle.join() {
587590
warn!(?err, "Failed to join sync actor");
@@ -593,7 +596,7 @@ impl Drop for SyncHandle {
593596
struct Actor {
594597
store: Store,
595598
states: OpenReplicas,
596-
action_rx: flume::Receiver<Action>,
599+
action_rx: async_channel::Receiver<Action>,
597600
content_status_callback: Option<ContentStatusCallback>,
598601
tasks: JoinSet<()>,
599602
}
@@ -619,10 +622,10 @@ impl Actor {
619622
}
620623
continue;
621624
}
622-
action = self.action_rx.recv_async() => {
625+
action = self.action_rx.recv() => {
623626
match action {
624627
Ok(action) => action,
625-
Err(flume::RecvError::Disconnected) => {
628+
Err(async_channel::RecvError) => {
626629
debug!("action channel disconnected");
627630
break None;
628631
}
@@ -979,17 +982,14 @@ impl OpenReplicas {
979982
}
980983

981984
async fn iter_to_channel_async<T: Send + 'static>(
982-
channel: flume::Sender<Result<T>>,
985+
channel: async_channel::Sender<Result<T>>,
983986
iter: Result<impl Iterator<Item = Result<T>>>,
984987
) -> Result<(), SendReplyError> {
985988
match iter {
986-
Err(err) => channel
987-
.send_async(Err(err))
988-
.await
989-
.map_err(send_reply_error)?,
989+
Err(err) => channel.send(Err(err)).await.map_err(send_reply_error)?,
990990
Ok(iter) => {
991991
for item in iter {
992-
channel.send_async(item).await.map_err(send_reply_error)?;
992+
channel.send(item).await.map_err(send_reply_error)?;
993993
}
994994
}
995995
}
@@ -1032,10 +1032,10 @@ mod tests {
10321032
let id = namespace.id();
10331033
sync.import_namespace(namespace.into()).await?;
10341034
sync.open(id, Default::default()).await?;
1035-
let (tx, rx) = flume::bounded(10);
1035+
let (tx, rx) = async_channel::bounded(10);
10361036
sync.subscribe(id, tx).await?;
10371037
sync.close(id).await?;
1038-
assert!(rx.recv_async().await.is_err());
1038+
assert!(rx.recv().await.is_err());
10391039
Ok(())
10401040
}
10411041
}

src/engine.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,15 +170,15 @@ impl Engine {
170170

171171
// Subscribe to insert events from the replica.
172172
let a = {
173-
let (s, r) = flume::bounded(SUBSCRIBE_CHANNEL_CAP);
173+
let (s, r) = async_channel::bounded(SUBSCRIBE_CHANNEL_CAP);
174174
this.sync.subscribe(namespace, s).await?;
175-
r.into_stream()
176-
.map(move |ev| LiveEvent::from_replica_event(ev, &content_status_cb))
175+
Box::pin(r).map(move |ev| LiveEvent::from_replica_event(ev, &content_status_cb))
177176
};
178177

179178
// Subscribe to events from the [`live::Actor`].
180179
let b = {
181-
let (s, r) = flume::bounded(SUBSCRIBE_CHANNEL_CAP);
180+
let (s, r) = async_channel::bounded(SUBSCRIBE_CHANNEL_CAP);
181+
let r = Box::pin(r);
182182
let (reply, reply_rx) = oneshot::channel();
183183
this.to_live_actor
184184
.send(ToLiveActor::Subscribe {
@@ -188,7 +188,7 @@ impl Engine {
188188
})
189189
.await?;
190190
reply_rx.await??;
191-
r.into_stream().map(|event| Ok(LiveEvent::from(event)))
191+
r.map(|event| Ok(LiveEvent::from(event)))
192192
};
193193

194194
Ok(a.or(b))

src/engine/live.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ pub enum ToLiveActor {
7878
Subscribe {
7979
namespace: NamespaceId,
8080
#[debug("sender")]
81-
sender: flume::Sender<Event>,
81+
sender: async_channel::Sender<Event>,
8282
#[debug("oneshot::Sender")]
8383
reply: sync::oneshot::Sender<Result<()>>,
8484
},
@@ -153,8 +153,8 @@ pub struct LiveActor<B: iroh_blobs::store::Store> {
153153
gossip: Gossip,
154154
bao_store: B,
155155
downloader: Downloader,
156-
replica_events_tx: flume::Sender<crate::Event>,
157-
replica_events_rx: flume::Receiver<crate::Event>,
156+
replica_events_tx: async_channel::Sender<crate::Event>,
157+
replica_events_rx: async_channel::Receiver<crate::Event>,
158158

159159
/// Send messages to self.
160160
/// Note: Must not be used in methods called from `Self::run` directly to prevent deadlocks.
@@ -192,7 +192,7 @@ impl<B: iroh_blobs::store::Store> LiveActor<B> {
192192
sync_actor_tx: mpsc::Sender<ToLiveActor>,
193193
gossip_actor_tx: mpsc::Sender<ToGossipActor>,
194194
) -> Self {
195-
let (replica_events_tx, replica_events_rx) = flume::bounded(1024);
195+
let (replica_events_tx, replica_events_rx) = async_channel::bounded(1024);
196196
Self {
197197
inbox,
198198
sync,
@@ -262,7 +262,7 @@ impl<B: iroh_blobs::store::Store> LiveActor<B> {
262262
}
263263
}
264264
}
265-
event = self.replica_events_rx.recv_async() => {
265+
event = self.replica_events_rx.recv() => {
266266
trace!(?i, "tick: replica_event");
267267
inc!(Metrics, doc_live_tick_replica_event);
268268
let event = event.context("replica_events closed")?;
@@ -865,7 +865,7 @@ impl From<&SyncFinished> for SyncDetails {
865865
struct SubscribersMap(HashMap<NamespaceId, Subscribers>);
866866

867867
impl SubscribersMap {
868-
fn subscribe(&mut self, namespace: NamespaceId, sender: flume::Sender<Event>) {
868+
fn subscribe(&mut self, namespace: NamespaceId, sender: async_channel::Sender<Event>) {
869869
self.0.entry(namespace).or_default().subscribe(sender);
870870
}
871871

@@ -930,15 +930,15 @@ impl QueuedHashes {
930930
}
931931

932932
#[derive(Debug, Default)]
933-
struct Subscribers(Vec<flume::Sender<Event>>);
933+
struct Subscribers(Vec<async_channel::Sender<Event>>);
934934

935935
impl Subscribers {
936-
fn subscribe(&mut self, sender: flume::Sender<Event>) {
936+
fn subscribe(&mut self, sender: async_channel::Sender<Event>) {
937937
self.0.push(sender)
938938
}
939939

940940
async fn send(&mut self, event: Event) -> bool {
941-
let futs = self.0.iter().map(|sender| sender.send_async(event.clone()));
941+
let futs = self.0.iter().map(|sender| sender.send(event.clone()));
942942
let res = futures_buffered::join_all(futs).await;
943943
// reverse the order so removing does not shift remaining indices
944944
for (i, res) in res.into_iter().enumerate().rev() {
@@ -977,8 +977,8 @@ mod tests {
977977
#[tokio::test]
978978
async fn test_sync_remove() {
979979
let pk = PublicKey::from_bytes(&[1; 32]).unwrap();
980-
let (a_tx, a_rx) = flume::unbounded();
981-
let (b_tx, b_rx) = flume::unbounded();
980+
let (a_tx, a_rx) = async_channel::unbounded();
981+
let (b_tx, b_rx) = async_channel::unbounded();
982982
let mut subscribers = Subscribers::default();
983983
subscribers.subscribe(a_tx);
984984
subscribers.subscribe(b_tx);

0 commit comments

Comments
 (0)