13 de junho de 2026 8 min

Diário de Dev #12 — Hardening de WebSockets, Bypass de Cloudflare na VPS e Visualização 3D com ClojureScript

Dev DiaryArk StreamsTechSentryGoClojureClojureScriptThree.js

Diário de Dev #12 — Hardening de WebSockets, Bypass de Cloudflare na VPS e Visualização 3D com ClojureScript

Período: 06 de Junho a 13 de Junho de 2026

Esta semana foi extremamente intensa em termos de infraestrutura, arquitetura de rede e interfaces interativas. Trabalhei em três frentes: estabilizei a captura de dados em tempo real da minha aplicação de trading, portei meus scrapers em Clojure para rodarem de forma autônoma em uma VPS contornando o Cloudflare, e criei uma visualização interativa tridimensional sobre ecossistemas Clojure.

Aqui está o relato técnico, as decisões tomadas e o que aprendi.


🌎 Segunda & Terça-Feira (08/06 - 09/06): A Recursão do Clojure Dialects Globe

Iniciei a semana construindo um novo projeto: o Clojure Dialects Globe. A tese é recursiva: construir uma visualização interativa sobre a versatilidade de compilação da linguagem Clojure, escrita em Clojure em todas as camadas da aplicação.

O objetivo é plotar 39 dialetos da linguagem Clojure em um globo terrestre 3D, posicionando o marcador geográfico no país de origem do criador do dialeto e definindo o tamanho do marcador proporcionalmente à sua quantidade de estrelas no GitHub.

A Arquitetura do Projeto (clj-dialects)

Para cobrir todo o espectro (scripts, backend, web e mobile), estruturei o projeto em 4 camadas:

  1. Babashka (Scripts): Script fetch_stars.bb que lê o arquivo de metadados (base.edn), consulta a API do GitHub e atualiza a contagem de estrelas de cada dialeto.
  2. Clojure JVM (API Backend): Um servidor web Jetty leve rodando na porta 3000, servindo as informações via Transit-JSON (um formato de transmissão mais otimizado que JSON bruto).
  3. ClojureScript + Three.js (Web Frontend): O motor tridimensional usando Three.js r175 sob Reagent (React para Clojure). Adicionei shaders GLSL customizados para a atmosfera da Terra, estrelas de fundo e renderização dinâmica dos sprites.
  4. ClojureDart + Flutter (Mobile): Protótipo estruturado para rodar a mesma interface tridimensional no mobile através do Flutter.

Desafio Técnico Superado: O Globo Azul sem Textura

Ao atualizar as bibliotecas do Three.js, a textura foto-realista da Terra (NASA) parou de carregar, exibindo apenas um globo azul genérico.

  • Causa: O Three.js r155+ alterou o tratamento de espaço de cores de texturas no canvas, exigindo a definição explícita do colorSpace para SRGBColorSpace.
  • Solução (ClojureScript):
    ;; Correção de espaço de cores no carregamento da textura
    (let [tex (.load (THREE/TextureLoader.) "textures/earth.jpg")]
      (aset tex "colorSpace" (.-SRGBColorSpace THREE))
      tex)
    

🛜 Quarta-Feira (10/06): Hardening de WebSockets e Ingestão com OKX

No meu projeto principal de trading, o ark-streams, enfrentei um problema invisível e clássico de engenharia de redes: conexões de WebSocket que travavam sem fechar ou disparar erros no Go, deixando a interface vazia de dados de mercado (empty streams).

A Causa: Ausência de Read Deadlines

Em conexões de longa duração, roteadores intermediários ou firewalls estaduais podem dropar a conexão de forma silenciosa (idle timeout). Se a sua aplicação não tenta ler ativamente com um tempo limite (ReadDeadline), a goroutine de leitura fica bloqueada indefinidamente no buffer TCP.

A Solução: ws_keepalive

Centralizei o ciclo de vida de conexão em um helper genérico ws_keepalive.go:

  • Configurei um timer de keepalive que redefine o ReadDeadline antes de enviar o ping correspondente.
  • Se o servidor falhar em retornar o pong correspondente ou dados novos dentro do intervalo de tolerância, a conexão é fechada ativamente pelo cliente e entra em ciclo de reconexão automática.
