nix-super/doc/manual/src/architecture/store/store.md
2022-08-04 12:37:47 +02:00

8.3 KiB

Store

A Nix store is a collection of store objects.

A store object can hold arbitrary data and references to other store objects. Nix makes no distinction if store objects are used as build inputs, build results, or build tasks.

data Store = Set StoreObject

data StoreObject = StoreObject {
  data       :: Data
, references :: Set Reference
}

A Nix store can add, retrieve, and delete store objects.

It can perform builds, that is, create new store objects by transforming build inputs into build outputs, using instructions from the build tasks.

As it keeps track of references, it can garbage-collect unused store objects.

add    :: Store -> Data -> (Store, Reference)
get    :: Store -> Reference -> StoreObject
delete :: Store -> Reference -> Store

build  :: Store -> Reference -> Maybe (Store, Reference)

collectGarbage :: Store -> Store

Store objects are immutable: once created, they do not change until they are deleted.

References are opaque, unique identifiers: The only way to obtain references is by adding or building store objects. A reference will always point to exactly one store object.

An added store object cannot have references, unless it is a build task.

Building a store object will add appropriate references, according to provided build instructions. These references can only come from declared build inputs, and are not known to build instructions a priori.

data Data = Data | Task BuildTask

data BuildTask = BuildTask {
  instructions ::  Reference
, inputs       :: [Reference]
}

A store object cannot be deleted as long as it is reachable from a reference still in use. Garbage collection will delete all store objects that cannot be reached from any reference in use.

Files and Processes

Nix provides a mapping between its store model and the Unix paradigm that governs the interplay of files and processes.

Nix encodes immutable store objects and opaque identifiers as file system primitives: files and directories, and paths. That allows processes to resolve references contained in files and thus access the contents of store objects.

+-----------------------------------------------------------------+
| Nix                                                             |
|                  [ commmand line interface ]------,             |
|                               |                   |             |
|                           evaluates               |             |
|                               |                manages          |
|                               V                   |             |
|                  [ configuration language  ]      |             |
|                               |                   |             |
| +-----------------------------|-------------------V-----------+ |
| | store                  evaluates to                         | |
| |                             |                               | |
| |             referenced by   V       builds                  | |
| |  [ build input ] ---> [ build plan ] ---> [ build result ]  | |
| |         ^                                        |          | |
| +---------|----------------------------------------|----------+ |
+-----------|----------------------------------------|------------+
            |                                        |
    file system object                          store path
            |                                        |
+-----------|----------------------------------------|------------+
| operating system        +------------+             |            |
|           '------------ |            | <-----------'            |
|                         |    file    |                          |
|                     ,-- |            | <-,                      |
|                     |   +------------+   |                      |
|          execute as |                    | read, write, execute |
|                     |   +------------+   |                      |
|                     '-> |  process   | --'                      |
|                         +------------+                          |
+-----------------------------------------------------------------+

Store objects are therefore implemented as the pair of

  • a file system object for data
  • a set of store paths for references.

There exist different types of stores, which all follow this model. Examples:

  • store on the local file system
  • remote store accessible via SSH
  • binary cache store accessible via HTTP

Every store ultimately has to make store objects accessible to processes through the file system.

A Rosetta stone for build system terminology

The Nix store's design is comparable to other build systems. Usage of terms is, for historic reasons, not entirely consistent within the Nix ecosystem, and still subject to slow change.

The following translation table points out similarities and equivalent terms, to help clarify their meaning and inform consistent use in the future.

generic build system Nix Bazel Build Systems à la Carte programming language
data (build input, build result) store object artifact value value
build instructions builder (depends on action type) function function
build task derivation action Task thunk
build plan derivation graph action graph, build graph Tasks call graph
build build build application of Build evaluation
persistence layer store action cache Store heap

All of these systems share features of declarative programming languages, a key insight first put forward by Eelco Dolstra et al. in Imposing a Memory Management Discipline on Software Deployment (2004), elaborated in his PhD thesis The Purely Functional Software Deployment Model (2006), and further refined by Andrey Mokhov et al. in Build Systems à la Carte (2018).