NEW

 🧱 Introdução

LEFT JOIN com filtro WHERE vs ON: entenda de uma vez por todas com exemplos práticos em SQL


Um dos temas mais confusos em SQL é o comportamento do LEFT JOIN quando usamos filtros.
Muita gente não percebe que a posição da condição (WHERE ou ON) muda completamente o resultado da consulta.

Neste artigo, você vai aprender:

  • A diferença entre aplicar o filtro no WHERE e no ON

  • Como preservar os registros da tabela principal

  • Exemplos práticos com tabelas de teste

  • Explicação visual com imagens do resultado


⚙️ Cenário de teste — criando o ambiente

Você pode rodar este script em SQL Server, PostgreSQL ou Oracle (ajusta só o CREATE TABLE se quiser):

-- Criando tabelas CREATE TABLE TABELA_PRINCIPAL ( id_produto INT PRIMARY KEY, nome_produto VARCHAR(50) ); CREATE TABLE TABELA_SECUNDARIA ( id_produto INT, preco DECIMAL(10,2) ); -- Inserindo dados na tabela principal INSERT INTO TABELA_PRINCIPAL (id_produto, nome_produto) VALUES (10, 'Teclado'), (11, 'Mouse'), (12, 'Monitor'), (13, 'Webcam'); -- Inserindo dados na tabela secundária INSERT INTO TABELA_SECUNDARIA (id_produto, preco) VALUES (10, 150.00), (11, 80.00), (12, 900.00);

📘 Perceba que o produto 13 (Webcam) não existe na tabela secundária.


🧩 Consulta 1 — LEFT JOIN normal

SELECT p.id_produto, p.nome_produto, s.preco FROM TABELA_PRINCIPAL p LEFT JOIN TABELA_SECUNDARIA s ON p.id_produto = s.id_produto;

🟢 Resultado esperado:

id_produtonome_produtopreco
10Teclado150.00
11Mouse80.00
12Monitor900.00
13WebcamNULL

✅ Todos os registros da tabela principal aparecem,
mesmo sem correspondência na secundária (Webcam → NULL).


🚫 Consulta 2 — Filtro no WHERE (perde o comportamento do LEFT JOIN)

SELECT p.id_produto, p.nome_produto, s.preco FROM TABELA_PRINCIPAL p LEFT JOIN TABELA_SECUNDARIA s ON p.id_produto = s.id_produto WHERE s.id_produto = 12;

🟡 Resultado:

id_produtonome_produtopreco
12Monitor900.00

💬 Explicação:
Ao colocar s.id_produto = 12 no WHERE, o SQL ignora as linhas onde s é NULL.
O LEFT JOIN perde o sentido e o resultado fica igual a um INNER JOIN filtrado.


✅ Consulta 3 — Filtro dentro do ON (mantém o comportamento do LEFT JOIN)

SELECT p.id_produto, p.nome_produto, s.preco FROM TABELA_PRINCIPAL p LEFT JOIN TABELA_SECUNDARIA s ON p.id_produto = s.id_produto AND s.id_produto = 12;

🟢 Resultado:

id_produtonome_produtopreco
10TecladoNULL
11MouseNULL
12Monitor900.00
13WebcamNULL

💬 Explicação:
Agora sim!
Todos os produtos da tabela principal aparecem.
Apenas o produto 12 traz dados da tabela secundária; os outros permanecem com NULL

LEFT JOIN com filtro WHERE vs ON: entenda de uma vez por todas com exemplos práticos em SQL

Leia mais

SketchBoard Free — desenhe e salve (sem login)

SketchBoard Free

SketchBoard Free — desenhe e salve no seu computador • sem login

Drawly Studio – Crie, desenhe e salve suas ideias online (Em desenvolvimento)

Leia mais

 Introdução rápida

Se sua conta do WhatsApp foi comprometida (mensagens estranhas, perda de acesso ou sessão desconhecida), siga imediatamente os 10 passos abaixo. Isso maximiza chances de recuperar o número e reduzir danos.


10 passos urgentes

1) Tente reativar sua conta IMEDIATAMENTE

Abra o WhatsApp no seu celular, solicite o código de verificação por SMS e insira-o. Se você ainda controla o chip, isso pode derrubar o invasor.

