Como conectar um serviço do Azure Fluid Relay

Este artigo explica as etapas para provisionar e preparar seu serviço do Azure Fluid Relay para uso.

Importante

Antes de conectar seu aplicativo a um servidor do Azure Fluid Relay, você deve provisionar um recurso do servidor do Azure Fluid Relay em sua conta do Azure.

O serviço do Azure Fluid Relay é um serviço Fluid hospedado na nuvem. Você pode conectar seu aplicativo Fluid a uma instância do Azure Fluid Relay usando o AzureClient no pacote @fluidframework/azure-client . O AzureClient lida com a lógica de conectar seu contêiner Fluid ao serviço, mantendo o próprio objeto de contêiner independente do sistema. Você pode usar uma instância desse cliente para gerenciar vários contêineres.

As seções a seguir explicarão como usar AzureClient em seu próprio aplicativo.

Conectando-se ao serviço

Para se conectar a uma instância do Azure Fluid Relay, primeiro você precisa criar um AzureClient. Você deve fornecer alguns parâmetros de configuração, incluindo a ID do locatário, a URL de serviço e um provedor de token para gerar o Token Web JSON (JWT) que será usado para autorizar o usuário atual no serviço. O pacote @fluidframework/test-client-utils fornece um InsecureTokenProvider que pode ser usado para fins de desenvolvimento.

Cuidado

O InsecureTokenProvider só deve ser usado para fins de desenvolvimento, pois usá-lo expõe o segredo da chave do locatário no pacote de códigos do lado do cliente. Isso deve ser substituído por uma implementação de ITokenProvider que busca o token de seu próprio serviço de back-end responsável por assiná-lo com a chave do locatário. Um exemplo de implementação é o AzureFunctionTokenProvider. Para obter mais informações, confira Como gravar um TokenProvider com uma função do Azure. Observe que os campos id e name são arbitrários.

const user = { id: "userId", name: "userName" };

const config = {
  tenantId: "myTenantId",
  tokenProvider: new InsecureTokenProvider("myTenantKey", user),
  endpoint: "https://myServiceEndpointUrl",
  type: "remote",
};

const clientProps = {
  connection: config,
};

const client = new AzureClient(clientProps);

Agora que você tem uma instância do AzureClient, pode começar a usá-la para criar ou carregar contêineres Fluid!

Provedores de token

O AzureFunctionTokenProvider é uma implementação que garante que o segredo da chave do locatário não seja exposto no código do pacote do lado do ITokenProvider cliente. O AzureFunctionTokenProvider recebe a URL da sua Função do Azure anexada por /api/GetAzureToken junto com o objeto de usuário atual. Posteriormente, ele faz uma solicitação GET para a Função do Azure passando o tenantId, o documentId e o userId/userName como parâmetros opcionais.

const config = {
  tenantId: "myTenantId",
  tokenProvider: new AzureFunctionTokenProvider(
    "myAzureFunctionUrl" + "/api/GetAzureToken",
    { userId: "userId", userName: "Test User" }
  ),
  endpoint: "https://myServiceEndpointUrl",
  type: "remote",
};

const clientProps = {
  connection: config,
};

const client = new AzureClient(clientProps);

Adicionando dados personalizados a tokens

O objeto de usuário também pode conter detalhes adicionais opcionais do usuário. Por exemplo:

const userDetails = {
  email: "xyz@outlook.com",
  address: "Redmond",
};

const config = {
  tenantId: "myTenantId",
  tokenProvider: new AzureFunctionTokenProvider(
    "myAzureFunctionUrl" + "/api/GetAzureToken",
    { userId: "UserId", userName: "Test User", additionalDetails: userDetails }
  ),
  endpoint: "https://myServiceEndpointUrl",
  type: "remote",
};

Sua Função do Azure gerará o token para o usuário determinado que está conectado usando a chave secreta do locatário e o retornará ao cliente sem expor o segredo.

Gerenciamento de contêineres

A AzureClient API expõe as funções createContainer e getContainer para criar e obter contêineres, respectivamente. Ambas as funções têm um esquema de contêiner que define o modelo de dados do contêiner. Para a função getContainer, há um parâmetro adicional para o contêiner id do contêiner que você deseja buscar.

No cenário de criação de contêiner, você pode usar o seguinte padrão:

const schema = {
  initialObjects: {
    /* ... */
  },
  dynamicObjectTypes: [
    /*...*/
  ],
};
const azureClient = new AzureClient(clientProps);
const { container, services } = await azureClient.createContainer(
  schema
);
const id = await container.attach();

A chamada container.attach() é quando o contêiner realmente se conecta ao serviço e é registrado em seu armazenamento de blob. Ele retorna um id que é o identificador exclusivo para essa instância de contêiner.

