In Chapter 8, Graph-Based Data Processing, we explored the use of the bspgraph package to implement a few popular graph-based algorithms such as Dijkstra's shortest path, graph coloring, and PageRank. To orchestrate the end-to-end execution of the aforementioned algorithms, we relied on the API provided by the package's Executor type. However, instead of having our algorithm implementations directly invoke the Executor types constructor, we allowed the end users to optionally specify a custom executor factory for obtaining an Executor instance.
Any Go function that satisfies the following signature can be effectively used in place of the default constructor for a new Executor constructor:
type ExecutorFactory func(*bspgraph.Graph, bspgraph.ExecutorCallbacks) *bspgraph.Executor
The key benefit of this approach is that the executor factory is given full access to the algorithm-specific callbacks for the various stages of the computation. In this chapter, we will be exploiting this mechanism to intercept and decorate the user-defined callbacks with the necessary glue logic for interfacing with the barrier primitive that we built in the previous section. The patched callbacks will then be passed to the original Executor constructor and the result will be returned to the caller.
This little trick, while completely transparent to the original algorithm implementation, is all that we really need to ensure that all callbacks are executed in lock-step with all other workers.