2) Ative a verificação em duas etapas (PIN) assim que recuperar o acesso

Vá em Configurações → Conta → Verificação em duas etapas → Ativar. Escolha um PIN forte e um e-mail de recuperação.

3) Encerre sessões desconhecidas do WhatsApp Web / Desktop

No app, toque em Aparelhos conectados e finalize todas as sessões que você não reconhece.

4) Contate sua operadora imediatamente (suspeita de SIM swap)

Peça bloqueio temporário do número e registre solicitação de investigação por fraude/portabilidade indevida.

5) Altere senhas dos serviços vinculados (email, banco, redes sociais)

Se o invasor teve acesso, troque senhas e ative 2FA (autenticação de dois fatores) em e-mail e contas financeiras.

6) Denuncie ao suporte do WhatsApp e registre ocorrência policial

Use o formulário do WhatsApp (“Meu número foi roubado”) e registre Boletim de Ocorrência na delegacia (importante para operadora/banco).

7) Informe e oriente seus contatos (modelo pronto abaixo)

Envie SMS ou outra via confiável: “Minha conta do WhatsApp foi comprometida. Ignore pedidos de dinheiro e códigos. Vou avisar quando recuperar.”

8) Faça scan por malware e avalie restauração do aparelho

Rode antivírus confiável; se houver suspeita forte, faça backup e reset de fábrica do celular para eliminar app espião.

9) Monitore transações e tentativas de fraude vinculadas ao número

Verifique movimentos bancários, cadastros e notifique bancos caso veja atividade suspeita.

10) Adote medidas permanentes de proteção

  • Use PIN para operadora (senha de atendimento).

  • Nunca compartilhe códigos SMS/OTP.

  • Revise rotineiramente Aparelhos conectados e backups do WhatsApp.

  • Atualize sistema e apps sempre.


Modelo de mensagem para avisar contatos (copiar e enviar)

Alerta: minha conta do WhatsApp foi comprometida. Ignore mensagens pedindo dinheiro ou códigos. Estou tomando providências e avisarei quando estiver normalizado.


Checklist rápido (imprima/cole)

  • Tentei reativar com SMS

  • Ativei verificação em duas etapas

  • Encerrei sessões do WhatsApp Web

  • Contatei a operadora (SIM swap)

  • Troquei senhas importantes

  • Denunciei ao WhatsApp + BO

  • Avisei meus contatos

  • Rodei antivírus/reset se necessário

  • Verifiquei contas bancárias

  • Configurei proteção permanente


Observações importantes (segurança & legal)

  • Não compartilhe códigos de verificação com ninguém — nem com “suporte”.

  • Em casos de SIM swap, a operadora pode reverter o número, mas é essencial o BO para fins legais.

  • Preserve prints e horários; serão úteis em investigações.

🛡️ Como Recuperar e Proteger Sua Conta do WhatsApp Roubada — 10 Passos Urgentes

Leia mais

servidor web local, JBoss WildFly, Windows 11, servidor Java

Você pode estar em qualquer lugar do mundo — Brasil, Portugal, Estados Unidos, Angola, Japão ou Índia — e ainda assim precisará, em algum momento, criar um ambiente local confiável para rodar uma aplicação web em Java. Ter um servidor web local no Windows 11 usando JBoss WildFly é uma das formas mais profissionais de desenvolver e testar APIs, sistemas corporativos e aplicações Java EE / Jakarta EE com segurança e alta performance.

🔧 1. O que é o JBoss WildFly?

O WildFly (antigo JBoss AS) é um servidor de aplicações Java open-source focado em alto desempenho, modularidade e fácil administração. Ele é muito usado em empresas, principalmente em projetos que precisam de:

  • APIs REST ou SOAP

  • Aplicações Web Java rodando com Servlets, JSP, JSF, EJB ou Spring

  • Conexão com bancos Oracle, PostgreSQL, SQL Server ou MySQL

  • Deploy corporativo em ambientes de desenvolvimento, homologação e produção


🧰 2. Requisitos para o ambiente

ItemVersão Recomendada
WindowsWindows 10 ou 11
Java JDK11, 17 ou superior
WildFly24+ ou última versão estável
Ferramentas extras (opcional)IntelliJ, Eclipse ou VS Code

