Pular para o conteúdo principal

appcore-core

Pacote publicado

Estável 1.0.0 · MSRV Rust 1.89 · crates.io · docs.rs · código-fonte

Guia e exemplos mantidos pelo crate

O repositório do Runtime mantém o guia detalhado, exemplo básico e exemplo intermediário. O wiki resume a fronteira pública; detalhes de API e execução ficam junto ao código do crate.

Responsabilidade: lifecycle, registro, dispatch, state, audit e idempotência genéricos dentro do processo.

Dependências internas: appcore-contracts, appcore-types.

API principal: RuntimeBuilder, RuntimeController, RuntimeInstance, RuntimeLifecycle, registries e buses de command/event, envelopes, CommandHandler, CommandResult, RuntimeContext, audit log/journal, idempotência em memória/arquivo, state e decision engines, clock, redaction e AppPlugin de compatibilidade.

Na linha de manutenção 1.0 atual, clones de RuntimeController compartilham lifecycle, idempotência e estado inflight, enquanto o command bus imutável possui handlers por Arc. Handlers independentes executam em paralelo; uma chave idempotente ainda admite no máximo uma execução. O shutdown fecha a admissão atomicamente antes da drenagem limitada dos comandos admitidos.

RuntimeLifecycle guarda um único enum de estado Copy no mutex e aplica as 12 transições estáveis exatas por uma função total. Nenhum nome validado ou tabela de transições é alocado por instância. A StateMachine pública genérica continua disponível e inalterada para estados pertencentes à aplicação.

O AuditLog local ao processo limita os snapshots de commands e entradas genéricas a 10.000 itens e um orçamento padrão compartilhado de 16 MiB. with_max_bytes pode apertar o orçamento; stats expõe bytes atuais/de pico, evictions e rejections; write_jsonl transmite um snapshot copy-on-write compartilhado depois de liberar o lock de estado. O adaptador compatível export_jsonl retorna intencionalmente uma String owned.

Use entries_snapshot para obter um array JSON estruturado. A visão imutável implementa Serialize, compartilha o armazenamento retido em vez de cloná-lo profundamente e permanece estável após mutações posteriores. A fixture pretty-JSON medida tinha 10.000 entradas e 2.996.676 bytes, com 1,12 ms p50 e 6,42 MiB de RSS pico no Apple M1.

records_snapshot fornece a visão correspondente dos registros de command. Os dois tipos de snapshot expõem recent(limit) para o caller emprestar somente a página mais nova após liberar o lock. Uma seleção de 1.000 em 10.000 mediu 2,06 us p50 e 11,88 MiB de RSS pico, contra 4,16 ms e 20,33 MiB para cópias owned integrais.

Com um FileOperationalJournal anexado, entradas de audit novas e entradas seguras restauradas retêm um único registro operacional imutável compartilhado. A leitura do journal valida a hash chain, verifica o texto de audit sem alocar, sanitiza apenas conteúdo inseguro e o regrava atomicamente antes de expô-lo. Anexações posteriores do log copiam somente handles Arc limitados. APIs owned, JSON do snapshot e persistência V1 não mudam. Uma única anexação sobre 384 entradas seguras (cerca de 3 MiB) reduziu p50 de 12,26 ms para 86,50 us (-99,29%), RSS pico em 0,57% e RSS da carga em 1,72% no Apple M1. A carga separada com fsync conserva os ganhos anteriores de 27,83% em p50, 37,30% em RSS pico e 47,93% em memória retida.

O EventBus local ao processo retém separadamente no máximo 10.000 eventos e 16 MiB por padrão. stats expõe bytes atuais/de pico, evictions e rejeições de eventos grandes; snapshot().recent(limit) empresta uma página estável. Selecionar 1.000 de 10.000 eventos mediu 2,39 us p50 e 8,48 MiB de RSS pico, contra 2,09 ms e 14,59 MiB do método compatível de cópia integral. Quando um FileOperationalJournal está anexado, ele e o bus retêm uma única alocação imutável compartilhada do registro de evento. O restore copia apenas handles Arc limitados; APIs owned, JSON do snapshot e formato V1 do journal não mudam. Uma carga real de fsync com 3 MiB reduziu o RSS pico de 8,11 para 5,08 MiB (-37,38%) e a memória retida em 48,00%, com p50 dominado por disco dentro de +0,95%.

Aplicações novas usam esses contratos por appcore_sdk; não montam o core manualmente. Mantenha I/O adapters e comportamento de domínio fora.

Maturidade: superfície low-level estável; builder/plugin são de compatibilidade e manifest-first é o caminho preferido.