This one has come up 3 or 4 times this year, so I thought it was about time I blogged about it.
Heart beats or keep alives are used in all shapes & forms of software development, from inter-process communications in UNIX systems programming to session keep alives in web development. It's an old, simple approach that has been tried and tested. This pattern is amazingly beautiful in Rx.
Lets start with a server, keeping a client session alive.
// For this scenario we can simply model the heart beat with a Unit (kind of like void, we have no payload)
var source = Observable.Return(new Unit()).Delay(TimeSpan.FromSeconds(1)).Repeat();
// Query converts this stream into a true/false switch.
var query = Observable.Switch
(
from hb in source
select Observable.Return(true)
.Concat(Observable.Return(false).Delay((TimeSpan.FromSeconds(2))))
).DistinctUntilChanged();
I'll break this into its components.
// Ensures that our timeout timer is cancels when a new heart beat arrives.
Observable.Switch
// Tells the consumer of the query that we are now connected / alive.
Observable.Return(true)
// Once we've told the consumer that we are connected, we will start a timer that will yield false if it ever expires.
.Concat(Observable.Return(false).Delay((TimeSpan.FromSeconds(2))))
// we don't want to yield, true, true, true to the consumer, they only need to be told once.
.DistinctUntilChanged()
If you'd like to test this query, play around with the event source. Here is one that goes up & down every few seconds.
var source = Observable.Concat
(
Observable.Return(new Unit()).Delay(TimeSpan.FromSeconds(1)).Repeat(3),
Observable.Empty<Unit>().Delay(TimeSpan.FromSeconds(3))
).Repeat();
If you found this interesting stay tuned for some more scenarios.
Comments