📌 Dica: Em qualquer sistema operacional, o essencial é que o Java esteja instalado e configurado no PATH.


💻 3. Baixando e instalando o WildFly

  1. Acesse o site oficial do WildFly

  2. Baixe a versão Final (ZIP)

  3. Extraia para um diretório, ex.:

    C:\wildfly

🔧 4. Configurando as variáveis de ambiente no Windows 11

Abra o Prompt de Comando (CMD) e verifique o Java:

java -version

Depois configure o JAVA_HOME e PATH no Windows.


🚀 5. Subindo o servidor local

No CMD, execute:

cd C:\wildfly\bin standalone.bat

Depois abra no navegador:

http://localhost:8080

Se aparecer a tela do WildFly, o servidor está ativo.


🔐 6. Criando usuário administrador

add-user.bat

Crie usuário Management User e depois acesse o console:

http://localhost:9990

🌎 7. Como adaptar o servidor para diferentes regiões do mundo 

(Locale, Timezone e Encoding)

Quando um servidor WildFly atende usuários em diferentes países, ele precisa estar preparado para lidar corretamente com:

RecursoExemploEvita problemas como
TimezoneAmerica/Sao_Paulo, UTC, Europe/Lisbonhorários incorretos em logs, agendamentos e auditoria
Localept-BR, en-US, es-ESdatas e números exibidos em formato errado
EncodingUTF-8caracteres quebrados (ç, ã, á, ñ, ü etc.)

7.1 Configurando o Timezone no Windows + WildFly

  1. Configure o timezone no Windows (PowerShell):

tzutil /s "E. South America Standard Time"
  1. Garanta que o WildFly siga o mesmo timezone, adicionando no standalone.conf.bat:

set "JAVA_OPTS=%JAVA_OPTS% -Duser.timezone=America/Sao_Paulo"

Dica: para servidores globais, use sempre UTC

set "JAVA_OPTS=%JAVA_OPTS% -Duser.timezone=UTC"

7.2 Configurando o Locale (Idioma/Formato de Data e Número)

Edite também o standalone.conf.bat e adicione:

set "JAVA_OPTS=%JAVA_OPTS% -Duser.language=pt -Duser.country=BR"

Para servidores multilíngues, o mais recomendado é en-US como padrão, decidindo o idioma na aplicação.


7.3 Garantindo UTF-8 em toda a aplicação (fundamental)

No mesmo arquivo:

set "JAVA_OPTS=%JAVA_OPTS% -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"

Isso evita:

✅ caracteres estranhos
✅ � trocando acentos
✅ erro em XML/JSON retornado pela API


Se estiver tudo certo até aqui, me responda apenas:

👉 "Continuar para o tópico 8"

Assim eu já continuo com a próxima seção:

🔐8. Segurança e Hardening do Servidor WildFly no Windows 11


Quando você transforma o WildFly em um servidor web — mesmo que local ou em rede interna — segurança precisa ser prioridade. Um servidor mal configurado pode expor dados, credenciais e aplicações, além de ser um alvo para ataques comuns como:
  • Brute Force
  • Port Scanning
  • Ataques via HTTP (XSS, Request Flood, Path Traversal, etc.)
  • Sequestro de sessão
  • Interceptação de tráfego (quando não há HTTPS)

A meta do hardening é simples: reduzir a superfície de ataque e proteger as portas críticas do servidor.

8.1 Use HTTPS (TLS) ao invés de HTTP


Mesmo em ambiente local, é boa prática habilitar HTTPS.
Opções para gerar certificados

CenárioCertificadoRede local Certificado self-signed
Produção global Let's Encrypt ou autoridade confiável (DigiCert, GlobalSign etc.)
Empresa Certificado interno fornecido pela TI

Gerando um certificado self-signed (PowerShell)

keytool -genkeypair -alias wildfly https \ -keyalg RSA -keystore wildfly.keystore \ -storepass changeit -keypass changeit \ -validity 365 -dname "CN=localhost"



Depois, edite o standalone.xml e configure o listener HTTPS:
<https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>

Benefícios imediatos: criptografia, integridade dos dados e compatibilidade com HTTP/2.


8.2 Bloqueie o acesso externo ao Console Admin

