Pular para conteúdo

title: Conceito: Signal description: O Signal como ocorrência tipada e motor da reatividade interna do framework.


Signal

O Signal é a forma como o local_middag comunica que algo aconteceu. Ele é o motor do barramento de eventos interno que permite reações rápidas, desacopladas e extensíveis a partir de um único fato.


O que é

Um Signal é uma ocorrência tipada publicada pelo Dispatcher principal do framework. Ele é representado por um objeto PHP rico (um DTO) que carrega o contexto do fato ocorrido.

Diferente de sistemas legados que usam arrays genéricos ou apenas strings, o Signal no framework é desacoplado de sua representação textual pública (Hook), priorizando o transporte de objetos de domínio entre os componentes internos.

Por que existe

O local_middag precisa reagir de forma lateral a diversas ações (ex: ao criar um item, precisamos gerar auditoria, notificar o Sentry e atualizar o BigQuery). Se colocarmos tudo isso dentro de um único service: 1. O service torna-se um "God Object". 2. Adicionar uma nova funcionalidade exigiria alterar o código do core. 3. O sistema ficaria lento devido a processamentos síncronos excessivos.

O Signal resolve isso ao separar o Emissor (quem faz a ação) do Receptor (quem reage à ação), permitindo um design fan-out (uma emissão para múltiplas reações).

Como se relaciona com outros conceitos

O framework utiliza quatro mecanismos reativos com papéis distintos:

  • Signal vs Evento Moodle: Signals são internos e desacoplados; Eventos Moodle são da plataforma externa. O framework captura os eventos Moodle através de um Observer Central e os traduz para Signals internos quando necessário.
  • Signal vs Hook: O Signal é o objeto interno rico. O Hook (middag/user_created) é a projeção pública desse Signal em formato de string para compatibilidade e facilidade de uso por terceiros.
  • Signal vs Filter: O Signal apenas observa um fato ("isso aconteceu"). O Filter intercepta e transforma um valor ("mude este dado antes de seguir").
  • Signal vs Audit: Muitos Signals geram Audit Logs, mas nem todo Signal é auditado (ex: Signals de busca ou de cache).

Decisões de design

  • Emissão Única: O core nunca deve disparar manualmente um Signal e um Hook para o mesmo fato. O framework projeta o Hook automaticamente a partir do Signal.
  • Dispatcher Centralizado: O ponto de entrada oficial para publicação é o método middag::dispatch(), tornando a reatividade uma cidadã de primeira classe na API pública do framework.
  • Naming Canônico: Hooks derivados seguem o padrão middag/prefixo/entidade_acao (ex: middag/revision/created), garantindo um contrato estável e previsível.

O que não é

  • Não é um Log: O Signal existe apenas em memória durante o request (a menos que seja capturado e salvo como Audit).
  • Não é um Queue (Fila): O Signal é executado de forma síncrona pelo Dispatcher. Se a reação for pesada, o listener deve abrir um Job assíncrono.
  • Não é uma Substituição de Chamada Direta: Não use Signals para esconder dependências obrigatórias da lógica principal. Se a operação precisa do retorno de um componente para seguir, use Injeção de Dependência.

Perspectiva para builders de extensions

Para sua extension ser reativa e "cidadã" do ecossistema: 1. Crie listeners: Coloque suas classes de reação em {extension}/hook/. O framework irá descobri-las automaticamente durante o boot. 2. Consuma Signals: Prefira ouvir Signals tipados do core para ganhar acesso a objetos ricos de domínio. 3. Use Hooks apenas na fronteira: Se precisar que plugins externos (não integrados ao framework) reajam à sua extension, defina um nome canônico de Hook para sua ocorrência.

Exemplo ilustrativo

Publicando uma ocorrência de negócio:

// No seu Service de Extensão
use local_middag\extensions\ecommerce\signal\order_processed_signal;
use local_middag\middag;

// 1. Prepara o Signal com o objeto da ordem
$signal = new order_processed_signal($order_item, $user_id);

// 2. Despacha
middag::dispatch($signal);

// A partir daqui, listeners do core atuarão:
// - O Audit salvará a mudança de status da ordem.
// - O BigQuery enviará os dados para o analytics (via Job).
// - O Moodle disparará qualquer plugin que ouça o hook 'middag/ecommerce/order_processed'.

Referências