Search code examples
javascriptjavaeventsthrift

Is there a clean way to define events using thrift?


In my application, there are several components which will generate various different types of application-specific events. These events will be published out to a broker and be delivered to N number of clients. Some of these clients are other Java classes in my server-side app, but the main consumer is my javascript-based WebUI.

My current approach thus-far was to define an abstract event base class to encapsulate some common fields, then implement a specific event class for each event.

This has been working fine, except now I need to maintain the event on both the javascript and java side so either side can react to the others events.

I had a thought this morning that I could utilize Thrift (which the project already makes heavy use of) to define the event data structures and auto-generate the classes on either side. This not only handles the tedium of writing the class files, but ensures consistency.

My issue is that since data objects in thrifts are Structs (which can't be extended), I have no way of encapsulating the common fields nor can I pass the events along using a single base class.

The workaround I've come up with thus far is to define a struct inside the thrift IDL to act as a 'base' class, with an optional field for each and every event type that I define. This would still let me have a single class to refer to events generically while also letting me capture the relevant data when spawning events.

Maybe this is just me not being very familiar with thrift, but this feels like a hack. Am I way off, or is this an ok approach? Is there a better way to accomplish this?


Solution

  • Thrift as an serialization and RPC mechanism allows only for one-to-one connections, so that will not really solve the task. But you're not lost.

    If you want to do one-to-many, you should use some messaging system. Thrift can be easily combined with messaging systems on various levels. The /contrib folder of the source tree holds a few examples on how to achieve that.

    Using a Thrift union as the envelope to hold all you various data structures is a valid solution, because it allows to minimize the serialization and deserialzation code - you only need one pair of functions to deal with always the same Envelope structure (which of course may have different contents).

    struct Foo { ... some member fields ... }
    struct Bar { ... some member fields ... }
    struct Baz { ... some member fields ... }
    
    union Envelope {
      1: Foo foo
      2: Bar bar
      3: Baz baz
    }