Application requirements:
This should work. The types differ, I didn't want to guess your probably abstract datatypes. You can apply them pretty easily (function parameters, key comparison and Select statements)
Idea is that for every emited value from a, we take the first value emited either by b.Where(keys match) or timeout (presented by Observable.Timer) and make our Select based on this information.
I assumed that in timeout cases you also want on OnNext notification with some error provisioning mechanism.
private IObservable MonitorAB(IObservable a, IObservable b,
TimeSpan threshold)
{
return Observable.Create((obs) =>
{
a = a.Publish().RefCount();
b = b.Publish().RefCount();
return a.Subscribe(i =>
{
Observable.Merge(Observable.Timer(threshold).Select(_ => $"Timeout for A{i}"),
b.Where(j => j == i).Select(_ => $"Got matching B for A{i}"))
.Take(1)
.Subscribe(obs.OnNext);
});
});
}
I tested it like this.
private void Test()
{
var a = Observable.Interval(TimeSpan.FromSeconds(2)).Take(5);
var b = Observable.Interval(TimeSpan.FromSeconds(5)).Take(5);
MonitorAB( a, b, TimeSpan.FromSeconds(13)).Subscribe(Console.WriteLine);
}
EDIT: to test the out of order case, you can flip the B stream e.g.
var b = Observable.Interval(TimeSpan.FromSeconds(2)).Select(i => 4 - i).Take(5);