···126126 {:state_directory, Path.expand(dir)}
127127 end
128128129129+ def external_config({:subscriptions, subscriptions})
130130+ when is_list(subscriptions) do
131131+ normalized_subscriptions =
132132+ Enum.map(subscriptions, fn subscription ->
133133+ case subscription do
134134+ %{schedule: schedule} when is_binary(schedule) ->
135135+ case Crontab.CronExpression.Parser.parse(schedule) do
136136+ {:ok, cron} ->
137137+ %{subscription | schedule: cron}
138138+139139+ {:error, error} ->
140140+ Logger.error(msg: "Failed to parse schedule", error: error)
141141+ subscription
142142+ end
143143+144144+ subscription ->
145145+ subscription
146146+ end
147147+ end)
148148+149149+ {:subscriptions, normalized_subscriptions} |> dbg()
150150+ end
151151+129152 def external_config({:__struct__, _}), do: nil
130153131154 def external_config(cfg), do: cfg
+3
apps/sower_agent/lib/sower_agent/scheduler.ex
···11+defmodule SowerAgent.Scheduler do
22+ use Quantum, otp_app: :sower_agent
33+end
+20-5
apps/sower_agent/lib/sower_agent/subscription.ex
···11defmodule SowerAgent.Subscription do
22 @moduledoc """
33- Agent-side subscription schema that extends the client subscription
44- with agent-only configuration fields like polling schedules.
55-66- Use `to_client_schema/1` to convert to the server-compatible schema
77- when communicating with the Sower server.
33+ Agent has its own idea of subscription to avoid sending
44+ everything to the server m
85 """
96 alias OpenApiSpex.Schema
107 require OpenApiSpex
88+ require Logger
1191210 alias SowerClient.Schemas.Orchestration.Subscription.Rule
1311···8280 {:ok, val} = cast(attrs)
8381 val
8482 end
8383+8484+ def start_schedule(%__MODULE__{sid: sid, schedule: schedule} = sub)
8585+ when not is_nil(sid) and not is_nil(schedule) do
8686+ SowerAgent.Scheduler.new_job()
8787+ |> Quantum.Job.set_name(:"sub_#{sid}")
8888+ |> Quantum.Job.set_schedule(sub.schedule)
8989+ |> Quantum.Job.set_task(fn ->
9090+ Logger.debug(
9191+ msg: "Running subscription schedule",
9292+ subscription_sid: sid,
9393+ schedule: schedule
9494+ )
9595+ end)
9696+ |> SowerAgent.Scheduler.add_job()
9797+ end
9898+9999+ def start_schedule(_), do: nil
8510086101 defp build_spec do
87102 %OpenApiSpex.OpenApi{
+1
apps/sower_agent/mix.exs
···2626 # Run "mix help deps" to learn about dependencies.
2727 defp deps do
2828 [
2929+ {:quantum, "~> 3.0"},
2930 {:cuid2_ex, "~> 0.2"},
3031 {:deps_nix, "~> 2.0", only: [:dev]},
3132 {:igniter, only: [:dev, :test]},