Being fairly new to Rx, I'm trying to achieve something that seems conceptually simple, but I've been struggling for a day trying to figure out how to achieve it in Rx.
I have 2 observables, one is an IObservable<Worker>
and the other is IObservable<Work>
. The idea is sort of a work balancer setup, where work is submitted through one observable, and paired up with a worker that is submitted on the other observable.
The simple case is easy enough to achieve using Observable.Zip
. But there is one additional requirement that throws a wrench in the works.
Each worker is only able to accept work for a limited time (there is a window that closes and the worker is no longer eligible to accept work and should not be paired with a work item).
Here is a marble diagram of what I'm trying to achieve:
-----A-----B-----C------D-----> (WORKERS IObservable<IObservable<Worker>>) | | | | | | | | -----------]| ----] | | | |----------] | |-----] --------1----------2--3------> (WORK IObservable<Work>) --------A1---------C2---D3--> (WORKER/WORK PAIRS IObservable<PairedWork>)
So to recap, the requirements:
When work comes in it should be assigned to the first worker who's window is still active at the time the work comes in.(In the diagram we have the A1 pair but no B2, since worker B is expired by the time work item 2 comes in and C2 becomes the correct pairing)
When a worker is paired up with a work item, it should not be eligible to be paired with subsequent work items (in a sense, its window should be force closed whenever it is used but this is the part I'm most struggling with how to achieve).
If work comes in and there is no available worker with an open window, it should wait until the next worker is emitted and pair with it (see D3 in the diagram).
I'm pretty sure this is somehow achievable with Join
or GroupJoin
, but I'm struggling to figure out how to get the exact semantics I'm looking for. Any help would be appreciated.