Inquir Compute logoInquir Compute
Сценарий · Inquir Compute

Синхронизация данных по расписанию: инкрементальный режим с курсором последней синхронизации

Типичный цикл выглядит так: по расписанию cron (например, раз в час) пайплайн читает из вашего хранилища отметку времени последней успешной синхронизации, запрашивает у источника только изменения после этой отметки, выполняет идемпотентную операцию вставки или обновления (UPSERT) в вашей базе и сдвигает курсор только после успешной фиксации данных. Так вы не пересканируете всю таблицу на каждом прогоне и не плодите дубликаты, если провайдер cron или платформа перезапустит задачу.

Обновлено: 2026-04-20

Суть ответа

Синхронизация данных по расписанию: инкрементальный режим с курсором последней синхронизации. Пайплайн по расписанию читает сохранённую отметку из базы или другого хранилища состояния, запрашивает у источника только строки с `updated_at` (или аналогом) новее этой отметки, выполняет UPSERT с уникальным ключом по бизнес-идентификатору и обновляет отметку только после успешной фиксации пакета.

Когда подходит и когда нет

  • Источник поддерживает фильтрацию по `updated_at`
  • Нужна инкрементальная синхронизация без полного перезапроса

На что обратить внимание

  • Сдвигать отметку `last_synced_at` (или аналог) до того, как транзакция с данными успешно зафиксирована: при ошибке записи курсор уже «уехал вперёд», а часть строк не попала в целевую базу — расхождение заметят поздно.
  • Без идемпотентной записи (UPSERT по первичному ключу или явная дедупликация) повторный прогон после сбоя или повтор доставки события создаёт дубликаты.

Почему инкрементальная синхронизация данных по расписанию без сохранённой отметки последнего успешного прогона даёт сбои и лишнюю нагрузку

  • VPS crontab: failed syncs go to /dev/null or root mail nobody reads
  • Full re-sync every run: re-fetching all records wastes API quota and increases sync time quadratically
  • Missing idempotency: network failure mid-sync creates partial state and duplicate records on retry
  • No run history: "did the sync run last night?" requires SSH and log search

Если на каждом прогоне вытягивать полный снимок данных, синхронизация со временем становится медленной и дорогой и перегружает источник; при росте объёма один прогон может занять дольше, чем интервал между запусками cron.

Типичные ошибки при инкрементальной синхронизации

Сдвигать отметку `last_synced_at` (или аналог) до того, как транзакция с данными успешно зафиксирована: при ошибке записи курсор уже «уехал вперёд», а часть строк не попала в целевую базу — расхождение заметят поздно.

Без идемпотентной записи (UPSERT по первичному ключу или явная дедупликация) повторный прогон после сбоя или повтор доставки события создаёт дубликаты.

Инкрементальная синхронизация в Inquir

Пайплайн по расписанию читает сохранённую отметку из базы или другого хранилища состояния, запрашивает у источника только строки с `updated_at` (или аналогом) новее этой отметки, выполняет UPSERT с уникальным ключом по бизнес-идентификатору и обновляет отметку только после успешной фиксации пакета.

В консоли видна история каждого прогона: сколько строк обработано, на какой отметке остановились при ошибке, когда был следующий запуск — проще отлаживать и согласовывать данные с владельцем источника.

Из чего складывается устойчивая инкрементальная синхронизация

Курсор состояния

Храните отметку последней успешной синхронизации (`last_synced_at` или эквивалент) в базе или key-value; запрашивайте у источника только строки новее этой отметки.

Идемпотентная вставка или обновление (UPSERT)

Используйте конструкцию вида `INSERT … ON CONFLICT (id) DO UPDATE …` или эквивалент в вашей СУБД, чтобы повторный прогон с теми же строками не создавал дубликаты.

Атомарный сдвиг курсора

Обновляйте отметку только после успешной записи всего батча (по возможности в одной транзакции с данными), чтобы сбой посередине не «перепрыгивал» курсор.

Расписание cron в пайплайне

Часовой или суточный прогон задаётся cron-выражением; в консоли сохраняются история запусков и политика повторов при временных сбоях.

Как организовать инкрементальную синхронизацию данных по расписанию с отметкой последнего успешного прогона

1

Прочитать курсор

Запросить `last_synced_at` из базы или persistent storage в начале каждого прогона.

2

Запросить дельту

`WHERE updated_at > last_synced_at ORDER BY updated_at LIMIT N` — инкрементальный запрос.

3

Upsert и сдвиг курсора

Сделать upsert батча, затем обновить `last_synced_at = MAX(updated_at)` в одной транзакции.

Incremental sync with watermark cursor

Reads cursor from environment/DB, fetches delta, upserts idempotently, returns new cursor. Cron trigger fires on schedule; retries on failure.

jobs/sync-crm-contacts.mjs
export async function handler(event) {
  // Read watermark — default to 24h ago on first run
  const cursor = await db.syncCursors.get('crm-contacts') ?? new Date(Date.now() - 86_400_000).toISOString();
  let page = 0, synced = 0, newCursor = cursor;
  do {
    const { contacts, nextPage } = await crm.fetchContacts({ updatedAfter: cursor, page });
    if (contacts.length === 0) break;
    await db.contacts.upsertBatch(contacts); // upsert by contacts[].externalId
    synced += contacts.length;
    newCursor = contacts.at(-1)?.updatedAt ?? newCursor;
    page = nextPage;
  } while (page);
  await db.syncCursors.set('crm-contacts', newCursor);
  return { synced, cursor, newCursor };
}

Когда уместен режим с курсором последней синхронизации

Когда это уместно

  • Источник поддерживает фильтрацию по `updated_at`
  • Нужна инкрементальная синхронизация без полного перезапроса

Когда лучше не трогать

  • Источник не поддерживает фильтрацию по времени — нужна полная выгрузка с hash-сравнением

Вопросы и ответы

Что если прогон упал на середине?

Следующий запуск по расписанию снова прочитает прежнюю отметку `last_synced_at`: те же строки запросятся повторно. При идемпотентном UPSERT дубликаты не появятся.

Где хранить состояние курсора?

Обычно отдельная таблица `sync_state` или key-value с одной записью на каждый источник и тип синхронизации.

Настройте инкрементальную синхронизацию по расписанию: отметка прогресса, UPSERT и журнал прогонов в одной консоли

Курсор последней синхронизации, идемпотентная запись UPSERT и пайплайн по расписанию cron с историей прогонов — в одной консоли.

Inquir Compute logoInquir Compute

Самый простой способ запускать AI-агентов и фоновые задачи без собственной инфраструктуры.

Связаться info@inquir.org

Привет, это команда Inquir Compute. Спроси AI о продукте:

© 2025 Inquir Compute. Все права защищены.