sidecar

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 9, 2026 License: AGPL-3.0 Imports: 7 Imported by: 0

Documentation

Overview

Package sidecar is the durable-file discipline Atlas's design-time stores share.

Deployments, drafts, projects, forms, workers, the secret vault and the rest all persist small records as one file per key under a directory (ADR-0019, ADR-0021). They differ in what they store and agree completely on how to put it on disk: temp file, fsync, rename, fsync the directory. That sequence lives here once, so "nil error means the record is durable" is one implementation rather than sixteen — the same durable-before-visible rule the engine's log follows (I2 / ADR-0005), applied to the sidecar files beside it.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FsyncDir

func FsyncDir(dir string) error

FsyncDir fsyncs a directory so a create/rename/remove of a file within it is itself durable.

func WriteFile

func WriteFile(dir, path string, data []byte) error

WriteFile writes raw bytes to path with the same discipline WriteJSON gives a record. It exists because not every durable artifact is JSON — a process documentation PDF (ADR-0143) is opaque bytes stored beside its sidecar, and it deserves the same "nil error means on disk" guarantee.

func WriteJSON

func WriteJSON(dir, path string, v any) error

WriteJSON marshals v and writes it to path atomically: temp file → fsync → rename → dir fsync. On return with nil error the record is durable, so a caller may treat it as saved (durable before visible, I2 / ADR-0005).

Types

type Option

type Option[T any] func(*Store[T])

Option configures a Store at construction. The defaults cover the common case (hex-encoded filenames, listing in filename order); an option is only needed where a store genuinely differs.

func Names

func Names[T any](enc func(string) string, ok func(string) bool) Option[T]

Names replaces the default filename scheme. enc maps a record's key to its filename stem, and ok reports whether a stem found in the directory is one of this store's records — the guard that lets an unrelated file share the directory without breaking a listing.

The default hex-encodes the key, which is what makes an arbitrary BPMN id or email address a safe, unique, deterministic filename. Override it only when the key is already filename-safe *and* recognizable: a hex token, a decimal entity key.

func Order

func Order[T any](less func(a, b T) bool) Option[T]

Order sets the order LoadAll returns records in. Without it a listing comes back in filename order, which is stable but arbitrary; with it a store states the order its UI expects — newest-first for drafts, creation order for projects. less has sort.Slice semantics.

type Store

type Store[T any] struct {
	// contains filtered or unexported fields
}

Store is a durable store for one kind of design-time record: one JSON file per key under a single directory, written with the durability discipline above.

Atlas has sixteen of these — drafts, projects, forms, workers, deployments, releases, users, deploy tokens and the rest. They differ in what they store, how a record names itself, and what order a listing comes back in. They agreed on everything else, which is what this type now holds: create the directory, encode the key into a safe filename, write atomically, read back, ignore files that are not ours, delete idempotently.

Like the stores it replaces, a Store does no locking of its own, and it needs none: it keeps no mutable memory, so every method is a syscall against the directory. Writing is still the run-loop goroutine's alone — it is the single writer of design-time state, and a check-then-write ("is this username taken?") is atomic only because both halves happen inside one loop turn.

Reading is not confined to the loop. A record is replaced by an atomic rename (see WriteJSON), so a concurrent reader sees the whole old record or the whole new one and never a torn one, and a temp file is not named like a record so a listing never picks one up. A caller that must not wait for the engine may therefore read directly — which is what keeps signing in independent of how busy the processor is (ADR-0265).

func NewStore

func NewStore[T any](dir, name string, key func(T) string, opts ...Option[T]) (*Store[T], error)

NewStore opens (creating if needed) the directory backing a store. name is the prefix every error from this store carries, so a failure names the store it came from; key extracts a record's identity, which is what Save files it under.

func (*Store[T]) Delete

func (s *Store[T]) Delete(key string) error

Delete removes the record filed under key. A missing record — or a key that could never name one — is not an error, so cleanup is idempotent.

func (*Store[T]) Dir

func (s *Store[T]) Dir() string

Dir is the directory the store's records live in. Callers that keep sibling artifacts beside a record — a documentation PDF (ADR-0143) — need it.

func (*Store[T]) FileFor

func (s *Store[T]) FileFor(key string) string

FileFor maps a key to its record path. It is a pure path helper and does not check the key — the entry points below do that; call it only with a key you have already addressed the store with.

func (*Store[T]) Get

func (s *Store[T]) Get(key string) (T, bool, error)

Get returns the record filed under key, or ok=false if there is none. A missing record is a normal state, not an error, and so is a key that could never name one.

func (*Store[T]) LoadAll

func (s *Store[T]) LoadAll() ([]T, error)

LoadAll reads every record in the store, in the order set by Order. Files that are not this store's records — a stray temp file, a sibling artifact, a subdirectory — are skipped rather than failing the listing, and so is a record deleted between the listing and its read, which is what a reader running off the run loop can meet.

func (*Store[T]) Save

func (s *Store[T]) Save(rec T) error

Save writes a record durably, overwriting any record already filed under the same key. On return with nil error it is on disk (I2 / ADR-0005). A record whose key could not name a file in this store is refused rather than written.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL