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
    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 com Firebase NÃO está implementado (ideia futura)
    Note over API,FB: O campo synced_to_firebase existe no banco como preparação

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.
  • A comanda é criada inteiramente local — sem nenhuma dependência de internet

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
    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 com Firebase NÃO está implementado (ideia futura)
    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 (ideia futura — não implementada)

Não implementado

Este fluxo descreve uma funcionalidade planejada mas não implementada. Atualmente não há sync com Firebase, então o cliente não tem como consultar saldo pelo celular via Firestore. Esta seção documenta a intenção arquitetural para referência futura.

Um 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: abre porta WebSocket

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

    Note over Servidor: operação normal retomada

Pontos de atenção:

  • O SQLite com WAL mode garante que nenhum evento confirmado é perdido
  • O downtime é o tempo de restart do servidor (tipicamente < 10 segundos)