How vladimirkhmelev/xkcd works
Purpose and execution surface
This is a Go microservice system for phrase search across XKCD comics. Docker Compose is the primary deployment boundary (docker-compose.yaml), starting five services plus infrastructure. Service entry points are search-services/api/main.go, search-services/frontend/main.go, search-services/update/main.go, search-services/search/main.go, and search-services/words/main.go.
Public HTTP edge and UI
api exposes the REST API, Swagger, authentication, and request controls; it translates HTTP calls into gRPC calls to domain services. JWT authentication, rate limiting, concurrency limiting, and metrics are HTTP middleware concerns at search-services/api/adapters/rest/api.go and search-services/api/adapters/rest/middleware/. User credentials are persisted through the API database adapter (search-services/api/adapters/db/db.go).
frontend is a separate server-rendered browser client for search, registration/login, and administration, implemented by search-services/frontend/main.go and search-services/frontend/handlers/handlers.go.
API application boundary
The API’s core declares service-facing models and interfaces, keeping transports and service clients replaceable: search-services/api/core/models.go, search-services/api/core/ports.go. Concrete gRPC client adapters route requests to search, update, and words services: search-services/api/adapters/search/search.go, search-services/api/adapters/update/update.go, and search-services/api/adapters/words/words.go. Shared protobuf contracts define this inter-service boundary in search-services/proto/search/search.proto, search-services/proto/update/update.proto, and search-services/proto/words/words.proto.
Update ingestion pipeline
The update service fetches comic data from the external XKCD API, stores comics in PostgreSQL, and publishes update events. Its core orchestration is search-services/update/core/service.go; external source and storage adapters are search-services/update/adapters/xkcd/xkcd.go and search-services/update/adapters/db/storage.go. Database schema lifecycle is local to this service via search-services/update/adapters/db/migrations/. The NATS publisher (search-services/update/adapters/broker/broker.go) is the asynchronous handoff that triggers search-index refreshes.
Search and indexing pipeline
The search service owns query execution and index lifecycle. search-services/search/core/service.go coordinates storage, tokenization, cache, and event-driven rebuilding. It receives gRPC requests through search-services/search/adapters/grpc/server.go, reads indexed/source data through search-services/search/adapters/db/storage.go, and consumes update notifications through search-services/search/adapters/broker/broker.go plus initialization logic in search-services/search/adapters/initiator/initiator.go. Query results are cached behind a replaceable cache port, with Redis and no-op implementations in search-services/search/adapters/cache/redis.go and search-services/search/adapters/cache/noop.go.
Text processing service
words is the shared phrase-normalization boundary used by search and update flows. It is a standalone gRPC service (search-services/words/main.go) whose implementation performs tokenization, stop-word handling, and stemming in search-services/words/words/words.go. This avoids duplicating index/query normalization rules across services.
Runtime infrastructure and observability
PostgreSQL stores users and comics; NATS carries update events; Redis holds search results with TTL. Compose also provisions VictoriaMetrics/Grafana, pgAdmin, and Jaeger. Prometheus-format scrape configuration and Grafana dashboard artifacts are metrics/promscrape.yml and metrics/dashboard.json. OpenTelemetry tracing is shared through search-services/pkg/tracing/tracing.go. Service-specific YAML configuration establishes runtime endpoints and settings, e.g. search-services/api/config.yaml, search-services/search/config.yaml, and search-services/update/config.yaml.
Main entry points: api.go API HTTP edge · core/service.go Search and index core · core/service.go Update orchestrator · search.go gRPC client adapters
Components 18
Clients
- Browser user
- Frontend · Search, account, and administration UI.
search-services/frontend/main.go
API service
- API HTTP edge · Swagger, JWT, rate and concurrency controls.
search-services/api/adapters/rest/api.go - API core ports · Service models and replaceable interfaces.
search-services/api/core/ports.go - gRPC client adapters · Routes API operations to domain services.
search-services/api/adapters/search/search.go - Protobuf contracts · Shared search, update, and words service contracts.
search-services/proto/search/search.proto
Domain services
- Update orchestrator · Fetches, stores, and publishes comic updates.
search-services/update/core/service.go - XKCD API
- Search gRPC server
search-services/search/adapters/grpc/server.go - Search and index core · Coordinates querying, normalization, caching, and rebuilds.
search-services/search/core/service.go - Words service · Shared tokenization, stop-word handling, and stemming.
search-services/words/words/words.go
Runtime infrastructure
- PostgreSQL
- NATS
- Redis · TTL-backed results cache with a no-op fallback.
search-services/search/adapters/cache/redis.go - Docker Compose · Starts services and local infrastructure.
docker-compose.yaml
Observability
- OpenTelemetry tracing
search-services/pkg/tracing/tracing.go - VictoriaMetrics and Grafana · Scrapes Prometheus metrics and presents dashboards.
metrics/promscrape.yml - Jaeger
Connections 26
- Browser user → Frontend: HTTP
- Frontend → API HTTP edge: API calls
- API HTTP edge → API core ports: invokes
- API HTTP edge → PostgreSQL: user credentials
- API core ports → gRPC client adapters: ports
- gRPC client adapters → Protobuf contracts: uses
- gRPC client adapters → Search gRPC server: search gRPC
- gRPC client adapters → Update orchestrator: update gRPC
- gRPC client adapters → Words service: words gRPC
- XKCD API → Update orchestrator: comic data
- Update orchestrator → Words service: normalizes text
- Update orchestrator → PostgreSQL: stores comics
- Update orchestrator → NATS: publishes updates
- Search gRPC server → Search and index core: requests
- NATS → Search and index core: update events · Triggers index refresh.
- Search and index core → PostgreSQL: reads comic data
- Search and index core → Words service: normalizes queries
- Search and index core → Redis: caches results
- API HTTP edge → OpenTelemetry tracing: traces
- Search and index core → OpenTelemetry tracing: traces
- OpenTelemetry tracing → Jaeger: exports spans
- API HTTP edge → VictoriaMetrics and Grafana: metrics
- Docker Compose → API HTTP edge: runs
- Docker Compose → Update orchestrator: runs
- Docker Compose → Search gRPC server: runs
- Docker Compose → Words service: runs