// ws_keepalive.go - Exemplo prático de enforcement
conn.SetReadDeadline(time.Now().Add(readDeadline))
conn.SetPongHandler(func(string) error {
    conn.SetReadDeadline(time.Now().Add(readDeadline))
    return nil
})

Ingestor: Migração forçada Binance → OKX

Como o servidor de produção roda nos EUA, a API da Binance retornava erro HTTP 451 (bloqueio geográfico). Migrei toda a captura de liquidações, contratos em aberto (OI) e taxas de captação (funding rate) para o WebSocket da OKX, adaptando os parsers e as suítes de teste.


🚀 Quinta-Feira (11/06): CI/CD, NATS Mirrors e deploy-vps.sh

Com a ingestão corrigida, automatizei o deploy. Substituí scripts baseados em systemd locais por uma imagem Docker enxuta e um pipeline completo de CI/CD:

  1. Compilação e Armazenamento: GitHub Actions compilam a imagem de Go + frontend Svelte e armazenam no repositório seguro GHCR (GitHub Container Registry).
  2. Deploy via Runner: Um runner self-hosted escuta por commits na master, executa deploy-vps.sh que limpa instâncias órfãs e recria os contêineres usando o docker-compose.
  3. NATS Overlap Fix: Configurei os streams históricos permanentes como mirrors de MARKET_DATA no JetStream, eliminando erros de colisão de subject overlap.

🛡️ Sexta-Feira (12/06): O Bypass de Cloudflare via Xvfb e Executor Quant

Na sexta-feira, dividi as atividades entre os dois projetos centrais.

Scrapers Clojure na VPS (techsentry) e a Batalha contra o Cloudflare

Queria rodar meus crawlers de preços de notebooks (OLX, AliExpress) da VPS Oracle. No entanto, o Cloudflare bloqueava acessos puros via HTTP/curl disparados por IPs conhecidos de datacenters.

  • A Descoberta: O Cloudflare bloqueia o fingerprint TLS de requests puros, mas tolera navegadores Chrome normais com interface ("headed") mesmo sob IPs de nuvem.
  • A Solução: Instalei o Chromium snap na VPS e o utilizei sob o comando xvfb-run -a (X Virtual Framebuffer), criando uma tela virtual na memória do Linux para que o Chromium rodasse pensando que tinha uma interface física de vídeo disponível.
  • O Cloudflare aceitou a navegação e permitiu a extração total de dados.
  • Sync Git: Corrigi um erro histórico na sincronização do repositório da VPS instalando chaves SSH exclusivas como Deploy Keys de leitura no GitHub.

O Executor Quant (Gate 3 Concluído)

Finalmente, finalizei o módulo do executor algorítmico automatizado no Go. Implementei o riskguard.go que atua como barreira entre o sinal recebido e o envio de ordens na Bitget:

  • Checks de Segurança: O sinal deve expirar se for mais velho que o candle correspondente (MAX_SIGNAL_AGE_MS); a corretagem para se o feed estiver sem updates por mais de 15 segundos (MAX_DATA_STALENESS_MS); e um circuit breaker local no banco de dados KV bloqueia novas operações se houver perda diária superior a 3%.

🛠️ Tecnologias, Conceitos e Conceitualização da Semana

Para facilitar a organização e indexação do meu blog, mapeei as principais tecnologias, padrões e metodologias que utilizei ativamente na prática esta semana:

1. Linguagens & Runtimes

  • Go (Golang): Implementação do executor de ordens e lógica concorrente do RiskGuard (canais, contexts e structs de controle).
  • Clojure (JVM & Babashka): Desenvolvimento de servidores de API REST e scripts Babashka (fetch_stars.bb) para enriquecimento rápido de dados do GitHub.
  • ClojureScript: Criação de WebGL interactives e controle reativo de estados de UI sob shadow-cljs e Reagent/React.
  • ClojureDart & Dart/Flutter: Estruturação multiplataforma para o aplicativo mobile e desktop do globo e especificações do Prompt-IDE.
  • Python: Desenvolvimento do script de Walk-Forward Analysis (walkforward.py) para simulação e teste out-of-sample das otimizações das estratégias.

