Pular para conteúdo

Sincronização Incremental

Estratégia: Incremental vs. Completa

A escolha da estratégia de sincronização impacta diretamente a performance e o consumo do rate limit.

Estratégia Quando usar Vantagem Desvantagem
Completa Primeira sync, reconciliação semanal Garante consistência total Consome mais rate limit
Incremental Syncs regulares (horária, diária) Rápida, consome menos rate limit Pode perder mudanças em caso de falha

Sincronização Incremental

Sincroniza apenas registros modificados desde a última sincronização bem-sucedida.

Fluxo

flowchart TD
    A[Início] --> B[Ler timestamp da última sync]
    B --> C[Buscar registros modificados desde então]
    C --> D[Para cada registro]
    D --> E{Existe na Pontotel?}
    E -->|Não| F[Criar via POST]
    E -->|Sim| G[Atualizar via PATCH]
    F --> H[Salvar resultado]
    G --> H
    H --> I[Salvar novo timestamp]
    I --> J[Fim]

Implementação

Python
import json
from datetime import datetime, timezone
from pathlib import Path

SYNC_STATE_FILE = Path(".sync_state.json")

def carregar_estado() -> dict:
    """Carrega o estado da última sincronização"""
    if SYNC_STATE_FILE.exists():
        return json.loads(SYNC_STATE_FILE.read_text())
    return {"ultima_sync": None}

def salvar_estado(timestamp: str):
    """Salva o timestamp da sincronização bem-sucedida"""
    SYNC_STATE_FILE.write_text(json.dumps({"ultima_sync": timestamp}))

def sincronizar_incremental(auth):
    estado = carregar_estado()
    ultima_sync = estado["ultima_sync"]

    inicio = datetime.now(timezone.utc).isoformat()

    print(f"📅 Sincronizando desde: {ultima_sync or 'início'}")

    # Sincronizar empregadores
    resultado_emp = sincronizar_empregadores_desde(ultima_sync, auth)

    # Sincronizar empregados
    resultado_func = sincronizar_empregados_desde(ultima_sync, auth)

    # Salvar novo estado somente se tudo deu certo
    salvar_estado(inicio)

    print(f"✅ Sync concluída!")
    print(f"   Empregadores: {resultado_emp}")
    print(f"   Empregados: {resultado_func}")

Sincronização Completa

Recomendada para a primeira sync ou reconciliação periódica:

Python
def sincronizar_completa(auth):
    """Sincronização completa — compara estado atual com Pontotel"""
    headers = auth.get_headers()

    # 1. Carregar todos os registros do seu sistema
    seus_empregados = seu_sistema.listar_todos_empregados()

    # 2. Carregar todos os registros da Pontotel
    empregados_pontotel = listar_todos_da_api(
        "https://apis.pontotel.com.br/pontotel/api/v4/empregados/",
        headers
    )
    pontotel_por_cpf = {e["cpf"]: e for e in empregados_pontotel}

    resultado = {"criados": 0, "atualizados": 0, "desativados": 0}

    for func in seus_empregados:
        cpf = func["cpf"]
        if cpf not in pontotel_por_cpf:
            criar_empregado(func, headers)
            resultado["criados"] += 1
        elif dados_diferentes(pontotel_por_cpf[cpf], func):
            atualizar_empregado(pontotel_por_cpf[cpf]["id"], func, headers)
            resultado["atualizados"] += 1

    return resultado

Tratamento de Falhas

Python
import time

def sync_com_retry(auth, max_tentativas=3):
    """Sincronização com retry automático em caso de falha"""
    for tentativa in range(1, max_tentativas + 1):
        try:
            return sincronizar_incremental(auth)
        except RateLimitError as e:
            wait = e.retry_after
            print(f"⏳ Rate limit: aguardando {wait}s...")
            time.sleep(wait)
        except APIError as e:
            if tentativa == max_tentativas:
                raise
            wait = 2 ** tentativa  # Backoff exponencial: 2s, 4s, 8s
            print(f"❌ Tentativa {tentativa} falhou. Aguardando {wait}s...")
            time.sleep(wait)

Agendamento Recomendado

Frequência Estratégia Observação
A cada hora Incremental Manter sistema em dia
Diariamente (madrugada) Completa Reconciliação
Após incidentes Completa Garantir consistência

Próximos Passos