Saltar al contenido principal

Arquitectura del Sistema

Diagrama completo de servicios

Infraestructura de producción

ComponenteRedAcceso externo
node-apiDocker bridge crimoo_netSolo via gtm-proxy (puerto 3000 expuesto en host)
PostgreSQLDocker bridge crimoo_netSolo dentro del bridge
ClickHouseDocker bridge crimoo_netSolo dentro del bridge
gtm-fabricHost networkVia Tailscale (100.97.60.119:8000)
gtm-proxyHost networkPúblico (:80/:443) + Tailscale

Control Plane vs Data Plane

Control PlaneData Plane
Servicionode-apigtm-fabric + gtm-proxy
RolGestión, configuración, billingProcesamiento de eventos en tiempo real
EscalaÚnica instancia (o pocas)Una VM por cliente/zona
BDPostgreSQL + ClickHouseSin BD propia — todo via node-api
EstadoStatefulStateless

gtm-fabric es stateless

gtm-fabric no tiene base de datos propia. Para cualquier dato de configuración consulta a node-api:

  • Al arrancar → GET /internal/fabric/gtms?vmId=X (carga GTMs en cache local)
  • Durante procesamiento → consulta node-api si necesita datos que no tiene en cache
  • Al capturar contactos → flush batch a POST /internal/fabric/contacts/batch
  • Al reportar uso → flush batch a POST /internal/fabric/usage

El único storage que usa directamente es ClickHouse para escribir eventos de tagging y logs de containers.

Comunicación node-api → gtm-fabric

node-api se comunica con gtm-fabric por HTTP directo (no Pub/Sub):

Acciónnode-api llama a gtm-fabric
Crear GTMPOST /api/v1/gtm
Eliminar GTMDELETE /api/v1/gtm/:id
Actualizar dominio primarioPOST /api/v1/gtm/:id/domains/update
Añadir dominio customPOST /api/v1/gtm/:id/domains/add
Remover dominioDELETE /api/v1/gtm/:id/domains/remove
Habilitar custom loaderPUT /api/v1/gtm/:id/custom-loader
Deshabilitar custom loaderDELETE /api/v1/gtm/:id/custom-loader
Activar preview headerPOST /api/v1/gtm/:id/preview-header
Remover preview headerDELETE /api/v1/gtm/:id/preview-header

Pub/Sub — proyecto, topics y subscriptions

Proyecto GCP: graceful-splice-493501-q7 (único). Cualquier referencia a mystical-accord-480500-p7 es legacy y debe migrarse.

TopicPublisherConsumer (subscription)Mensaje
gtm-tagging-topicgtm-proxytagging-events-vm-{vmId}-sub (gtm-fabric)TaggingEvent (eventos HTTP del browser)
gtm-operations-topicnode-apigtm-operations-vm-{vmId}-sub (gtm-fabric)Comandos de gestión GTM por VM

Patrón de subscriptions dinámicas: una subscription por VM, con nombre derivado del vmId. Las subscriptions se crean externamente (Terraform / scripts de despliegue) — PubSubSubscriptionManager solo las identifica al arrancar y falla con IllegalStateException si la subscription no existe.

Service Account única: crimoo-pubsub-sa@graceful-splice-493501-q7.iam.gserviceaccount.com

  • Roles: pubsub.publisher, pubsub.subscriber, pubsub.viewer, secretmanager.secretAccessor, monitoring.metricWriter, logging.logWriter
  • Key montada en /opt/crimoo/gcp-credentials.json en el VPS, compartida por gtm-proxy y gtm-fabric (volume mount idéntico en ambos docker-compose.yml).

Fail-fast al startup: PubSubEventPublisher (gtm-proxy) verifica con TopicAdminClient.getTopic() que el topic existe antes de inicializar el publisher. Si no existe → el bean falla y el proxy no levanta.

Comunicación entre servicios