Eventide Custom Metadata: Properties vs. Local Properties

tl;dr

  • Eventide allows custom metadata
  • Don’t put it directly on the metadata property of a message
  • Put it in the metadata.properties hash if you want that metadata propagated to later messages
  • Put it in the metdata.local_properties hash if you don’t want it propagated to later messages

properties are followed

When using the Eventide Project, you use message’s metadata property to hold things related to the mechanics of messaging. So things like user_id or timing information about your domain operation don’t belong in metadata– they are data properties.

Also, the attributes directly on metadata are decided by the framework. So don’t try adding things there.

For custom metadata properties, you assign things to the [metadata.properties](http://metadata.properties) hash. A common use case for this is a trace_id. Imagine assigning each incoming HTTP request a unique identifier that you put into whatever command that handler writes as follows:

# Inside some HTTP handler

deposit = Deposit.build

deposit.deposit_id = "123"
deposit.account_id = "abc"
deposit.amount = 5

deposit.metadata.properties["trace_id"] = request.trace_id # xyz-456

Here we imagine the existence of a request object that contains a trace_id.

When handling a command, we typically use the follow method of the resulting message class. Deposit is typically followed by Deposited:

# ...earlier code in handler

desposited = Deposited.follow(deposit)

This deposited event’s metadata will have our trace_id:

puts deposited.metadata.properties["trace_id"]
# => "xyz-456"

As long as you use follow, Eventide will propagate your metadata.properties to the following messages. In the case of our trace_id, you’d now have a single identifier that originated with your user input attached to every message in your system resulting from that stimulus.

local properties are not followed

Sometimes you want custom metadata on a message, but you don’t want it followed. That is the job of the metadata.local_properties. Again, this is strictly for data related to the mechanics of messaging.

A use case I’ve had for this is I once needed a stream that held onto messages intended for multiple different streams until some other event happened. When we got that other event, we needed to write the “buffered” events to their correct stream.

Using metadata.local_properties removed the complication. When we wrote the message into the buffer, we assigned the stream name where it ultimately ended up as a target_stream_name property:

buffered_event.metadata.local_properties["target_stream_name"] = "destination-123"

write.(buffered_event, buffer_stream_name)

local_properties are not followed, so when we got the event that let us move these messages to their ultimate location, we were safe to use follow:


Like this message? I send out a short email each day to help software development leaders build organizations the deliver value. Join us!


Get the book!

Ready to learn how to build an autonomous, event-sourced microservices-based system? Practical Microservices is the hands-on guidance you've been looking for.

Roll up your sleeves and get ready to build Video Tutorials, the next-gen web-based learning platform. You'll build it as a collection of loosely-coupled autonomous services, developing a message store interface along the way.

When you're done, you'll be ready to contribute to microservices-based projects.

In ebook or in print.