If we do this, the usage can be much more idiomatic:
receiver1 = some_chan.get_receiver()
timer = channel.Timer(30.0)
select = Select(receiver1=receiver1, timer=timer)
async for selected in select.ready():
match selected.origin:
case receiver1:
process_data(selected.value)
case timer:
# something to do once every 30 seconds
pass
case _:
raise Exception("Unknown origin")
So .ready() should return an async iterator itself, by just yielding for each ready message.
With this we also don't need to keep a reference to the Select instance around, we can just do async for selected in Select(...).ready(), or we could just add an utility function to make it even more compact, as 99% of the cases nobody will need to even know Select is a class: async for selected in select(...). This also completely removes the temptation of adding the option to dynamically change the Select instance inside the loop (like in #24).
This also sort of depends on #27, as it could make breaking from the loop even more natural, and cause data loss in that case.
Originally posted by @leandro-lucarella-frequenz in #27 (comment)
If we do this, the usage can be much more idiomatic:
So
.ready()should return an async iterator itself, by justyielding for each ready message.With this we also don't need to keep a reference to the
Selectinstance around, we can just doasync for selected in Select(...).ready(), or we could just add an utility function to make it even more compact, as 99% of the cases nobody will need to even knowSelectis a class:async for selected in select(...). This also completely removes the temptation of adding the option to dynamically change theSelectinstance inside the loop (like in #24).This also sort of depends on #27, as it could make breaking from the loop even more natural, and cause data loss in that case.
Originally posted by @leandro-lucarella-frequenz in #27 (comment)