... | ... | @@ -293,11 +293,28 @@ We have a special `context.Context` structure in Go. It is a bag for variety, un |
|
|
|
|
|
### Exchange data using callout parameters
|
|
|
|
|
|
In this case, the data sharing is controlled by the core. It means that the core knows the data meaning and may interrupt the hook execution or modify the data between calling the callout points.
|
|
|
|
|
|
There are two approaches to implementation. The first uses a single mutable object that is passed to callout points. It's similar to the data exchange using the context described in the previous section. The main difference is the core knows the structure of the data and may analyze its content. The second approach is passing the output of the previous callout as the arguments of the current callout. These solutions are very similar and differ mainly in code clarity and testability.
|
|
|
|
|
|
### Exchange data using both techniques
|
|
|
|
|
|
Using both exchange solutions in a single callout point may be beneficial. The context may be used to share the data, and the particular callout point argument/output may be used to control the execution.
|
|
|
|
|
|
The data structure will be maintained internally by the hooks, but there will be a dedicated output enum or a controller object known for the core. This entry will be used to interrupt the execution or control the hook order.
|
|
|
|
|
|
It is assumed that the communication between hooks and core is done only in a few cases. It's possible to implement a generic solution applicable to many callout points.
|
|
|
|
|
|
### Hook execution interruption
|
|
|
|
|
|
The callout point may implement the chain of responsibility pattern. It means that some data are passed sequentially to hooks. Each hook analyzes the data and decides if the processing is ready or should be continued with the next hook.
|
|
|
|
|
|
This solution may be implemented in the core or internally in the hooks.
|
|
|
|
|
|
In the first case, the hook decides if the execution should be stopped. The hook executor receives the decision and breaks the hook loop if needed. The decision may be returned as a dedicated enum or notified as a method call of a controller object (that will be passed as an argument to the callout point).
|
|
|
|
|
|
In the second case, the hook executor always continues the hook loop to the end. But the decision from the previous hook is passed to the current hook. The hook must suppress the execution if the previous one decides to stop. The decision should be passed between hooks using a shared object (i.e., context, see below).
|
|
|
|
|
|
### Execution order
|
|
|
|
|
|
### Comparison
|
... | ... | |