Skip to content

khepri_machine: Add where trigger option#410

Draft
dumbbell wants to merge 3 commits into
mainfrom
add-where-option-to-triggers
Draft

khepri_machine: Add where trigger option#410
dumbbell wants to merge 3 commits into
mainfrom
add-where-option-to-triggers

Conversation

@dumbbell

@dumbbell dumbbell commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Why

Historically, a triggered stored procedure was always executed on the leader at the time of the trigger. In the future, we will want this trigger to be executed on a specific member or all members.

This option allows the caller of khepri:register_trigger/5 to indicate on which cluster member the action should run. This is only valid with the extended trigger support added in the parent commit.

This option supports the following values:

  • leader: this is the same as the historical behaviour, i.e., the action is executed on the leader at the time of the trigger.
  • {member, MemberNode}: the action is executed on the designated cluster member. If this node is not part of the cluster at the time of the trigger, it is executed on the leader.
  • local: this is basically synonymous to {member, node()}, i.e., the action is executed on the node where khepri_machine:register_trigger/5 was executed.
  • all_members: the action is executed on all cluster members.

How

There is no mod_call side effect in Ra to execute an arbitrary function call on a specific cluster member (or all of them). The mod_call side effect always runs on the leader.

Therefore, we use an aux handler, which is executed on all cluster members, to let each cluster member evaluate if it should executed the action or not.

There is a caveat though: if a follower skips command processing because it received a snapshot, it will not process the aux commands and thus will not execute the triggers that were suposed to run on it if it had seen all the commands sequentially.

@dumbbell dumbbell added this to the v0.19.0 milestone Jul 16, 2026
@dumbbell dumbbell self-assigned this Jul 16, 2026
@dumbbell dumbbell added the enhancement New feature or request label Jul 16, 2026
@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.74074% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.42%. Comparing base (d399d0e) to head (5a750cc).

Files with missing lines Patch % Lines
src/khepri_machine.erl 91.47% 11 Missing ⚠️
src/khepri_machine_v1.erl 87.87% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #410      +/-   ##
==========================================
- Coverage   90.47%   90.42%   -0.05%     
==========================================
  Files          24       25       +1     
  Lines        3956     4083     +127     
==========================================
+ Hits         3579     3692     +113     
- Misses        377      391      +14     
Flag Coverage Δ
erlang-26 90.39% <90.74%> (+0.10%) ⬆️
erlang-27 90.39% <90.74%> (+0.10%) ⬆️
erlang-28 90.39% <90.74%> (-0.05%) ⬇️
os-ubuntu-latest 90.42% <90.74%> (-0.05%) ⬇️
os-windows-latest 90.42% <90.74%> (+0.10%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dumbbell
dumbbell force-pushed the add-where-option-to-triggers branch 2 times, most recently from 2ff3ab1 to edcb6cf Compare July 16, 2026 14:20
dumbbell added 3 commits July 16, 2026 16:32
[Why]
We will need this as part of the implementation of the `where` trigger
options.

[How]
The machine state is expanded with the `cached_members` field at the end
of the record. The state conversion function takes care of adding this
new field.

Then, we leverage the `eval` aux effect to query the current cluster
members and compare this list to the one cached in the machine state. If
it is different or if there is no cached list so far, the aux handler
appends a command with the latest list. This command allows the machine
to update its state.

This command is only used once the machine version reaches version 3 or
more.
[Why]
Historically, a triggered stored procedure was always executed on the
leader at the time of the trigger. In the future, we will want this
trigger to be executed on a specific member or all members.

This option allows the caller of `khepri:register_trigger/5` to indicate
on which cluster member the action should run. This is only valid with
the extended trigger support added in the parent commit.

This option supports the following values:
* `leader`: this is the same as the historical behaviour, i.e., the
  action is executed on the leader at the time of the trigger.
* `{member, MemberNode}`: the action is executed on the designated
  cluster member. If this node is not part of the cluster at the time of
  the trigger, it is executed on the leader.
* `local`: this is basically synonymous to `{member, node()}`, i.e., the
  action is executed on the node where
  `khepri_machine:register_trigger/5` was executed.

[How]
There is no `mod_call` side effect in Ra to execute an arbitrary
function call on a specific cluster member (or all of them). The
`mod_call` side effect always runs on the leader.

Therefore, we use an `aux` handler, which is executed on all cluster
members, to let each cluster member evaluate if it should executed the
action or not.

There is a caveat though: if a follower skips command processing because
it received a snapshot, it will not process the `aux` commands and thus
will not execute the triggers that were suposed to run on it if it had
seen all the commands sequentially.
[Why]
This allows to run a trigger on all members of a cluster.

This required a few more changes to allow this because we need to be
able to ack execution for each member. That's why it couldn't be part of
the initial implementation of `where`.
@dumbbell
dumbbell force-pushed the add-where-option-to-triggers branch from edcb6cf to 5a750cc Compare July 16, 2026 14:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant