Sincronización incremental
Estrategia: Incremental vs. Completado
La elección de la estrategia de sincronización impacta directamente el desempeño y el consumo del rate limit.
| Estrategia | Cuando use | Ventaja | Desventaje |
| Completado | Primera sync, reconciliación semanal | Garante consistencia total | Consome más rate limit |
| Incremental | Syncs regulares (horária, diaria) | Rápido, consume menos rate limit | Puede perder cambios en caso de fallo |
Sincronización incremental
Sincroniza sólo registros modificados desde la última sincronización exitosa.
Flujo
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]
Implementación
| 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}")
|
Sincronización completa
Recomendada para la primera sync o reconciliación 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
|
Tratamiento de fallos
| 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)
|
Planificación recomendada
| Frecuencia | Estrategia | Observación |
| Cada hora | Incremental | Mantener sistema en día |
| Diariamente (madrugada) | Completado | Reconciliación |
| Después de incidentes | Completado | Garantizar consistencia |
Siguientes pasos