Por padrão, a console de administração fica acessível na porta 9990. Em um ambiente seguro, apenas a máquina local ou a rede restrita deve acessá-la.

Edite o standalone.xml e altere o binding para localhost:
<interface name="management"> <inet-address value="127.0.0.1"/> </interface>
Resultado: ninguém de fora consegue gerenciar o WildFly.

8.3 Crie usuários e funções com o mínimo de privilégios

Nunca use usuário admin para tudo.

Categorias recomendadas:

FunçãoIndicado paraManagement Administradores do servidor
Application User Apps, sistemas e serviços
Read-Only Admin Auditoria ou monitoramento


Crie usuários com:
add-user.bat

Seguindo a política:
✅ Menor privilégio possível
✅ Senhas fortes com expiração periódica

8.4 Firewall e portas do WildFly

Portas mais comuns do WildFly:

PortaFunção8080 HTTP
8443 HTTPS
9990 Admin Console
9999 CLI remota

No Windows, ative regras no Firewall do Windows Defender, liberando apenas o que for necessário.

Boa prática global:

✅ Liberar 8080/8443 somente para acesso interno ou VPN
✅ Bloquear 9990 e 9999 para acesso público
✅ Preferir HTTPS sempre 8.5 Remova serviços e módulos que não usa

  • Quanto mais módulos ativos, maior o risco. No standalone.xml, desative subsystems que não usa, como:
  • WebSockets (se não houver necessidade)
  • Messaging
  • EJB Remoting
  • Deploy Scanner externo

Com isso você:

✅ reduz memória
✅ aumenta segurança
✅ melhora desempenho


8.5 Remova serviços e módulos que não usa

Quanto mais módulos ativos, maior o risco. No standalone.xml, desative subsystems que não usa, como:

  • WebSockets (se não houver necessidade)

  • Messaging

  • EJB Remoting

  • Deploy Scanner externo

Com isso você:

✅ reduz memória
✅ aumenta segurança
✅ melhora desempenho


8.6 Proteções adicionais (blindagem de servidor)


ProteçãoResultadoRate Limit (no proxy ou firewall) Ajuda contra DoS simples
Desativar TRACE e OPTIONS Evita fingerprint HTTP
HSTS e CSP (via headers) Protege front-end e cookies
Logar falhas de login Detecção precoce de ataque

9. Monitoramento e Logs no WildFly — Mantendo seu Servidor Saudável e Observável

Após ter seu servidor WildFly rodando no Windows 11, com segurança aplicada e aplicações no ar, o próximo passo é garantir visibilidade total do ambiente. Monitorar o servidor não é opcional — é o que permite identificar gargalos, prever falhas e agir antes que o usuário perceba qualquer instabilidade.

Uma aplicação sem monitoramento é como dirigir à noite com os faróis apagados.
Então, nesta seção, você vai aprender como monitorar, analisar métricas, gerenciar logs e implementar observabilidade real.


9.1 Logs principais do WildFly no Windows

No modo standalone, os logs ficam em:

WILDFLY_HOME\standalone\log\

Os arquivos mais importantes são:

LogFunção
server.logLog principal do servidor e da aplicação
boot.logLogs da inicialização do servidor
audit.logEventos administrativos e de segurança

Dicas práticas ao trabalhar com logs:

✅ Sempre usar log rotation
✅ Arquivar logs antigos automaticamente
✅ Ajustar nível de log (INFO → WARN → DEBUG conforme necessidade)

No standalone.xml, você pode alterar o nível de log facilmente:

<root-logger> <level name="INFO"/> </root-logger>
Em produção, evite DEBUG ou TRACE, pois geram muito volume e impactam desempenho.

9.2 Monitorando via Console Web (modo GUI)

O WildFly já oferece, nativamente, um painel de monitoramento.
Acesse: http://localhost:9990

Na console você acompanha:

  • Consumo de memória

  • Threads

  • Pools de conexão JDBC

  • Estado dos deployments

  • Subsistemas ativos

  • Tempo de resposta e status do servidor

É ideal para monitoramento rápido e visual.


9.3 Monitoramento via CLI (administradores avançados)

Para automação, o CLI é poderoso:

jboss-cli.bat --connect

Comandos úteis:

