From cd124f7d4a45385eeb385f170a5a54c5b924dbab Mon Sep 17 00:00:00 2001 From: Vlad Durnea Date: Mon, 30 Mar 2026 14:39:26 +0300 Subject: [PATCH] docs: generate gitea wiki pages + publish script add wiki/ markdown pages (Home, Sidebar, architecture, transport, developer, usage) add scripts/publish_gitea_wiki.sh to sync wiki repo fix: serialize aggregate env-setting tests to avoid parallel env var races --- README.md | 1 + aggregate/src/config/settings.rs | 9 +++++++++ scripts/publish_gitea_wiki.sh | 29 +++++++++++++++++++++++++++++ wiki/API-Examples.md | 28 ++++++++++++++++++++++++++++ wiki/Architecture-Overview.md | 21 +++++++++++++++++++++ wiki/Developer-Setup.md | 24 ++++++++++++++++++++++++ wiki/Home.md | 15 +++++++++++++++ wiki/NATS-Reference.md | 17 +++++++++++++++++ wiki/Quick-Start.md | 19 +++++++++++++++++++ wiki/Testing.md | 16 ++++++++++++++++ wiki/Transport-Contracts.md | 23 +++++++++++++++++++++++ wiki/_Sidebar.md | 13 +++++++++++++ 12 files changed, 215 insertions(+) create mode 100644 scripts/publish_gitea_wiki.sh create mode 100644 wiki/API-Examples.md create mode 100644 wiki/Architecture-Overview.md create mode 100644 wiki/Developer-Setup.md create mode 100644 wiki/Home.md create mode 100644 wiki/NATS-Reference.md create mode 100644 wiki/Quick-Start.md create mode 100644 wiki/Testing.md create mode 100644 wiki/Transport-Contracts.md create mode 100644 wiki/_Sidebar.md diff --git a/README.md b/README.md index 3214387..be36f6d 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ - Architecture: docs/architecture/overview.md, docs/architecture/transport.md - Developer: docs/developer/setup.md, docs/developer/testing.md - Usage: docs/usage/quickstart.md, docs/usage/api.md, docs/usage/nats.md +- Gitea Wiki: run `scripts/publish_gitea_wiki.sh` (publishes `wiki/` to the repo wiki) ## Quick Start (Docker Compose) diff --git a/aggregate/src/config/settings.rs b/aggregate/src/config/settings.rs index 970bde6..f647ee1 100644 --- a/aggregate/src/config/settings.rs +++ b/aggregate/src/config/settings.rs @@ -205,8 +205,16 @@ mod tests { use super::*; use tempfile::tempdir; + fn env_lock() -> std::sync::MutexGuard<'static, ()> { + static LOCK: std::sync::OnceLock> = std::sync::OnceLock::new(); + LOCK.get_or_init(|| std::sync::Mutex::new(())) + .lock() + .unwrap() + } + #[test] fn settings_from_env() { + let _guard = env_lock(); std::env::set_var("AGGREGATE_NATS_URL", "nats://localhost:4222"); let settings = Settings::from_env().unwrap(); assert_eq!(settings.nats_url, "nats://localhost:4222"); @@ -224,6 +232,7 @@ mod tests { #[test] fn settings_from_yaml_file_and_env_override() { + let _guard = env_lock(); let dir = tempdir().unwrap(); let file_path = dir.path().join("aggregate.yaml"); std::fs::write( diff --git a/scripts/publish_gitea_wiki.sh b/scripts/publish_gitea_wiki.sh new file mode 100644 index 0000000..c0ba7e2 --- /dev/null +++ b/scripts/publish_gitea_wiki.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +ORIGIN_URL="$(git -C "$ROOT_DIR" remote get-url origin)" +DEFAULT_WIKI_URL="$ORIGIN_URL" +if [[ "$DEFAULT_WIKI_URL" == *.git ]]; then + DEFAULT_WIKI_URL="${DEFAULT_WIKI_URL%.git}.wiki.git" +else + DEFAULT_WIKI_URL="${DEFAULT_WIKI_URL}.wiki.git" +fi + +WIKI_URL="${WIKI_REMOTE:-$DEFAULT_WIKI_URL}" +TMP_DIR="$(mktemp -d)" +trap 'rm -rf "$TMP_DIR"' EXIT + +git clone "$WIKI_URL" "$TMP_DIR/wiki" +rm -rf "$TMP_DIR/wiki/"*.md +cp -R "$ROOT_DIR/wiki/." "$TMP_DIR/wiki/" + +git -C "$TMP_DIR/wiki" add -A +if git -C "$TMP_DIR/wiki" diff --cached --quiet; then + echo "wiki: no changes" + exit 0 +fi + +git -C "$TMP_DIR/wiki" commit -m "Update wiki (generated from repo)" +git -C "$TMP_DIR/wiki" push diff --git a/wiki/API-Examples.md b/wiki/API-Examples.md new file mode 100644 index 0000000..f04f824 --- /dev/null +++ b/wiki/API-Examples.md @@ -0,0 +1,28 @@ +# API Examples + +## Projection Query via Gateway (HTTP → gRPC) +```bash +curl -sS -X POST \ + -H "x-tenant-id: tenant-a" \ + -H "x-correlation-id: demo" \ + -H "traceparent: 00-00000000000000000000000000000001-0000000000000001-01" \ + http://localhost:8080/v1/query/User \ + -d '{"uqf":"{\"eq\":{\"id\":\"u1\"}}"}' +``` + +## Projection Query via gRPC (direct, internal) +```bash +grpcurl -d '{"tenant_id":"tenant-a","view_type":"User","uqf":"{}"}' \ + -H 'x-tenant-id: tenant-a' \ + -H 'x-correlation-id: demo' \ + -H 'traceparent: 00-00000000000000000000000000000001-0000000000000001-01' \ + -plaintext localhost:9090 projection.gateway.v1.QueryService/ExecuteQuery +``` + +## Runner Admin via Gateway (HTTP → gRPC) +```bash +curl -sS -X POST \ + -H "x-tenant-id: tenant-a" \ + -H "authorization: Bearer " \ + http://localhost:8080/admin/runner/drain?wait_ms=0 +``` diff --git a/wiki/Architecture-Overview.md b/wiki/Architecture-Overview.md new file mode 100644 index 0000000..13b732c --- /dev/null +++ b/wiki/Architecture-Overview.md @@ -0,0 +1,21 @@ +# Architecture Overview + +## Monorepo +- Rust workspace: aggregate, projection, runner, gateway, control/api, shared +- Frontend: control/ui +- Infra: docker, observability, swarm + +## Data Flow +- Clients → Gateway (HTTP/JSON) +- Gateway ↔ Nodes (gRPC) +- Nodes ↔ NATS (JetStream + KV) + +## Services +- Aggregate: command handling + event sourcing; publishes events to JetStream +- Projection: materialized views; consumes aggregate events; exposes QueryService (gRPC) +- Runner: workflow/saga engine + effects/outbox; exposes RunnerAdmin (gRPC) +- Gateway: edge, authn/z, routing to nodes, admin entry points + +## Observability +- /health, /ready, /metrics on all services +- Correlation and tracing propagated across HTTP, gRPC, and NATS diff --git a/wiki/Developer-Setup.md b/wiki/Developer-Setup.md new file mode 100644 index 0000000..cecd6b0 --- /dev/null +++ b/wiki/Developer-Setup.md @@ -0,0 +1,24 @@ +# Developer Setup + +## Prerequisites +- Rust toolchain (stable) +- Node.js (LTS) for control/ui +- Docker (optional) for local stack + +## Build +```bash +cargo build +cd control/ui && npm ci && npm run build +``` + +## Workspace Verification +```bash +cargo fmt --check +cargo clippy --workspace --all-targets -- -D warnings +cargo test --workspace +cd control/ui && npm ci && npm run lint && npm run typecheck && npm run test && npm run build +``` + +## Environment +- Projection: PROJECTION_GRPC_ADDR +- Runner: RUNNER_GRPC_ADDR diff --git a/wiki/Home.md b/wiki/Home.md new file mode 100644 index 0000000..be84058 --- /dev/null +++ b/wiki/Home.md @@ -0,0 +1,15 @@ +# Cloudlysis Wiki + +This wiki is generated from the repository `docs/` directory. + +## Start Here +- Architecture Overview: [[Architecture-Overview]] +- Transport Contracts: [[Transport-Contracts]] +- Developer Setup: [[Developer-Setup]] +- Testing: [[Testing]] +- Quick Start: [[Quick-Start]] +- API Examples: [[API-Examples]] +- NATS Reference: [[NATS-Reference]] + +## Repos +- Source: https://git.madapes.com/madapes/cloudlysis diff --git a/wiki/NATS-Reference.md b/wiki/NATS-Reference.md new file mode 100644 index 0000000..bb2eeeb --- /dev/null +++ b/wiki/NATS-Reference.md @@ -0,0 +1,17 @@ +# NATS Reference + +## Subjects +- Aggregate events: tenant..aggregate.. +- Workflow commands/events: shared helpers define exact formats + +## Headers (Producers) +- tenant-id: required +- Nats-Msg-Id: idempotency key (event_id, command_id, etc.) +- x-correlation-id and correlation-id +- traceparent and trace-id + +## Consumers +- AckPolicy::Explicit +- ack_wait: bounded timeout +- max_deliver: bounded +- max_ack_pending: aligned with concurrency diff --git a/wiki/Quick-Start.md b/wiki/Quick-Start.md new file mode 100644 index 0000000..7a9e322 --- /dev/null +++ b/wiki/Quick-Start.md @@ -0,0 +1,19 @@ +# Quick Start + +## Compose +```bash +docker compose up -d --build +``` + +Full stack with observability: +```bash +docker compose -f docker-compose.yml -f observability/docker-compose.yml up -d --build +``` + +## Local Dev (minimal) +```bash +cargo run -p aggregate +cargo run -p projection +cargo run -p runner +cargo run -p gateway +``` diff --git a/wiki/Testing.md b/wiki/Testing.md new file mode 100644 index 0000000..d310aa2 --- /dev/null +++ b/wiki/Testing.md @@ -0,0 +1,16 @@ +# Testing + +## Unit and Integration +```bash +cargo test --workspace +``` + +## Gated Tests (require external services) +- Runner NATS: +```bash +RUNNER_TEST_NATS_URL=nats://127.0.0.1:4222 cargo test -p runner -- --ignored +``` +- Projection NATS: +```bash +PROJECTION_TEST_NATS_URL=nats://127.0.0.1:4222 cargo test -p projection -- --ignored +``` diff --git a/wiki/Transport-Contracts.md b/wiki/Transport-Contracts.md new file mode 100644 index 0000000..d43765b --- /dev/null +++ b/wiki/Transport-Contracts.md @@ -0,0 +1,23 @@ +# Transport Contracts + +## Context +- Tenant: HTTP x-tenant-id; NATS tenant-id +- Correlation: HTTP x-correlation-id; NATS x-correlation-id + correlation-id +- Trace: HTTP traceparent; NATS traceparent + trace-id + +## Internal RPC (gRPC) +- Aggregate: CommandService (submit commands) +- Projection: QueryService (execute queries) +- Runner: RunnerAdmin (drain, status, reload) +- All calls set deadlines and propagate context metadata + +## NATS JetStream +- Streams: + - AGGREGATE_EVENTS: tenant.*.aggregate.*.* + - WORKFLOW_COMMANDS, WORKFLOW_EVENTS +- Producers set headers: tenant-id, Nats-Msg-Id, correlation, traceparent/trace-id +- Consumers use AckPolicy::Explicit, bounded ack_wait, max_deliver, max_ack_pending + +## Routing +- Gateway routes per-tenant to shards for Aggregate/Projection/Runner +- Routing tables hot-reload atomically diff --git a/wiki/_Sidebar.md b/wiki/_Sidebar.md new file mode 100644 index 0000000..467e133 --- /dev/null +++ b/wiki/_Sidebar.md @@ -0,0 +1,13 @@ +# Navigation + +- [[Home]] +- Architecture + - [[Architecture-Overview]] + - [[Transport-Contracts]] +- Developer + - [[Developer-Setup]] + - [[Testing]] +- Usage + - [[Quick-Start]] + - [[API-Examples]] + - [[NATS-Reference]]