docs(c4): add L3 backend search component diagram
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
33
docs/architecture/c4/l3-backend-3h-search.puml
Normal file
33
docs/architecture/c4/l3-backend-3h-search.puml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
@startuml
|
||||||
|
!include <C4/C4_Component>
|
||||||
|
|
||||||
|
title Component Diagram: API Backend — NL Search
|
||||||
|
|
||||||
|
Container(frontend, "Web Frontend", "SvelteKit")
|
||||||
|
ContainerDb(db, "PostgreSQL", "PostgreSQL 16")
|
||||||
|
Container(ollama, "Ollama", "ollama/ollama — port 11434 (internal only)")
|
||||||
|
|
||||||
|
System_Boundary(backend, "API Backend (Spring Boot)") {
|
||||||
|
Component(nlCtrl, "NlSearchController", "Spring MVC — POST /api/search/nl", "REST entry point for natural language search. Enforces READ_ALL permission. Uses @AuthenticationPrincipal UserDetails to obtain the caller's email for rate limiting. Delegates to NlQueryParserService and returns NlSearchResponse.")
|
||||||
|
Component(rateLimiter, "NlSearchRateLimiter", "Spring Service", "Bucket4j + Caffeine LoadingCache keyed on user email. Allows 5 NL search requests per minute per user. Throws DomainException(SMART_SEARCH_RATE_LIMITED / HTTP 429) when the bucket is exhausted. Node-local — same caveat as LoginRateLimiter.")
|
||||||
|
Component(parserSvc, "NlQueryParserService", "Spring Service", "Orchestrates the full NL search pipeline: (1) validates query length, (2) calls OllamaClient.parse() to extract structured intent, (3) resolves each person name via PersonService.findByDisplayNameContaining(), (4) applies multi-name / personRole heuristics, (5) delegates to DocumentService.searchDocuments() or searchDocumentsByPersonId(). Returns NlSearchResponse. Never logs raw query content (PII).")
|
||||||
|
Component(ollamaClient, "RestClientOllamaClient", "Spring Service — implements OllamaClient + OllamaHealthClient", "HTTP client for the Ollama API. Uses two separate RestClient instances: inference client (30 s read timeout) and health-check client (2 s connect timeout). Calls POST /api/generate with grammar-constrained JSON schema (personNames, personRole, dateFrom, dateTo, keywords). isHealthy() polls GET /api/tags. Null-coalesces absent personNames/keywords to List.of(). Defaults unknown personRole to 'any' with a warning log. Maps timeout/5xx/parse errors to DomainException(SMART_SEARCH_UNAVAILABLE / HTTP 503).")
|
||||||
|
Component(ollamaProps, "OllamaProperties", "@ConfigurationProperties(\"app.ollama\")", "Config bean: baseUrl, model (qwen2.5:7b-instruct-q4_K_M), timeoutSeconds (default: 30), healthCheckTimeoutSeconds (default: 2).")
|
||||||
|
Component(rateLimitProps, "NlSearchRateLimitProperties", "@ConfigurationProperties(\"app.nl-search.rate-limit\")", "Config bean: maxRequestsPerMinute (default: 5).")
|
||||||
|
}
|
||||||
|
|
||||||
|
Component(personSvc, "PersonService", "Spring Service", "See diagram 3e. findByDisplayNameContaining(fragment) delegates to PersonRepository.searchByName() — covers first+last name, alias, and name aliases via LEFT JOIN.")
|
||||||
|
Component(documentSvc, "DocumentService", "Spring Service", "See diagram 3b. searchDocuments() for keyword/sender/receiver/date queries. searchDocumentsByPersonId() for OR-semantics single-person queries (person as sender OR receiver, no keyword filter).")
|
||||||
|
|
||||||
|
Rel(frontend, nlCtrl, "POST /api/search/nl with JSON query", "HTTP / JSON")
|
||||||
|
Rel(nlCtrl, rateLimiter, "checkAndConsume(userEmail)")
|
||||||
|
Rel(nlCtrl, parserSvc, "parse(query)")
|
||||||
|
Rel(parserSvc, ollamaClient, "parse(rawQuery) — extracts intent", "HTTP / JSON")
|
||||||
|
Rel(ollamaClient, ollama, "POST /api/generate (grammar-constrained JSON schema)", "HTTP / REST")
|
||||||
|
Rel(ollamaClient, ollama, "GET /api/tags (health check)", "HTTP / REST")
|
||||||
|
Rel(parserSvc, personSvc, "findByDisplayNameContaining(name) for each extracted name")
|
||||||
|
Rel(parserSvc, documentSvc, "searchDocuments() or searchDocumentsByPersonId()")
|
||||||
|
Rel(documentSvc, db, "JPA queries", "JDBC")
|
||||||
|
Rel(personSvc, db, "JPA queries", "JDBC")
|
||||||
|
|
||||||
|
@enduml
|
||||||
Reference in New Issue
Block a user