Skip to content

fix(swarm): add evo-flow, ClickHouse and RabbitMQ to the deploy stack - #163

Merged
gomessguii merged 1 commit into
developfrom
fix/swarm-stack-evoflow-segments
Jul 14, 2026
Merged

fix(swarm): add evo-flow, ClickHouse and RabbitMQ to the deploy stack#163
gomessguii merged 1 commit into
developfrom
fix/swarm-stack-evoflow-segments

Conversation

@gomessguii

@gomessguii gomessguii commented Jul 14, 2026

Copy link
Copy Markdown
Member

Problema

/settings/segments responde 500 (INTERNAL_ERROR) em qualquer ambiente subido a partir deste stack.

A tela é um proxy: o CRM recebe GET /api/v1/segments e repassa ao evo-flow via EvoFlow::Client. Só que o docker-compose.swarm.yaml nunca declarou o serviço evo-flow, nem as variáveis que o client precisa. Sem AUTH_APIKEY_INTEGRATION_LOCAL, o CRM levanta EvoFlow::ConfigurationError já na construção do client (app/services/evo_flow/client.rb:99), antes de qualquer chamada de rede — o controller só faz rescue EvoFlow::HTTPError, então a exceção escapa e vira 500 opaco.

Diagnosticado no staging (evo_crm_test), onde nenhum dos três serviços existia:

ERROR -- : Internal Server Error: EvoFlow::ConfigurationError - AUTH_APIKEY_INTEGRATION_LOCAL is not set
  /app/app/services/evo_flow/client.rb:99:in 'EvoFlow::Client#validate_config!'
  /app/app/controllers/api/v1/evo_flow/segments_controller.rb:92:in 'Class#new'
  /app/app/controllers/api/v1/evo_flow/segments_controller.rb:28:in '#index'

O que muda

3 serviços novos. O evo-flow não sobe sozinho:

  • evocrm_evoflow — porta 3334 (a porta do projeto, conforme o .env.example do evo-flow). Usa um Postgres dedicado (evo_campaign), criado no boot junto com as migrations; o banco do CRM não é tocado.
  • evocrm_clickhouse — exigido por STORAGE_MODE=clickhouse. O evo-flow cria database e tabelas sozinho.
  • evocrm_rabbitmq — o BrokerModule aborta o boot se BROKER_TYPE não estiver setado, mesmo com QUEUE_MODE=direct. Usuário dedicado porque o guest do RabbitMQ recusa conexão remota.

4 envs em evocrm_crm e evocrm_crm_sidekiq:

EVO_FLOW_ENABLED=true
EVO_FLOW_API_URL=http://evocrm_evoflow:3334/api/v1
AUTH_APIKEY_INTEGRATION_LOCAL=    # vazio no template; mesmo valor nos 3 serviços
EVO_FLOW_ALLOW_INSECURE=true

EVO_FLOW_ALLOW_INSECURE não é opcional aqui: o stack roda RAILS_ENV=production sobre uma URL http:// interna, e sem a flag o client se recusa a mandar a chave em cleartext — ou seja, o 500 voltaria mesmo com todo o resto cabeado.

Mais: 2 volumes (evocrm_clickhouse_data, evocrm_rabbitmq_data) e o cabeçalho de segredos do arquivo atualizado com os 3 novos.

