Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,20 @@ ENABLE_INBOX_EVENTS=true
FB_VERIFY_TOKEN=evolution
FACEBOOK_API_VERSION=v23.0

# =============================================================================
# EVO-FLOW (histórico / tracking de eventos do contato) — Port 3334
# =============================================================================
# Liga os listeners EvoFlow no CRM (sem isso eles viram no-op e nenhum evento sai)
# e configura o proxy de leitura (GET /api/v1/contacts/:id/events).
# Sobe com: docker compose -f docker-compose.yml -f docker-compose.evoflow.yaml up -d
EVO_FLOW_ENABLED=true
EVO_FLOW_API_URL=http://evo-flow:3334/api/v1
# Chave de serviço (header X-Integration-API-Key) — DEVE ser igual no container
# evo-flow (o docker-compose.evoflow.yaml lê esta mesma variável).
AUTH_APIKEY_INTEGRATION_LOCAL=evoflow-dev-key
# Permite http cleartext em dev (o evo-flow recusaria o key sobre http em prod).
EVO_FLOW_ALLOW_INSECURE=true

# =============================================================================
# CORE SERVICE (evo-ai-core-service-community) — Port 5555
# =============================================================================
Expand Down
102 changes: 102 additions & 0 deletions docker-compose.evoflow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Override que adiciona evo-flow + ClickHouse ao MESMO projeto/rede do
# docker-compose.yml principal (rede default `evo-crm-community_default`),
# para que o container evo-crm alcance http://evo-flow:3334 por hostname.
#
# PRÉ-REQUISITO: o evo-flow NÃO é submódulo deste umbrella (removido nos
# rc4/rc5) e o diretório ./evo-flow é gitignored. O serviço evo-flow abaixo
# builda de `context: ./evo-flow`, então num clone fresco esse path não
# existe — é preciso cloná-lo na raiz do umbrella antes de subir:
# git clone https://github.com/evolution-foundation/evo-flow.git ./evo-flow
#
# Uso:
# git clone https://github.com/evolution-foundation/evo-flow.git ./evo-flow # só na 1ª vez
# docker compose -f docker-compose.yml -f docker-compose.evoflow.yaml up -d --build clickhouse evo-flow
#
# Modo mínimo de boot (sem Kafka/Temporal): RUN_MODE=api + QUEUE_MODE=direct +
# WRITE_MODE=ch-sync + STORAGE_MODE=clickhouse. Serve a API de eventos (write
# síncrono direto no ClickHouse) e a leitura GET /contacts/:id/events.
services:
clickhouse:
image: clickhouse/clickhouse-server:latest
restart: unless-stopped
ports:
- "8123:8123"
- "9000:9000"
environment:
CLICKHOUSE_USER: default
CLICKHOUSE_PASSWORD: password
CLICKHOUSE_DB: default
volumes:
- clickhouse_data:/var/lib/clickhouse
ulimits:
nofile:
soft: 262144
hard: 262144
healthcheck:
test: ["CMD", "clickhouse-client", "--user", "default", "--password", "password", "--query", "SELECT 1"]
interval: 10s
timeout: 5s
retries: 10
start_period: 20s

evo-flow:
build:
context: ./evo-flow
dockerfile: Dockerfile
restart: unless-stopped
ports:
- "3334:3334"
# Recorrência: o banco Postgres do evo-flow é DEDICADO (evo_campaign) — NÃO
# compartilha o evo_community do CRM (as migrations do evo-flow criam tabelas
# contacts/labels/custom_attribute_definitions que colidiriam com o Chatwoot;
# o evo-flow lê o CRM via HTTP, não via Postgres). Como o evo-flow não tem
# passo oficial de db:create, este command cria o DB se faltar + roda as
# migrations (idempotente) + sobe a app — sem nenhum passo manual.
command:
- sh
- -c
- |
node -e 'const{Client}=require("pg");const db=process.env.POSTGRES_DB_DATABASE;const c=new Client({host:process.env.POSTGRES_DB_HOST,port:+(process.env.POSTGRES_DB_PORT||5432),user:process.env.POSTGRES_DB_USERNAME,password:process.env.POSTGRES_DB_PASSWORD,database:"postgres"});c.connect().then(()=>c.query("CREATE DATABASE "+db)).then(()=>console.log("[init] created "+db)).catch(e=>console.log("[init] "+(e.code==="42P04"?"db already exists":e.message))).finally(()=>c.end());'
node_modules/.bin/typeorm migration:run -d dist/database/ormconfig.js || echo "[init] migration:run failed (continuing)"
Comment on lines +59 to +60

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Inline Node DB bootstrap script is hard to maintain and lacks failure signaling.

