Canonical Hero service template + meta-domain catalog seed (parent: hero_skills#262, this issue: #261).
  • Rust 61.6%
  • HTML 32.5%
  • Nushell 5.9%
Find a file
Timur Gordon c99cda0ad9
fix(admin,web): lazy SDK via OnceCell so axum binds the UDS before connecting to server
Mirrors hero_blueprint @ 7b71b0f. The previous fix (78bf51d) blocked
`AppState::from_env` on the server-side `connect_socket` retry, which
moved the failure mode from "admin crashes before logging" to "admin
runs but its own UDS isn't bound yet, smoke tests fail with `cannot
connect to socket … No such file or directory`" — `axum::serve` needs
the state up front, so blocking on the connect also blocks the
listener.

Restructure:

- `AppState::sdk` becomes `Arc<tokio::sync::OnceCell<HeroServiceClient>>`
  with a pre-resolved `sock_str` alongside. `AppState::new()` is
  synchronous (no I/O, no retry) so main can construct state, bind
  the listener, and start serving immediately — `/health`,
  `/openrpc.json`, and `/.well-known/heroservice.json` all respond
  from the moment the socket is bound.
- `AppState::sdk(&self).await` does the bounded retry inside
  `get_or_try_init`. First caller pays the connect cost (60 × 500ms);
  the rest share the cached `&HeroServiceClient`.
- `AppState::preheat()` spawns a background task that pre-warms the
  cell so a real user request usually doesn't pay the connect
  latency.
- main.rs in admin + web drops `AppState::from_env().await?` in
  favour of `AppState::new()? + app_state.preheat()`.
- Route handlers in admin + web change from `app.sdk.method(…)` to
  `app.sdk().await?.method(…)` — 30 call sites swept across
  indexed_multi, indexed_none, indexed_non_str, indexed_single, and
  service_definition routes for both crates.

Verified: `cargo check -p hero_service_admin -p hero_service_web`
finishes clean (only the pre-existing `sid: String` unused-field
warnings in the askama templates).
2026-05-28 20:33:58 +02:00
.forgejo/workflows Bootstrap canonical hero_service template repo (hero_skills#261) 2026-05-19 16:14:53 +02:00
benches refactor: rename hero_rpc → hero_blueprint across workspace 2026-05-28 19:13:47 +02:00
crates fix(admin,web): lazy SDK via OnceCell so axum binds the UDS before connecting to server 2026-05-28 20:33:58 +02:00
docs refactor: rename hero_rpc → hero_blueprint across workspace 2026-05-28 19:13:47 +02:00
examples refactor: rename hero_rpc → hero_blueprint across workspace 2026-05-28 19:13:47 +02:00
schemas refactor: rename hero_rpc → hero_blueprint across workspace 2026-05-28 19:13:47 +02:00
tests refactor: drop hero_rpc_openrpc + enable openrpc-transport on hero_rpc2 (hero_blueprint#146) 2026-05-28 19:26:04 +02:00
.gitignore refactor(template): regenerate against latest hero_rpc scaffolder 2026-05-28 15:47:37 +02:00
Cargo.lock refactor: drop hero_rpc_openrpc + enable openrpc-transport on hero_rpc2 (hero_blueprint#146) 2026-05-28 19:26:04 +02:00
Cargo.toml refactor: drop hero_rpc_openrpc + enable openrpc-transport on hero_rpc2 (hero_blueprint#146) 2026-05-28 19:26:04 +02:00
PURPOSE.md refactor: rescaffold against lab blueprint + revert SDK to crates/<svc>_sdk 2026-05-27 03:53:42 +02:00
README.md refactor: rename hero_rpc → hero_blueprint across workspace 2026-05-28 19:13:47 +02:00

HeroService

Example Hero service generated from the blueprint at https://forge.ourworld.tf/lhumina_code/hero_blueprint.

Use it as a reference implementation or starting point for new services.

Layout

crates/hero_service/            — domain types library
crates/hero_service_server/     — JSON-RPC backend (kind = "server")
crates/hero_service_admin/      — admin dashboard (kind = "admin")
crates/hero_service_web/        — public read-only web surface (kind = "web")
crates/hero_service_sdk/        — typed Rust client (openrpc_client! macro over docs/openrpc.json)
schemas/                        — OSchema source files for the typed model
examples/                       — runnable usage examples
benches/                        — criterion benchmarks
tests/                          — end-to-end integration tests
docs/                           — OpenRPC spec + service docs

Build & run

# Build all binaries via lab (skips unchanged targets)
lab build hero_service --install

# Start the service (registers with hero_proc + supervises restart)
lab service hero_service --start

# Status / logs
lab service hero_service --status
hp logs.tail --service hero_service_server

# Stop
lab service hero_service --stop

Each binary embeds its service.toml via hero_lifecycle::service_base!(). Lifecycle is owned by lab; the binaries themselves carry no --start / --stop flags. See /skill:hero_service_implementation for the canonical wiring patterns.

Schemas

Domain models live in schemas/<domain>.oschema. Run hero_blueprint's generator (lab build hero_service) to regenerate the typed code under crates/hero_service/src/, crates/hero_service_sdk/src/, and docs/openrpc.json whenever the schemas change.

Scaffolded with lab blueprint

This repo was generated from the blueprint at https://forge.ourworld.tf/lhumina_code/hero_blueprint.

To regenerate a workspace like this one, pass --schemas-dir pointing at the OSchema sources:

lab blueprint --dst <path> --name hero_service --schemas-dir schemas

That delegates to hero_blueprint_generator::build::WorkspaceScaffolder and produces a runnable workspace (lib + server + admin + web + sdk + examples + benches + tests + .forgejo) from the OSchema sources alone.