Runtime Module
The graviton-runtime project bridges the pure data model from graviton-core with effectful infrastructure. It defines the service ports, policies, and coordination utilities that every deployment must satisfy.
Storage ports
All storage backends implement the following traits under graviton.runtime.stores:
BlobStore: streaming CRUD operations for deduplicated blobs (put,get,stat,delete).BlockStore: lower-level content-addressed block access for chunk-oriented ingestion.ImmutableObjectStore/MutableObjectStore: abstractions for manifests and binary assets that may or may not be mutated after ingest.KeyValueStore: generic metadata persistence for manifests, replication plans, and coarse-grained indexes.
The ports are intentionally minimal—backends compose them to express capabilities (e.g., S3 supplies immutable + blob, PostgreSQL implements every port).
Policies and layout
BlobLayoutandStorePolicydescribe how manifests and chunks are stored (single object vs framed) and how large each part should be.ReplicationModecaptures sync/async strategies; policies flow into replication planners once they are implemented in the runtime.
Indexes and range tracking
ReplicaIndex: maps a logical blob ID to the set of locators where data lives. Backends such as PostgreSQL will provide durable implementations.RangeTracker: tracks byte spans that have been persisted, enabling resumable uploads and repair jobs.SchemaStore: placeholder for schema evolution metadata, ensuring manifests remain forward-compatible.
Constraints and throttling
Under graviton.runtime.constraints you will find:
Quota,Throttle, andSemaphoreLimitprimitives for concurrency control and rate limiting.SpillPolicyand related value objects that describe how to offload large uploads to disk when in-memory buffering would exceed limits.
These abstractions will be composed by higher-level services (CLI ingest, HTTP gateways, background repair) once wiring is complete.
Metrics facade
MetricsRegistryoffers a uniform API for counters, gauges, and histograms.MetricKeysenumerates the well-known labels consumed by the registry (bytes ingested, backend failures, queue depth, etc.).
Backend adapters obtain a MetricsRegistry and emit events via module-specific metric helpers (see PgMetrics, S3Metrics). The runtime module stays vendor-neutral by restricting itself to key naming conventions.
Reference implementations
InMemoryBlockStoreprovides a deterministic, thread-safeBlockStorebacked by aRef[Map[BinaryKey.Block, CanonicalBlock]]. It deduplicates blocks, assemblesBlockManifests, and callsBlockFramer.synthesizeBlockfor fresh blocks when the write plan uses supported framing (plain block-per-frame).InMemoryBlobStoreis a test-onlyBlobStore(undersrc/test) that hashes whole blobs for quick contract tests — do not reference it from productionmaincode.Graviton.inMemory()andGraviton.fs(...)are the supported ways to obtain aBlobStorein examples and applications without Postgres.
InMemoryBlockStore exposes a layer helper. For a BlobStore layer in tests, build from Graviton:
import graviton.runtime.Graviton
import graviton.runtime.stores.BlobStore
import zio.*
val blobStoreLayer: ZLayer[Any, Nothing, BlobStore] =
ZLayer.fromZIO(Graviton.inMemory().map(_.blobStore))Use filesystem + inline manifests (Graviton.fs) or the test InMemoryBlobStore when you need a different trade-off inside test sources only.
Usage
- Choose the backend layers you need (e.g.,
S3Layers.live,PgLayers.live). - Provide a
StorePolicyandMetricsRegistryat startup. - Wire the runtime ports into the protocol servers (
graviton-http,graviton-grpc) or your own services.
Many ports still have stub backends; see Storage backends for a truthful module-by-module status.