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

bedrock-kv / bedrock / 0850df93b9ea4ea28180ff458bb454f490642e5f
82%

Build:
DEFAULT BRANCH: develop
Ran 13 Sep 2026 04:00AM UTC
Jobs 1
Files 216
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

13 Sep 2026 03:56AM UTC coverage: 80.747% (+0.04%) from 80.704%
0850df93b9ea4ea28180ff458bb454f490642e5f

push

github

web-flow
302: Make LocalFilesystem version-matched writes atomic (#305)

Concurrent writers holding the same version token could all succeed
against the LocalFilesystem backend, because its compare-and-swap was an
unlocked read, a hash comparison, and a plain rename. Every mutation now
runs inside a small native call that holds a per-directory `flock` while
it re-checks the current bytes and publishes, so one observed version
authorizes at most one replacement, even across independent BEAMs
sharing a root.

Ticket: bedrock-162
Closes #302

## Why

The cluster bootstrap record is replaced through the conditional write,
and the recovery-generation work in #296 (bedrock-7i1) needs that to be
a single-winner operation.

On the base, `put_if_version_matches` read the object, compared its hash
to the token, then renamed the new file over the key. Nothing tied the
rename to the comparison. Eight writers with one token could all pass
the comparison, all rename, and all be told `:ok`, with seven of them
silently overwritten. Issue #302 reproduced this through the public API
(logs `302-red-1.log` through `302-red-5.log` under
`/tmp/bedrock-followups-20260905.zKTZxP/`).

A BEAM-side mutex would not do, since one root is routinely shared by
several VMs, and locking only the CAS path would still let a plain put
or delete slip in between comparison and rename. So every publication
takes an OS lock.

## What changed

- A new NIF, `Native.mutate/5`, performs put, create-only link, CAS
rename, and delete under a per-directory lock; all four mutators route
through it, with no unlocked fallback.
- New errors: `{:error, :invalid_key}` for absolute keys, `.` or `..`
components, or any component under the reserved `.bedrock-lock` prefix;
`{:error, :eloop}` for a symlink target. A malformed token returns
`:version_mismatch` instead of raising.
- Source builds now need a C compiler, make, and OTP headers on Linux or
macOS; `guides/local-filesystem.md` states the filesystem and upgrad... (continued)

34 of 37 new or added lines in 2 files covered. (91.89%)

3 existing lines in 2 files now uncovered.

7088 of 8778 relevant lines covered (80.75%)

1153.08 hits per line

Uncovered Changes

Lines Coverage ∆ File
2
93.48
7.92% lib/bedrock/object_storage/local_filesystem.ex
1
50.0
lib/bedrock/object_storage/local_filesystem/native.ex

Coverage Regressions

Lines Coverage ∆ File
2
71.26
-2.3% lib/bedrock/data_plane/resolver/tree.ex
1
93.25
-0.61% lib/bedrock/data_plane/materializer/olivine/index_update.ex
Jobs
ID Job ID Ran Files Coverage
1 0850df93b9ea4ea28180ff458bb454f490642e5f.1 13 Sep 2026 04:00AM UTC 216
80.75
GitHub Action Run
Source Files on build 0850df93b9ea4ea28180ff458bb454f490642e5f
  • Tree
  • List 216
  • Changed 3
  • Source Changed 0
  • Coverage Changed 3
Coverage ∆ File Lines Relevant Covered Missed Hits/Line
  • Back to Repo
  • 0850df93 on github
  • Prev Build on develop (#14B53774...)
  • Next Build on develop (#D6F26B06...)
  • 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