Eventos, RPC e contratos
Três mecanismos concretos de comunicação: notificar fatos, pedir respostas e consumir serviços versionados.
Escolha pelo tipo de interação
| Necessidade | API | Resultado |
|---|---|---|
| Notificar um fato sem resposta | emit / on |
Evento com identidade e dados |
| Pedir uma resposta a um provedor | request / handle |
Promise com valor ou erro |
| Invocar métodos de um serviço local | provide / consume |
Proxy de um contrato versionado |
Os três mecanismos vivem no processo JavaScript do navegador. RPC neste contexto não implica HTTP nem transporte entre servidores. Uma implementação pode fazer fetch internamente, mas esse efeito e sua autorização pertencem à implementação.
Os fragmentos que usam wu pressupõem import { wu } from 'wu-framework' no módulo cliente do shell e sua inicialização com await wu.init(...). Os fragmentos com appWu usam o context.wu entregue a uma app em mount(container, context). Para copiar um exemplo completo, siga Uma soma entre aplicações: cliente, provedor, manifestos, concessões e página Astro, com uma resposta observável e um caso de erro recuperável.
Eventos e envelope
// Código del shell, con autoridad host.
const stop = wu.on('catalog:*', (event) => {
console.log(event.name, event.data, event.appName, event.verified);
});
const accepted = wu.emit('catalog:selected', { productId: 'p-42' });
if (!accepted) console.info('El bus rechazó el evento');
stop();
O callback recebe um objeto com name, data, timestamp, appName, meta e verified. Os dados são separados e congelados ao cruzar a fronteira do barramento. once remove sua inscrição após a primeira entrega; off remove uma inscrição específica.
Em uma app, use context.wu.on e context.wu.emit. A fachada anexa sua identidade e verifica as concessões. No modo estrito, emitir sem identidade válida, sem capacidade ou para um namespace reservado retorna false. Inscrições e RPC negados podem lançar erros: verifique o booleano de emit e trate as exceções das APIs que as produzem.
O barramento guarda até 100 eventos por padrão. eventBus.replay(pattern, callback) entrega novamente entradas existentes ao callback fornecido; não executa novamente o sistema nem garante recuperar efeitos externos. history: false permite excluir uma emissão do histórico.
RPC com timeout e versão
const release = wu.eventBus.handle('catalog:lookup', ({ productId }) => {
return { productId, title: 'Producto de demostración' };
}, { version: '1.0.0', allow: ['search'] });
// Dentro del lifecycle de la app search, con rpc.call:catalog:lookup:
async function lookup(appWu, productId, signal) {
return appWu.request('catalog:lookup', { productId }, {
version: '^1.0.0',
timeout: 2500,
signal,
});
}
// Cuando el proveedor del shell ya no deba atender:
release();
Uma app provedora precisa de rpc.provide e uma consumidora, de rpc.call sobre o canal. Além disso, allow filtra identidades das chamadas. Para um provedor de app com escopo no modo estrito, o allow padrão permite essa mesma app; para comunicação entre apps, declare os consumidores explicitamente.
wu.handle(channel, handler, options) preserva version, allow e replace. Dentro do lifecycle, context.wu.handle também adiciona a identidade e os grants da app; use essa facade para handlers de uma microapp.
O timeout padrão de request é 0, sem limite de tempo. Use um valor finito para interações de UI. O handler recebe um segundo argumento com dados de correlação e identidade e um signal. Deve cooperar com esse signal para cancelar seu próprio trabalho; rejeitar a espera não reverte uma operação já realizada.
Um canal tem um provedor ativo. Substituir o mesmo provedor requer { replace: true } nas condições estritas; outra identidade não pode se apropriar de um canal que já tem proprietário. Liberação, substituição e revogação do provedor abortam as solicitações associadas. O barramento emite rastros <canal>:request, <canal>:response e <canal>:error com correlação.
Contratos de métodos locais
const handle = wu.provide('formatters', {
price(value) {
return new Intl.NumberFormat('es-MX', {
style: 'currency', currency: 'MXN',
}).format(value);
},
}, {
version: '1.0.0',
shape: { price: 'function' },
});
const formatters = wu.consume('formatters', '^1.0.0');
console.log(formatters.price(120));
handle.revoke();
consume entrega um proxy vivo. Sem { wait: true }, criar o proxy não exige a existência do provedor: o primeiro acesso a um membro valida existência e versão. Com { wait: true, timeout: 2500 }, espera até encontrar um provedor compatível.
A versão padrão de provide é 0.0.0, diferente de handle RPC, cujo padrão é 1.0.0. shape verifica a presença ou o typeof dos membros; não substitui um schema completo de argumentos/resultados.
Uma fachada de app exige rpc.provide/rpc.call também para contratos e associa automaticamente o provedor à app. Os proxies consumidos não são promises; um método chamado literalmente then não é acessível por essa via. Contratos não implementa a mesma lista de permissões nem a mesma separação de payloads que o RPC do barramento; escolha o contrato considerando esse limite.
Erros que convém tratar
| Código RPC | Causa |
|---|---|
WU_RPC_NO_HANDLER |
Não há provedor do canal |
WU_RPC_VERSION_MISMATCH |
A versão não atende ao intervalo |
WU_RPC_CALLER_DENIED |
O consumidor não está em allow |
WU_RPC_CALL_DENIED / WU_RPC_PROVIDE_DENIED |
Falta uma concessão efetiva |
WU_RPC_CHANNEL_OWNED |
Outro proprietário já registrou o canal |
WU_RPC_REPLACE_REQUIRED |
Falta intenção explícita de substituição |
WU_RPC_PROVIDER_RELEASED / WU_RPC_PROVIDER_REPLACED |
O provedor deixou de ser o mesmo durante a solicitação |
Referência de implementação
Eventos: src/core/wu-event-bus.js; RPC: src/core/wu-event-bus.js e src/core/wu-event-bus.js; atalho handle do singleton: src/index.js; replay: src/core/wu-event-bus.js; contratos: src/core/wu-contracts.js e src/core/wu-contracts.js; fachada: src/core/wu-core.js. Testes: tests/unit/event-bus.test.js, tests/unit/contracts.test.js, tests/unit/capability-security-v3.test.js, tests/unit/scoped-events-teardown.test.js.
O primeiro provider é dono do nome de um contrato. Outra app, ou o host substituindo um contrato de app, recebe WU_CAPABILITY_OWNED até o proprietário revogar o contrato ou desmontar. O mesmo proprietário pode substituir sua implementação. Quando há shape, portas remotas só expõem os métodos declarados por ela.