v0.7.0

Socket Daemon

Last updated

The core/daemon package gives every process that opens the same data directory one shared unix socket, and this page explains how daemon.New decides whether a process becomes the server or a client.

Requirements It Satisfies

# Requirement How
1 One shared socket per ToriiDB location One Store is opened by the first process; everyone else talks to it over the socket
2 Different locations get different sockets The socket name is a hash of the resolved absolute directory
3 Repeated New on one location shares the socket New dials first; a live socket means client mode
4 Callers never check their role Get/Set/Del/... behave the same in both modes

Transport is a unix socket with a custom length-prefixed JSON frame. There is no HTTP.

Mode Resolution

daemon.New(dir, apiKey...) runs:

  1. Reject an empty dir.
  2. resolveDir: CheckDir(dir, true) → filepath.Abs → filepath.EvalSymlinks.
  3. resolveSocket: /tmp/toriidb-<uid>-<hex(sha256(realDir)[:8])>.sock.
  4. probeSocket: net.DialTimeout("unix", path, 500ms).
Probe result Mode What New does
Dial succeeds ModeClient Creates a pooled client; no store is opened
ECONNREFUSED or ENOENT ModeServer Opens store.New(realDir, apiKey...)
Any other dial error error Returns probe socket <path>: ...
Design rule Reason
Socket directory is hard-coded /tmp os.TempDir() reads $TMPDIR, which would make the socket depend on environment instead of location
Paths go through EvalSymlinks On macOS /tmp is a symlink to /private/tmp; relx, ./relx, /tmp/relx/, /private/tmp/relx, and symlinks must converge
Liveness is decided by dialing, never by os.Stat kill -9 leaves the socket file behind; a stale file must not block a new server
uid is part of the file name /tmp is shared between users
New takes dir, not *store.Store Probing must happen before a store is opened; a client must not open a second store on the same directory
中文