Pular para o conteúdo principal

Sync Queue Service

Gerencia operações relacionadas à fila de sincronização de dados, permitindo iniciar sincronizações, consultar histórico e filtrar por entidade.

Visão Geral

O SyncQueueService é responsável por:

  • Iniciar sincronização total de dados
  • Consultar histórico de sincronizações básico
  • Consultar histórico de sincronizações com filtros avançados por entidade
  • Filtrar sincronizações por entidade, status, solicitante e dispositivo
  • Monitorar status e tempo de processamento
  • Rastrear registros incluídos e alterados

O serviço gerencia a fila de sincronização entre dispositivos e servidor, mantendo registro de todas as operações de sincronização realizadas.

Localização: services/sync-queue/sync-queue.service.ts

Endpoints Utilizados

Base URL

Todos os endpoints são relativos à base URL configurada em services/api.service.ts

Métodos

initTotalSync(params)

Inicia uma sincronização total de dados para um usuário e dispositivo.

Endpoint: POST /historicoSincronizacao/sincronizacaoTotal

Parâmetros:

type InitTotalSyncParams = {
idUsuario: string;
idDispositivo: string;
};

Query Params enviados:

  • idUsuario: ID do usuário
  • idDispositivo: ID do dispositivo

Retorno:

Promise<SyncQueue>;

Exemplo de uso:

import { syncQueueService } from "@/services/sync-queue/sync-queue.service.instance";

const syncResult = await syncQueueService.initTotalSync({
idUsuario: "user-123",
idDispositivo: "device-456",
});

console.log("Sincronização iniciada:", syncResult.id);
console.log("Status:", syncResult.statusSync);

Tratamento de erros:

  • Lança Error se o status da resposta não for 2xx
  • Mensagem: SyncQueueService.initTotalSync failed: {status}

getSyncHistory(params)

Busca histórico básico de sincronizações.

Endpoint: GET /historicoSincronizacao/historico

Parâmetros:

type GetSyncHistoryParams = {
idDispositivo?: string; // Filtrar por dispositivo
idUsuario?: string; // Filtrar por usuário
dataHora?: string; // Filtrar por data/hora
};

Query Params enviados:

  • idDispositivo: ID do dispositivo (opcional)
  • idUsuario: ID do usuário (opcional)
  • dataHora: data e hora (opcional)

Retorno:

Promise<SyncQueue[]>;
// Buscar todo histórico
const history = await syncQueueService.getSyncHistory({});

// Buscar por dispositivo
const deviceHistory = await syncQueueService.getSyncHistory({
idDispositivo: "device-456",
});

// Buscar por usuário
const userHistory = await syncQueueService.getSyncHistory({
idUsuario: "user-123",
});

// Buscar com múltiplos filtros
const filteredHistory = await syncQueueService.getSyncHistory({
idDispositivo: "device-456",
idUsuario: "user-123",
dataHora: "2024-03-01T10:00:00",
});

Tratamento de erros:

  • Lança Error se o status da resposta não for 2xx
  • Mensagem: SyncQueueService.getSyncHistory failed: {status}

getSyncHistoryByEntity(params)

Busca histórico de sincronizações com paginação e filtros avançados por entidade.

Endpoint: GET /historicoSincronizacao/historico/filtrar

Parâmetros:

type GetSyncHistoryByEntityParams = {
page?: number; // Número da página (opcional)
size?: number; // Quantidade de itens por página (opcional)
entidade: keyof typeof ENTITIES_AVAILABLE_FOR_SYNC; // Filtrar por entidade (obrigatório)
solicitante?: string; // Filtrar por solicitante
status?: string; // Filtrar por status
idDispositivo?: string; // Filtrar por dispositivo
dtIni?: string; // Data inicial
};

Query Params enviados:

  • entidade: nome da entidade (obrigatório)
  • status: status da sincronização (opcional)
  • idDispositivo: ID do dispositivo (opcional)
  • dtIni: data de início (opcional)

Retorno:

Promise<SyncQueue[]>;

Exemplo de uso:

import { syncQueueService } from "@/services/sync-queue/sync-queue.service.instance";

// Buscar por entidade específica
entidade: "Produto",
});

// Buscar com paginação
const historyPage = await syncQueueService.getSyncHistoryByEntity({
entidade: "Cliente",
page: 0,
size: 20,
});

