Pular para conteúdo

Diagramas de Sequência

Todos os fluxos principais do sistema documentados com diagramas de sequência. Esses diagramas descrevem a ordem exata das operações e quem é responsável por cada passo.


1. Criação de comanda

O administrador emite uma comanda para um participante com saldo inicial.

sequenceDiagram
    actor Admin
    participant API as Servidor (FastAPI)
    participant DB as SQLite
    participant FB as Firebase

    Admin->>API: WS message: create_comanda {holder_name, initial_balance}
    API->>DB: INSERT INTO comandas (generates code Fxxx)
    API->>DB: INSERT INTO events (type=credit, amount=initial_balance)
    DB-->>API: ok
    API-->>Admin: WS: comanda_created {comanda_id, code: "F001", balance}
    API-->>Outros: WS: update_next_code {next_code: "F002"}

    Note over API,FB: sync assíncrono (background task)
    API->>FB: write comanda + evento (best-effort)
    FB-->>API: ok (ou timeout — ignorado)

Pontos de atenção:

  • O código da comanda (code) é gerado no servidor no formato F001, F002, etc.
  • O WebSocket garante que todos os ~5 operadores vejam o próximo código disponível em tempo real, evitando duplicidade.
  • Se o Firebase estiver offline, a comanda ainda é criada normalmente

2. Débito em loja (fluxo principal)

Um participante compra algo numa loja. É o fluxo mais crítico do sistema.

sequenceDiagram
    actor Cliente
    actor Lojista
    participant WS as WebSocket (Terminal)
    participant API as Servidor (FastAPI)
    participant DB as SQLite
    participant Outros as Outros Terminais
    participant FB as Firebase

    Cliente->>Lojista: informa o código da comanda
    Lojista->>WS: digita código → debit_request {code, amount, store_id}

    WS->>API: WS message: debit_request

    API->>DB: SELECT balance FROM events WHERE comanda_id = ?
    DB-->>API: balance atual

    alt saldo suficiente
        API->>DB: INSERT INTO events (type=debit, ...)
        DB-->>API: ok
        API-->>WS: debit_confirmed {new_balance, event_id}
        API-->>Outros: broadcast: balance_updated {comanda_id, new_balance}

        Note over API,FB: sync assíncrono
        API->>FB: write event
    else saldo insuficiente
        API-->>WS: debit_rejected {reason: insufficient_balance, current_balance}
    end

    WS-->>Lojista: exibe resultado (confirmado / rejeitado)

Pontos de atenção:

  • A validação de saldo e a inserção do evento acontecem dentro de uma transação SQLite — são atômicas
  • O broadcast para outros terminais permite que o painel admin veja movimentações em tempo real
  • O Firebase só recebe o evento após confirmação local — nunca antes

3. Consulta de saldo pelo cliente

O participante quer saber quanto tem no celular, sem interagir com nenhuma loja.

sequenceDiagram
    actor Cliente
    participant FB as Firebase Firestore
    participant Cache as Cache Firebase (local no celular)

    Cliente->>FB: GET /comandas/{comanda_id}/balance

    alt Firebase online e sync em dia
        FB-->>Cliente: {balance: X, last_updated: timestamp}
    else Firebase offline (celular sem internet)
        Cache-->>Cliente: {balance: X (cached), stale: true}
    else Firebase online mas sync atrasada
        FB-->>Cliente: {balance: X (pode estar desatualizado), last_updated: timestamp}
        Note over Cliente: UI exibe aviso de "pode estar desatualizado"
    end

Pontos de atenção:

  • O cliente nunca consulta o servidor principal — esse canal é reservado para operações de loja
  • O saldo no Firebase pode estar levemente desatualizado — isso é esperado e documentado (eventual consistency)
  • A UI deve sempre exibir o last_updated para o cliente ter contexto da atualização

4. Reconexão de terminal após queda

Um terminal de loja perde a conexão WebSocket (WiFi momentâneo, por exemplo) e reconecta.

sequenceDiagram
    participant WS as Terminal (browser)
    participant API as Servidor

    WS->>API: WS connect
    API-->>WS: connected {session_id}

    Note over WS: conexão cai (WiFi, etc.)

    WS->>WS: detecta disconnect
    WS->>WS: aguarda 2s (backoff fixo)
    WS->>API: WS reconnect
    API-->>WS: connected {estado atual}

    Note over WS: terminal volta ao estado inicial da sessão

Pontos de atenção:

  • O frontend implementa reconnect automático com backoff fixo (2–3 segundos)
  • Ao reconectar, o terminal recebe o estado atual (info da loja ou próximo código de comanda), e pode continuar operando normalmente
  • Nenhuma transação é perdida no servidor — o event store é a fonte da verdade
  • Transações pendentes no terminal durante a desconexão não são processadas — o lojista deve refazer a operação após a reconexão

5. Recuperação após queda do servidor

O notebook do servidor é desligado (ou cai). O evento é reiniciado após o servidor voltar.

sequenceDiagram
    participant Servidor
    participant DB as SQLite (arquivo em disco)
    participant Terminais

    Note over Servidor: servidor cai (energia, crash, etc.)
    Note over Terminais: terminais exibem "Servidor offline"

    Note over Servidor: servidor reinicia
    Servidor->>DB: open ouroboros.db
    DB-->>Servidor: estado completo restaurado (WAL mode)

    Servidor->>Servidor: inicia worker de sync Firebase
    Servidor->>Servidor: abre porta WebSocket

    Terminais->>Servidor: reconnect automático
    Servidor-->>Terminais: connected + estado atual

    Note over Servidor: operação normal retomada
    Note over Servidor: eventos não-synced são enviados ao Firebase

Pontos de atenção:

  • O SQLite com WAL mode garante que nenhum evento confirmado é perdido
  • O worker de sync ao reiniciar identifica eventos com synced = 0 e os envia
  • O downtime é o tempo de restart do servidor (tipicamente < 10 segundos)