Closed Wouter01 closed 4 months ago
This wasn't the intentional behavior. What do you think should happen here? And, do you know why adding a delay helped?
If you are talking about multiple consumers of eventSequence
, that is, sadly, not supported by AsyncSequence
today. But, it is desperately needed, in my opinion. https://github.com/apple/swift-async-algorithms/issues/110
In my case, adding the delay mostly worked because then I would only start listening to the stream once, so I wouldn't have the issue.
You're right that it isn't possible at the moment to broadcast the events. I guess it could be done by using another method, however this isn't a huge issue so I don't think it's needed
The behavior isn't good, but it's more about how AsyncSequence works than this library. If you do not agree, please re-open!
The problem is eventSequence is an instance var of a class but it should be a computed var so it can be created by multiple clients, since that is the how they are designed to work. E.g. you can create a streams for NotificationCenter notifications all over your app and filter or process each one how you like, you aren't limited to one notification stream. I noticed the CoreLocation team has made the same design flaw in their CLMonitor events stream.
Ok, I'm listening! If eventSequence
creates a new sequence on invocation, it does fix this issue client side. Right now the design uses AsyncStream, so there would have to a collection of continuations somewhere. How should that work?
Continuations are for bridging between delegates/closures to async. Since you say your design already is async perhaps you could have a collection of Channel
s, one per client:
Then you might also like to wrap each Channel
in an AsyncSequence
similar to how streams are usually wrapped in sequences for public facing APIs:
https://forums.swift.org/t/how-do-you-completely-cancel-an-asyncstream/53733/2
I'll give this design a try tomorrow to see if it fixes the issue with CLMonitor
and report back.
Here is an implementation that did choose to use a collection of continuations: https://github.com/reddavis/Asynchrone/blob/main/Sources/Asynchrone/Sequences/SharedAsyncSequence.swift
I've looked into this and learned the best way to implement multiple consumers of the eventSequence is for the client to hold an array of AsyncChannel
s and send the event to all of them. This design worked fine for CLMonitor
:
One place:
@MainActor
class MonitorController {
let monitor: CLMonitor
var channels: [AsyncChannel<CLMonitor.Event>] = []
init() async {
monitor = await CLMonitor("SampleMonitor")
}
func start() async {
print("Started")
do {
for try await event in await monitor.events {
for channel in channels {
await channel.send(event)
}
}
}catch {}
print("Ended")
}
Many places:
.task {
print("started")
let channel = AsyncChannel<CLMonitor.Event>()
monitorController.channels.append(channel)
for await event in channel {
print("event")
}
monitorController.channels.removeAll { e in
e === channel
}
}
Since AsyncChannel
is a class, it's best for the client to manage that reference. Trying from inside the server is error-prone and might be an anti-pattern anyway. So you can probably just close this issue again 😉
Thanks for all your investigations and input here. I do appreciate it!
Hi,
I was refactoring some of my code and stumbled upon a weird issue: I couldn't get events from
eventSequence
(inRestartingServer
) anymore. When I added a delay, it works fine. Turns out, it was because I accidentally started the task containing thefor await _ in eventSequence
twice, and cancelled the first one. Cancelling a task will cancel the streams inside it too, therefore cancellingeventSequence
. A cancelled stream cannot be restarted, removing the ability to get any more events from the language server, as I cannot find a way to make a newEventSequence
with the public API.I was wondering if this falls under "intended behavior"? Could it be beneficial to have the ability to create multiple
EventSequence
instances, so a sequence can be cancelled and multiple tasks can get the events?