defmodule ArcadiaCloud.Sync.BalanceWorker do @moduledoc """ Hourly poll of `/v2/customers/my/balance`. Records a snapshot row so the cost dashboard can show MTD usage in real time. """ use Oban.Worker, queue: :cloud_billing, max_attempts: 3 alias ArcadiaCloud.Billing alias ArcadiaCloud.DigitalOcean.Client @impl Oban.Worker def perform(_job) do with {:ok, body} <- Client.get_balance() do Billing.record_balance(%{ provider: "digitalocean", month_to_date_balance_cents: dollars_to_cents(body["month_to_date_balance"]), account_balance_cents: dollars_to_cents(body["account_balance"]), month_to_date_usage_cents: dollars_to_cents(body["month_to_date_usage"]), generated_at: parse_iso(body["generated_at"]), raw: body }) :ok end end defp dollars_to_cents(nil), do: nil defp dollars_to_cents(value) when is_binary(value) do case Float.parse(value) do {float, _} -> round(float * 100) :error -> nil end end defp dollars_to_cents(value) when is_number(value), do: round(value * 100) defp parse_iso(nil), do: DateTime.utc_now() |> DateTime.truncate(:second) defp parse_iso(str) when is_binary(str) do case DateTime.from_iso8601(str) do {:ok, dt, _} -> DateTime.truncate(dt, :second) _ -> DateTime.utc_now() |> DateTime.truncate(:second) end end end