5

I have a system, connected to financial markets, that makes a very heavy use of events.

All the code is structured as a cascade of events with filters, aggregations, etc in between.

Originally the system was written in C# and then ported to F# (which in retrospect was a great move) and events in the C# code got replaced by events in F# without giving it much thoughts.

I have heard about the observer pattern, but I haven't really gone through the topic. And recently, I have read, through some random browsing, about F#'s Mailbox processor.

I read this: Difference between Observer Pattern and Event-Driven Approach and I didn't get it, but apparently over 150 people voted that the answer wasn't too clear as well :)

In an article like this: https://hackernoon.com/observer-vs-pub-sub-pattern-50d3b27f838c it seems like the observer pattern is strictly identical to events...

At first glance, they seem to be solving the same kind of problems, just with different interfaces but that got me to think about 2 questions:

  • Is the mailbox processor really a thing being used? it seems to appear mostly in older documentation and, in the packages I'm using, I haven't come across any using it

  • Regarding the observer pattern, only one package across the sizeable amount we're using makes internal use of it, but everything else is just using basic events.

Are there specific use cases fitting the Observable pattern and the MailboxProcessor? Do they have features that are unique? or are they just syntactic help around events in the end?

Thomas
  • 10,933
  • 14
  • 65
  • 136
  • The MailboxProcessor of F# is one incarnation of the actor model. Others are Akka.NET, Proto.Actor and Orleans. Just to begin to understand the actor model, I recommend you read the home page of [Proto.Actor](http://proto.actor/) – Bent Tranberg May 26 '20 at 17:36
  • I believe the reason you don't see actors used in libraries, is because you make up applications from a hierarchy of actors. I can't imagine it ever being used in a library not specifically tied to an application. – Bent Tranberg May 26 '20 at 17:45
  • Suggest you look at this [page](https://fsharpforfunandprofit.com/posts/concurrency-intro/) for an overview of concurrent programming mechanisms in F#. Quite possible you already have a good overview, but perhaps don't quite know where to fit in actors in the landscape. – Bent Tranberg May 26 '20 at 17:47
  • For your use case, I suspect [Hopac](http://hopac.github.io/Hopac/Hopac.html) can be even more interesting to you than the actor model. It's a bit like the actor model, but with the jobs typically communicating with each other in a slightly different way, that I think you will like. On that page, scroll down past the Synopsis to the Description. – Bent Tranberg May 26 '20 at 18:00
  • It is possible [Gjallarhorn](http://reedcopsey.github.io/Gjallarhorn/) can be of use somehow. – Bent Tranberg May 26 '20 at 18:12
  • @Brent, I've seen the concurrency page at fsharpforfunandprofit.com, I came from there before writing this question :) my question is about the fact that Mailbox processor seems to be found nowhere but in <2014 documentation, and I don't see any difference between the observer pattern and an plain simple event. There are a lot of pages explaining how to use these concepts, but none saying: these 3 things look the same but they are difference because of 'x'. – Thomas May 26 '20 at 18:21
  • if you look on SO for mailbox processor for example, most of the questions are very old; there are a few recent ones (2017-2018), but the vast majority is much older as if it somehow vanished – Thomas May 26 '20 at 18:23

1 Answers1

4

As simplified as possible:

Mailbox

This is a minimal implementation of the actor model. You post messages to a queue, and your loop reads the messages from the queue, one by one. Maybe it posts to another mailbox or it does something with the messages.

  • Any action can only take place when a message is received.
  • Posting to the queue is non-blocking, i.e, no back-pressure.
  • All exceptions are caught and exposed as an event on the mailbox. They are expected to be handled by the actor above it.
  • Other actor frameworks provide features like supervisors, contracts, failover, etc.

Events

Events are a language supported callback mechanism.

It's a simple implementation. You register a callback delegate, and when the event is raised, your delegate is called.

  • Delegates are called in the order they are added.
  • Events are blocking, and synchronous. The one delegate blocks, the rest are delayed.
  • Events are about writing code to respond to events, as opposed what came before it, which was polling.
  • The handler for an event is usually the final end-point for that event, and it usually has side-effects.
  • Sharing a handler is common. For example, ten buttons might have the same function handling clicks, because the sender of the event is known.
  • You handle exceptions by yourself, typically in the handler code

Observables

There's a source (Observable) which you can subscribe to with a sink (Observer). An observable represents a bounded or un-bounded stream of values. An unbounded stream (an Observable which never completes) seems similar to an event, but there are several important properties to Observables.

  • An Observable emits a series of notifications, which follows this contract:
    OnNext* (OnError|OnCompleted)+
  • All notifications are serialized
  • Notifications may or may not be synchronous. There's no guarantee of back-pressure.
  • The value of Observables lies in the fact that they are compose-able.
  • An observable represents a stream of future notifications, operators act to transform this stream.
  • This approach is sometimes called complex event processing (CEP).
  • Exception handling is part of the pipeline, and there are many combinators to deal with it.
  • You typically never implement an Observer yourself. You use combinators to set up a pipeline which models the behavior you want.
Asti
  • 12,447
  • 29
  • 38