WEBSOCKETload.thread

Carregar Thread de Revisão

Evento WebSocket recebido pelo frontend quando um thread de revisão de resultado de laboratório é carregado ou atualizado. Este evento é sempre emitido via broadcast para todos os clientes conectados da mesma conta, permitindo sincronização automática. O evento é emitido em dois contextos: 1. **Solicitação direta**: Quando o cliente solicita um thread específico via 'load.review', o servidor busca o thread completo com todas as mensagens e propaga via 'load.thread' para todos os clientes da conta. 2. **Propagação automática**: Quando um evento interno 'send.thread' é emitido (ex.: após enviar uma nova mensagem), o listener busca o thread atualizado e propaga automaticamente via 'load.thread' para todos os clientes. O frontend escuta este evento para atualizar o histórico de mensagens do thread em tempo real, permitindo que múltiplos usuários vejam as mesmas mensagens simultaneamente.

Access Token

Para realizar requisições GET, POST, PUT, DELETE e PATCH nos endpoints da API você precisa de uma chave de autorização. Chamamos essa chave de accessToken.

Para ter acesso ao accessToken, é necessário que o usuário master da licença efetue a liberação deste pela interface do ImageMais Clinic. O accessToken tem validade de 1 hora.

Headers

AuthorizationOBRIGATÓRIO
Tipo:string
Token de autenticação no formato Bearer {accessToken}. O token deve ser enviado durante o handshake de conexão WebSocket.

Parâmetros

Este método não possui parâmetros.

Fluxo passo a passo: load.thread

1

Contexto 1: Cliente solicita thread via 'load.review'

Quando o componente page.tsx é montado ou quando o reviewId muda, o frontend emite o evento 'load.review' com o UUID do resultado da integração e o ID da revisão. O gateway recebe esta solicitação e busca o thread completo no banco de dados e no OpenAI, incluindo todas as mensagens. Após buscar, propaga o thread via broadcast usando notifyOnEvent('load.thread', thread, payload), garantindo que todos os clientes da conta recebam o thread simultaneamente:

// accounts.gateways.ts
@SubscribeMessage('load.review')
async handleLoadReview(
    @ConnectedSocket() client: Socket,
    @MessageBody() data: {
        resultsIntegrationUuid: string;
        reviewId: number;
    },
) {
    const payload = client.data.payload as PayloadTokenDto;
    
    // Busca thread completo com mensagens
    const thread = await this.laboratoriesService.findOneReview(
        data.resultsIntegrationUuid,
        data.reviewId,
        payload,
    );
    
    // Propaga via broadcast para todos os clientes da conta
    await this.notifyOnEvent('load.thread', thread, payload);
    
    return { status: true };
}
Quem emite: backend (accounts.gateways.ts) após buscar thread via 'load.review'
Modo de envio: broadcast (todos os clientes da conta)
Dados: objeto Thread completo com todas as mensagens
2

Contexto 2: Propagação automática via evento interno

Quando um evento interno 'send.thread' é emitido (por exemplo, após enviar uma nova mensagem no thread), o listener review.listener.ts escuta este evento e busca o thread atualizado no banco de dados e no OpenAI. Após buscar, propaga automaticamente via broadcast usando notifyOnEvent('load.thread', thread, payload), garantindo que todos os clientes recebam as mensagens atualizadas em tempo real:

// review.listener.ts
@OnEvent('send.thread')
async handleSendThread(event: ReviewEvent) {
    try {
        const { resultUuid, reviewId, payload } = event;
        
        // Busca thread atualizado com novas mensagens
        const thread = await this.laboratoriesService.findOneReview(
            resultUuid,
            reviewId,
            payload,
        );
        
        // Propaga via broadcast para todos os clientes da conta
        this.accountsGateway.notifyOnEvent('load.thread', thread, payload);
    } catch (error) {
        this.logger.error('Erro ao propagar thread', error);
    }
}
Quem emite: backend (review.listener.ts) após evento interno 'send.thread'
Modo de envio: broadcast (todos os clientes da conta)
Quando: automaticamente quando thread é atualizado (ex.: nova mensagem)
3

Servidor propaga evento 'load.thread' via broadcast

O método `notifyOnEvent` verifica se o evento 'load.thread' está na lista de eventos permitidos e, em seguida, envia para todos os sockets conectados que estão na room específica da conta (formato: 'orders.account.{accountId}'). O broadcast garante que todos os clientes da mesma conta recebam o thread simultaneamente, permitindo sincronização em tempo real. Cada cliente recebe o objeto Thread completo com todas as mensagens, permitindo que a interface seja atualizada imediatamente:

// accounts.gateways.ts
async notifyOnEvent(
    event: string,
    data: any,
    payload: PayloadTokenDto,
): Promise<any> {
    if (this._events.includes(event)) {
        this.server
            .to(`${this.room}${payload.accountId}`)
            .emit(event, data);
    }
}

// this.room = 'orders.account.'
// Envia para: orders.account.{accountId}
// Evento: 'load.thread'
// Dados: objeto Thread completo com todas as mensagens
Room: orders.account.{accountId}
Evento: 'load.thread' (está na lista de eventos permitidos)
Modo: broadcast (todos os clientes da conta)
4

