Skip to content

Check append condition against events after a position - #921

Merged
DavidBadura merged 1 commit into
4.0.xfrom
fix-append-condition-after
Oct 3, 2026
Merged

DavidBadura merged 1 commit into
4.0.xfrom
fix-append-condition-after

Conversation

@DavidBadura

@DavidBadura DavidBadura commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

The append condition checked that the highest matching event is exactly highestSequenceNumber. The DCB spec defines it differently: the append fails if an event matching the query exists after the given position, and that position may be higher than the last matching event. So passing anything other than the exact last matching index, like the global head, led to a false AppendConditionNotMet.

AppendCondition now takes after instead of highestSequenceNumber, defaulting to 0 (no matching event may exist at all). Both stores check that no matching event with a higher index exists, on the dbal side as a NOT EXISTS (... WHERE events.id > :after). The query is now required, since new AppendCondition() would otherwise mean "the store must be empty". For decision models built with StoreDecisionModelBuilder nothing changes.

The append condition required the highest matching event to be exactly
`highestSequenceNumber`. The DCB spec instead fails the append only if a
matching event exists after the given position, which may be higher than
the last matching event. A caller passing e.g. the global head got a false
AppendConditionNotMet.

AppendCondition now takes `after` (default 0) and both stores check that no
matching event with a higher index exists. The query is required now, since
an empty query matches all events.
@DavidBadura DavidBadura added this to the 4.0.0 milestone Oct 3, 2026
@DavidBadura DavidBadura added the enhancement New feature or request label Oct 3, 2026
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown

Hello 👋

here is the most recent benchmark result:

SplitStreamBench
================

+-------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
|                         | time (kde mode)                                     | memory                                     |
+-------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| subject                 | Tag: <current>     | Tag: base          | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+-------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| benchLoad10000Events () | 2.757ms (±0.00%)   | 3.081ms (±0.00%)   | -10.51%   | 35.774mb        | 36.295mb   | -1.43%      |
| benchSave10000Events () | 472.960ms (±0.00%) | 487.762ms (±0.00%) | -3.03%    | 35.909mb        | 35.909mb   | 0.00%       |
+-------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+

SimpleSetupTaggableStoreBench
=============================

+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
|                                        | time (kde mode)                                     | memory                                     |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| subject                                | Tag: <current>     | Tag: base          | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| benchLoad1Event ()                     | 1.207ms (±0.00%)   | 1.129ms (±0.00%)   | +6.88%    | 36.312mb        | 36.312mb   | 0.00%       |
| benchLoad10000Events ()                | 74.569ms (±0.00%)  | 75.071ms (±0.00%)  | -0.67%    | 36.312mb        | 36.312mb   | 0.00%       |
| benchSave1Event ()                     | 1.541ms (±0.00%)   | 1.606ms (±0.00%)   | -4.08%    | 36.312mb        | 36.312mb   | 0.00%       |
| benchSave10000Events ()                | 315.517ms (±0.00%) | 323.129ms (±0.00%) | -2.36%    | 36.312mb        | 36.312mb   | 0.00%       |
| benchSave10000Aggregates ()            | 10.299s (±0.00%)   | 10.030s (±0.00%)   | +2.69%    | 36.312mb        | 36.312mb   | 0.00%       |
| benchSave10000AggregatesTransaction () | 7.144s (±0.00%)    | 7.113s (±0.00%)    | +0.44%    | 36.312mb        | 36.312mb   | 0.00%       |
| benchAppend1Event ()                   | 1.681ms (±0.00%)   | 1.651ms (±0.00%)   | +1.79%    | 36.312mb        | 36.312mb   | 0.00%       |
| benchAppend100Events ()                | 8.670ms (±0.00%)   | 8.426ms (±0.00%)   | +2.89%    | 36.312mb        | 36.312mb   | 0.00%       |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+

SubscriptionEngineBench
=======================

+---------------------------+-----------------+-----------------+-----------+-----------------+------------+-------------+
|                           | time (kde mode)                               | memory                                     |
+---------------------------+-----------------+-----------------+-----------+-----------------+------------+-------------+
| subject                   | Tag: <current>  | Tag: base       | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+---------------------------+-----------------+-----------------+-----------+-----------------+------------+-------------+
| benchHandle10000Events () | 3.494s (±0.00%) | 3.500s (±0.00%) | -0.15%    | 48.301mb        | 48.301mb   | 0.00%       |
+---------------------------+-----------------+-----------------+-----------+-----------------+------------+-------------+

NoopSubscriptionEngineBench
===========================

+---------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
|                           | time (kde mode)                                     | memory                                     |
+---------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| subject                   | Tag: <current>     | Tag: base          | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+---------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| benchHandle10000Events () | 109.110ms (±0.00%) | 111.012ms (±0.00%) | -1.71%    | 48.301mb        | 48.301mb   | 0.00%       |
+---------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+

SimpleSetupStreamStoreBench
===========================

