Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071defmodule GitSync.Sync.Runner do @moduledoc """ Drives one source on its own timer. The first tick uses a stable source-ID offset within its interval, including after a restart or interval edit. Subsequent ticks wait the full interval after each sync completes. A `sync_now` from a webhook or the UI pulls the next tick forward, and a burst of requests coalesces into a single sync. """
use GenServer, restart: :permanent
require Logger
alias GitSync.Mirror alias GitSync.Source alias GitSync.Sync
@debounce_ms 2_000
def start_link(opts) do source = Keyword.fetch!(opts, :source) GenServer.start_link(__MODULE__, opts, name: Sync.via(source.id)) end
@doc """ Asks the runner for this source to sync ahead of its next tick. """ def sync_now(source_id), do: GenServer.cast(Sync.via(source_id), :sync_now)
@impl GenServer def init(opts) do source = Keyword.fetch!(opts, :source)
state = %{ source: source, sync_fun: Keyword.get(opts, :sync_fun, &Mirror.sync/1), interval_ms: Keyword.get(opts, :interval_ms, source.interval_seconds * 1_000), debounce_ms: Keyword.get(opts, :debounce_ms, @debounce_ms), timer: nil }
{:ok, schedule(state, :erlang.phash2(source.id, state.interval_ms))} end
@impl GenServer def handle_cast(:sync_now, state), do: {:noreply, schedule(state, state.debounce_ms)}
@impl GenServer def handle_info(:tick, state) do sync(state) {:noreply, schedule(%{state | timer: nil}, state.interval_ms)} end
defp sync(state) do %Source{} = source = state.source state.sync_fun.(source) rescue error -> Logger.error( msg: "sync raised", source_id: to_string(state.source.id), error: Exception.message(error) ) end
defp schedule(state, delay_ms) do if state.timer, do: Process.cancel_timer(state.timer) %{state | timer: Process.send_after(self(), :tick, delay_ms)} endend