-
Notifications
You must be signed in to change notification settings - Fork 195
Description
Hi,
I'm a bit stuck trying to use a shared trace in an iterative scope. I'm trying to emulate a database transaction, where you have some existing data, updates in a transaction, and if these updates pass some validation they should become part of the "existing data". I have run into an issue where the trace import operator seems to get stuck in a downgrade loop.
To create a minimal repro, I have a program where I have a set of pre-existing values
(simple string values "a"
, "b"
, "c"
), and I want to be able to submit updates
to these values. I submit 2 transactions:
- Transaction 1 adds
"c"
- invalid because "c" already exists - Transaction 2 adds
"d"
- valid
The transaction updates enter an iterative context, semi-join with existing committed values to find "violations", and then set a validated_tx_var
variable with the valid transaction ID's (2
in this case). The "committed" values are defined as a values
input collection, plus updates
semi-joined with validated_tx_var
.
If I turn the committed values into a trace and then use that to find violations, it appears to create a downgrade loop. I added a no-op inspect_frontier
operator that prints out the input frontier (without holding onto any capabilities) and it prints out (0,1)
, (0,2)
, ... (0,n)
etc. The code inside TraceAgent::import_core
appears to be repeatedly calling capabilities.downgrade(&frontier.borrow()[..]);
with TraceReplayInstruction::Frontier
as the matched instruction.
Here is the code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=26347c68458ecf8c175f45cf77a313c6. You can toggle the bool
on line 29 to see broken vs expected behaviour. Hopefully I've just missed something in the rules for using traces :)