2. Infraestrutura, Redes & DevOps

  • NATS JetStream (e KV Store): Utilização de streams persistentes duráveis para o track record de ordens, mirrors para replicação estável, e a Key-Value Store nativa do NATS para controle de estado e kill-switch resiliente a restarts.
  • Docker & Docker Compose: Criação de contêineres e otimização de contextos de compilação via cache de layers e arquivos .dockerignore.
  • CI/CD Automático: Configuração de GitHub Actions (publicando imagens no GHCR) e automatização de deploys contínuos em um runner self-hosted na VPS.
  • Oracle Cloud Infrastructure (OCI): Utilização de VPS ARM de alta performance para execução dos robôs e extração distribuída.
  • Virtual Framebuffer (Xvfb): Emulação gráfica na memória RAM do Linux para execução de navegadores gráficos sem monitor físico (xvfb-run -a).

3. Engenharia de Redes & Concorrência

  • Bypass de Cloudflare: Estudo de assinaturas e fingerprints de TLS/HTTP, migrando de requisições cruas HTTP para instâncias Chromium headed sob Xvfb.
  • Controle de Timeout TCP: Implementação de ReadDeadline e WriteDeadline no pacote de sockets do Go para prevenir timeouts ocultos e sockets zumbis.
  • Idempotência em 3 Camadas: Garantia contra re-entrega de eventos por meio de hashes determinísticos, logs locais em KV e IDs determinísticos na Bitget (ClientOID).
  • Garantias de Entrega: Lógica At-Least-Once no JetStream exigindo Acks explícitos das mensagens consumidas.

4. Finanças Quantitativas

  • Indicadores Técnicos (Alligator, MFI, ATR, BB Squeeze, Awesome Oscillator): Implementação de algoritmos matemáticos para sinalização e tomada de decisões.
  • Walk-Forward Analysis (WFA): Metodologia de validação rolling de estratégias de trading com divisão rígida in-sample/out-of-sample.

📜 Registro Completo de Commits (Histórico Git da Semana)

Para manter a fidelidade e o registro dos dados reais do blog, aqui está o log exato de todos os commits realizados durante a semana nos três repositórios principais:

1. Repositório: ark-streams

  • ec2e61c - feat(executor): Gate 3 completo — executor automatizado com shadow mode e documentação de fusão.
  • cd5836c - fix(docker): exclude go.work from build context — remove referências ao nexus-desktop no contexto de build do contêiner.
  • 54890ec - perf(docker): cache Go deps separately — cache de dependências em layer separada para acelerar compilações Docker.
  • af9674f - fix(cicd): remove LIQUIDATIONS from smoke test — correção de teste de fumaça dependente de mercado para mirror streams.
  • 88699b0 - fix(cicd): opt into Node.js 24 for GitHub Actions — migração preventiva do workflow do Node.js.
  • 0a0f06e - feat(cicd): full CI/CD pipeline — setup de GitHub Actions, publicação de imagem no GHCR e CD via runner self-hosted na VPS.
  • 0ac7555 - docs(ops): track bastion-connect.sh — documentação de SSH bastion e tunnel setup.
  • 17edef7 - fix(deploy): replace broken systemd deploy — migração para deploy dockerizado automático via script deploy-vps.sh.
  • 9146c8c - ui: overhaul high-contrast theme — remodelagem visual de alto contraste no Svelte e fix de mark price.
  • b06fc49 - fix(analysis): compact AggressorEngine checkpoint — compactação de serialização para respeitar o payload máximo do NATS JetStream.
  • b8989be - fix(streams): create archive streams as mirrors — resolução de subject overlaps de streams históricos de market data.
  • b6d45d2 - fix(collector): enforce read deadlines + heartbeat — aplicação de keepalives e limites temporais em WebSockets.
  • 0e86028 - fix(collector): use Bitget's literal "ping" — correção de heartbeat específico do WS Bitget.
  • 051cb9c - feat(collector): replace Binance funding/OI/aggtrade feeds with OKX — novos coletores OKX.
  • d2e2232 - feat(collector): replace Binance liquidation feed with OKX — novo parser de liquidações OKX.
  • 1501742 - fix(nexus-desktop): local timezone + expand history to 7d — melhorias visuais de exibição de histórico.
  • 12ff5a9 - feat(nexus-desktop): portrait monitor layout — suporte a split vertical para monitores em formato retrato.

