// por dentro
Como foi construído
O doknyu é um binário Rust (edition 2024, MSRV 1.89) com interface em iced 0.14, que segue a Elm architecture: um estado único (`App`), mensagens tipadas, `update` que devolve `Task`s assíncronas e `subscription` para fluxos contínuos (eventos do Docker, logs, estatísticas). Toda a comunicação com o daemon passa por um trait `DockerClient` (async-trait) com duas implementações: a real, sobre bollard 0.21 e Tokio, e um `FakeClient` em memória, ativado pela feature `fake`, que permite rodar e testar a UI sem Docker. O núcleo (buffer de logs, cálculo de estatísticas, busca fuzzy, mapa de teclas, detecção de sandbox) é Rust puro, sem dependência de UI, o que deixa a maior parte da lógica coberta por testes unitários.
- Linguagem
- Rust (edition 2024, MSRV 1.89)
- UI
- iced 0.14 (Elm architecture, canvas para os gráficos)fontes IBM Plex e ícones Lucide
- Docker
- bollard 0.21 sobre Tokio 1 (async-trait, futures)
- Terminal embutido
- iced_term 0.8 (alacritty_terminal) + ponte de exec própria com rustix
- i18n
- rust-i18n 4 + sys-locale (pt-BR e en)
- Erros e logs
- thiserror 2anyhowtracing
- Empacotamento
- cargo-debAppImage (linuxdeploy)FlatpakAUR (doknyu, -bin, -git)RPM/COPR e Nix flake
- Qualidade
- cargo fmtclippy com -D warningstestes unitários e de integração com Docker realjob de MSRV no GitHub Actions
Arquitetura
Cliente Docker atrás de um trait, com fake para testes
A UI só conhece o trait `DockerClient`; a implementação real usa bollard e a `FakeClient` simula containers, eventos, logs e estatísticas em memória. Com isso o app roda com `cargo run --features fake`, os testes exercitam o `App::update` de ponta a ponta e os prints do site saem com dados de exemplo, sem expor nada da máquina.
Concorrência
Eventos do Docker com debounce e backoff exponencial
A lista não fica fazendo polling: o app assina o stream de eventos do daemon e recarrega containers, volumes ou redes só quando algo muda, agrupando rajadas numa janela de 300 ms. Se o stream cai, espera de 1 s a 30 s (dobrando a cada falha) antes de checar o daemon de novo, e um stream que ficou saudável zera o backoff.
Arquitetura
Terminal no container sem depender da CLI do Docker
A ADR 0001 mostra, lendo o código do iced_term 0.8, que ele só aceita um processo filho com PTY. A solução foi o próprio binário virar uma ponte (`doknyu --exec-bridge <container>`): coloca o terminal em modo raw com rustix, abre um exec com TTY pela API do Docker e repassa o redimensionamento. Funciona igual na aba embutida, no terminal do sistema e dentro do sandbox do Flatpak, onde não existe a CLI `docker`.
Performance
Logs e métricas com memória limitada
O buffer de logs guarda no máximo 10 mil linhas, remove sequências ANSI, decodifica UTF-8 com perdas e trunca linhas gigantes. As estatísticas mantêm uma janela móvel de amostras por segundo e tratam contadores que voltam para trás (container reiniciado) sem gerar NaN nem picos falsos.
Testes
Testes em várias camadas
Há centenas de testes: unitários no núcleo puro, testes da UI que executam as `Task`s do `update` com iced_runtime, fixtures JSON reais da API do Docker e testes de integração (`--ignored`) que sobem containers de verdade no CI. Um teste também confere que en.yml e pt-BR.yml têm as mesmas chaves e que não há texto de interface fixo no código.
DevOps
Release reprodutível e verificada no CI
Uma tag `v*` dispara o build no Ubuntu 22.04 (glibc 2.35, para rodar em distros mais novas), confere se a tag bate com a versão do Cargo.toml e do metainfo, gera .deb e AppImage, faz um teste de fumaça que extrai o AppImage e procura bibliotecas faltando com ldd, e publica com SHA256SUMS. As actions são fixadas por SHA e o manifesto do Flatpak tem o commit da tag conferido automaticamente.