Qualquer cliente que deseja ingressar na mesma sessão colaborativa precisa chamar getContainer com o mesmo contêiner id.

const { container, services } = await azureClient.getContainer(
  id,
  schema
);

Para obter mais informações sobre como iniciar a gravação de logs emitidos pelo Fluid, confira Registro em log e telemetria.

O contêiner que está sendo buscado conterá o initialObjects conforme definido no esquema de contêiner. Consulte Modelagem de dados em fluidframework.com para saber mais sobre como estabelecer o esquema e usar o objeto container.

Obter detalhes do público

Chama e createContainer getContainer retorna dois valores: a container -- descrito acima -- e um objeto services.

O container contém o modelo de dados Fluid e é independente do serviço. Qualquer código que você gravar nesse objeto de contêiner retornado pelo AzureClient é reutilizável com o cliente para outro serviço. Um exemplo é se você prototipou seu cenário usando TinyliciousClient, todo o seu código interagindo com os objetos compartilhados dentro do contêiner Fluid pode ser reutilizado ao mover para o uso AzureClientdo .

O objeto services contém dados específicos para o serviço do Azure Fluid Relay. Esse objeto contém um valor da audiência que pode ser usado para gerenciar a lista de usuários que estão conectados ao contêiner no momento.

O código a seguir demonstra como você pode usar o objeto audience para manter uma exibição atualizada de todos os membros que estejam atualmente em um contêiner.

const { audience } = containerServices;
const audienceDiv = document.createElement("div");

const onAudienceChanged = () => {
  const members = audience.getMembers();
  const self = audience.getMyself();
  const memberStrings = [];
  const useAzure = process.env.FLUID_CLIENT === "azure";

  members.forEach((member) => {
    if (member.userId !== (self ? self.userId : "")) {
      if (useAzure) {
        const memberString = `${member.userName}: {Email: ${member.additionalDetails ? member.additionalDetails.email : ""},
                        Address: ${member.additionalDetails ? member.additionalDetails.address : ""}}`;
        memberStrings.push(memberString);
      } else {
        memberStrings.push(member.userName);
      }
    }
  });
  audienceDiv.innerHTML = `
            Current User: ${self ? self.userName : ""} <br />
            Other Users: ${memberStrings.join(", ")}
        `;
};

onAudienceChanged();
audience.on("membersChanged", onAudienceChanged);

audience fornece duas funções que retornarão objetos AzureMember que têm uma ID de usuário e um nome de usuário:

  • O getMembers retorna um mapa de todos os usuários conectados ao contêiner. Esses valores serão alterados sempre que um membro ingressar ou sair do contêiner.
  • O getMyself retorna o usuário atual neste cliente.

O audience também emite eventos para quando a lista de membros se alterar. O membersChanged irá disparar para quaisquer alterações na lista de membros, enquanto memberAdded e memberRemoved irão disparar para suas respectivas alterações com os valores clientId e member que foram modificados. Depois que qualquer um desses eventos disparar, uma nova chamada para getMembers retornará a lista de membros atualizada.

Um objeto AzureMember de exemplo se parece com o seguinte:

{
  "userId": "0e662aca-9d7d-4ff0-8faf-9f8672b70f15",
  "userName": "Test User",
  "connections": [
    {
      "id": "c699c3d1-a4a0-4e9e-aeb4-b33b00544a71",
      "mode": "write"
    },
    {
      "id": "0e662aca-9d7d-4ff0-8faf-9f8672b70f15",
      "mode": "write"
    }
  ],
  "additionalDetails": {
    "email": "xyz@outlook.com",
    "address": "Redmond"
  }
}

Juntamente com o ID do usuário, nome e detalhes adicionais, AzureMember os objetos também mantêm uma matriz de conexões. Se o usuário estiver conectado à sessão com apenas um cliente, o connections terá apenas um valor com a ID do cliente e se estiver no modo de leitura/gravação. No entanto, se o mesmo usuário estiver conectado de vários clientes (ou seja, eles estiverem conectados de diferentes dispositivos ou têm várias guias do navegador abertas com o mesmo contêiner), o connections aqui conterá vários valores para cada cliente. Nos dados de exemplo acima, podemos ver que um usuário com o nome "Usuário de Teste" e a ID "0e662ções-9d7d-4ff0-8faf-9f8672b70f15" atualmente tem o contêiner aberto em dois clientes diferentes. Os valores no campo additionalDetails correspondem aos valores fornecidos na geração de AzureFunctionTokenProvider token.

Essas funções e eventos podem ser combinados para apresentar uma exibição em tempo real dos usuários na sessão atual.

Parabéns! Agora você conectou com êxito seu contêiner Fluid ao serviço do Azure Fluid Relay e retornou os detalhes do usuário para os membros em sua sessão colaborativa!