2. Repositório: techsentry (TechSentry)

  • 4774a020 - feat: iPhone enrich no ciclo da VPS — nova flag --enrich-iphones para enriquecimento de dados de busca.
  • 90ace35d - feat: modo --gc no jar — ativação de Garbage Collector programático de Datahike no jar de produção.
  • 8461b249 - chore: scripts de diagnóstico e GC — limpeza e indexação interna do banco Datahike.
  • 65551359 - fix: scan-vps.sh usa TECHSENTRY_DB_PATH relativo — caminho do banco de dados ajustado para portabilidade.
  • dfbd7bfc - fix: scan-vps.sh garante /usr/local/bin no PATH — ajuste para consistência do cron daemon na VPS.
  • 128ccaec - fix: scan-vps.sh sem --clobber no release download — compatibilidade com a CLI do GitHub v2.4.0.
  • 5bd16741 - feat: CI/CD com VPS como runner de scan via uberjar — automação completa do ciclo de execução remota de jars.
  • e60737be - Merge branch 'feat/vectra-monitor' — consolidação do monitoramento de ofertas.
  • ec3aa9da - chore: scripts de diagnóstico CDP/cookie OLX — validação de controle do browser real.
  • d31a3eb0 - feat: OLX enricher com Chrome real não-headless — bypass de bloqueios Cloudflare.
  • 3f3b47ef - docs: sync VPS↔GitHub resolvido — setup e deploy de chaves Deploy Keys e sonda OLX versionada.
  • 066f51d3 - docs: relatório da missão de scraping na VPS nexus — documentação inicial da infraestrutura de crawls na VPS.

3. Repositório: clj-dialects (Clojure Dialects Globe)

  • 4b086ec - feat(flutter): minimal working app — aplicativo ClojureDart integrado para busca e consumo de estado da API.
  • e9a7cab - chore(ci): setup stable github pages deployment — automação de deploy estático do globo web no GitHub Pages.
  • f1c4ce0 - feat(mobile): ClojureDart Flutter implementation — código base mobile Dart/Clojure.
  • cf7fbbb - feat(web): implement 3d globe visualization using Three.js — o motor tridimensional WebGL do globo.
  • 1ae9dab - chore: initial project structure — setup de dependências e banco de dados de dialetos base.edn.

💡 Lições da Semana

  1. Navegadores Headed no Linux Headless: Usar xvfb-run com Chromium configurado para evitar detecção de automação (AutomationControlled desativado) é a tática definitiva para crawlers rodarem em VPS sem sofrer bloqueio automático.
  2. Network timeouts são obrigatórios: Nunca confie em conexões TCP persistentes sem implementar explicitamente keepalives e read-deadlines a nível de aplicação.
  3. Immutabilidade de Sinais: Construir o executor baseado em idempotência de hashes determinísticos (SignalID = strategy-symbol-tf-time-action) garante que mesmo em caso de crash e re-entrega de eventos (at-least-once do JetStream), o robô nunca executará a mesma ordem duas vezes.

📅 Próxima Semana

  • Executar os testes em modo sombra (Shadow Mode) na VPS por pelo menos 14 dias para mapear latência de sinal e desvios de PnL por drift de preços.
  • Acompanhar os logs cron de extração do OLX via Chromium sob display virtual na VPS.
  • Melhorar o filtro e busca de ecossistemas na visualização 3D de dialetos do Clojure.