arizuko › concepts › the store
the store
Every row arizuko keeps, such as messages, routes, grants, runs and logins, lives on one DynamoDB-protocol server. Each instance is one account on that server, and each daemon has its own key. The group folders on disk are the second durable store.
A row passes four layers from a daemon to PostgreSQL
Read the figure from top to bottom. A daemon asks for rows by key, and four layers later PostgreSQL writes them.
┌──────────────────────────────────────────────────────────────┐
│ daemons: routd, runed, authd, onbod, dashd, webd, adapters │
│ each through its store layer: store, runstore, authstore, │
│ chanstore, emaistore, dashstore │
└──────────────────────────────┬───────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────┐
│ objstore.Store: Query, GuardedBatch │
│ protocols over the two: Increment, Replace, ReadConsistent, │
│ AddEdge and Reachable │
└──────────────────────────────┬───────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────┐
│ dynstore: a table is <owner>.<entity>; the daemon signs with │
│ its own key; data calls: Query, TransactWriteItems │
└──────────────────────────────┬───────────────────────────────┘
│ DynamoDB protocol over TLS,
│ DYNAMODB_URL
▼
┌──────────────────────────────────────────────────────────────┐
│ ExtendDB: one account per instance; one IAM user per daemon, │
│ its policy bounded to the owners store.StoreReach lists │
└───────────────┬──────────────────────────────┬───────────────┘
▼ ▼
┌──────────────────────────────┐ ┌─────────────────────────────┐
│ PostgreSQL <data-db>: one │ │ <data-db>_catalog: accounts,│
│ table per DynamoDB table │ │ IAM, the table registry, │
│ │ │ settings │
└──────────────────────────────┘ └─────────────────────────────┘
The store interface has two methods
Every daemon talks to the store through objstore.Store, which has exactly two methods. Query reads by key. GuardedBatch writes a set of items, all or none, and only if every condition holds. A refused batch is an answer, not an error: another writer changed the items first. Counters, the replacement of a whole scope and the cycle check on group membership use the two methods. They are never added as new methods.
Each instance is one account on the server
The server is ExtendDB. ExtendDB speaks the DynamoDB wire protocol and keeps the data in PostgreSQL. An arizuko instance is one account on that server, so one server can hold every instance on a host and still keep the instances apart. The account is the boundary, not a PostgreSQL role. If you point the same driver at Amazon’s own DynamoDB, nothing above the driver changes.
Each daemon signs with its own key
Each daemon signs in as its own IAM user with its own access key. The policy of that user names the owners the daemon opens. A table name has the form <owner>.<entity>, for example routd.acl, so one line of policy covers all the tables of routd. store/owner_reach.go lists which daemon opens which owner, and a test fails when the code reaches an owner that the list does not name. A daemon that has the server address and no key refuses to start. timed and ttsd hold no key: they call the /v1 API of an owner.
A backup is a tar of the stopped instance
Stop the instance, then tar its data directory. The PostgreSQL files are under store/extenddb_db/, next to the group folders, so one tar holds both. A tar of a running instance is not a backup, because PostgreSQL still writes the files while you copy them.
The details live in three places
- reference / schema: every entity, its coordinate, and which daemon can read it.
- [objstore/README.md]: the two methods, the protocols on top, and the DynamoDB driver.
- [INSTALL.md]: how to start the server and create the key for each daemon.