ComandoO que faz
/core-service=platform-mbean/type=memory:read-resource()Métricas de memória
/subsystem=datasources:read-resource()Monitora datasources
:reloadReinicia serviços sem desligar o servidor

9.4 Observabilidade real — integração com ferramentas globais

Para ambientes distribuídos ou quando o servidor atende usuários em diferentes países, você pode integrar o WildFly com:

FerramentaFinalidadeEscala
PrometheusColeta de métricas (pull)Global
GrafanaDashboards avançadosGlobal
Elastic Stack (ELK)Análise de logsCorporativo
ZabbixMonitoramento tradicionalEnterprise
JaegerTrace distribuídoMicrosserviços

Com isso, você transforma o WildFly em um ambiente observável com:

✅ Monitoramento em tempo real
✅ Alertas automáticos
✅ Dashboards acessíveis internacionalmente
✅ Tracing de requisições (ótimo para APIs)


9.5 Log Rotation e boas práticas

Para não encher disco em servidores Windows, configure rotation, por tamanho (recomendado) ou por data:

<periodic-rotating-file-handler name="FILE" autoflush="true"> <level name="INFO"/> <file relative-to="jboss.server.log.dir" path="server.log"/> <suffix value=".yyyy-MM-dd"/> <append value="true"/> </periodic-rotating-file-handler>

Checklist final de monitoramento inteligente:

ItemSituação ideal
Logs rotacionando
Alertas configurados
Painel de métricas
Console e CLI acessíveis
Tracing ativado em produção

10. Otimização de Desempenho (HTTP, Thread, Datasource e Windows)

(Resumo — porque este é um tópico grande e sensível, mas essencial)

Otimize:

ComponenteAjuste
HTTP/2 + HTTPSRespostas mais rápidas
Connection PoolPool adequado ao volume
GZIPReduz tamanho da resposta
CacheAcelera recursos estáticos
Windows ServicesDesativar serviços inúteis

11. Conclusão — Seu Servidor WildFly Local Está Pronto

Agora você possui:

✅ WildFly instalado e executando localmente no Windows 11
✅ Deploy de aplicações (WAR) funcionando
✅ Datasource configurado
✅ Segurança com HTTPS, firewall e usuários corretos
✅ Monitoramento, logs e observabilidade
✅ Um ambiente preparado para desenvolvimento global

Este servidor agora pode servir:

🌍 APIs
🌍 Aplicações corporativas
🌍 Portais Java
🌍 Microservices (com ajustes)

Chamada final (CTA):

Se este guia ajudou você, compartilhe, salve nos favoritos e visite nosso blog para mais conteúdos sobre servidores, segurança e desenvolvimento Java.


🌍 Criando um servidor WEB local no Windows 11 com JBoss WildFly (Guia Completo)

Leia mais


 

Diagrama de arquitetura microserviços FastAPI: Auth, Product, Sales com SQLite e chamadas HTTP entre serviços
Diagrama de arquitetura microserviços FastAPI: Auth, Product, Sales com SQLite e chamadas HTTP entre serviços

Introdução

Neste tutorial você vai aprender a construir uma arquitetura de micro-APIs similar ao diagrama:

  • Auth API: gera e valida tokens JWT;

  • Product API: CRUD de produtos com SQLite;

  • Sales API: registra vendas (SQLite) e faz chamadas para outras APIs (ex: validação de produto);

Tudo sem containers, ideal para desenvolvimento local e testes rápidos. Tudo em FastAPI, com exemplos prontos para rodar em portas diferentes.

Por que essa arquitetura?

  • Permite separar responsabilidades (autenticação, catálogo, vendas).

  • Cada serviço pode escalar de forma independente no futuro.

  • Fácil evolução para filas assíncronas (RabbitMQ) ou bancos separados (Postgres/Mongo) quando desejar.

Requisitos (instalação rápida)

No seu ambiente Python (recomendo criar um venv):

python -m venv venv

source venv/bin/activate   # macOS / Linux

venv\Scripts\activate      # Windows

pip install fastapi uvicorn sqlalchemy pydantic jwt passlib[bcrypt] requests

Arquivo requirements.txt sugerido:

 fastapi

uvicorn[standard]

sqlalchemy

pydantic

PyJWT

passlib[bcrypt]

requests

Estrutura de pastas (sugestão)

