> ## Documentation Index
> Fetch the complete documentation index at: https://docs.base44.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Internal links on these pages omit the .md extension. Append .md to a docs page URL, or send an Accept: text/markdown header, to get that page as markdown.

# Actors: fluxos de exemplo

> Fluxos de exemplo para handlers de ciclo de vida, timers, conexões, armazenamento, entidades e funções de backend

<div className="dev-docs-banner">
  <div className="dev-docs-banner-content">
    <div className="dev-docs-banner-title">
      Você está vendo a documentação para desenvolvedores
    </div>

    <div className="dev-docs-banner-text">
      Esta documentação é para desenvolvedores que trabalham com a plataforma para desenvolvedores
      Base44.
    </div>
  </div>
</div>

Use estes fluxos de exemplo como ponto de partida para sua implementação.

## Conectar um cliente a uma sessão

Quando o frontend precisa entrar em uma sessão ao vivo, receber mensagens do actor e enviar mensagens para o actor, conecte um cliente a uma sessão de actor.

**Para conectar um cliente a uma sessão:**

1. Chame [`base44.actors.ActorName(sessionId)`](/pt-BR/developers/references/sdk/docs/type-aliases/actors) para selecionar a sessão.
2. Chame [`.connect()`](/pt-BR/developers/references/sdk/docs/type-aliases/actors#connect) para abrir a conexão WebSocket.
3. Chame [`conn.subscribe()`](/pt-BR/developers/references/sdk/docs/type-aliases/actors#subscribe) para registrar um listener para as mensagens do actor.
4. Chame [`conn.send()`](/pt-BR/developers/references/sdk/docs/type-aliases/actors#send) para enviar uma mensagem para o actor.

O exemplo a seguir se conecta a uma sessão do actor `chatRoom`, escuta mensagens e envia uma mensagem:

```typescript theme={null}
const conn = base44.actors.chatRoom("lobby-1").connect();

conn.subscribe((msg) => {
  if (msg.type === "message") console.log(msg.text);
});

conn.send({ type: "message", text: "Hello" });
```

Para saber mais sobre conexões, veja [conexões](/pt-BR/developers/backend/resources/actors/reference#connections).

## Executar ticks

Quando um trabalho precisa se repetir em um intervalo enquanto há clientes na sessão, execute ticks. Exemplos incluem transmitir o estado do jogo ou atualizar um timer de rodada.

**Para executar ticks:**

1. Defina [`tickIntervalMs`](/pt-BR/developers/backend/resources/actors/reference#timer-handlers-and-settings) com a duração do intervalo em milissegundos.
2. Implemente [`shouldTick()`](/pt-BR/developers/backend/resources/actors/reference#timer-handlers-and-settings) para retornar `true` para continuar os ticks e `false` para pará-los.
3. Em [`handleTick()`](/pt-BR/developers/backend/resources/actors/reference#timer-handlers-and-settings), execute o trabalho de cada intervalo.

O exemplo a seguir executa um tick a cada segundo enquanto há pelo menos dois clientes na sessão, transmitindo uma contagem regressiva a cada tick:

```typescript theme={null}
export default class Game extends Actor<Incoming, Outgoing> {
  tickIntervalMs = 1000;
  countdown = 60;

  shouldTick() {
    return this.getConnections().length >= 2;
  }

  async handleTick() {
    this.countdown--;
    this.broadcast({ type: "tick", countdown: this.countdown });
  }
}
```

Para saber mais sobre ticks, veja [handlers e configurações de timers](/pt-BR/developers/backend/resources/actors/reference#timer-handlers-and-settings).

## Agendar wakes

Quando um trabalho precisa ser executado uma vez em um horário específico, esteja a sessão ativa ou inativa, agende um wake. Exemplos incluem encerrar uma vez após 30 segundos ou fechar um lobby vazio.

**Para agendar um wake:**

1. Chame [`schedule()`](/pt-BR/developers/backend/resources/actors/reference#timer-handlers-and-settings) com uma chave e um horário para agendar o wake.
2. Em [`handleWake()`](/pt-BR/developers/backend/resources/actors/reference#timer-handlers-and-settings), verifique a chave e execute o trabalho desse wake.
3. Quando o wake não for mais necessário, chame [`cancelSchedule()`](/pt-BR/developers/backend/resources/actors/reference#timer-handlers-and-settings) com a chave.

O exemplo a seguir agenda um tempo limite quando uma vez começa e transmite uma mensagem quando o tempo limite é disparado:

```typescript theme={null}
export default class Game extends Actor<Incoming, Outgoing> {
  async handleMessage(_conn, msg) {
    if (msg.type === "start-turn") {
      await this.schedule("turn-timeout", Date.now() + 30_000);
    }
    if (msg.type === "end-turn") {
      await this.cancelSchedule("turn-timeout");
    }
  }

  async handleWake(key: string) {
    if (key === "turn-timeout") {
      this.broadcast({ type: "timeout" });
    }
  }
}
```

Para saber mais sobre wakes, veja [handlers e configurações de timers](/pt-BR/developers/backend/resources/actors/reference#timer-handlers-and-settings).

## Gerenciar conexões de clientes

Quando você precisa decidir quem pode entrar em uma sessão, responder a um cliente específico e alcançar todos os clientes da sessão, gerencie as conexões de clientes.

**Para gerenciar conexões de clientes:**

1. Em [`handleConnect()`](/pt-BR/developers/backend/resources/actors/reference#lifecycle-handlers), verifique [`conn.identity`](/pt-BR/developers/backend/resources/actors/reference#connections) e chame [`conn.reject()`](/pt-BR/developers/backend/resources/actors/reference#connections) para recusar um cliente.
2. Chame [`conn.send()`](/pt-BR/developers/backend/resources/actors/reference#connections) para responder apenas a esse cliente.
3. Em [`handleMessage()`](/pt-BR/developers/backend/resources/actors/reference#lifecycle-handlers), chame [`broadcast()`](/pt-BR/developers/backend/resources/actors/reference#connections) para alcançar todos os clientes conectados. Para identificar o remetente, inclua campos de `conn` na mensagem.

O exemplo a seguir rejeita clientes anônimos, envia o histórico para o cliente que está se conectando e transmite mensagens com o ID de usuário do remetente:

```typescript theme={null}
async handleConnect(conn) {
  if (conn.identity.type === "anonymous") {
    conn.reject(401, "Login required");
    return;
  }
  conn.send({ type: "history", messages: this.messages });
}

async handleMessage(conn, msg) {
  this.broadcast({ type: "message", from: conn.identity.userId, text: msg.text });
}
```

Para saber mais sobre conexões, veja [conexões](/pt-BR/developers/backend/resources/actors/reference#connections).

## Persistir dados da sessão

Quando os valores precisam sobreviver a um período de inatividade, persista os dados da sessão. Exemplos incluem um tabuleiro, uma lista de histórico ou a vez atual.

**Para persistir dados da sessão:**

1. Em [`handleStart()`](/pt-BR/developers/backend/resources/actors/reference#lifecycle-handlers), carregue os valores de [`this.storage`](/pt-BR/developers/backend/resources/actors/reference#storage) para os campos da classe.
2. Após cada mudança, chame [`this.storage.put()`](/pt-BR/developers/backend/resources/actors/reference#storage) para salvar o valor atualizado.
3. Para redefinir a sessão, chame [`this.storage.delete()`](/pt-BR/developers/backend/resources/actors/reference#storage) ou [`this.storage.deleteAll()`](/pt-BR/developers/backend/resources/actors/reference#storage).

O exemplo a seguir carrega um tabuleiro ao iniciar, salva-o após cada jogada e limpa o armazenamento quando o último cliente se desconecta:

```typescript theme={null}
async handleStart() {
  this.board = (await this.storage.get<Board>("board")) ?? newBoard();
}

async handleMessage(_conn, msg) {
  applyMove(this.board, msg.move);
  await this.storage.put("board", this.board);
}

async handleClose(_conn) {
  if (this.getConnections().length === 0) {
    await this.storage.deleteAll();
  }
}
```

Para saber mais sobre armazenamento, veja [armazenamento](/pt-BR/developers/backend/resources/actors/reference#storage).

## Gravar dados de entidades a partir de uma sessão

Quando a sessão precisa criar ou atualizar registros do app, grave dados de entidades. Exemplos incluem uma pontuação final ou um pedido concluído.

**Para gravar dados de entidades a partir de uma sessão:**

1. Valide a mensagem recebida antes de gravar.
2. Leia o ID do usuário em [`conn.identity.userId`](/pt-BR/developers/backend/resources/actors/reference#connections).
3. Use [`this.client.asServiceRole`](/pt-BR/developers/backend/resources/actors/reference#entity-access) para acesso elevado. Grave com uma chave estável, como o ID da sessão, para que um handler repetido atualize o mesmo registro.

O exemplo a seguir salva uma pontuação final para o cliente autenticado. Um salvamento posterior para a mesma sessão atualiza esse registro:

```typescript theme={null}
async handleMessage(conn, msg) {
  if (msg.type !== "save-score" || conn.identity.type !== "authenticated") return;
  if (typeof msg.score !== "number") return;

  const fields = {
    sessionId: this.instanceId,
    userId: conn.identity.userId,
    score: msg.score,
  };
  const [existing] = await this.client.asServiceRole.entities.Score.filter({
    sessionId: this.instanceId,
  });

  if (existing) {
    await this.client.asServiceRole.entities.Score.update(existing.id, fields);
  } else {
    await this.client.asServiceRole.entities.Score.create(fields);
  }
}
```

Para saber mais sobre acesso a entidades, veja [acesso a entidades](/pt-BR/developers/backend/resources/actors/reference#entity-access).

## Chamar uma função de backend para trabalhos com secrets

Os actors podem ler secrets do app com [`secrets.get()`](/pt-BR/developers/backend/resources/actors/reference#read-secrets). Quando um handler precisa de um trabalho que usa um secret, como chamar uma API externa com uma chave de API, recomendamos chamar uma [função de backend](/pt-BR/developers/backend/resources/backend-functions/overview). A função lê o secret e retorna o resultado, nunca o secret.

**Para chamar uma função de backend a partir de um actor:**

1. Crie uma função de backend que leia o secret com `secrets.get()`, faça o trabalho e retorne o resultado.
2. Em um handler, chame [`this.client.functions.invoke()`](/pt-BR/developers/references/sdk/docs/interfaces/functions#invoke) com o nome da função e os dados a serem enviados.
3. Use o resultado na sua sessão, por exemplo transmitindo-o para os clientes conectados.

O exemplo a seguir mostra uma função de backend que lê uma chave de API e retorna uma tradução:

```typescript theme={null}
// base44/functions/translateText/entry.ts
import { secrets } from "base44:runtime";

export default async function (req: Request): Promise<Response> {
  const { text } = await req.json();
  const apiKey = secrets.get("TRANSLATE_API_KEY");

  const res = await fetch("https://api.example.com/translate", {
    method: "POST",
    headers: { Authorization: `Bearer ${apiKey}` },
    body: JSON.stringify({ text }),
  });
  const { translation } = await res.json();

  return Response.json({ translation });
}
```

O exemplo a seguir chama essa função a partir de um actor e transmite o resultado:

```typescript theme={null}
export default class ChatRoom extends Actor<Incoming, Outgoing> {
  async handleMessage(_conn, msg) {
    const result = await this.client.functions.invoke("translateText", { text: msg.text });
    this.broadcast({ type: "message", text: result.data.translation });
  }
}
```

## Veja também

* [Visão geral de actors](/pt-BR/developers/backend/resources/actors/overview): Conceitos e terminologia
* [Criar um actor](/pt-BR/developers/backend/resources/actors/create-actor): Arquivos do actor e uma classe mínima
* [Arquivos e código de actors](/pt-BR/developers/backend/resources/actors/reference): API completa da classe de backend
* [`actors deploy`](/pt-BR/developers/references/cli/commands/actors-deploy): Implante actors locais

<Note>Esta página foi traduzida usando IA. Para as informações mais precisas e atualizadas, consulte a [versão em inglês](/). </Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.