Recursos
A parte difícil do realtime, já rodando
Um recurso realtime é um pouco de código de produto sobre muita maquinaria de entrega: quem está inscrito, quem tem permissão, quem ainda está lá. O PushCaster é essa segunda parte.
Channels
Quatro tipos, e o prefixo é o contrato
O nome de um channel decide como ele se comporta. O prefixo diz à biblioteca se ela deve pedir autorização ao seu servidor, se deve esperar uma lista de membros e se deve criptografar.
| Prefixo | Quem pode se inscrever | Para que serve | Autorização |
|---|---|---|---|
| public | Qualquer pessoa com a app key. | Status de build, placares ao vivo, feeds públicos. | Nenhuma |
| private- | Seu servidor decide, inscrito por inscrito. | Qualquer coisa restrita a uma conta ou a um recurso. | Assinada |
| presence- | Autorizado, e traz a lista de membros. | Salas e sessões, em que a participação é o recurso. | Assinada |
| private-encrypted- | Autorizado; os payloads são criptografados pelos seus clientes. | Payloads que devem ficar opacos para nós também. | Assinada |
cache- os channels entregam events ao vivo mas não reproduzem estado guardado — veja diferenças conhecidas.
Autorização
Seu servidor continua sendo a autoridade
Não somos nós que concedemos as inscrições private e presence. É a sua aplicação, e ela assina a resposta com o seu app secret. Nós verificamos a assinatura e mais nada.
- Um endpointPOST /pusher/auth mantém o formato da requisição e da resposta.
- Suas regrasSe este socket pode entrar neste channel é uma pergunta que só você responde.
- Identidade em presenceA mesma chamada devolve o member id e o que os outros membros devem ver.
import Pusher from 'pusher'const pusher = new Pusher({ appId: process.env.PUSHCASTER_APP_ID, key: process.env.PUSHCASTER_KEY, secret: process.env.PUSHCASTER_SECRET, host: 'api-eu1.pushcaster.io', useTLS: true,})// Called by the client library whenever it subscribes to a// private-, presence- or private-encrypted- channel.app.post('/pusher/auth', (req, res) => { const { socket_id, channel_name } = req.body const user = req.session.user if (!user || !mayJoin(user, channel_name)) { return res.sendStatus(403) } res.send( pusher.authorizeChannel(socket_id, channel_name, { user_id: String(user.id), user_info: { name: user.name }, }), )})Webhooks
O que a camada de sockets vê, seu backend escuta
Ocupação e participação só são visíveis na conexão. Os webhooks devolvem isso, assinado — para você começar o trabalho quando chega o primeiro espectador e parar quando o último sai.
| Event | Dispara quando |
|---|---|
| channel_occupied | O primeiro inscrito entrou num channel vazio. |
| channel_vacated | O último inscrito saiu. |
| member_added | Alguém entrou num channel presence. |
| member_removed | Alguém saiu de um channel presence. |
| client_event | Um cliente mandou um event direto para um channel. |
| cache_miss | Um channel cache recebeu um pedido de estado que ele não tinha. |
app.post('/pushcaster/webhooks', (req, res) => { const hook = pusher.webhook({ headers: req.headers, rawBody: req.rawBody }) // The signature is computed with your app secret, so an // unsigned or mismatched delivery never reaches your logic. if (!hook.isValid()) return res.sendStatus(401) for (const event of hook.getEvents()) { if (event.name === 'channel_occupied') startFeed(event.channel) if (event.name === 'channel_vacated') stopFeed(event.channel) } res.sendStatus(200)})Bibliotecas
Não existe SDK do PushCaster, de propósito
O PushCaster fala o protocolo Pusher Channels no fio, então as bibliotecas oficiais funcionam com ele sem modificação. Nenhum pacote nosso para adicionar, e nada nosso que quebra quando lançamos.
- pusher-js
- Laravel Echo
- pusher/pusher-php-server
- pusher-http-node
- Python
- Go
- Ruby
- Java
- Android
- iOS
- Flutter
- Unity
Linha de instalação, completa: npm i pusher-js.
Infraestrutura
Duas camadas, e um cluster que você escolhe
A entrega roda numa camada separada da cobrança e da configuração, então uma queda do control plane degrada o painel sem interromper a entrega.
Rodando agora
- eu1Europa Oeste
- eu2Europa Central
Os clusters são de alta disponibilidade para mensageria e não para presence: se um armazenamento de presence se perde, presence e ocupação degradam enquanto os channels public e private continuam entregando. Melhor ler aqui do que descobrir depois.
Veja o caminho de um publish