load.threadCarregar 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
| Nome | Tipo | Obrig. | Descrição |
|---|---|---|---|
Authorization | string | Sim | Token de autenticação no formato Bearer {accessToken}. O token deve ser enviado durante o handshake de conexão WebSocket. |
AuthorizationOBRIGATÓRIOParâmetros
Este método não possui parâmetros.
Fluxo passo a passo: load.thread
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 };
}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);
}
}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 mensagensFrontend 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]);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]);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{
"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"
}