Skip to content

Conclude#consider writes bypass the per-fact transaction #1347

Description

@gemshrine

Steps to reproduce

  1. Create a fact with a property and run Fbe.conclude with on '(exists property)' and a consider block.
  2. In the block, mutate the yielded fact and then abort the transaction with throw(:rollback) (or raise an error).
  3. Read the fact after the block returns or raises.

Actual result

The mutation can remain in the factbase even though its transaction rolled back. roll materializes the matching facts with @fb.query(@query).each.to_a before opening each transaction. The consider callback then receives that pre-transaction fact handle (yield(a)), while the transaction's fbt handle is ignored. A write through the yielded fact therefore changes the original map directly instead of the transaction's copy-on-write map.

Expected result

A consider block's changes to its current fact should go through the transaction and be discarded when that transaction rolls back.

Technical evidence

In lib/fbe/conclude.rb, roll queries into a before @fb.txn, then calls the block inside @fb.txn. consider is implemented as roll { |_fbt, a| yield(a); nil }, so it passes the old handle rather than a transaction-backed one. Factbase transactions use copy-on-write, so writes through that handle bypass rollback.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions