ChaosSQL

Especificação

Especificação da Linguagem Declarativa (chaos.yaml DSL)

Referência exaustiva da DSL declarativa YAML: taxonomia completa de campos, sintaxe de captura léxica, interpolação de expressões dinâmicas, predicados de guarda condicional, asserções de invariantes e injeção de falhas controladas.

Visão Geral da Linguagem Declarativa (DSL)

O ChaosSQL utiliza uma DSL declarativa em YAML (chaos.yaml) para especificar cenários de teste de concorrência de forma desacoplada do código da aplicação. A especificação modela formalmente o ambiente de banco de dados, o agendamento de workers, as transações concorrentes e as invariantes indutivas que garantem a consistência dos dados.

Taxonomia Completa de Propriedades Raiz

Campo Tipo Obrigatório Descrição Técnica
version string Sim Versão da especificação da DSL (suporta "1.0" e "1.1").
name string Sim Identificador único do cenário (ex: banking_lost_update).
description string Não Documentação textual da hipótese concorrente e regras de negócio.
database object Sim Configuração do driver, scripts DDL de esquema e DML de seed.
engine object Sim Parâmetros do motor de execução: workers, semente PRNG e jitter.
operations array Sim Lista de transações atômicas a serem executadas pelos workers.
invariants array Sim Asserções de integridade global pós-execução e contínuas.
faults object Não Configurações de injeção de falhas estocásticas (aborts, desconexões).

O Bloco database

Define o motor de banco de dados alvo e os scripts de inicialização de estado:

database:
  driver: "sqlite"             # Suportados: "sqlite", "postgres", "mysql"
  schema: "schema.sql"         # Caminho relativo para arquivo DDL ou string SQL inline
  seed: "seed.sql"             # Caminho relativo para arquivo DML de dados iniciais
  dsn: "file:memdb?mode=memory&cache=shared" # DSN opcional (obrigatório para Postgres/MySQL)

O Bloco engine

Controla a orquestração concorrente do agendamento PCT-SQL:

engine:
  workers: 8                   # Quantidade de goroutines simultâneas
  iterations: 50               # Total de transações a serem agendadas
  seed: 1337                   # Semente do PRNG PCG64 (determinismo estrito)
  jitter_ms: [1, 10]           # Faixa de atraso estocástico [min, max] entre passos SQL
  isolation: "READ COMMITTED"  # Opcional: forçar nível transacional

Operações, Captura de Variáveis e Expressões Dinâmicas

Cada item em operations define uma transação concorrente atômica. Cada passo (step) é executado sequencialmente dentro da transação alocada para um worker.

Sintaxe de Captura Léxica (-> var_name ou => var_name)

Permite ler valores de colunas de uma query SELECT e armazená-los no contexto léxico local da transação para uso em instruções subsequentes:

operations:
  - name: "transfer_funds"
    steps:
      # Captura a coluna 'balance' da linha retornada na variável 'current_bal'
      - "SELECT balance FROM accounts WHERE id = 1 -> current_bal"
      - "UPDATE accounts SET balance = {current_bal - 100} WHERE id = 1"

Interpolação de Expressões Dinâmicas ({expr})

O ChaosSQL incorpora o motor de compilação expr-lang, permitindo operações aritméticas, lógicas e chamadas em tempo de execução:

  • Operações Aritméticas: {current_bal - 100}, {price * quantity * 0.9}
  • Operações Condicionais: {avail > 0 ? avail - 1 : 0}
  • Interpolação de Variáveis: UPDATE products SET stock = {avail - 1} WHERE id = {target_product}

Predicados de Guarda Condicional em SQL

Você pode combinar a sintaxe de expressão com cláusulas WHERE para criar predicados de concorrência com guarda atômica:

operations:
  - name: "conditional_checkout"
    steps:
      - "SELECT stock FROM products WHERE id = 1 -> avail"
      - "UPDATE products SET stock = {avail - 1} WHERE id = 1 AND {avail > 0}"

Parâmetros Dinâmicos (params)

A versão 1.1 da DSL permite declarar variáveis pseudoaleatórias por transação:

operations:
  - name: "dynamic_transfer"
    params:
      sender_id: "rand_int(1, 10)"
      receiver_id: "rand_int(11, 20)"
      amount: "rand_int(50, 200)"
    steps:
      - "UPDATE accounts SET balance = balance - {amount} WHERE id = {sender_id}"
      - "UPDATE accounts SET balance = balance + {amount} WHERE id = {receiver_id}"

Asserções de Invariantes Globais (invariants)

As invariantes representam as leis de conservação do sistema que nunca podem ser violadas, independentemente da ordem de intercalação dos workers.

Campo Tipo Descrição
name string Nome descritivo da invariante (ex: conservation_of_money).
query string Query SQL agregada executada ao final do teste para obter o estado consolidado.
assert string Expressão booleana avaliada sobre o resultado da query.

Variáveis Especiais Injetadas no Contexto da Asserção

  • col_name: O valor retornado por qualquer coluna da query da invariante (ex: total_balance, active_doctors).
  • total_completed: Quantidade total de transações confirmadas com sucesso (EventCommit).
  • total_aborted: Quantidade de transações que abortaram por conflito de serialização ou deadlock.
  • total_operations: Total absoluto de operações agendadas.
invariants:
  # 1. Lei de conservação de patrimônio
  - name: "conservation_of_money"
    query: "SELECT sum(balance) AS total FROM accounts;"
    assert: "total == 2000"

  # 2. Relação linear entre operações concluídas e saldo
  - name: "balance_audit"
    query: "SELECT balance FROM accounts WHERE id = 1;"
    assert: "balance == 1000 - (total_completed * 100)"

  # 3. Predicado de não-negatividade
  - name: "stock_non_negative"
    query: "SELECT stock FROM products WHERE id = 1;"
    assert: "stock >= 0"

  # 4. Quórum de segurança hospitalar
  - name: "at_least_one_doctor_on_call"
    query: "SELECT count(*) AS on_duty FROM doctors WHERE on_call = true;"
    assert: "on_duty >= 1"

Injeção de Falhas Controladas (faults)

Permite injetar adversidades de rede e comportamento transacional estocástico:

faults:
  transient_abort_rate: 0.15  # 15% de chance de ROLLBACK abrupto no meio de uma transação (testa G1a)
  connection_drop_rate: 0.05  # 5% de chance de corte de conexão durante a execução
  latency_spikes:
    probability: 0.10
    delay_ms: 100             # Injeta 100ms de atraso assíncrono para ampliar janela de corrida
Linter Estático Obrigatório: Antes de executar cenários complexos, utilize sempre o comando chaossql validate <arquivo.yaml> para compilar antecipadamente as expressões da DSL e prevenir falhas de tipagem durante a execução.