Skip to content

Scheduled Sync

Reference for Conflux's automatic sync scheduling — the sync:dispatch Artisan command and the single scheduler entry that runs it across all active connections.

Command: sync:dispatch

php artisan sync:dispatch [--full]

Queries every SystemConnection with an active status, then dispatches one BulkSyncJob per connection that has at least one pull-in domain.

Option Default Effect
--full absent Dispatches BulkSyncJob with forceFull: true; fetches every record from the source platform, ignoring any existing cursor
(absent) — Dispatches BulkSyncJob with forceFull: false; uses the delta cursor

The command is driver-agnostic: it queries SystemConnection directly and works across all integration drivers (WooCommerce, PrestaShop). Which data domains a connection syncs is not read from its System alone — it is the intersection of three things, via SystemConnection::pullInCapabilities():

  1. the capabilities the connection's System declares,
  2. the connector-widget opt-in in configuration.data_types, when the connection carries one, and
  3. the data_domains of active SyncRules naming that connection as source.

A connection is skipped entirely — silently, with no error — when that intersection is empty: no linked System, an empty opt-in, or no active outgoing rule all end the same way. See Sync Rules for where those rules come from. The command always exits 0 (success) regardless of how many jobs were dispatched.

Scheduler Entry

One entry in routes/console.php fires the command on a configurable cron schedule, in delta mode:

Entry Default schedule Mode
sync:dispatch Every 2 hours (0 */2 * * *) Delta

There is no scheduled full sync. --full is only ever invoked on demand — via the CLI or the Filament "Bulk Sync" action on a connection — and doesn't need its own cron entry: a connection/capability with no prior completed SyncBatch has no delta cursor, so a scheduled delta run already fetches everything for it the first time (see Sync Modes below). Periodic full resyncs are deliberately not scheduled — deletion detection runs on every sync via Deletion Log Sync, not by comparing full snapshots, so there's no correctness reason a full sync needs to recur on its own cadence.

Configuration

File: config/sync.php

Key Env variable Default Description
sync.delta_cron SYNC_DELTA_CRON 0 */2 * * * Cron expression for delta syncs

Set this in .env to override the default without touching the config file:

SYNC_DELTA_CRON="*/30 * * * *"   # every 30 minutes

Duplicate-Dispatch Safety

BulkSyncJob implements ShouldBeUnique keyed on system_connection_id. If a sync for a given connection is already queued or running when the scheduler fires again, the duplicate dispatch is a no-op. No double-processing occurs.

Deactivation Safety

sync:dispatch only queries connections that are active at dispatch time — a connection can still be deactivated while its BulkSyncJob (or one of its child FetchBulkPageRangeJobs) is sitting in the queue. Both jobs re-check $connection->isHealthy() at the top of handle() and return early, without fetching or persisting anything, if the connection is no longer Active. See Connection Flow — Defending Against In-Flight Work.

Sync Modes

Delta sync (default, no --full flag)
Passes the cursor from the last completed SyncBatch to the integration as ExportRequest::$modifiedAfter. The integration returns only records modified since that point. When no completed SyncBatch exists yet for a connection/capability — a brand-new connection, or one where every prior attempt failed — there is no cursor, so $modifiedAfter is null and the integration performs a full fetch, exactly as --full would. This is what lets the scheduled delta cron alone cover both "keep up to date" and "first sync ever" without a separate full-sync schedule. See Delta Sync for the cursor derivation logic.
Full sync (--full flag)
Passes modifiedAfter = null unconditionally, causing the integration to return all records — refreshing the baseline dataset even when a cursor already exists. Only triggered on demand (CLI or Filament), never by the scheduler. See Sync Batches for the SyncBatch mechanics both modes share.

Both modes also dispatch FetchDeletionLogJob on completion, passing the same cursor used for the mode's bulk export — this runs regardless of --full, since it detects deletions directly from the platform's deletion log rather than by comparing snapshots. See Deletion Log Sync.