Sync Monitoring

Keeping it running

Run the agent as a resident process on one side and under a scheduler on the other.

The agent does one cycle per invocation. Something has to invoke it repeatedly, and the two sides are usually set up differently.

Local — resident watch mode

On the school's machine there is usually no reliable scheduler, so run the agent as a resident process. It sleeps on the school's sync interval and stops cleanly on Ctrl+C:

cd C:\laragon\www\pac_local
.\sync-agent\sync-agent-windows-x64.exe --watch

It opens with the settings it resolved, then adds a line per cycle and counts down to the next one in place:

  sync-agent PAC001 LOCAL
  server   http://localhost:3002
  database pac_local at 127.0.0.1:3306
  syncing  captures UP, applies DOWN
  interval 5 min
  Ctrl+C to stop

15:30:04  DOWN applied 3, skipped 1 · UP pushed 12                          1.1s
15:30:13  idle                                                             864ms
          next run in 4:51

A failed cycle costs one tick — the agent reports the error and retries on the next one, so a database restart or a brief network outage recovers on its own. For unattended installs, register this under a service supervisor so it restarts on reboot.

Online — one-shot under the scheduler

The online database sits on a server that already has a scheduler, which gives you crash and reboot recovery for free. Run the agent one-shot on a timer instead:

app/Console/Kernel.php
$schedule->exec(base_path('sync-agent/sync-agent-windows-x64.exe'))
    ->everyMinute()
    ->withoutOverlapping()
    ->runInBackground();

Tick faster than the sync interval

The scheduler frequency is a floor on the sync interval. If it fires every 5 minutes and the school's interval is 5 minutes, each cycle lands a couple of seconds short of its own slot and syncing happens every 10 minutes instead. Run it every minute and let the school interval do the throttling.

Overlapping runs

Overlap is safe: the agent takes a MySQL advisory lock before draining, so a slow run makes the next one skip with another run is still in progress rather than draining the same rows twice. The lock releases itself when the connection closes, including on a crash.

The lock is named after the database, not the school. Two agents on one MySQL host pointing at different databases never block each other, and two agents pointed at the same database will.

Remove any previous sync job

If the host application has its own sync command scheduled, remove it first. Two processes draining the same outbox will fight over rows.

Changing the interval later

A new sync interval takes effect without touching the host. A watch-mode agent checks in with the server every couple of seconds while it waits, and picks up the change in the wait already under way:

          interval changed to 1 min
          next run in 0:48

The wait is measured from when it began. Lengthening the interval pushes the next run back. Shortening it past the time already waited starts the next cycle straight away. This holds after a failed cycle too: an agent stuck on an error retries on the dashboard's interval, and falls back to 5 minutes only while it cannot reach the server at all.

A one-shot agent never acts on the interval at all — the scheduler sets its cadence, and the dashboard value is a record of intent.

An agent started with --interval ignores the dashboard value entirely.

On this page