Conn2Flow
Navegação das docs

SDD

req-234 — Fracionamento Determinístico de Arquivos de Dados Grandes (*Data.json) e Leitor Unificado de Tabelas Particionadas

Limite Estrito do Git/GitHub e Arquivos de Dados Gigantes: - O GitHub rejeita qualquer arquivo individual que exceda 100 MiB (com avisos a partir de 50 MiB). - Com o crescimento…

  • Status: complete

  • Modo de Autonomia: autonomo_monitorado

  • Lote Alvo: BATCH-243

  • Data de Criação: 2026-10-05

  • Repositório: conn2flow (Core) em [REDACTED]

  • Origem: Engenheiro Chefe Humano / Parecer Técnico: Limite de tamanho de arquivo no Git/GitHub (100 MiB) atingido por PaginasData.json (105,53 MiB); necessidade de fracionamento determinístico na esteira oficial com leitor transparente e proteção contra exclusões indevidas no banco.

  • Aviso de Concorrência: Isolar na branch feat/req-234 via worktree limpo (conn2flow-req234) derivado de main. Proibido usar git add -A ou git add ..


1. Contexto & Diagnóstico

  1. Limite Estrito do Git/GitHub e Arquivos de Dados Gigantes:

    • O GitHub rejeita qualquer arquivo individual que exceda 100 MiB (com avisos a partir de 50 MiB).

    • Com o crescimento do sistema, templates e páginas ricas em HTML e CSS pré-compilado, o arquivo gestor/db/data/PaginasData.json ultrapassou 105,53 MiB.

    • Mesmo com compactação de formatação JSON (sem indentação), o payload excede o limite aceito pelo Git.

    • Na branch feat/req-225, o arquivo foi enviado provisoriamente via Git LFS (c6e5f7a9), mas o Git LFS é uma medida paliativa e adiciona complexidade e dependência de storage externo.

  2. Fragilidade de uma Divisão Ingênua:

    • Uma simples numeração de arquivos ou quebra arbitrária quebraria a esteira do Conn2Flow:

      • O gerador de dados (atualizacao-dados-recursos.php:1060) grava uma tabela inteira em um único JSON usando jsonWrite().

      • O recuperador de dados (recuperacao-dados-recursos.php:438) varre *Data.json e assume que cada arquivo representa a tabela inteira.

      • PONTO MAIS CRÍTICO — Sincronizador de Banco de Dados (atualizacoes-banco-de-dados.php:1141): Ele compara os registros existentes no banco com os registros do arquivo para identificar dados removidos/órfãos. Se ler as partes de forma isolada, ao processar a parte 2, interpretará todos os registros da parte 1 como deletados, apagando dados válidos do banco de dados!

      • A API de recuperação / ZIP (gestor/controladores/api/api.php:604), instaladores de plugins e rotinas de exportação assumem *Data.json monolíticos.


2. Princípios e Desenho Arquitetural da Solução

2.1. Convenção de Particionamento e Nomenclatura

  • Limite Padrão por Parte: 80 MiB (83.886.080 bytes serializados), configurável por constante ou parâmetro.

  • Tabelas Menores que o Limite (< 80 MiB):

    • Mantêm-se como <PascalCase>Data.json (ex: UsuariosData.json, LayoutsData.json).

    • Total retrocompatibilidade com o ecossistema existente.

  • Tabelas Maiores que o Limite (>= 80 MiB):

    • Fatiadas entre registros completos (cada parte é um array JSON sintaticamente válido [...]).

    • NUNCA quebrar um registro/objeto JSON no meio.

    • Preservar rigorosamente a ordenação determinística e estável (por chaves naturais / PKs).

    • Nomenclatura das partes: <PascalCase>Data.part-001.json, <PascalCase>Data.part-002.json, etc.

    • Manifesto da Tabela: <PascalCase>Data.manifest.json contendo:

      {
      "schema_version": 1,
      "table": "paginas",
      "data_file_base": "PaginasData",
      "total_parts": 2,
      "total_records": 1420,
      "total_bytes": 110657430,
      "generated_at": "2026-10-05T08:00:00Z",
      "parts": [
      {
        "file": "PaginasData.part-001.json",
        "index": 1,
        "records": 750,
        "size_bytes": 58450120,
        "sha256": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945"
      },
      {
        "file": "PaginasData.part-002.json",
        "index": 2,
        "records": 670,
        "size_bytes": 52207310,
        "sha256": "8e35c249a21e428c0451a99a888c3a1e05d96a73c15562723c21a4731804b712"
      }
      ]
      }
    • Quando a tabela é particionada, o arquivo monolítico <PascalCase>Data.json é removido do disco para evitar duplicidade de leitura e garantir que ferramentas antigas não processem dados incompletos.

