HarperFast / HarperFast/harper-pro

Record locks: decide what it would take to enable replication.recordLocks by default

Open
#853 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
3
Forks
0
Avg merge
1d 21h
Merged PRs (30d)
80

Description

## Summary

`replication.recordLocks` is an explicit opt-in and defaults to off. This issue records what would have to be true to make cluster record locks safe by default, so the decision is tracked rather than rediscovered.

It is **not** blocked on the lock protocol being incomplete. The successor-freshness work (harper#2542, harper#2613, harper#2625) is done on harper-pro#822. It is blocked on three things that are each a design call.

## Why it cannot simply be flipped today

The home map is **operator-published by design**: `homeMap()` is never derived from `hdb_nodes` or liveness, because a locally-derived ring is the two-arbiter bug `replication/RECORD_LOCK_HOMES_DESIGN.md` §4 exists to prevent. With the switch on and no activated generation, `homeMap()` returns `undefined` and **every** cluster-scoped `lock()` on a replicated database returns 503 — strictly worse than today's honest opt-in, where the 503 at least names the switch.

Note this also means the current default is not "lock() behaves as it always did". On a replicated database with the feature off, a default-scope `lock()` already answers 503 naming `replication.recordLocks` (`replicator.ts` registers a fail-closed transport for every replicated database). Turning the default on without the items below moves that from one honest 503 to a different, less actionable one.

## What has to be true

1. **A bootstrap path for generation 1.** Landing on harper-pro#822 as `record_lock_bootstrap_generation { database, homes? }`: a local, fresh-state-only write of generation 1 that derives `homes` from `hdb_nodes` and refuses unless the node has never had a home map. That covers a *new* cluster. What is still open is the default-on case: who calls it, and when — first replicated database? first `lock()`? — and what happens for a node that joins later, which must not silently re-derive a ring.
2. **Cluster locks usable at `threads.count > 1`** — harper-pro#852. Default-on while a cluster-scoped `lock()` only succeeds on one worker would break `lock()` for most deployments rather than fix it.
3. **Placement that does not tax non-lock users.** Enabling the switch moves a database's whole inbound apply onto the coordinating worker (`subscriptionManager.ts` `placeSubscription`; `recordLockConfig.ts` says this is precisely why it is opt-in). A default would need placement to move only once a database actually has lock activity, or the throughput change lands on every cluster whether or not it ever calls `lock()`.

Also worth clearing first, all from harper-pro#822's `## For the human reviewer`: the startup `refreshCache` / incarnation-bump latch (one transient storage error leaves `homeMap()` undefined until an operator re-stages), and `homeMap()`'s per-acquisition cost.

## Acceptance

A fresh cluster with no record-lock configuration can call `lock()` on a replicated table and get cluster-wide exclusion, at the default worker count, without an operator running the §4.3 runbook — and a node joining that cluster later either participates or fails closed, never derives its own ring.

## Not in scope

The §4.3 stage → drain → activate runbook stays exactly as it is for every generation **after** the first; nothing here proposes deriving a ring for a live cluster.

Contributor guide

Open the contributing guide

Research direction

Read replication/RECORD_LOCK_HOMES_DESIGN.md §4, then inspect replicator.ts, subscriptionManager.ts, and recordLockConfig.ts. Review harper-pro#822 and the referenced worker-count work before resolving the generation-1 bootstrap, multi-worker locking, placement, and startup-latch decisions. Done means a fresh cluster gets safe cluster-wide exclusion by default and later nodes participate or fail closed.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
databases, distributed-systems
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.