Skip to content

animagram-jp/state-engine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

150 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

state-engine

Declarative state data management system for a process. Structures state data on process and keeps it syncable using your store clients. It behaves as described in YAML DSL.

Version

Version Status Date description
0.1 Released 2026-2-12 initial
0.1.3 Current 2026-2-26 improve #32
0.1.4 Scheduled 2026-3-22 improve #37

Provided Functions

mod description fn
Manifest reads static YAMLs and returns processed obj get_value(), get_meta()
State operates state data following Manifest get(), set(), delete(), exists()

Why state-engine?

Before:

// Manual cache management
let cache_key = format!("user:{}", id);
let user = redis.get(&cache_key).or_else(|| {
    let user = db.query("SELECT * FROM users WHERE id=?", id)?;
    redis.set(&cache_key, &user, 3600);
    Some(user)
})?;

After:

let user = state.get("cache.user")?;
  • ✅ Multi-tenant DB without junction tables
  • ✅ Automatic KVS/DB synchronization
  • ✅ No manual cache invalidation

Installation

# Cargo.toml
[dependencies]
state-engine = "0.1"

Quick Start

  1. Write a yaml file.
# manifest/example.yml
session:
  user-key:
  _state:
    type: integer
  _store:
    client: InMemory
    key: "request-attributes-user-key"
  _load:
    client: InMemory
    key: "request-header-user-key"


user:
  _store:
    client: KVS
    key: "user:${example.session.user-key}"
  _load:
    client: Db
    table: "users"
    where: "id=${example.session.user-key}"
    map:
      name: "name"
  name:
    _state:
      type: string
case sample
cache in KVS cache.yml
database connection config connection.yml
request scope session.yml
  1. Implement some Required Ports for your stores.
Interface expected store fn sample
InMemoryClient Local Process Memory get() / set() / delete() InMemoryAdapter
KVSClient Key-Vlue Store get() / set() / delete() KVSAdapter
DbClient SQL Database fetch() DbAdapter
EnvClient Environment Variables get() EnvAdapter
  • "Db" and "Env" will be used only in Loading(Read).
  • It's not essential to implement all *Client.
  1. Initialize State with your adapters and use it.
use state_engine::{State, Load};

// Create adapter instances
let mut in_memory = InMemoryAdapter::new();
let mut kvs = KVSAdapter::new()?;
let db = DbAdapter::new()?;

// Build Load with adapters
let load = Load::new()
    .with_in_memory(&mut in_memory)
    .with_kvs_client(&mut kvs)
    .with_db_client(&db);

// Build State with adapters
let mut state = State::new("./manifest", load)
    .with_in_memory(&mut in_memory)
    .with_kvs_client(&mut kvs);

// Use state-engine
let user = state.get("example.user.name")?;

Full working example: examples/app/src/main.rs

Architecture

┌─────────────┐  ┌───────────────────┐
│ Application │  │ manifestDir/*.yml │
└──────┬──────┘  └───────────────────┘
       │ uses             ▲ read
       ▼                  │
┌─────────────────────────┴───────────┐
│     Provided Ports (Public API)     │
├─────────────────────────────────────┤
│                                     │
│      State    -->    Manifest       │
│                                     │
└───────┬─────────────────────────────┘
        │ depends on
        ▼
┌─────────────────────────────────────┐
│    Required Ports (App Adapters)    │
├─────────────────────────────────────┤
│    InMemory, Env, KVS, Db clients   │
└─────────────────────────────────────┘

see for details Architecture.md

tree

./
  README.md           # this file
  Cargo.toml
  docs/               # guide documents
    en/
      Architecture.md
      YAML-guide.md
    ja/
      README.md
      Architecture.md
      YAML-guide.md
  core/
    Cargo.toml
    src/
      common/           # library common mod
        fix_bits.rs
        pool.rs
        parser.rs
        log_format.rs
  crate/
    Cargo.toml
    src/
      ports/            # library external interface traits
        provided.rs     # library provides
        required.rs     # Library requires
        manifest.rs       # Manifest impl
        state.rs          # State impl
        store.rs          # Store internal mod
        load.rs           # Load internal mod

    examples/
      manifest/         # manifest YAML examples
        connection.yml  # sample 1
        cache.yml       # sample 2
        session.yml     # sample 3
      adapters/
      app/
        docker-compose.yml
        Cargo.toml
        Dockerfile
        db/
        src/
          main.rs
          adapters.rs

tests

unit tests, intergeration tests on example app (docker compose) passed

  1. cargo test:
cargo test --features=logging -- --nocapture
  1. example application test:
cd crate/examples/app
docker compose up --build

Background

reimagined web architecture

  • computer: A network-capable node in the system.
  • server: A computer that serves human users.
  • orchestrator: A computer responsible for internal system coordination and maintenance. (optional)
  • database: A server that persists data without an inherent expiration and accepts CRUD operations.
  • terminal: A server that provides a direct human-facing interface.
  • conductor: A server that communicates independently with both a database and terminals, and maintains a synchronized state between them. (optional)
# terms relationship
computer:
  orchestrator:
  server:
    database:
    terminal:
    conductor:

License

MIT