2.2. Publicação Atômica e Segura (Atomic Write Pipeline)

  • Toda escrita de tabela particionada deve seguir a ordem segura:

    1. Escrever as partes em arquivos temporários (<PascalCase>Data.part-XXX.json.tmp).

    2. Mover atomicamente os temporários para seus nomes definitivos.

    3. Escrever e validar o manifesto <PascalCase>Data.manifest.json.

    4. Remover partes antigas excedentes (ex: se antes havia 3 partes e a tabela reduziu para 2, apagar part-003).

    5. Remover o <PascalCase>Data.json monolítico obsoleto.

  • Se a tabela encolher e passar a caber em < 80 MiB:

    1. Grava o <PascalCase>Data.json monolítico.

    2. Remove o <PascalCase>Data.manifest.json e todas as partes <PascalCase>Data.part-*.json.

2.3. Leitor Unificado e Compartilhado (gestor/bibliotecas/db-data.php)

  • Criar a biblioteca canônica gestor/bibliotecas/db-data.php (com fallback e carregamento no bootstrap):

    • db_data_read_table(string $table, string $dir): array:

    • Verifica se existe <PascalCase>Data.manifest.json:

      • Valida o manifesto; se qualquer parte listada estiver ausente ou tiver SHA-256 divergente, dispara RuntimeException e aborta imediatamente (fail-fast).

      • Carrega e concatena todas as partes em ordem estrita de índice, retornando o array completo de registros da tabela.

    • Se não houver manifesto, verifica se existe <PascalCase>Data.json e carrega normalmente.

    • Se nenhum existir, retorna [].

    • db_data_write_table(string $table, array $rows, string $dir, array $options = []): array:

    • Recebe o conjunto completo de registros da tabela.

    • Avalia o tamanho serializado e aplica o fracionamento quando necessário (> 80 MiB ou limite customizado via $options['part_size_limit']).

    • db_data_list_tables(string $dir): array:

    • Descobre a lista única de tabelas presentes em $dir.

    • Identifica tabelas tanto por <PascalCase>Data.json quanto por <PascalCase>Data.manifest.json.

    • Ignora expressamente arquivos <PascalCase>Data.part-*.json para evitar que partes soltas sejam listadas como tabelas individuais.

    • db_data_table_manifest(string $table, string $dir): ?array:

    • Retorna o manifesto da tabela se particionada, ou null se arquivo único.


3. Escopo de Integração nos Subsistemas do Core

3.1. Gerador e Compilador de Recursos (atualizacao-dados-recursos.php)

  • Substituir a chamada direta de jsonWrite($DB_DATA_DIR . $file, ...) por db_data_write_table().

  • Em carregarDadosExistentes(), usar db_data_read_table() para que tabelas particionadas (como paginas) sejam lidas integralmente para cálculo de versão e checksum.

  • Em schema-metadata.json, registrar metadados de partição (partitioned: true/false, contagem de partes) no contrato da tabela.

3.2. Sincronizador de Banco de Dados (atualizacoes-banco-de-dados.php)

  • Em comparacaoDados():

    • Substituir glob($DB_DATA_DIR . '*Data.json') por db_data_list_tables($DB_DATA_DIR).

    • Carregar os registros da tabela via db_data_read_table($tabela, $DB_DATA_DIR).

    • Garantia Inviolável: O conjunto de registros entregue ao algoritmo de detecção de órfãos/exclusão é 100% completo, prevenindo falsas deleções no SQL.

3.3. Recuperação de Recursos (recuperacao-dados-recursos.php)

  • Em rdr_processar():

    • Usar db_data_list_tables() e db_data_read_table() para que tabelas particionadas sejam reunidas antes da descompilação de páginas e metadados.

3.4. API de Recuperação / Pacote ZIP (gestor/controladores/api/api.php)

  • Na rotina de compactação ZIP de recuperação (linha 604):

    • Incluir no ZIP: *Data.json, *Data.manifest.json e *Data.part-*.json.

    • Garantir que um ambiente que exporta uma tabela particionada gere um ZIP restaurável em outro ambiente.


4. Critérios de Aceite & Checklist de Validação

  • [ ] Biblioteca gestor/bibliotecas/db-data.php implementada com funções db_data_read_table, db_data_write_table, db_data_list_tables e db_data_table_manifest.

  • [ ] Round-trip perfeito: dataset de teste com tamanho simulado acima do limite gera part-001, part-002 e manifest.json; db_data_read_table remonta exatamente o array original ($original === $reconstruido).

  • [ ] Detecção de corrupção: teste unitário que altera 1 byte de uma parte ou remove uma parte provoca falha imediata (RuntimeException) com hash inválido ou arquivo ausente.

  • [ ] Transição dinâmica: quando o dataset encolhe para menos de 80 MiB, a rotina grava o arquivo monolítico e limpa as partes e o manifesto sem sobras no disco.

  • [ ] O sincronizador do banco (atualizacoes-banco-de-dados.php) carrega a tabela particionada sem disparar exclusões falsas de registros entre partes.

  • [ ] recuperacao-dados-recursos.php e a API de ZIP recuperam tabelas particionadas com integridade total.

  • [ ] Suíte de testes PHPUnit focada cobrindo todos os cenários com 100% de sucesso.

  • [ ] git diff --check e php -l limpos.

O Futuro é Híbrido: Humano + IA.

O Conn2Flow é a ferramenta. Se você precisa do Arquiteto para desenhar a estratégia da sua empresa usando essa tecnologia...

Contrate Consultoria Especializada