Engines / Connecting
Connecting
One core serves every language. A Rust program runs it in its own process. A
program in TypeScript, Python or Go reaches the same core one of four ways,
and every call after open is the same whichever it is.
const shared = await open('./data') // the directory's sidecar, shared with every process here
const mine = await open('./data', { private: true }) // a child of this process alone
const inside = await open('./data', { embedded: true }) // the core in this process
const remote = await connect('tls://db.internal:7443', { token: process.env.TINYSTORE_TOKEN! })shared = await tinystore.open("./data")
mine = await tinystore.open("./data", private=True)
inside = await tinystore.open("./data", embedded=True)
remote = await tinystore.connect("tls://db.internal:7443", token=os.environ["TINYSTORE_TOKEN"])shared, err := tinystore.Open(ctx, "./data")
mine, err := tinystore.Open(ctx, "./data", tinystore.Private())
inside, err := tinystore.Open(ctx, "./data", tinystore.Embedded())
remote, err := tinystore.Connect(ctx, "tls://db.internal:7443", os.Getenv("TINYSTORE_TOKEN"))let store = Store::open("./data", Options::default())?; // always the core in this processWhich one
| Way | What runs | Choose it for |
|---|---|---|
| sidecar, the default | one tinystore serve beside the directory, started by the first process that opens it | a web server and its workers in several processes |
private | a child on this process's stdin and stdout, ending with it | tests, scripts, one process alone; a test's clock |
embedded | the core inside this process: no child, no socket | one process that wants the shortest path |
connect | a server on another machine, over TLS with a token | programs on several machines |
- One directory, one holder. A store's directory is held by one process,
through its
LOCK. Several processes on one machine share it through the sidecar, which the first starts and the others find through<dir>/server/SERVE. A secondembeddedorprivateopen of a directory another process holds failsin use. - The sidecar stays 30 seconds after its last connection goes, unless
idlesays otherwise, so a quick restart finds it running. - Embedded loads the core's library: under Bun the C library, under Node its addon, in Python the extension module, in Go the core's library. The host's event loop never blocks: every call answers through a completion.
- A private child can run on a test's clock:
clocksets it, andstore.clock.advance('1h')moves time instead of the test waiting.
A remote server
tinystore token new data >> tokens.txt
tinystore serve ./data --listen tls://0.0.0.0:7443 --tls-cert cert.pem --tls-key key.pem --tokens tokens.txtThe client checks the server's certificate before the token leaves. A
connection that drops is made again by the SDK: a subscription comes back
with onMissed, and a worker's jobs return to the queue as a dead worker's
would. tcp:// sends the token in the clear, for a network its operator
trusts. See serve.
What every way shares
The calls, their errors and their limits are the same in every way, since
they are the same core speaking the same protocol. What differs is cost: an
embedded call skips a socket, and a remote one crosses a network. A program
moves from private in its tests to the sidecar in development to connect
in production by changing one line.
See also
- All engines.
- One core in the Handbook: frames, credit, the pipe and the sidecar's proof.
- The server in the Handbook.