Rollback Defensivo de Estado
Workers persistentes não reinicializam o estado global do processo PHP automaticamente entre requisições.
Se o código da aplicação ou de um pacote terceiro alterar configurações globais (como o fuso horário padrão, níveis de reporte de erro ou abrir buffers de saída sem fechá-los), essas alterações permanecem e poluem as requisições subsequentes.
Entidades de Estado Gerenciadas
Durante o ciclo de cada requisição, o Leakless captura e restaura automaticamente três pontos críticos de estado:
1. Restauração do Fuso Horário Padrão (Timezone)
Se alguma rotina invocar date_default_timezone_set():
- O Leakless registra o fuso horário inicial no
$leakless->startRequest(). - Se o timezone tiver sido alterado durante a requisição, o Leakless executa
date_default_timezone_set($originalTimezone)no$leakless->endRequest().
2. Esvaziamento de Buffers de Saída Residuais
Se um erro ou fluxo não fechar buffers de saída (ob_start() sem ob_end_clean() ou ob_get_clean()):
- O Leakless mede a profundidade inicial dos buffers (
ob_get_level()) nostartRequest(). - No
endRequest(), o Leakless esvazia os buffers adicionais comob_end_clean()até restaurar o nível original, impedindo que fragmentos de HTML ou JSON vazem para as próximas respostas.
3. Níveis de Reporte de Erro (error_reporting)
Se o código alterar temporariamente o nível de reporte (error_reporting(E_ALL) ou desativar avisos):
- O Leakless grava o bitmask original de
error_reporting(). - Restaura o nível original ao término da requisição.
4. Engine de Resettables Zero-Reflection (StateResetter)
Além das configurações globais do PHP, serviços persistentes e singletons com propriedades mutáveis frequentemente acumulam estado entre requisições (como caches, buffers e sessões).
O Leakless inclui um motor de alta performance baseado no modelo Zero Reflection no Hot Path:
registerTarget($target) / Config::$resettables ──► [Warmup / Registro (Reflection roda 1 vez)]
│
▼
Compila Closures nativas
│
▼
endRequest() ─────────────────────────────────────► foreach ($closures) { $closure(); }
[Hot Path: Closures nativas puras]Tipos de Alvos Suportados
Callbacks / Closures Anônimas:
php$config = new Config( resettables: [ fn () => LegacyRegistry::$cache = [], ], );Métodos Convencionais de Reset (
ResetInterface/reset()/cleanup()):phpclass CartSession { public array $items = []; public function reset(): void { $this->items = []; } }Métodos Estáticos de Limpeza em Classes:
phpclass MetricsBuffer { public static array $logs = []; public static function resetState(): void { self::$logs = []; } }Atributo Declarativo
#[ResetOnRequest]em Alvos Registrados:phpuse TheMattos\Leakless\Attributes\ResetOnRequest; class UserContext { // Propriedades estáticas são resetadas ao registrar UserContext::class em resettables: #[ResetOnRequest] public static ?string $token = null; #[ResetOnRequest(default: 'guest')] public static string $role = 'guest'; // Propriedades de instância são resetadas ao registrar a instância do objeto em resettables: #[ResetOnRequest(default: [])] public array $permissions = []; }Registre o alvo na sua configuração:
php$config = new Config( resettables: [ // Reseta propriedades estáticas #[ResetOnRequest]: UserContext::class, // Para resetar propriedades de instância, informe a instância resolvida: // $userContextInstance, ], );
Importante: Sem Varredura Automática de Projeto
O atributo #[ResetOnRequest] define o plano de compilação de reset de propriedades e métodos, mas exige que a classe ou instância seja explicitamente registrada no array resettables ou via $leakless->registerResetTarget(). O Leakless não faz varreduras globais de reflexão ou AST para manter o boot com overhead zero.
Ao término de cada requisição (endRequest()), o Leakless executa todas as closures compiladas sem nenhum overhead de reflexão em tempo de execução.