docs(refactor): complete api architecture phase
This commit is contained in:
@@ -30,10 +30,10 @@ The `api` gateway is the **only** HTTP-facing service. All inter-service communi
|
||||
|
||||
### API Gateway (api/)
|
||||
|
||||
- **Entry**: `api/main.go` → `cmd.Execute()` (Cobra) → `cmd/serve.go` sets up Gin router
|
||||
- **Service layer**: `api/service/main.go` — `DaranoService` interface composes all upstream gRPC clients. Each service gets a persistent gRPC connection created lazily, with automatic reconnection after a **2-minute timeout**. URL lookup uses **reflection** on the `Peer` struct via `ServicesEnum` — field names must match `ServicesEnum` values exactly.
|
||||
- **Handlers**: `api/handler/` — one file per domain. All handlers embed `service.DaranoService`.
|
||||
- **Routing**: `api/handler/routing.go` — routes grouped into `/v1/public/`, `/v1/client/`, `/v1/admin/`. The `/v1/internal/` routes are commented out (placeholder).
|
||||
- **Entry/composition**: `api/main.go` → `cmd.Execute()` (Cobra) → `cmd/apiRuntime`, which explicitly owns clients, handlers, router, HTTP servers, permission synchronization, and cleanup.
|
||||
- **Upstream boundary**: `api/application/port.Upstreams` composes generated service contracts. `api/infrastructure/grpcclient` implements lazy connection creation, active-call tracking, configurable idle closure (**2-minute default**), reconnection, health checks, and explicit shutdown without reflection.
|
||||
- **Handlers**: `api/interface/http/handler/` — one file per domain. Handlers depend on `application/port.Upstreams`.
|
||||
- **Routing**: `api/interface/http/handler/routing.go` — routes grouped into `/v1/public/`, `/v1/client/`, `/v1/admin/`. The admin group is protected but currently empty; internal routes remain disabled.
|
||||
- **Middleware chain** (order matters): APM → Profiling → Prometheus → CORS → JSON → I18n → Error → optional Logger
|
||||
- **Endpoints**: `GET /` (health), `GET /metrics` (Prometheus), `GET /swagger/*any`, `GET /ws` (WebSocket)
|
||||
- **Profiling**: `net/http/pprof` is imported (blank import `_`); runs on a separate port when `Profiling.Enabled` in config
|
||||
@@ -150,12 +150,12 @@ In `wallet`, `core/` contains sub-packages: `walletImp/`, `marketImp/`, `alertIm
|
||||
### Request/Response Flow
|
||||
|
||||
```
|
||||
HTTP request → middleware chain → routing.go → handler/*.go → DaranoService.gRPC → backend service
|
||||
HTTP request → interface/http middleware → interface/http/handler → application Upstreams port → infrastructure/grpcclient → backend service
|
||||
```
|
||||
|
||||
- **Response helpers**: `handler/response.go` — `JSON()` and `JSONList[X]()` wrap responses in `transport.Response{Meta, Data}`. `JSONList` has a known issue: pointer-to-empty-slice marshals as `null` instead of `[]`, fixed via `EmptyList{make([]string, 0)}` sentinel.
|
||||
- **HTTP-to-gRPC context**: `handler/contextWithMetadata()` converts HTTP headers to gRPC metadata using `util.ConvertHTTPHeaderToGRPCMetadata()`.
|
||||
- **Handler interface**: Each handler file defines a `handle` interface; `handler/main.go` defines `Server` struct embedding `service.DaranoService`.
|
||||
- **Response helpers**: `interface/http/handler/response.go` — `JSON()` and `JSONList[X]()` wrap responses in `transport.Response{Meta, Data}`. Pointer-backed empty lists use the `EmptyList` sentinel to serialize `[]` rather than `null`.
|
||||
- **HTTP-to-gRPC context**: `interface/http/handler/contextWithMetadata()` copies HTTP headers into incoming and outgoing gRPC metadata.
|
||||
- **Handler interface**: `interface/http/handler.Server` receives the `application/port.Upstreams` boundary and configuration explicitly.
|
||||
|
||||
### Route conventions
|
||||
|
||||
@@ -186,9 +186,9 @@ All Go services instrumented with Elastic APM and Prometheus metrics. Traefik ha
|
||||
## Gotchas and Non-Obvious Details
|
||||
|
||||
1. **Config library**: Services use `knadh/koanf` with TOML parser, not `fig`. Tags are `koanf:"field-name"`.
|
||||
2. **gRPC connection lifecycle**: Connections are lazy — created on first call, not at startup. A background goroutine closes and nils connections after 2 minutes of inactivity, triggering reconnection.
|
||||
3. **Enum codegen**: `api/service/servicesenum_enumer.go` is auto-generated via `//go:generate go run github.com/alvaroloes/enumer`. Adding enum values requires `go generate`.
|
||||
4. **Swagger docs**: Generated by `swag init` and served via gin-swagger. URL adapts per environment (prod → `api.darano.ir`, dev → `dev.api.darano.ir`, local → `localhost:<port>`).
|
||||
2. **gRPC connection lifecycle**: Connections are lazy — created on first RPC. Active calls prevent idle closure; peers close after the configured inactivity timeout (2-minute default) and reconnect on the next call.
|
||||
3. **Peer mapping**: `infrastructure/grpcclient` maps configured peers explicitly; the former reflection/enum generator is removed.
|
||||
4. **Swagger docs**: Generated by `swag init` and served via `interface/http`. URL adapts per environment (prod → `api.darano.ir`, dev → `dev.api.darano.ir`, local → `localhost:<port>`).
|
||||
5. **Multi-service wallet**: The wallet binary serves 5 sub-services. `make run` kills existing processes matching the service name pattern via `pgrep | xargs kill` before starting.
|
||||
6. **Concurrent dev**: Running multiple `make dev-*` targets simultaneously requires the `flock` serialization in the Makefile. Using `make -j` without flock will corrupt the build.
|
||||
7. **Proto stubs excluded from watchers**: `.air.toml` excludes `domain/stub/` from file watching. Air also excludes `swagger/` and `testdata/`.
|
||||
@@ -212,7 +212,7 @@ All Go services instrumented with Elastic APM and Prometheus metrics. Traefik ha
|
||||
|
||||
This repository is being migrated to a unified Domain-Driven Design / Clean Architecture. See [`REFACTORING-PLAN.md`](REFACTORING-PLAN.md) for the full plan.
|
||||
|
||||
**Go services current state**: `api/` uses koanf, `auth/` uses fig with `usecase/`, `wallet/` uses fig with `core/walletImp/` mixing gRPC server and business logic. Config libraries differ. Domain entities and persistence models are conflated.
|
||||
**Go services current state**: API, Auth, and Wallet configuration and architecture phases are complete on `feat/refactor-v1`; use the refactoring tracker and audit for the current package boundaries and verification evidence.
|
||||
|
||||
**AdminPanel current state**: Direct DB access to `core_db` with no gRPC layer. Business logic duplicated in Django admin classes (`check_token_policy`, `auto_gen` instead of delegating to Go services). `managed = False` models drift from Go GORM models.
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ All committed work was pushed. `api`, `auth`, `wallet`, `proto`, and `dev-procfi
|
||||
- Auth refactoring tasks `A001`–`A009` are complete, including configurable periodic identity validation.
|
||||
- Wallet `W001`–`W013` are complete. The final W005–W012 series ends at `240b8d0` on `feat/refactor-v1`.
|
||||
- Recent Wallet completion commits include `03da6fd` atomic trustline transaction persistence, `c7f442a` failed IPG fulfillment recording, `ae0b185` canceled-maker balance release, `ca2dc50` synchronous settlement, `fbca6fa` stream application service, `14c5d35` lock persistence workflow, `200d6d6` market lifecycle, `d91d51b` transaction balance processor, and `240b8d0` final interface boundaries.
|
||||
- API `G001`–`G008` are complete. The compatibility inventory begins at `95c4264`; the final removal of superseded packages is `31e3043`. Upstream clients live in `infrastructure/grpcclient`, HTTP adapters live in `interface/http`, and `cmd/apiRuntime` owns explicit composition.
|
||||
|
||||
### Wallet completion state
|
||||
|
||||
@@ -98,6 +99,10 @@ Use `REFACTORING-TODO.md` and `REFACTORING-AUDIT.md` as the authoritative detail
|
||||
|
||||
Final Wallet verification on 2026-08-31: protobuf regeneration produced no diff; `go test ./...`, `go test -race ./...`, `go vet ./...`, and `go build ./...` all passed.
|
||||
|
||||
### API completion state
|
||||
|
||||
No API refactoring task remains open. Final API verification on 2026-08-31: protobuf and Swagger regeneration produced no diff; `go test ./...`, `go test -race ./...`, `go vet ./...`, and `go build ./...` all passed. Swagger regeneration requires `GOCACHE=/tmp/darano-api-go-cache` in this environment.
|
||||
|
||||
### Commands and cautions
|
||||
|
||||
- Prefix shell commands with `rtk` as required by `/home/navid/.codex/RTK.md`.
|
||||
|
||||
@@ -509,3 +509,14 @@ Migration order implied by the map: isolate shared infrastructure constructors (
|
||||
- `W011`: all six runtime modes use explicit dependency profiles; superseded generic strict/safe repository setup entry points and option names are removed.
|
||||
- `W012`: gRPC adapters moved from `core/*Imp` to `interface/grpc`, cron moved to `interface/process/cron`, legacy `*Imp` package names were removed, and superseded helpers/shims were deleted. No live code references the old core packages or generic setup entry points.
|
||||
- Final Wallet commit is `240b8d0` on `feat/refactor-v1`. Protobuf regeneration produced no diff; full tests, race tests, vet, build, and whitespace checks all pass.
|
||||
|
||||
## API phase completion — `G001`–`G008` (2026-08-31)
|
||||
|
||||
- `G001`: API `ARCHITECTURE-COMPATIBILITY.md` records all 57 active `/v1` method/path contracts, four auxiliary endpoints, optional static serving, middleware order, success/error envelopes, header-to-gRPC metadata behavior, Swagger selection, pprof, WebSocket messages, and peer lifecycle expectations.
|
||||
- `G002`: `application/port.Upstreams` is the transport-facing boundary and `infrastructure/grpcclient` owns generated clients. Connections are created on first RPC, connection creation is serialized, active calls prevent idle closure, the configured inactivity timeout defaults to two minutes, idle peers close, later calls reconnect, health failures remain request-tolerant, and process shutdown explicitly closes all peers. Focused tests cover no eager dial, reuse, idle close/reconnect, and invalid composition.
|
||||
- `G003`: middleware moved to `interface/http/middleware`. `Chain` makes the compatibility-critical APM → profiling → Prometheus → CORS → JSON → i18n → error → optional logger order explicit and tested. The legacy profiling adapter's missing `c.Next()` path was corrected so non-verbose deployments serve requests.
|
||||
- `G004`/`G005`: all public and authenticated handlers, binder, response helpers, middleware-facing IAM logic, and route registration moved to `interface/http/handler`. A complete route-matrix test asserts every versioned method/path; existing authorization, metadata, protobuf binding, status/error translation, and response envelopes are retained.
|
||||
- `G006`: `interface/http` now owns the Gin router, readiness, metrics, Swagger, WebSocket, main HTTP server, separate pprof server, timeouts, and graceful shutdown. Tests cover auxiliary route registration, environment-specific Swagger URLs, and WebSocket wire-message formatting.
|
||||
- `G007`: `cmd/apiRuntime` is the explicit dependency graph for upstream clients, HTTP handlers, router, server ownership, startup permission synchronization, and shutdown. Construction is side-effect-free and its complete 61-route graph is tested.
|
||||
- `G008`: removed root `service`, `handler`, and `middlewares` packages; the generated service enum/reflection lookup, unused mock-data helper, empty error-enum shell, commented legacy handlers/routes, and `gofakeit` dependency are gone. No legacy package import or duplicate client/handler implementation remains.
|
||||
- Final API commit is `31e3043` on `feat/refactor-v1`. `make build-proto` and writable-cache `make build-swag` reproduce committed outputs with no diff; `go test ./...`, `go test -race ./...`, `go vet ./...`, `go build ./...`, and whitespace checks pass.
|
||||
|
||||
+16
-8
@@ -136,14 +136,14 @@ This is the authoritative execution tracker for the refactor. Work is performed
|
||||
|
||||
| ID | Status | Task | Acceptance check / note |
|
||||
|---|---|---|---|
|
||||
| G001 | `TODO` | Inventory routes, middleware, response contracts, WebSocket, Swagger, metrics, profiling, and gRPC clients. | Compatibility matrix exists before package moves. |
|
||||
| G002 | `TODO` | Move upstream clients into `infrastructure/grpcclient`. | Lazy connection and two-minute idle-close behavior remain intact. |
|
||||
| G003 | `TODO` | Move middleware into `interface/http/middleware`. | Existing middleware order is unchanged and tested. |
|
||||
| G004 | `TODO` | Move public HTTP handlers and routes into `interface/http`. | Public endpoints retain paths, status codes, and envelopes. |
|
||||
| G005 | `TODO` | Move authenticated client/admin handlers and routes. | JWT, metadata forwarding, errors, and route behavior remain compatible. |
|
||||
| G006 | `TODO` | Move WebSocket and auxiliary endpoints into interface adapters. | WebSocket, health, metrics, Swagger, and profiling still work. |
|
||||
| G007 | `TODO` | Replace API bootstrap with explicit dependency composition. | Gateway builds and all contract tests pass. |
|
||||
| G008 | `TODO` | Remove superseded API packages and shims. | No duplicate handlers or clients remain. |
|
||||
| G001 | `DONE` | Inventory routes, middleware, response contracts, WebSocket, Swagger, metrics, profiling, and gRPC clients. | `ARCHITECTURE-COMPATIBILITY.md` records 57 versioned routes, four auxiliary endpoints, middleware order, envelopes, metadata, Swagger, pprof, WebSocket, and intended peer lifecycle. |
|
||||
| G002 | `DONE` | Move upstream clients into `infrastructure/grpcclient`. | Generated clients use a lazy connection interface with serialized dialing, active-call tracking, configurable inactivity closure (two-minute default), reconnection, health checks, explicit close, and focused lifecycle tests. |
|
||||
| G003 | `DONE` | Move middleware into `interface/http/middleware`. | The exact APM → profiling → Prometheus → CORS → JSON → i18n → error → optional logger order is centralized and tested; non-verbose profiling now continues the handler chain. |
|
||||
| G004 | `DONE` | Move public HTTP handlers and routes into `interface/http`. | Public handlers/routes live under `interface/http/handler`; the complete method/path matrix is asserted and response behavior remains unchanged. |
|
||||
| G005 | `DONE` | Move authenticated client/admin handlers and routes. | Client/admin handlers and authorization routing share the interface boundary; JWT/IAM, header metadata, errors, and all authenticated method/path contracts remain intact. |
|
||||
| G006 | `DONE` | Move WebSocket and auxiliary endpoints into interface adapters. | `interface/http` owns router, health, metrics, Swagger URL selection, WebSocket, main HTTP server, pprof server, and graceful shutdown; auxiliary contracts are tested. |
|
||||
| G007 | `DONE` | Replace API bootstrap with explicit dependency composition. | `cmd/apiRuntime` explicitly owns clients, handlers, router, HTTP servers, permission synchronization, shutdown, and client closure; composition and route-count tests pass. |
|
||||
| G008 | `DONE` | Remove superseded API packages and shims. | Legacy root `service`, `handler`, `middlewares`, enum-generator/mock shells, dead handler comments, and obsolete dependency are removed; no duplicate clients or handlers remain. |
|
||||
|
||||
## Phase 5 — AdminPanel write service layer
|
||||
|
||||
@@ -340,3 +340,11 @@ Append one row whenever a task changes status. Existing rows are never rewritten
|
||||
| 2026-08-31 | W010 | `STARTED` | `DONE` | Extracted the Stellar stream payment workflow, narrowed cron/stream composition, and removed duplicate cron registration; all validation gates pass through `240b8d0`. |
|
||||
| 2026-08-31 | W011 | `STARTED` | `DONE` | Replaced generic bootstrap internals with explicit process dependency profiles and removed legacy strict/safe setup names; all validation gates pass through `240b8d0`. |
|
||||
| 2026-08-31 | W012 | `STARTED` | `DONE` | Moved adapters out of `core`, removed duplicate helpers/shims, renamed legacy `*Imp` packages to interface-owned names, and verified no legacy core/bootstrap references remain; all validation gates pass through `240b8d0`. |
|
||||
| 2026-08-31 | G001 | `TODO` | `DONE` | Recorded the pre-move route, middleware, envelope, metadata, auxiliary endpoint, Swagger/pprof/WebSocket, and peer lifecycle compatibility matrix in API `95c4264`. |
|
||||
| 2026-08-31 | G002 | `TODO` | `DONE` | Added the application upstream port and lazy reconnecting gRPC infrastructure with inactivity and explicit-close tests in API `0edea98`. |
|
||||
| 2026-08-31 | G003 | `TODO` | `DONE` | Moved middleware below `interface/http`, centralized/tested its exact order, and fixed the non-verbose chain stop in API `1d9b6ca`. |
|
||||
| 2026-08-31 | G004 | `TODO` | `DONE` | Moved public handlers/routes below `interface/http/handler` and locked the public method/path matrix in API `41fac0c`. |
|
||||
| 2026-08-31 | G005 | `TODO` | `DONE` | Moved authenticated client/admin handlers and authorization routing into the same tested interface boundary in API `41fac0c`. |
|
||||
| 2026-08-31 | G006 | `TODO` | `DONE` | Extracted router, health, metrics, Swagger, WebSocket, HTTP/pprof server ownership, and graceful shutdown into `interface/http` in API `380aad4`. |
|
||||
| 2026-08-31 | G007 | `TODO` | `DONE` | Added explicit typed API runtime composition with startup permission synchronization and owned cleanup in API `163114f`. |
|
||||
| 2026-08-31 | G008 | `TODO` | `DONE` | Removed legacy service/handler/middleware packages, generated enum/mock shims, dead shells, and unused dependencies in API `31e3043`; protobuf/Swagger regeneration, tests, race, vet, build, and whitespace checks pass. |
|
||||
|
||||
Reference in New Issue
Block a user