Frontend atualiza histórico na página de review (page.tsx)

O componente page.tsx escuta o evento 'load.thread' através do listener configurado no useEffect. Quando recebe o thread, atualiza o estado do histórico usando setHistory(data), que armazena o thread completo com todas as mensagens. Também limpa qualquer erro anterior usando setError(undefined). A atualização do estado dispara uma re-renderização automática do componente, exibindo as mensagens atualizadas na interface. O listener é removido quando o componente desmonta ou quando o reviewId muda:

// page.tsx
useEffect(() => {
    if (!socket || !reviewId) return;
    
    // Solicita thread ao montar ou quando reviewId muda
    socket.emit('load.review', {
        resultsIntegrationUuid: uuid,
        reviewId: reviewId,
    }, (response: any) => {
        if (!response.status) {
            setHistory(undefined);
            setError(response.error);
        }
    });
    
    // Escuta thread atualizado
    socket.on('load.thread', (data: Thread) => {
        setHistory(data);
        setError(undefined);
    });
    
    return () => {
        socket.off('load.thread');
    };
}, [socket, reviewId]);
Ação: atualiza histórico de mensagens do thread
Quando: ao receber thread solicitado ou quando thread é atualizado
Sincronização: todos os clientes veem as mesmas mensagens em tempo real
5

Frontend seleciona thread na lista (Threads.tsx)

O componente Threads.tsx escuta o evento 'load.thread' apenas quando há um thread sendo carregado (threadsIdLoading está definido). Quando recebe o thread, verifica se é o thread correto comparando o ID (threadsIdLoading === thread.id). Se for o thread correto, remove o estado de carregamento usando setThreadsIdLoading(undefined) e seleciona automaticamente o thread usando onReviewSelect?.(thread.id). Esta funcionalidade permite que o usuário veja o thread recém-carregado automaticamente selecionado na lista:

// Threads.tsx
useEffect(() => {
    if (!socket || !threadsIdLoading) return;
    
    socket.on('load.thread', (thread: Thread) => {
        // Verifica se é o thread que está sendo carregado
        if (threadsIdLoading === thread.id) {
            setThreadsIdLoading(undefined);
            onReviewSelect?.(thread.id);
        }
    });
    
    return () => {
        socket.off('load.thread');
    };
}, [socket, threadsIdLoading, onReviewSelect]);
Ação: seleciona automaticamente o thread carregado na lista
Quando: apenas quando há um thread sendo carregado (threadsIdLoading)
Validação: verifica se é o thread correto antes de processar
6

Resumo: Diferenças entre os contextos de uso

O evento 'load.thread' é sempre emitido via broadcast para todos os clientes da conta, independente do contexto. No contexto 1 (via 'load.review'), o evento é emitido quando um cliente solicita explicitamente um thread. No contexto 2 (via 'send.thread'), o evento é emitido automaticamente quando o thread é atualizado (ex.: nova mensagem adicionada). O frontend usa o evento de duas formas: na página de review para atualizar o histórico de mensagens, e na lista de threads para selecionar automaticamente o thread carregado. A sincronização em tempo real garante que todos os usuários vejam as mesmas mensagens simultaneamente:

// Contexto 1: Via 'load.review' (solicitação direta)
// - Emitido quando cliente solicita thread específico
// - Enviado para TODOS os clientes da conta (broadcast)
// - Usa: notifyOnEvent('load.thread', thread, payload)
// - Todos os clientes recebem o thread solicitado

// Contexto 2: Via 'send.thread' (propagação automática)
// - Emitido quando thread é atualizado (ex.: nova mensagem)
// - Enviado para TODOS os clientes da conta (broadcast)
// - Usa: notifyOnEvent('load.thread', thread, payload)
// - Todos os clientes recebem o thread atualizado

// Uso no frontend:
// - page.tsx: atualiza histórico de mensagens do thread
// - Threads.tsx: seleciona automaticamente o thread carregado
Broadcast: sempre broadcast (todos os clientes recebem o thread)
Sincronização: todos os usuários veem as mesmas mensagens em tempo real
Múltiplos usos: frontend usa o evento para diferentes ações dependendo do componente
{
  "id": 123,
  "messages": [
  ...
{
  "id": 123,
  "messages": [
    {
      "id": "msg_abc123",
      "role": "user",
      "content": "Pode explicar este resultado?",
      "createdAt": "2025-01-23T10:30:00.000Z"
    },
    {
      "id": "msg_def456",
      "role": "assistant",
      "content": "Este resultado indica...",
      "createdAt": "2025-01-23T10:30:15.000Z"
    }
  ],
  "createdAt": "2025-01-23T10:00:00.000Z",
  "updatedAt": "2025-01-23T10:30:15.000Z"
}

Respostas

{
  "id": 123,
  "messages": [],
  ...
{
  "id": 123,
  "messages": [],
  "createdAt": "2025-01-23T10:00:00.000Z",
  "updatedAt": "2025-01-23T10:30:15.000Z"
}