microservices-fastapi/
├── auth_api/
│   └── main.py
├── product_api/
│   └── main.py
├── sales_api/
│   └── main.py
└── README.md

1) Auth API — gerar e validar JWT

Objetivo: emitir token JWT ao autenticar usuário (aqui exemplo simples com usuário hardcoded para demo).

Arquivo: auth_api/main.py

# auth_api/main.py

from fastapi import FastAPI, HTTPException

from pydantic import BaseModel

import jwt, datetime

from passlib.context import CryptContext


app = FastAPI(title="Auth API")

SECRET_KEY = "troque_isto_por_um_segredo_forte"

ALGORITHM = "HS256"

ACCESS_TOKEN_EXPIRE_MINUTES = 60


pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")


# Exemplo simples: usuário fixo (em produção, use DB)

fake_user = {

    "username": "admin",

    "hashed_password": pwd_context.hash("123")

}


class LoginIn(BaseModel):

    username: str

    password: str


@app.post("/login")

def login(payload: LoginIn):

    if payload.username != fake_user["username"] or not pwd_context.verify(payload.password, fake_user["hashed_password"]):

        raise HTTPException(status_code=401, detail="Usuário ou senha incorretos")

    expire = datetime.datetime.utcnow() + datetime.timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)

    token = jwt.encode({"sub": payload.username, "exp": expire}, SECRET_KEY, algorithm=ALGORITHM)

    return {"access_token": token, "token_type": "bearer"}

Executar:
uvicorn auth_api.main:app --host 0.0.0.0 --port 8000 --reload
Teste:
curl -X POST "http://localhost:8000/login" -H "Content-Type: application/json" -d '{"username":"admin","password":"123"}'

2) Product API — CRUD com SQLite

Objetivo: fornecer endpoints para criar/listar produtos; protegido por JWT.

Arquivo: product_api/main.py

# product_api/main.py

from fastapi import FastAPI, Depends, HTTPException

from pydantic import BaseModel

from sqlalchemy import create_engine, Column, Integer, String, Float

from sqlalchemy.orm import sessionmaker, declarative_base

import jwt

from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

import requests


DATABASE_URL = "sqlite:///./product.db"

SECRET_KEY = "troque_isto_por_um_segredo_forte"  # o mesmo do Auth em demo


engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})

SessionLocal = sessionmaker(bind=engine)

Base = declarative_base()


class Product(Base):

    __tablename__ = "products"

    id = Column(Integer, primary_key=True, index=True)

    name = Column(String, index=True)

    price = Column(Float)


Base.metadata.create_all(bind=engine)


app = FastAPI(title="Product API")

security = HTTPBearer()


class ProductIn(BaseModel):

    name: str

    price: float


def verify_token(creds: HTTPAuthorizationCredentials = Depends(security)):

    token = creds.credentials

    try:

        payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])

    except jwt.PyJWTError:

        raise HTTPException(status_code=401, detail="Token inválido")

    return payload


@app.post("/products")

def create_product(prod: ProductIn, payload=Depends(verify_token)):

    db = SessionLocal()

    p = Product(name=prod.name, price=prod.price)

    db.add(p)

    db.commit()

    db.refresh(p)

    db.close()

    return {"id": p.id, "name": p.name, "price": p.price}


@app.get("/products")

def list_products(skip: int = 0, limit: int = 100, payload=Depends(verify_token)):

    db = SessionLocal()

    items = db.query(Product).offset(skip).limit(limit).all()

    db.close()

    return items

Executar:
uvicorn product_api.main:app --host 0.0.0.0 --port 8001 --reload

Fluxo de teste (usar token do Auth):

  1. Obter token no Auth (/login).

  2. Criar produto:

curl -X POST "http://localhost:8001/products" \
 -H "Authorization: Bearer <TOKEN>" \
 -H "Content-Type: application/json" \
 -d '{"name":"Mouse","price":29.9}'
Listar:
curl -H "Authorization: Bearer <TOKEN>" "http://localhost:8001/products"

3) Sales API — registrar venda e validar produto via Product API

Objetivo: registrar vendas localmente em SQLite e validar produto consultando Product API (HTTP).

Arquivo: sales_api/main.py

# sales_api/main.py

