• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bedrock-kv / bedrock / eecf16dcfafe2a292a260de84aa84802b538deaf
73%

Build:
DEFAULT BRANCH: develop
Ran 17 Jul 2026 02:39AM UTC
Jobs 1
Files 215
Run time 1min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

17 Jul 2026 02:38AM UTC coverage: 72.989% (+0.4%) from 72.6%
eecf16dcfafe2a292a260de84aa84802b538deaf

push

github

web-flow
Record read conflicts when a read is issued; cover key-selector scan spans (bedrock-udr, bedrock-v2c) (#109)

## Why

Two transactions could both read a missing key, both write it, and both
commit:

```
Transaction A                     Transaction B
get("job/123/owner") → not found
                                  get("job/123/owner") → not found
set("job/123/owner", "worker-A")
                                  set("job/123/owner", "worker-B")
commit ✓                          commit ✓   ← should have aborted
```

The resolver can only abort B if A's read conflict set contains the key
— but a storage miss (`{:error, :not_found}`) took an error path that
skipped conflict recording entirely. **Reading nothing is still
reading:** "the key was absent" is information the transaction acted on.
(Same defect as #108; found via Job Queue QA.)

Key-selector reads had the same hole, wider: a selector's result depends
on *every* key between its anchor and the key it resolves to — an insert
anywhere in that span changes the resolution — but only the resolved key
was recorded on a hit, and nothing on a miss.

## What

Both fixes follow FoundationDB (`fdbclient/NativeAPI.actor.cpp`):

- **Point reads** register the conflict **when the read is issued**,
before storage answers (`record_read_intent/3`). No result shape —
value, miss, or error — can dodge it, because recording never looks at
the result. Mirrors `Transaction::get()`'s
`push_back(singleKeyRange(key))` before the read.
- **Selector reads** register **after resolution** (the span isn't
knowable earlier — FDB's `extraConflictRanges`): a hit records
`[min(anchor, resolved), key_after(max(anchor, resolved)))`; a miss
records the shard range that was scanned and found empty (FDB's
empty-range-read analog).

Deliberate, FDB-matching behaviors: `snapshot: true` reads record
nothing; reads satisfied from your own writes record nothing; a point
read that *fails* after issue still leaves its conflict behind.

## ... (continued)

25 of 26 new or added lines in 1 file covered. (96.15%)

1 existing line in 1 file now uncovered.

5734 of 7856 relevant lines covered (72.99%)

1003.27 hits per line

Uncovered Changes

Lines Coverage ∆ File
1
82.14
41.52% lib/bedrock/internal/transaction_builder/point_reads.ex

Coverage Regressions

Lines Coverage ∆ File
1
82.14
41.52% lib/bedrock/internal/transaction_builder/point_reads.ex
Jobs
ID Job ID Ran Files Coverage
1 eecf16dcfafe2a292a260de84aa84802b538deaf.1 17 Jul 2026 02:39AM UTC 215
72.99
GitHub Action Run
Source Files on build eecf16dcfafe2a292a260de84aa84802b538deaf
  • Tree
  • List 215
  • Changed 3
  • Source Changed 0
  • Coverage Changed 3
Coverage ∆ File Lines Relevant Covered Missed Hits/Line
  • Back to Repo
  • eecf16dc on github
  • Prev Build on develop (#06EEE2EF...)
  • Delete
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc