Publish Subscribe Development Pattern - samvera/hyrax GitHub Wiki

< Back to Patterns

NOTE: At this writing, all links are to code in Release 3.0.1.

Publish-Subscribe

General Overview

This is often referred to as Pub-Sub. Using the Pub-Sub approach, code will publish a message (e.g. metadata_updated). There is a corresponding listener that subscribes to listen for that message. The listener has a method that will execute some statements in response to the message.

See also Hyrax's Event Bus (Hyrax::Publisher).

Terminology

Term Description
Publish (aka pub) The act of publishing a message.
Publisher The infrastructure code that processes the pub-sub registration, listening for messages, and forwarding to the code implementing the response to events in listeners.
Subscribe (aka sub) Registering a listener to listen for a message in a registered Listener class.
Message A string message that is registered as an event in a Listener class. In our implementation, all Listener methods beginning with on_ (e.g. on_object_metadata_updated) are registered as possible event messages (e.g. object.metadata.updated).
Listener A class registered to listen for specific messages. It has methods that process each message. The method follows naming conventions to match a message (e.g. object.metadata.updated) to the event method (e.g. on_object_metadata_updated) that processes it.

Hyrax Specifics

  • Publisher (information only - you won't need to make any changes here)
  • Listener
  • Messages
    • A message can be published from anywhere with Hyrax.publisher.publish('message.name', param: value)

An Example

  • Listener MetadataIndexListener
  • Publish a message
    • Hyrax.publisher.publish('object.metadata.updated', object: saved, user: user)

General Observations

Multiple events can be published to process the changes that have happened. For example, when a work is created, two messages will be published...

  Hyrax.publisher.publish('object.deposited', object: curation_concern, user: user)
  Hyrax.publisher.publish('object.metadata.updated', object: curation_concern, user: user)

Transactions will publish events once a step or series of steps have successfully completed. For example, the above messages are only published if the save was successful. See lib/hyrax/transactions/steps/save.rb

Testing

The following is an example of testing that a published method was successfully called. You need to following:

  • require 'hyrax/specs/spy_listener'
  • define a listener
  • subscribe to the listener before the test
  • unsubscribe from the listener after the test
  • test that the message was called

These requirements are seen in the following example...

require 'hyrax/specs/spy_listener'

describe "MyClass" do
  describe "#my_method that publishes a message" do
    let(:listener) { Hyrax::Specs::SpyListener.new }

    before { Hyrax.publisher.subscribe(listener) }
    after  { Hyrax.publisher.unsubscribe(listener) }

    it 'publishes a message' do
      # using object_metadata_updated message as an example; change to the actual published message
      expect { described_class.new.my_method }
        .to change { listener.object_metadata_updated&.payload }
    end
  end
end