The Plugin Event Loop

If you've done user interface or even Node.js programming, you're probably familiar with the concept of an event loop. Each Hobson plugin has its own event loop referred to as the plugin event loop. This is a single thread that is responsible for delivering events to your plugin when they occur. Events are delivered by the Hobson runtime to your plugin via lifecycle callback methods that it invokes when the event occurs.

Any methods in the HobsonPluginRuntime interface that start with the prefix "on" are lifecycle callbacks and will always be invoked by the event loop thread.

NameDescription
onStartupInvoked at plugin startup after all dependencies (including all manager instances) have been injected
onShutdownInvoked when the plugin is being shutdown
onRefreshInvoked every x number of seconds where x is the value > 0 returned from getRefreshInterval().
onPluginConfigurationUpdateInvoked when the plugin configuration has been changed
onDeviceConfigurationUpdateInvoked when the configuration for one of the plugin's devices has been changed

There are some distinct advantages to the event loop approach:

  1. Plugin callback methods are guaranteed to be invoked using the same thread. This means that you don't need to worry about writing thread-safe code. That is unless you decide to create your own threads from within your plugin -- see the disadvantages section below for how to handle that.
  2. Each plugin running on the Hobson Hub is "sandboxed" by its event loop. In other words, one misbehaving plugin shouldn't have an impact on other plugins that may also be running.

There are also some disadvantages to this approach:

  1. At the moment, each plugin has a unique thread resource to run its event loop. This will effect the maximum number of plugins a single Hub can support.
  2. It is important not to execute operations in plugin callback methods that can block or take a significant amount of time to run. If that happens, the plugin will stop receiving events until the long-running operation completes. Hobson provides handy asynchronous mechanisms for common blocking operations such as HTTP calls and socket I/O that are event loop friendly.
  3. If a plugin must create its own thread(s) to do work, it must make sure that when it returns the results of that work to the Hobson runtime it does so through the event loop. There is a plugin method executeInEventLoop() that facilitates this.

Even with its disadvantages, the plugin event loop makes writing plugins much simpler and less error-prone for plugin developers.