In the typical filter or handler pattern, we have set of data and filters/handlers. We are filtering the available data set using available filters.
These filters may have some dependencies. For example, let's say that filter 2 depends on filter 1, while some filters do not have dependencies with other filters. With the existing approach, some time-consuming filters are designed to use several threads to process the received records parallelly to improve performance.
However, we are executing each filter one after another. Even though we are using multiple threads for highly time-consuming filters, we need to wait until all the records finish before we execute the next filter. Sometimes, we need to populate some data from the database for filters, but with the existing architecture, we need to wait until the relevant filter is executed.
We can improve this by using the nonblocking approach as much as possible. The following diagram shows the proposed architecture.
According to the diagram, we are publishing routes to the disruptor (the disruptor is simple ring buffer but it has many performance improvements, including cache padding) and we have multiple handlers that are running on different threads. Each handler belongs to different filters. We can add more handlers to the same filter based on the requirement. A major advantage is that we can process simultaneously across all of the routes. Cases like dependencies between the handlers can be handled at the implementation level. With this approach, we don't need to wait until all the routes are filtered by the single routes. The other advantage is that we can add separate handlers to populate data for future use.
Disruptors normally consume more resources and depend on the waiting strategies that we can use for the handlers. So, we need to decide what kind of disruptor configuration patterns we can use for the application. It can be a single disruptor, a single disruptor for the user, or multiple disruptors based on the configuration. Or, we can configure some disruptions for selected filters (handlers) and different ones for other handlers.