Segredos ficam vazios, seguindo a convenção do template (# Ex.: gere com "openssl rand -hex 32").

Validação

Aplicado no staging (evo_crm_test) antes de virar commit. Os 3 serviços subiram, o evo-flow criou o evo_campaign no Postgres, rodou as migrations e criou as 16 tabelas no ClickHouse. O caminho que estava 500 agora responde 200:

CRM → evo-flow (mesmo client do SegmentsController):
OK: {"success" => true, "data" => {"segments" => [], "total" => 0, "page" => 1, "limit" => 20}}

Tela confirmada funcionando no browser.

Fora de escopo (ficam abertos)

  • EvoFlow::ConfigurationError não tratada no SegmentsController → misconfig continua virando 500 opaco em vez de 503 legível. É outro repo (evo-ai-crm-community), PR separada.
  • CRM assume porta 3000 (EvoFlow::Client::DEFAULT_API_URL e .env.example:275), divergindo do 3334 do evo-flow. Mesma PR do item acima.
  • evo-flow-community:develop está congelada em 04/jul — o evo-flow não aparece em nenhum workflow de publish do umbrella (só no release.yml, que roda em tag). Mesmo padrão do EVO-1998.
  • Journey triggers no staging apontam para um Kafka inexistente (localhost:9092, pois KAFKA_BROKERS_INTERNAL não está setada). Não afeta Segments (QUEUE_MODE=direct).

Summary by Sourcery

Add EvoFlow and its required infrastructure services to the swarm stack so the CRM Segments feature works in swarm-based environments.

New Features:

  • Introduce evo-flow service (evocrm_evoflow) to serve segments and event tracking behind the CRM.
  • Add dedicated ClickHouse service as evo-flow event storage backend.
  • Add dedicated RabbitMQ service as evo-flow message broker.

Enhancements:

  • Wire CRM and Sidekiq services to evo-flow via new environment variables, including API URL, shared auth key, and insecure-HTTP allowance.
  • Define persistent volumes for ClickHouse and RabbitMQ data within the swarm stack.
  • Document new secrets and configuration required for evo-flow, ClickHouse, and RabbitMQ in the swarm compose file.

The Segments screen proxies /api/v1/segments through the CRM to evo-flow, but
the swarm stack never declared the service — nor the four env vars the CRM
client needs. Without AUTH_APIKEY_INTEGRATION_LOCAL the CRM raises
EvoFlow::ConfigurationError while building the client, before any network call,
so every segments endpoint answers 500.

evo-flow cannot boot alone: it requires ClickHouse (STORAGE_MODE=clickhouse) and
a broker (BrokerModule aborts when BROKER_TYPE is unset, even with
QUEUE_MODE=direct), plus a dedicated Postgres database it creates on boot.

EVO_FLOW_ALLOW_INSECURE is set because the stack runs RAILS_ENV=production over
an internal http:// URL, which the client otherwise refuses.

Secrets stay empty, following the template convention.
@sourcery-ai

sourcery-ai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds evo-flow and its required infrastructure (ClickHouse, RabbitMQ, env vars, volumes, and secrets) to the swarm stack so that /settings/segments works correctly in swarm deployments.

File-Level Changes

Change Details Files
Wire evo-flow into the swarm stack alongside required ClickHouse and RabbitMQ services and configuration.
  • Add EVO_FLOW_* and AUTH_APIKEY_INTEGRATION_LOCAL environment variables to crm and crm_sidekiq services so EvoFlow::Client can be configured in swarm deployments.
  • Introduce evocrm_clickhouse service with credentials, internal networking, and persistent volume to back evo-flow event storage in ClickHouse.
  • Introduce evocrm_rabbitmq service with dedicated user, password, internal networking, and persistent volume to satisfy evo-flow broker requirements.
  • Add evocrm_evoflow service (NestJS) configured for single-node mode with ClickHouse storage, RabbitMQ broker, dedicated Postgres database (evo_campaign), and Redis cache, including a shell entrypoint that waits for ClickHouse, creates the database, runs migrations, then boots the app.
  • Extend swarm volumes and secrets documentation/comments with AUTH_APIKEY_INTEGRATION_LOCAL, CLICKHOUSE_PASSWORD, and RABBITMQ_DEFAULT_PASS, and declare new ClickHouse and RabbitMQ data volumes.
docker-compose.swarm.yaml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • Consider pinning the service images (clickhouse/clickhouse-server:latest, rabbitmq:3-alpine, evoapicloud/evo-flow-community:develop) to explicit versions/tags to avoid unexpected behavior when base images are updated.
  • The RABBITMQ_URL currently embeds the password as a literal placeholder string; it would be more robust to compose this from environment variables or secrets to avoid duplicating the password in multiple places and reduce the chance of configuration drift.
  • The multi-line shell in evocrm_evoflow’s command (ClickHouse wait, DB create, migrations) is quite dense; consider extracting this bootstrapping logic into a script or entrypoint to make it easier to maintain and reason about failures.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider pinning the service images (clickhouse/clickhouse-server:latest, rabbitmq:3-alpine, evoapicloud/evo-flow-community:develop) to explicit versions/tags to avoid unexpected behavior when base images are updated.
- The RABBITMQ_URL currently embeds the password as a literal placeholder string; it would be more robust to compose this from environment variables or secrets to avoid duplicating the password in multiple places and reduce the chance of configuration drift.
- The multi-line shell in evocrm_evoflow’s command (ClickHouse wait, DB create, migrations) is quite dense; consider extracting this bootstrapping logic into a script or entrypoint to make it easier to maintain and reason about failures.

## Individual Comments

### Comment 1
<location path="docker-compose.swarm.yaml" line_range="614" />
<code_context>
+      - |
+        until node -e 'require("http").get("http://evocrm_clickhouse:8123/ping",r=>process.exit(r.statusCode===200?0:1)).on("error",()=>process.exit(1))'; do echo 'Waiting for clickhouse...'; sleep 5; done
+        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)"
+        exec node dist/main.js
+
</code_context>
<issue_to_address>
**issue (bug_risk):** Failing to run migrations should probably stop the container instead of being ignored

Letting `typeorm migration:run` fail but still starting the app means it can run against an outdated or partially applied schema, leading to subtle runtime errors. Consider making migration failure cause a non‑zero exit (or only calling `exec node dist/main.js` when migrations succeed) and rely on orchestration to restart the container.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread docker-compose.swarm.yaml
- |
until node -e 'require("http").get("http://evocrm_clickhouse:8123/ping",r=>process.exit(r.statusCode===200?0:1)).on("error",()=>process.exit(1))'; do echo 'Waiting for clickhouse...'; sleep 5; done
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)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): Failing to run migrations should probably stop the container instead of being ignored

Letting typeorm migration:run fail but still starting the app means it can run against an outdated or partially applied schema, leading to subtle runtime errors. Consider making migration failure cause a non‑zero exit (or only calling exec node dist/main.js when migrations succeed) and rely on orchestration to restart the container.

@gomessguii
gomessguii merged commit 1b512f3 into develop Jul 14, 2026
5 checks passed
@gomessguii
gomessguii deleted the fix/swarm-stack-evoflow-segments branch July 14, 2026 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant