defmodule DaProductApp.Workers.AppPackageWorker do @moduledoc """ Oban worker for handling app package deployment jobs. """ use Oban.Worker, queue: :app_package, max_attempts: 3 require Logger alias DaProductApp.TerminalManagement alias DaProductApp.TerminalManagement.AppPackageService @impl Oban.Worker def perform(%Oban.Job{args: %{"type" => "single_deploy", "device_serial" => device_serial, "package_id" => package_id, "config_id" => config_id}}) do Logger.info("Processing app package deployment job for device: #{device_serial}, package: #{package_id}") case AppPackageService.deploy_package_to_device(device_serial, package_id, config_id) do {:ok, message} -> Logger.info("App package deployment successful for #{device_serial}: #{message}") :ok {:error, reason} -> Logger.error("App package deployment failed for #{device_serial}: #{reason}") {:error, reason} end end def perform(%Oban.Job{args: %{"type" => "batch_deploy", "device_serials" => device_serials, "package_id" => package_id, "config_id" => config_id}}) do Logger.info("Processing batch app package deployment for #{length(device_serials)} devices") results = Enum.map(device_serials, fn device_serial -> case AppPackageService.deploy_package_to_device(device_serial, package_id, config_id) do {:ok, message} -> {device_serial, :ok, message} {:error, reason} -> {device_serial, :error, reason} end end) successes = Enum.count(results, fn {_, status, _} -> status == :ok end) failures = Enum.count(results, fn {_, status, _} -> status == :error end) Logger.info("Batch app package deployment completed: #{successes} successful, #{failures} failed") if failures == 0 do :ok else Logger.warning("Batch deployment had #{failures} failures out of #{length(device_serials)} devices") :ok # Don't retry whole batch, individual failures are logged end end def perform(%Oban.Job{args: %{"type" => "upgrade_rollback", "device_serial" => device_serial, "target_version" => target_version}}) do Logger.info("Processing app package rollback for device: #{device_serial} to version: #{target_version}") case AppPackageService.rollback_package(device_serial, target_version) do {:ok, message} -> Logger.info("App package rollback successful for #{device_serial}: #{message}") :ok {:error, reason} -> Logger.error("App package rollback failed for #{device_serial}: #{reason}") {:error, reason} end end @doc """ Schedules an app package deployment job for a single device. """ def schedule_package_deployment(device_serial, package_id, config_id, opts \\ []) do schedule_at = Keyword.get(opts, :schedule_at, DateTime.utc_now()) %{ type: "single_deploy", device_serial: device_serial, package_id: package_id, config_id: config_id } |> new(scheduled_at: schedule_at) |> Oban.insert() end @doc """ Schedules batch app package deployment for multiple devices. """ def schedule_batch_package_deployment(device_serials, package_id, config_id, opts \\ []) do schedule_at = Keyword.get(opts, :schedule_at, DateTime.utc_now()) %{ type: "batch_deploy", device_serials: device_serials, package_id: package_id, config_id: config_id } |> new(scheduled_at: schedule_at) |> Oban.insert() end @doc """ Schedules an app package rollback job. """ def schedule_package_rollback(device_serial, target_version, opts \\ []) do schedule_at = Keyword.get(opts, :schedule_at, DateTime.utc_now()) %{ type: "upgrade_rollback", device_serial: device_serial, target_version: target_version } |> new(scheduled_at: schedule_at) |> Oban.insert() end end