from fastapi import FastAPI, HTTPException, Depends

from pydantic import BaseModel

from sqlalchemy import create_engine, Column, Integer, String, Float, DateTime

from sqlalchemy.orm import sessionmaker, declarative_base

import datetime

import requests


DATABASE_URL = "sqlite:///./sales.db"

engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})

SessionLocal = sessionmaker(bind=engine)

Base = declarative_base()


class Sale(Base):

    __tablename__ = "sales"

    id = Column(Integer, primary_key=True, index=True)

    product_id = Column(Integer)

    product_name = Column(String)

    quantity = Column(Integer)

    total = Column(Float)

    created_at = Column(DateTime, default=datetime.datetime.utcnow)


Base.metadata.create_all(bind=engine)


app = FastAPI(title="Sales API")


class SaleIn(BaseModel):

    product_id: int

    quantity: int


PRODUCT_API_URL = "http://localhost:8001/products"  # endpoint base


@app.post("/sales")

def create_sale(sale: SaleIn):

    # Consulta Product API para validar produto (simples: buscar lista e filtrar)

    resp = requests.get(PRODUCT_API_URL)

    if resp.status_code != 200:

        raise HTTPException(status_code=502, detail="Product API indisponível")

    products = resp.json()

    product = next((p for p in products if p["id"] == sale.product_id), None)

    if not product:

        raise HTTPException(status_code=404, detail="Produto não encontrado")


    total = product["price"] * sale.quantity

    db = SessionLocal()

    s = Sale(product_id=product["id"], product_name=product["name"], quantity=sale.quantity, total=total)

    db.add(s)

    db.commit()

    db.refresh(s)

    db.close()


    # Aqui você poderia publicar uma mensagem na fila RabbitMQ (opcional)

    return {"sale_id": s.id, "product": s.product_name, "total": s.total}

Executar:
uvicorn sales_api.main:app --host 0.0.0.0 --port 8002 --reload

Testando (exemplo):

  1. Criar produto via Product API (veja acima).

  2. Criar venda:

curl -X POST "http://localhost:8002/sales" -H "Content-Type: application/json" -d '{"product_id":1,"quantity":2}'

Comunicação entre serviços (HTTP calls)

No exemplo da Sales API usamos requests.get para consultar GET /products e validar o produto. Em arquiteturas reais, você pode:

  • Usar chamadas HTTP síncronas (como no exemplo) — simples, mas acoplamento temporal.

  • Mudar para mensageria (RabbitMQ) para eventos assíncronos (venda registrada → event published).

  • Implementar retries, circuit breaker e timeouts (ex.: requests.get(url, timeout=3)).


Boas práticas e melhorias recomendadas

  • Variáveis de ambiente: mova segredos (SECRET_KEY) e URLs para variáveis (use python-decouple ou pydantic.Settings).

  • Migrations: use Alembic para gerenciar schema do SQLAlchemy em produção.

  • Autenticação real: troque usuário hardcoded por tabela users no DB e endpoint de registro.

  • HTTPS em produção (Nginx/Traefik + certificado).

  • Logs estruturados e monitoramento (Prometheus/Grafana).

  • Testes automatizados: unit + integration tests com pytest e httpx.


Erros comuns e tratamento

  • Token expirado: implemente refresh token (rota /refresh).

  • Product API indisponível: adicione fallback ou fila para processar vendas offline.

  • SQLite limita concorrência: para produção use PostgreSQL (mais robusto para multi-conexões).


Conclusão (call to action)

Com esse guia você tem uma base funcional para montar as três APIs em FastAPI com SQLite, imitando a arquitetura do seu diagrama. É um ponto de partida rápido para testes locais e evolução para um ambiente em containers ou nuvem.

👉 Próximos passos sugeridos:

  • Migrar Product e Sales para PostgreSQL/Mongo;

  • Adicionar RabbitMQ para comunicação assíncrona;

  • Implementar testes automáticos e CI/CD.

Recursos adicionais e links úteis

🔐 Construindo 3 Micro-APIs em Python com FastAPI (Auth, Product, Sales) — Arquitetura, JWT e SQLite

Leia mais

✝ Copyright © Blog do KDS - Isaías 40:5 “A glória do Senhor se manifestará, e toda a humanidade a verá.”