Extending Koukan¶
router yaml:
modules:
sync_filter:
my_filter: path.to.my.filter
recipient_router_policy:
my_policy: path.to.my.policy:my_policy_factory
will do something like:
from path.to.my.filter import factory
filter = factory(filter_yaml)
from path.to.my.policy import my_policy_factory
policy = my_policy_factory(policy_yaml)
Filters¶
Filter: returns FilterResult with a delta to be unconditionally merged into the upstream result. This enables a sort-of tail-call optimization; the filter is not invoked in the return path.
ProxyFilter: whereas a regular Filter only conservatively extends the transaction, ProxyFilter has separate upstream and downstream transaction objects that it can implement an arbitrary transformation between. e.g. any filter that replaces/modifies tx.body (message builder, message parser, received header) must be ProxyFilter.
CoroutineFilter: whereas regular Filter is not invoked in the return path, CoroutineFilters take a Callable to “yield to the scheduler” to continue the upstream chain which in turn yields a continuation to invoke in the return path. This allows arbitrary code in the return path. Historical note: we started with CoroutineFilter, then discovered the tail-call optimization was possible for filters in a “normal form” and then discovered that all of the filters fit into that. So we don’t actually have a use case for this currently.
CoroutineProxyFilter: ProxyFilter + CoroutineFilter
Example: hello_filter.py
RecipientRouterFilter Policies¶
Implement recipient_router_filter.RoutingPolicy
RoutingPolicy.endpoint_for_rcpt() is passed an element from
TransactionMetadata.rcpt_to and returns either a Destination
which controls where RestEndpoint sends it or a Response which is
returned downstream in TransactionMetadata.rcpt_response if the
address does not exist.
Example: hello_policy.py