+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
|                                        | time (kde mode)                                     | memory                                     |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| subject                                | Tag: <current>     | Tag: base          | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| benchLoad1Event ()                     | 1.302ms (±0.00%)   | 1.283ms (±0.00%)   | +1.50%    | 35.146mb        | 35.146mb   | 0.00%       |
| benchLoad10000Events ()                | 75.113ms (±0.00%)  | 74.548ms (±0.00%)  | +0.76%    | 35.146mb        | 35.146mb   | 0.00%       |
| benchSave1Event ()                     | 1.659ms (±0.00%)   | 1.741ms (±0.00%)   | -4.69%    | 35.146mb        | 35.146mb   | 0.00%       |
| benchSave10000Events ()                | 296.382ms (±0.00%) | 290.825ms (±0.00%) | +1.91%    | 35.146mb        | 35.146mb   | 0.00%       |
| benchSave10000Aggregates ()            | 10.322s (±0.00%)   | 10.148s (±0.00%)   | +1.72%    | 35.146mb        | 35.146mb   | 0.00%       |
| benchSave10000AggregatesTransaction () | 7.166s (±0.00%)    | 7.130s (±0.00%)    | +0.50%    | 35.147mb        | 35.147mb   | 0.00%       |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+

SubscriptionEngineBatchBench
============================

+---------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
|                           | time (kde mode)                                     | memory                                     |
+---------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| subject                   | Tag: <current>     | Tag: base          | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+---------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| benchHandle10000Events () | 112.404ms (±0.00%) | 128.143ms (±0.00%) | -12.28%   | 35.726mb        | 35.726mb   | 0.00%       |
+---------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+

PersonalDataBench
=================

+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
|                                        | time (kde mode)                                     | memory                                     |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| subject                                | Tag: <current>     | Tag: base          | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+
| benchLoad1Event ()                     | 873.500μs (±0.00%) | 913.800μs (±0.00%) | -4.41%    | 37.008mb        | 37.008mb   | 0.00%       |
| benchLoad10000Events ()                | 231.874ms (±0.00%) | 233.990ms (±0.00%) | -0.90%    | 37.008mb        | 37.008mb   | 0.00%       |
| benchSave1Event ()                     | 2.343ms (±0.00%)   | 2.496ms (±0.00%)   | -6.12%    | 37.008mb        | 37.008mb   | 0.00%       |
| benchSave10000Events ()                | 479.876ms (±0.00%) | 500.507ms (±0.00%) | -4.12%    | 37.063mb        | 37.063mb   | 0.00%       |
| benchSave10000Aggregates ()            | 15.551s (±0.00%)   | 15.678s (±0.00%)   | -0.81%    | 37.008mb        | 37.008mb   | 0.00%       |
| benchSave10000AggregatesTransaction () | 12.373s (±0.00%)   | 12.463s (±0.00%)   | -0.72%    | 37.008mb        | 37.008mb   | 0.00%       |
+----------------------------------------+--------------------+--------------------+-----------+-----------------+------------+-------------+

SnapshotsBench
==============

+----------------------------------------+-------------------+-------------------+-----------+-----------------+------------+-------------+
|                                        | time (kde mode)                                   | memory                                     |
+----------------------------------------+-------------------+-------------------+-----------+-----------------+------------+-------------+
| subject                                | Tag: <current>    | Tag: base         | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+----------------------------------------+-------------------+-------------------+-----------+-----------------+------------+-------------+
| benchLoad10000EventsMissingSnapshot () | 74.182ms (±0.00%) | 75.039ms (±0.00%) | -1.14%    | 35.151mb        | 35.151mb   | 0.00%       |
| benchLoad10000Events ()                | 1.087ms (±0.00%)  | 1.082ms (±0.00%)  | +0.46%    | 35.151mb        | 35.151mb   | 0.00%       |
+----------------------------------------+-------------------+-------------------+-----------+-----------------+------------+-------------+

CommandToQueryBench
===================

+----------------+------------------+------------------+-----------+-----------------+------------+-------------+
|                | time (kde mode)                                 | memory                                     |
+----------------+------------------+------------------+-----------+-----------------+------------+-------------+
| subject        | Tag: <current>   | Tag: base        | time-diff | Tag: <current>  | Tag: base  | memory-diff |
+----------------+------------------+------------------+-----------+-----------------+------------+-------------+
| benchCreate () | 4.038ms (±0.00%) | 3.819ms (±0.00%) | +5.73%    | 5.057mb         | 5.057mb    | 0.00%       |
| benchUpdate () | 5.229ms (±0.00%) | 5.204ms (±0.00%) | +0.47%    | 5.067mb         | 5.067mb    | 0.00%       |
| benchBoth ()   | 8.754ms (±0.00%) | 8.891ms (±0.00%) | -1.54%    | 5.072mb         | 5.389mb    | -5.89%      |
+----------------+------------------+------------------+-----------+-----------------+------------+-------------+

This comment gets update everytime a new commit comes in!

@DavidBadura DavidBadura added bug Something isn't working and removed enhancement New feature or request labels Oct 3, 2026
@DavidBadura
DavidBadura merged commit e7a9641 into 4.0.x Oct 3, 2026
37 of 39 checks passed
@DavidBadura
DavidBadura deleted the fix-append-condition-after branch October 3, 2026 18:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants