HarperFast / HarperFast/documentation

Document transaction read-your-own-writes semantics + safe concurrent-write patterns (read-back-to-decide is unsafe)

Open
#531 0 comments 0 reactions 0 assignees View on GitHub
content
Dominant language
MDX
Stars
9
Forks
9
Avg merge
2d 12h
Merged PRs (30d)
32

Description

## Summary
Document Harper v5's within-transaction read visibility and the safe concurrent-write patterns. Exploratory QA found a real footgun that is a documentation/guidance gap (committed data is always correct — this is about in-request reads and concurrency patterns, not data corruption).

## What to document

**1. Within-transaction read-your-own-writes / snapshot semantics**
- A FRESH read in a subsequent request (and SQL reads) always reflect committed writes on both engines — committed data is correct.
- WITHIN the same open request transaction: a table-level read-back (`tables.X.get(id)`, `put()`-then-`get()`, `addTo`-then-refetch) returns the **start-of-transaction snapshot on LMDB** (it does NOT see the pending write), whereas RocksDB sees the pending write. The loaded resource instance's own `this.get()` is fresh on both engines.
- Guidance: don't rely on a table refetch within the same transaction to observe your own pending write (especially on LMDB); use `this.get()` or re-read after the transaction.

**2. Safe concurrent-write primitives (the practical guidance customers need)**
- Atomic deltas (`addTo`/`subtractFrom`) are the only primitive whose committed aggregate is exact under concurrency — model concurrent counters as commutative deltas.
- "Write-then-read-the-value-back-to-decide" (rate limiters, claims, state-machine gates) is **unsafe** under concurrency on both engines (the read-back is not a reliable serialized position; severe on LMDB). `addTo` returns no value, so there's no read-your-position.
- For non-commutative correctness (exactly-once claim, admit-only-N, don't-go-below-zero): either serialize through a single writer / external lock, or use the async pattern that DOES work in-Harper — each claimant writes its own non-contended row, use `addTo` only to count, and let a single-reader sweep over committed state pick the winner.

## Source
Exploratory QA campaign (qa-explorer), scenarios QA-099/100/101/103/104/105/106. Harper `001bf7b9c` (v5.1.0). Reference tests in `integrationTests/qa-scratch/` (`raw-visibility`, `rate-limiter`, `cas-audit`, `claim-recipe`, `inventory-oversell`). Engineering-side tracking of the underlying primitive behavior is in harper#1288 + the read-back/visibility findings.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.