Compilando e executando com recursos da máquina
Você pode compilar os módulos do sistema individualmente e executá-los usando o próprio ambiente Rust.
Introdução
Este artigo trata da situação mais comum durante o desenvolvimento das partes do sistema, que envolve utilizá-las individualmente em um ambiente de desenvolvimento.
O deploy usando Docker Compose e Kubernetes, enquanto possível em ambiente de homologação e de testes manuais, utiliza muitos recursos da máquina, e não é o ideal de ser utilizado enquanto o programador estiver debugando a aplicação. Além disso, pela própria forma como o sistema foi planejado, é possível executar porções individuais do sistema em que haja interdependência entre elas.
Objetivo
Compilar todos os módulos ou módulos individuais é muito importante do ponto de vista do desenvolvimento. Neste artigo, tratamos de como isso pode ser feito na máquina local de um desenvolvedor.
Dependências
Você precisará de:
- Rust (compilador
rustc
e gerenciador de pacotescargo
, versão 1.60.0 ou superior); - Diesel (versão 1.4.1 ou superior, com suporte a PostgreSQL);
- Flutter (versão 3.0.0 ou superior, canal
stable
. Apenas necessário o target de compilação paraweb
); - Dart (versão 2.17.0 ou superior, canal
stable
); - Docker (versão 2.10 ou superior).
O compilador Rust e o Docker são essenciais para compilar os módulos individuais do back-end do projeto, enquanto o Flutter é importante para a confecção do front-end da aplicação. Sendo assim, as dependências podem ser instaladas de acordo com o bom-senso do desenvolvedor.
O Diesel pode ser instalado através do gerenciador de pacotes cargo
,
e sua instalação pode ser consultada em seu site, linkado acima. Além
disso, a linguagem Dart será instalada através do Flutter, de acordo
com as instruções que podem ser encontradas no site do mesmo.
Estrutura do projeto
O repositório do projeto é um monorepo, isto é, engloba todas as
partes do sistema inteiro. Por isso, as partes relacionadas a back-end
estão dispostas em um Workspace, configurável através das próprias
ferramentas do cargo
e da linguagem Rust, enquanto o front-end
encontra-se unicamente no diretório minerva_frontend
, e não faz
parte do Workspace em si.
Preparação do ambiente
A primeira parte a ser executada deverá ser a preparação do ambiente. Isso inclui a preparação de quaisquer serviços ou bancos de dados externos que possam ser importantes para a execução da aplicação.
No Sistema Minerva, o serviço RUNONCE
é responsável por executar
essas operações, sendo também o serviço que executa migrations no
banco de dados, por exemplo.
Para tanto, precisaremos compilar este módulo específico antes de qualquer outro. Isso será melhor delineado na seção sobre compilação do back-end, mas realizaremos uma configuração rápida nesta seção.
Criando recursos locais com Docker
Para executar localmente, o sistema precisa que alguns serviços sejam instanciados antes de sua execução.
É importante lembrar que os métodos a seguir não são considerados seguros para persistência de dados. Por isso, use-os apenas com a finalidade de testes.
Usando recursos por meio externo (Kubernetes)
Caso você não queira executar os serviços essenciais
mais pesados em termos de recursos (PostgreSQL, MongoDB, Redis e
RabbitMQ), poderá reaproveitá-los caso tenha realizado deploy dos
mesmos em Kubernetes. Para tanto, você poderá usar um script
preparado que realiza esse processo. Veja que esse script assume
que você possua a ferramenta kubectl
com acesso padrão configurado
para o cluster que seja seu target.
O script encontra-se excepcionalmente em helpers/port-forwards.sh
,
na raiz do projeto.
Banco de dados relacional
Como primeira dependência, recomenda-se criar o banco de dados relacional via Docker. Também seria possível instalar o PostgreSQL 15 na máquina local, mas o Docker provê a comodidade necessária para o BD.
Para subir o banco de dados relacional, execute o script make_postgres_db.sh
no diretório minerva-runonce
, ou execute:
docker run --name minerva-postgres \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-p 5432:5432 \
-d postgres:15-alpine
O contêiner poderá então ser gerenciado através do Docker, como um contêiner qualquer.
Banco de dados não-relacional
Recomenda-se também criar o banco de dados não-relacional via Docker. Igualmente, é possível instalar o MongoDB 4 por métodos convencionais.
Veja que o MongoDB é usado aqui em sua versão 4 especialmente por ser mais compatível com ambientes IoT, em especial K3s executando em um Raspberry Pi 4 Model B, que foi utilizado para testar o deploy em um cluster Kubernetes.
Para subir o banco de dados não-relacional, execute o script
make_mongo_db.sh
no diretório minerva-runonce
, ou execute:
docker run --name minerva-mongo \
-e MONGO_INITDB_ROOT_USERNAME=root \
-e MONGO_INITDB_ROOT_PASSWORD=mongo \
-p 27017:27017 \
-d mongo:4
Como esperado, o contêiner pode ser gerenciado normalmente através do Docker.
Banco de dados in-memory (cache)
Para o uso do serviço de cache, recomenda-se usar diretamente o Redis através
do Docker. Para tanto, execute o script make_redis_db.sh
no diretório
minerva-runonce
, ou execute:
docker run --name minerva-redis \
-p 6379:6379 \
-d redis:7-alpine
Assim como antes, gerencie o contêiner criado usando o Docker.
Broker de mensagens (com gerenciador)
O message broker RabbitMQ deverá também ser executado através do Docker. Para a execução do mesmo, todavia, atente-se para o uso de memória elevado que essa ferramenta possui.
Você poderá executar o script make_rabbitmq.sh
no diretório
minerva_runonce
, ou simplesmente executar:
docker run --name minerva-rabbitmq \
-e RABBITMQ_DEFAULT_USER=rabbitmq \
-e RABBITMQ_DEFAULT_PASS=minerva \
-p 15672:15672 \
-p 5672:5672 \
-d rabbitmq:3-management-alpine
Executando configuração inicial (módulo RUNONCE
)
A seguir, execute o módulo RUNONCE
para preparar todos os bancos de
dados de tenants, executar as migrations, criar o usuário admin
em cada banco e outras operações em outros serviços também.
Você poderá executar o módulo diretamente a partir da raiz do projeto:
cargo run --bin minerva-runonce
Caso haja algum problema com o comando anterior (por exemplo, se o
módulo não encontrar o diretório migrations
), vá para o diretório do
módulo e execute-o:
cd minerva-runonce
cargo run
Após a compilação do módulo RUNONCE
, o mesmo aguardará o banco de
dados estar pronto para receber as conexões e aplicará as migrations.
Compilação (Back-end)
Você poderá compilar todos os módulos do projeto de uma só vez, ou compilar apenas os módulos necessários.
Compilando todos os módulos
Para compilar todos os módulos, vá para a raiz do projeto e execute um comando de compilação para todo o workspace:
cargo build
De forma similar, você poderá compilar o projeto para produção através
da flag --release
:
cargo build --release
Compilando um módulo específico
Existem duas formas de compilar um módulo específico: a partir do workspace (diretório raiz do repositório) ou a partir do diretório do módulo específico.
Qualquer módulo pode ser compilado a partir do diretório raiz com um
comando como o mostrado a seguir (substitua <módulo>
pelo nome do
diretório do módulo em questão):
cargo build --bin <módulo>
Isto compilará qualquer módulo que faça parte do workspace, exceto
bibliotecas auxiliares (como minerva-rpc
, minerva-data
e
minerva-cache
) e o front-end (contido em minerva_frontend
).
Da mesma forma, você também poderá ir ao diretório do módulo específico e compilá-lo diretamente; neste caso, a compilação também funcionará para bibliotecas auxiliares.
cd <módulo>
cargo build
De forma similar à compilação geral, ambos os comandos também admitem
a flag --release
para compilar os módulos para produção.
Execução
É possível executar diretamente um módulo qualquer através do cargo
,
o que também implica na sua compilação.
Para executar a partir do diretório do workspace (apenas para módulos que geram executáveis):
cargo run --bin <módulo>
Para executar a partir do diretório do módulo em questão:
cd <módulo>
cargo run
Da mesma forma, é possível compilar e executar os módulos no modo
de produção através da flag --release
.
Testes
Para executar testes unitários e integração, basta seguir um processo
similar à execução dos módulos. Testes com binários compilados para
produção podem ser igualmente controlados pela flag --release
.
Para executar quaisquer testes, é necessário garantir que o banco de dados esteja acessível e adequadamente configurado.
# Para testar todos os módulos do workspace
cargo test
# Para testar apenas um módulo do workspace
cargo test --bin <módulo>
# Para testar apenas um módulo em seu diretório
cd <módulo>
cargo test
Compilação (Front-end)
O front-end é um módulo separado do restante dos módulos, sendo o sistema que envolve a interface gráfica do Sistema Minerva.
Executando o projeto via console
Para executar o projeto via console, basta usar a ferramenta de linha de comando do Flutter.
Preparando o Flutter
Antes de mais nada, garanta que o Flutter esteja configurado para compilar projetos Web:
flutter config --enable-web
Além disso, o Google Chrome deverá estar disponível para ser utilizado
no debug. O estado do ambiente Flutter pode ser verificado com o
comando flutter doctor
.
Caso haja alguma inconsistência no seu ambiente, veja a seção de preparação do Flutter para Web na documentação oficial.
Executando o projeto
Para executar o projeto, vá até o diretório do módulo de front-end, baixe as dependências necessárias, e então execute o projeto no Google Chrome:
cd minerva_frontend
flutter pub get
flutter run -d chrome
Compilando para produção
Para compilar o projeto para produção, vá até a pasta do módulo e execute os comandos a seguir. Eles baixarão as dependências faltantes (caso já não tenham sido baixadas) e gerarão os arquivos estáticos da aplicação.
cd minerva_frontend
flutter pub get
flutter build web
Você poderá encontrar a versão compilada da aplicação front-end no
diretório minerva_frontend/build/web
.