// Buscar por dispositivo e entidade
const deviceHistory = await syncQueueService.getSyncHistoryByEntity({
entidade: "Pedido",
idDispositivo: "device-456",
});

// Buscar por status e entidade
const completedSyncs = await syncQueueService.getSyncHistoryByEntity({
entidade: "Estoque",
status: "COMPLETED",
});
const filteredHistory = await syncQueueService.getSyncHistoryByEntity({
status: "COMPLETED",
solicitante: "App Mobile",
idDispositivo: "device-456",
dtIni: "2024-03-01",
page: 0,
size: 20,
});

Tratamento de erros:

  • Lança Error se o status da resposta não for 2xx
  • Mensagem: SyncQueueService.getSyncHistoryByEntity failed: {status}

fetchChangedEntities(dataHora)

Busca entidades que foram alteradas desde uma data/hora específica. Este método foi adicionado recentemente ao serviço.

Endpoint: GET /historicoIntegracao/entidadesAlteradas

Parâmetros:

// enviado como query param
{
dataHora: string;
} // ISO string ou timestamp aceito pelo backend

Query Params enviados:

  • dataHora: data/hora de referência para buscar entidades alteradas (obrigatório)

Retorno:

Promise<ChangedEntity[]>;

Exemplo de uso:

import { syncQueueService } from "@/services/sync-queue/sync-queue.service.instance";

const changed = await syncQueueService.fetchChangedEntities(
"2024-05-01T00:00:00",
);

console.log(
"Entidades alteradas:",
changed.map((c) => c.entidade),
);

Tratamento de erros:

  • Lança Error se o status da resposta não for 2xx
  • Mensagem: SyncQueueService.fetchChangedEntities failed: {status}

Estruturas de Dados

Enum ENTITIES_AVAILABLE_FOR_SYNC

enum ENTITIES_AVAILABLE_FOR_SYNC {
"Produto",
"Cliente",
"Empresa",
"Forma de pagamento",
"Tipo de operação",
"Local",
"Unidade medida",
"Unidade alternativa",
"Estoque",
"Item",
"Pedido",
"Promoção",
"Vendedor",
"Titulos em aberto",
"Tabelas de preço",
"Grupo de produto",
"Desconto por quantidade",
}

Interface SyncQueue

interface SyncQueue {
id: string;
usuarioId: string;
organizationId: string;
idDispositivo: string;
entidade: keyof typeof ENTITIES_AVAILABLE_FOR_SYNC;
dtIni: string;
dtFim: string;
tempoProcessamento: number;
registrosIncluidos: number;
registrosAlterados: number;
solicitante: string;
logs: string;
statusSync: string;
origem: string;
tipo: string;
formato: string;
}

Componentes Relacionados

buildQueryParams Helper

Função utilitária que converte objeto de parâmetros em URLSearchParams.

Localização: helpers/buildQueryParams.ts

PageResponse Interface

Interface compartilhada para respostas paginadas.

Localização: services/client/client.service.ts


Casos de Uso

Iniciar Sincronização em Login

async function syncOnLogin(userId: string, deviceId: string) {
try {
const sync = await syncQueueService.initTotalSync({
idUsuario: userId,
idDispositivo: deviceId,
});

console.log(`Sincronização iniciada: ${sync.id}`);
console.log(`Status: ${sync.statusSync}`);

return sync;
} catch (error) {
console.error("Erro ao iniciar sincronização:", error);
throw error;
}
}

Monitorar Histórico de Sincronizações

async function checkSyncHistory(deviceId: string, userId: string) {
const history = await syncQueueService.getSyncHistory({
idDispositivo: deviceId,
idUsuario: userId,
});

console.log(`${history.length} sincronizações encontradas:`);
history.forEach((sync) => {
console.log(`- ${sync.entidade}: ${sync.statusSync}`);
console.log(` Tempo: ${sync.tempoProcessamento}ms`);
console.log(
` Incluídos: ${sync.registrosIncluidos}, Alterados: ${sync.registrosAlterados}`,
);
});

return history;
}

Verificar Status de Sincronização por Entidade

