Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always pass exported functions to Ra queries #242

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

dumbbell
Copy link
Member

@dumbbell dumbbell commented Jan 12, 2024

Why

Using fun() is fragile if it has to be executed on a remote node. Indeed, the remote node may have another version of the module hosting the function and the function reference may be invalid.

How

There are two parts:

  1. We always use an exported function inside Khepri.
  2. We ensure that the caller of folding APIs passes MFA if they request leader or consistent queries. fun() are only accepted for local queries.

Fixes #238.

[Why]
We were already making sure that the path was native and valid but we
were not using it in the actual query… We were using the original
argument instead.
@dumbbell dumbbell added the enhancement New feature or request label Jan 12, 2024
@dumbbell dumbbell added this to the v0.11.0 milestone Jan 12, 2024
@dumbbell dumbbell requested a review from ansd January 12, 2024 14:05
@dumbbell dumbbell self-assigned this Jan 12, 2024
Copy link

codecov bot commented Jan 12, 2024

Codecov Report

Attention: 3 lines in your changes are missing coverage. Please review.

Comparison is base (b75785f) 88.74% compared to head (f02a92b) 89.37%.

Files Patch % Lines
src/khepri_machine.erl 95.23% 2 Missing ⚠️
src/khepri.erl 96.55% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #242      +/-   ##
==========================================
+ Coverage   88.74%   89.37%   +0.63%     
==========================================
  Files          20       21       +1     
  Lines        2896     3079     +183     
==========================================
+ Hits         2570     2752     +182     
- Misses        326      327       +1     
Flag Coverage Δ
erlang-24 88.34% <98.66%> (+0.66%) ⬆️
erlang-25 88.34% <98.66%> (+0.66%) ⬆️
erlang-26 88.98% <98.66%> (+0.62%) ⬆️
os-ubuntu-latest 89.34% <98.66%> (+0.60%) ⬆️
os-windows-latest 89.08% <98.66%> (+0.68%) ⬆️

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

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

@dumbbell dumbbell force-pushed the replace-funs-by-mfa-in-ra-queries branch 6 times, most recently from 55396b7 to bc0a556 Compare January 18, 2024 14:14
[Why]
Using `fun()` is fragile if it has to be executed on a remote node.
Indeed, the remote node may have another version of the module hosting
the function and the function reference may be invalid.

[How]
Now, we always use an exported function.

Callers of any folding APIs should do the same.

Fixes #238.
[Why]
Using `fun()` is fragile if it has to be executed on a remote node.
Indeed, the remote node may have another version of the module hosting
the function and the function reference may be invalid.

[How]
In the previous commit, Khepri stopped using fun references internally
where we know they can be executed on a remote node.

In this commit, we ensure that we apply the same constraint to external
functions passed to fold/foreach/map/filter queries and read-only
transactions.

If the caller passes such a function as a function reference instead of
the MFA tuple, Khepri will throw an exception to indicate this is not
permitted.

Here is an example for those queries and R/O transactions:

    khepri:fold(
      StoreId,
      PathPattern
      {my_mod, my_fold_func, [SomeState]},
      InitialAcc).

Where `my_mod:my_fold_func()` looks like:

    my_fold_func(SomeState, Path, NodeProps, Acc) ->
        ...
	NewAcc.
@dumbbell dumbbell force-pushed the replace-funs-by-mfa-in-ra-queries branch from bc0a556 to f02a92b Compare January 18, 2024 14:25
@dumbbell dumbbell marked this pull request as ready for review January 18, 2024 15:29
@dumbbell dumbbell marked this pull request as draft January 18, 2024 16:41
@dumbbell
Copy link
Member Author

The patch is finished but I would like to test it with RabbitMQ before merging it.

@dumbbell
Copy link
Member Author

I have second thoughts on the fact that MFAs are good enough as a solution to execute code remotely. Yes, with the current patch, we ensure that a query won’t break because the function reference is invalid on another node. But that doesn’t mean that the function exported remotely is the same as the local one. This is quite unintuitive.

Thinking out loud here; if a leader query was requested, what about we check the cursor on the leader, wait for the local cursor to catch up, then execute the query function locally? Don’t we have the same consistency guaranty? It may take more time to answer the query though, because the catch up can be longer than a remote execution.

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.

Passing fun() to ra:*_query() may break when executed on a remote node
2 participants