defmodule Mix.Tasks.JoinRequests.CleanupExpired do @moduledoc """ Hard-deletes JoinRequests in status `pending_confirmation` whose confirmation link has expired. Retention: records with `confirmation_token_expires_at` older than now are deleted. Intended for cron or Oban (e.g. every hour). See docs/onboarding-join-concept.md. ## Usage mix join_requests.cleanup_expired ## Examples $ mix join_requests.cleanup_expired Deleted 3 expired join request(s). """ use Mix.Task require Ash.Query alias Mv.Membership.JoinRequest @shortdoc "Deletes join requests in pending_confirmation with expired confirmation token" @impl Mix.Task def run(_args) do Mix.Task.run("app.start") now = DateTime.utc_now() query = JoinRequest |> Ash.Query.filter(status == :pending_confirmation) |> Ash.Query.filter(confirmation_token_expires_at < ^now) # Bypass authorization: cleanup is a system maintenance task (cron/Oban). case Ash.read(query, domain: Mv.Membership, authorize?: false) do {:ok, requests} -> count = delete_expired_requests(requests) Mix.shell().info("Deleted #{count} expired join request(s).") count {:error, error} -> Mix.raise("Failed to list expired join requests: #{inspect(error)}") end end defp delete_expired_requests(requests) do Enum.reduce_while(requests, 0, fn request, acc -> case Ash.destroy(request, domain: Mv.Membership, authorize?: false) do :ok -> {:cont, acc + 1} {:error, _} -> {:halt, acc} end end) end end