nustack

Interaction model

The interaction model is the solution.

A program that touches the world needs two things: a name for what it touches, and a description of what it does with it.

Atoms

  • Ref - a pointer to a resource: a kv slot, db row, a file path, an in-memory slot, a config key. Carries the address, not the value at the address.
  • Interaction - what a program does with Refs (and with other Interactions): read, write, compute, branch, iterate, compose.

Two citizens. In the interaction model every element is either a Ref or an Interaction. Every touch of the world goes through a Ref - the Ref is the handle. An Interaction is everything else: composition, control flow, computation.

Set(                                # Interaction (write)
    Ref("orders.total"),            #   Ref (the address)
    Add(                            #   Interaction (compute)
        Ref("orders.total"),
        1,
    ),
)

The whole interaction model collapses to: name the locations, describe what to do with them. Refs name. Interactions describe. Anything richer (typing, scopes, orchestration) is layered on top.

Context

  • Fabric - an addressable space where Refs live. The machinery that resolves Refs and executes Interactions over them. Postgres, fs, http api, in-memory dict are all fabrics. Not a citizen of the model; lives below it.
  • Context - the union of Fabrics. The full addressable space a program runs against; each Fabric is an element of it.

A program names Refs symbolically and composes them with Interactions. It runs against a Context, which routes each Ref to a Fabric; the Fabric resolves the address and carries out the Interaction. Same program, different Context = different bag of Fabrics, different worlds - test, staging, and prod all run the same description by swapping the binding.

Refs name, Interactions describe, Fabrics execute.

program = Set(Ref("counter"), Add(Ref("counter"), 1))
ctx     = { "counter": 41 }       # binds Ref("counter") to an in-memory fabric

evaluate(program, ctx)
# ctx now is { "counter": 42 }

The program is the Interaction; the world is in the Context.

Purpose

A program's single purpose is to update the Context.

Context v0
  →
program
  →
Context v1

v1 ≠ v0. If the Context doesn't change, the program has no reason to run.

On this page