async function checkEntitySyncStatus(
entity: keyof typeof ENTITIES_AVAILABLE_FOR_SYNC,
) {
const syncs = await syncQueueService.getSyncHistoryByEntity({
entidade: entity,
page: 0,
size: 5,
});

const completed = syncs.filter((s) => s.statusSync === "COMPLETED").length;
const failed = syncs.filter((s) => s.statusSync === "FAILED").length;

console.log(`Status de sincronização para ${entity}:`);
console.log(`Completas: ${completed}, Falhas: ${failed}`);

return { completed, failed, total: syncs.length };
}

Buscar Sincronizações Falhadas por Entidade

async function getFailedSyncsByEntity(
entity: keyof typeof ENTITIES_AVAILABLE_FOR_SYNC,
deviceId?: string,
) {
const failedSyncs = await syncQueueService.getSyncHistoryByEntity({
entidade: entity,
status: "FAILED",
idDispositivo: deviceId,
});

console.log(
`${failedSyncs.length} sincronizações falhadas encontradas para ${entity}`,
);

failedSyncs.forEach((sync) => {
console.log(`- ${sync.entidade}: ${sync.logs}`);
console.log(` Dispositivo: ${sync.idDispositivo}`);
console.log(` Data: ${sync.dtIni}`);
});

return failedSyncs;
}

Relatório de Sincronização por Solicitante e Entidade

async function getSyncReportBySolicitor(
entity: keyof typeof ENTITIES_AVAILABLE_FOR_SYNC,
solicitante: string,
) {
const syncs = await syncQueueService.getSyncHistoryByEntity({
entidade: entity,
solicitante,
page: 0,
size: 100,
});

const report = {
total: syncs.length,
completed: syncs.filter((s) => s.statusSync === "COMPLETED").length,
failed: syncs.filter((s) => s.statusSync === "FAILED").length,
totalRecordsIncluded: syncs.reduce(
(sum, s) => sum + s.registrosIncluidos,
0,
),
totalRecordsUpdated: syncs.reduce(
(sum, s) => sum + s.registrosAlterados,
0,
),
avgProcessingTime:
syncs.reduce((sum, s) => sum + s.tempoProcessamento, 0) / syncs.length,
};

console.log(`Relatório de sincronização para ${entity} - ${solicitante}:`);
console.log(`Total: ${report.total}`);
console.log(`Completas: ${report.completed}, Falhas: ${report.failed}`);
console.log(`Registros incluídos: ${report.totalRecordsIncluded}`);
console.log(`Registros alterados: ${report.totalRecordsUpdated}`);
console.log(`Tempo médio: ${report.avgProcessingTime.toFixed(2)}ms`);

return report;
}

Testes

Localização

services/sync-queue/sync-queue.service.test.ts

Executar Testes

# Teste específico do serviço
npx jest services/sync-queue/sync-queue.service.test.ts

# Modo watch
npx jest services/sync-queue/sync-queue.service.test.ts --watch

# Com coverage
npx jest services/sync-queue/sync-queue.service.test.ts --coverage

Casos de Teste

  • initTotalSync: inicia sincronização total com sucesso
  • initTotalSync: retorna SyncQueue em status 2xx
  • initTotalSync: tratamento de erros para status não-2xx
  • getSyncHistory: busca histórico básico com sucesso
  • getSyncHistory: retorna array de SyncQueue em status 2xx
  • getSyncHistory: tratamento de erros para status não-2xx
  • getSyncHistoryByEntity: busca histórico por entidade com sucesso
  • getSyncHistoryByEntity: retorna content da resposta em status 2xx
  • getSyncHistoryByEntity: tratamento de erros para status não-2xx

Mocks

Localização

__mocks__/sync-queue.mock.ts

Dados Disponíveis

Mock com exemplos de sincronizações:

  • Diferentes entidades (Produto, Cliente, Pedido, Estoque)
  • Diversos status (COMPLETED, FAILED)
  • Diferentes origens (MOBILE, DESKTOP, API)
  • Tipos variados (EXPORT, SYNC, IMPORT)
  • Formatos diversos (JSON, CSV, XML)

Exemplo de uso em testes:

import { syncQueuesResponseMock } from "@/__mocks__/sync-queue.mock";

// Mock getSyncHistory
const apiWithoutAccessToken: any = {
get: jest.fn(async () => ({
status: 200,
data: syncQueuesResponseMock,
})),
};

const service = new SyncQueueService({ apiWithoutAccessToken });
const result = await service.getSyncHistory();

expect(result).toEqual(syncQueuesResponseMock.content);