Skip to content

fix(backend): keep a beacon's identity across restarts - #4

Merged
XxHugheadxX merged 1 commit into
mainfrom
fix/beacon-identity
Aug 25, 2026
Merged

XxHugheadxX merged 1 commit into
mainfrom
fix/beacon-identity

Conversation

@XxHugheadxX

Copy link
Copy Markdown
Contributor

Stacked on #3 — targets fix/discovery-crash, so this diff stays to the two
files it actually changes. Retarget to main once #3 lands.

What changes

getStorageDir() suffixed the corestore path with process.pid:

const suffix = process.pid
return path.join(persistent(), 'towerbell-corestore-' + suffix)

A beacon's identity is the key of its hypercore, and that hypercore lives in
the corestore. A fresh directory per run meant a shop came back as a
different peer every time it restarted
, and every run left a dead corestore
directory behind.

Now the storage root is stable, and bin.mjs passes the --storage value the
CLI already accepted — the backend used to ignore it entirely.

Opening a Corestore also moved out of module load and into the first scan()
or beacon() call, which is what lets the caller pick the root.

Running two peers on one machine

That is what the pid suffix bought, and it is the normal way to test this app,
so it still works — via the flag that already existed:

towerbell --storage /tmp/a beacon
towerbell --storage /tmp/b scan

Without it, the second instance now hits Corestore's directory lock. That used
to surface as an unhandled rejection out of rocksdb:

Uncaught (in promise) Error: File descriptor could not be locked
    at FDLock._resume (node_modules/fd-lock/index.js:67:13)
    ...
    at async CorestoreStorage._migrateStore (node_modules/hypercore-storage/index.js:652:9)

It now says what to do:

[towerbell] another Towerbell instance is already using /tmp/pear/towerbell — pass --storage <dir> to run a second one on this machine

Beacon._init() was an uncaught async call in the constructor, so any failure
there became an unhandled rejection. It rejects into an 'error' event now,
and bin.mjs listens — an EventEmitter with no 'error' listener throws on
emit.

Verified

  • Beacon discovered — ID: 9cc02f51e01d
  • Beacon killed and restarted against the same storage → rediscovered as
    the same id, 9cc02f51e01d. Before this change it came back as a
    different peer.
  • Two instances with separate --storage still discover each other
  • Second instance without --storage prints the one-line message, exit 1,
    no stack trace
  • pnpm run lint — exit 0
  • pnpm test — 4/4 tests, 5/5 asserts

Note

The frontend is untouched. startTravelerPanel/startBeaconPanel call
backendFn() with no arguments, so the storage root is bound in bin.mjs
where those callables are built.

@XxHugheadxX
XxHugheadxX changed the base branch from fix/discovery-crash to main August 25, 2026 05:39
@XxHugheadxX XxHugheadxX reopened this Aug 25, 2026
@XxHugheadxX
XxHugheadxX merged commit f4b7c06 into main Aug 25, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant