From 6700e55e5099cdebf6d7518ca4b30ef32f1abd24 Mon Sep 17 00:00:00 2001 From: ITQ Date: Tue, 24 Feb 2026 09:13:24 +0300 Subject: [PATCH] docs(diagrams): added C4 diagrams --- .../raw/c4-component-critical-path.puml | 39 +++++++++++++++++++ assets/plantuml/raw/c4-container.puml | 28 +++++++++++++ assets/plantuml/raw/c4-context.puml | 29 ++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 assets/plantuml/raw/c4-component-critical-path.puml create mode 100644 assets/plantuml/raw/c4-container.puml create mode 100644 assets/plantuml/raw/c4-context.puml diff --git a/assets/plantuml/raw/c4-component-critical-path.puml b/assets/plantuml/raw/c4-component-critical-path.puml new file mode 100644 index 0000000..04ff62a --- /dev/null +++ b/assets/plantuml/raw/c4-component-critical-path.puml @@ -0,0 +1,39 @@ +@startuml +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml + +LAYOUT_TOP_DOWN() + +title LOTTY Backend - C4 Component + +Container_Boundary(api, "Backend Container (Django + Django Ninja)") { + Component(decision_endpoint, "Decision Endpoint", "api/v1/decision/endpoints.py", "POST /api/v1/decide") + Component(decision_service, "Decision Service", "apps/decision/services.py", "Flag lookup, targeting DSL, participation limits, hash-based variant assignment") + + Component(events_endpoint, "Events Endpoint", "api/v1/events/endpoints.py", "POST /api/v1/events") + Component(events_service, "Events Service", "apps/events/services.py", "Validation, dedup, exposure/conversion attribution, pending promotion") + + Component(reports_endpoint, "Reports Endpoint", "api/v1/reports/endpoints.py", "GET /reports/{experiment_id}") + Component(reports_service, "Reports Service", "apps/reports/services.py", "Per-variant metric calculation (ratio, count, average, percentile)") + + Component(guardrails_service, "Guardrails Service", "apps/guardrails/services.py", "Threshold checks, auto pause/rollback") +} + +ContainerDb(db, "Relational DB", "PostgreSQL / SQLite", "Flags, experiments, variants, decisions, events, exposures") +Container(cache, "Cache", "Valkey / LocMem", "Flag and active experiment cache") +Container(worker, "Celery Beat", "Celery", "Periodic guardrail checks (60s)") + +Rel(decision_endpoint, decision_service, "Delegates") +Rel(decision_service, cache, "Reads cached flag / active experiment") +Rel(decision_service, db, "Reads variants, writes Decision") + +Rel(events_endpoint, events_service, "Delegates batch") +Rel(events_service, db, "Writes Event / Exposure / PendingEvent") + +Rel(reports_endpoint, reports_service, "Builds report") +Rel(reports_service, db, "Reads attributed events / exposures") + +Rel(guardrails_service, reports_service, "Uses metric calculations") +Rel(guardrails_service, db, "Writes triggers, updates experiment status") +Rel(worker, guardrails_service, "Periodic check_all") + +@enduml diff --git a/assets/plantuml/raw/c4-container.puml b/assets/plantuml/raw/c4-container.puml new file mode 100644 index 0000000..da5aaca --- /dev/null +++ b/assets/plantuml/raw/c4-container.puml @@ -0,0 +1,28 @@ +@startuml +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml + +LAYOUT_LEFT_RIGHT() + +title LOTTY - C4 Container + +Person(product_client, "Product Client", "Web/Mobile app") +Person(ops_user, "Experimenter/Approver/Admin/Viewer") + +System_Boundary(lotty_boundary, "LOTTY Backend") { + Container(api, "Backend API", "Django + Ninja", "REST endpoints: flags, experiments, decide, events, reports, guardrails, notifications, conflicts, metrics, learnings, reviews, users, auth") + ContainerDb(db, "PostgreSQL / SQLite", "Relational DB", "Experiments, variants, decisions, events, exposures, outcomes, guardrails, notifications, conflicts, logs") + Container(cache, "Valkey / LocMem Cache", "Cache + Celery broker", "Flag/experiment cache, Celery task broker") + Container(worker, "Celery Worker / Beat", "Background worker", "Periodic: guardrails check, notifications flush, pending events cleanup") +} + +System_Ext(notifications, "Notification Channels", "Telegram / SMTP") + +Rel(product_client, api, "Gets flag decisions, sends events", "HTTP/JSON") +Rel(ops_user, api, "Admin/experiment/review calls", "HTTP/JSON") +Rel(api, db, "Read/write application state", "SQL") +Rel(api, cache, "Read/write cache", "Redis protocol") +Rel(worker, db, "Read/write application state", "SQL") +Rel(worker, cache, "Receives tasks, reads cached state", "Redis protocol") +Rel(worker, notifications, "Delivers queued notifications", "HTTP / SMTP") + +@enduml diff --git a/assets/plantuml/raw/c4-context.puml b/assets/plantuml/raw/c4-context.puml new file mode 100644 index 0000000..57f5c45 --- /dev/null +++ b/assets/plantuml/raw/c4-context.puml @@ -0,0 +1,29 @@ +@startuml +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml + +LAYOUT_LEFT_RIGHT() + +title LOTTY - C4 Context + +Person(product_client, "Product Client", "Web/Mobile app") +Person(analyst, "Experimenter", "Creates experiments and analyzes outcomes") +Person(approver, "Approver", "Reviews and approves experiments") +Person(admin, "Admin", "Manages users, roles, review policies") +Person(viewer, "Viewer", "Can only view") + +System_Boundary(lotty_boundary, "LOTTY Backend") { + System(lotty, "LOTTY Backend", "Django + Ninja API", "Feature flags, experiments, decisions, events, reports, guardrails, notifications, conflicts") +} + +System_Ext(notification_channels, "Notification Channels", "Telegram / SMTP", "Receives operational notifications") +System_Ext(observability, "Observability Stack", "VictoriaMetrics / Grafana / Loki / Tempo", "Metrics, logs, traces") + +Rel(product_client, lotty, "Gets flag decisions, sends events", "HTTP/JSON") +Rel(analyst, lotty, "Configures experiments, views reports", "HTTP/JSON") +Rel(approver, lotty, "Approves/rejects experiments", "HTTP/JSON") +Rel(admin, lotty, "Manages users and review settings", "HTTP/JSON") +Rel(viewer, lotty, "Views objects on platform", "HTTP/JSON") +Rel(lotty, notification_channels, "Sends experiment/guardrail notifications", "HTTP / SMTP via Celery worker") +Rel(lotty, observability, "Exports metrics, logs, traces", "OTLP") + +@enduml