The node -e database creation command is difficult to read, test, and debug, and migration:run failures are deliberately ignored, so the container can appear healthy with an incomplete schema. Consider moving this logic into a dedicated JS/TS bootstrap file in the repo and calling it here, and decide whether migration failures should instead cause the container to exit so misconfigurations fail fast.

Suggested implementation:

    # Recorrência: o banco Postgres do evo-flow é DEDICADO (evo_campaign) — NÃO
    # compartilha o evo_community do CRM (as migrations do evo-flow criam tabelas
    # contacts/labels/custom_attribute_definitions que colidiriam com o Chatwoot;
    # o evo-flow lê o CRM via HTTP, não via Postgres). Como o evo-flow não tem
    # passo oficial de db:create, o script bootstrap cuida de:
    # - criar o DB se faltar
    # - rodar as migrations (idempotente)
    # - subir a app
    # Se as migrations falharem, o container sai com erro para que a má
    # configuração seja detectada rapidamente.
    command:
      - sh
      - -c
      - |
        set -e
        node dist/bootstrap.js

      CLICKHOUSE_PASSWORD: password
      CLICKHOUSE_DB: default

To fully implement your suggestion, the repository also needs a dedicated bootstrap script (e.g. src/bootstrap.ts compiled to dist/bootstrap.js) that encapsulates the previous inline behavior and exits non-zero on migration failure. For example, it should:

  1. Use pg to connect to the Postgres server, create the target database if it does not exist, and log informative messages.
  2. Run typeorm migration:run -d dist/database/ormconfig.js (via child_process.spawn/exec) and propagate any non-zero exit code.
  3. Start the application (e.g. require('./main'); or import('./main');) only if the above steps succeed.
    Also ensure the Docker build produces dist/bootstrap.js and that the working directory in the container is where dist/ is located so node dist/bootstrap.js resolves correctly.

exec node dist/main.js
environment:
NODE_ENV: development
# api + QUEUE_MODE=direct: UM container só. api serve a HTTP (leitura +
# ingestão) e o DirectQueueProcessor grava DIRETO no ClickHouse na própria
# request (sem fila/broker, sem worker/consumer). 'direct' foi adicionado
# ao QueueProcessorFactory (antes era um gap). 'single' travaria o HTTP na
# Journey Trigger Queue (Kafka); 'api' não trava.
RUN_MODE: api
QUEUE_MODE: direct
STORAGE_MODE: clickhouse
WRITE_MODE: ch-sync
PORT: "3334"
# Auth de serviço — MESMO valor que AUTH_APIKEY_INTEGRATION_LOCAL no .env do CRM
AUTH_APIKEY_INTEGRATION_LOCAL: ${AUTH_APIKEY_INTEGRATION_LOCAL:-evoflow-dev-key}
EVO_AUTH_SERVICE_URL: http://evo-auth:3001
EVO_AUTH_VALIDATE_TOKEN_ENDPOINT: /api/v1/auth/validate
# ClickHouse (mesmo container desta override)
CLICKHOUSE_HOST: clickhouse
CLICKHOUSE_PORT: "8123"
CLICKHOUSE_DATABASE: evo_campaign
CLICKHOUSE_USERNAME: default
CLICKHOUSE_PASSWORD: password
CLICKHOUSE_TABLE: contact_events
# Postgres (TypeORM conecta no boot — usa o postgres compartilhado, DB evo_campaign)
POSTGRES_DB_HOST: postgres
POSTGRES_DB_PORT: "5432"
POSTGRES_DB_USERNAME: ${POSTGRES_USERNAME:-postgres}
POSTGRES_DB_PASSWORD: ${POSTGRES_PASSWORD:-evoai_dev_password}
POSTGRES_DB_DATABASE: evo_campaign
# CRM client (enriquecimento / chamadas reversas)
EVOAI_CRM_BASE_URL: http://evo-crm:3000
EVOAI_CRM_API_TOKEN: ${EVOAI_CRM_API_TOKEN:-6e10e689-58ce-4416-bf0d-f5818bf2dcf8}
LOG_LEVEL: log
depends_on:
clickhouse:
condition: service_healthy
postgres:
condition: service_healthy

volumes:
clickhouse_data:
Loading