1

I want to enable some real-time notifications about friend's activities (social network).
Technical context is: Webapp calling backend (REST API's).

Scenario is:

Kevin follows Bob.
When Bob posts a new comment, Kevin should be notified immediately (near real-time).
Besides, when Kevin logs in, he should be able to see some past notifications, similar to what Facebook does.
Meaning that notifications should be stored somewhere.

Here's the technical workflow:

  1. Bob posting a new comment involves an insert in database of this new comment.
  2. As following Domain-Driven-Design, the event CommentedItemEvent is triggered.
  3. A distinct worker in the same bounded context (long-running process, polling the database each second) listening to this event captures it.

At the end of 3, I see 2 possibilities:

  • Creating the corresponding notification, storing it in database and THEN sending it to Redis Pub/sub. This one would feed some specific subscribers acting on the WebSocket connection to send the notification to Kevin's client.
  • Creating the corresponding notification, then sending it to Redis THEN storing them in database.

Regarding the first possibility, the advantage would be the transactional aspect. Indeed, no noticification could be sent if it wasn't saved before. => Integrity.
However, the drawback is that the database insertion could slow down the process of "near real-time notification".

Regarding the second possibility, notifications are immediately sent but if some failure happens regarding database insertion, Kevin might have wondered:

"Humm... I received the Bob's notification, I'm sure I saw it. So why a simple page refresh doesn't show it anymore?" => Indeed, it wasn't persist successfully, so can't query it.

What is a good practice regarding this use case?

Of course, one faster way would be to not involve an event listener for this case, but it would violate some principles regarding Domain-Driven Design. IMHO, listener polling database in its own bounded context is necessary. (evoked by Vaughn Vernon in this book IDDD - "Building an event store")

  • @Mik378: Just how much delay are we talking about here due to the database update? If it is in the order of 1 second or less, only a very critical user would notice it and they would already notice the delay that you seem to have in processing the initial trigger. – Bart van Ingen Schenau Jul 2 '14 at 15:15
  • @Bart Actually, the real use case is very similar to a Chat, although dealing with item's comments. Bob types something, Kevin should be notified, as a real chat application. I noticed that my updates could take up to 3 seconds regarding the observing/following user number. For instance, let's take Whatsapp, or Facebook Chat, I really wonder how their mechanism of persisting conversations is efficient, or may they skip the pure transactional aspect? with a loss of 1 per 1 millions for instance. – Mik378 Jul 2 '14 at 15:18
  • 1
    If you want a guarantee that it will be persisted, you absolutely positively must wait until the database transaction is finished. I honestly think it is overrated. Send the confirmation immediately. Should it fail, you can always retry. Should it continually fail, you could always remove the confirmation later with an error of some sort, though this will almost never happen. – Neil Jul 2 '14 at 16:22
  • @Neil I agree with your point of view. Would you also skip the event listener step (polling database)? Meaning sending to Redis strictly as soon as Bob's comment is persisted? Indeed, in that case, it would be faster but I would have no clue that the notification was successfully sent. The advantage of event store is that I can mark a flag "processed" on the event, ensuring that the notification has well been sent, and can serve for retry otherwise. – Mik378 Jul 2 '14 at 16:47
  • @Mik378 I don't like making servers retain state, which implies you'd have to continually poll the database. That said, I dislike continually polling the database more, so I just assume retain whatever information I need on the server. If you're worried about how much memory would be required for this, the next best thing is to, as you say, keep a dirty flag that tells you that the client has a comment that he's not yet seeing, until the next time the client updates the page. – Neil Jul 15 '14 at 7:24
1

Event handling is not necessarily something internal only to the Domain instance. Sometimes, an external service handles more appropriately such events needs than an internal implementation.

Text Messaging for instance, can be handled better by an XMPP or IRC services, which are interfaced as dependencies into the domain, through an common interface (i.e. notify(message) looks the same to the sender within the domain).

So you may have few domains: one for the Message Logic, another for Message Persistence and another for Message Sharing.

A specialised external service could accept connections from Message Sharing instances, which handles cases and events, putting them through Message Logic specifications and rules.

Message Persistence can connect to the same service, and just handle the storage of the messages in an appropriate database, and even update some search engine.

All related, yet uncoupled, domains. For sure, you will need to work more on the guarantees of each domain (like CAP theorem and latency).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.