defmodule Mobilizon.Service.Workers.RefreshParticipantStats do @moduledoc """ Worker to refresh the participant event stats based on participants data """ use Oban.Worker, unique: [period: :infinity, keys: [:event_uuid, :action]] alias Mobilizon.Events alias Mobilizon.Events.{Event, Participant} alias Mobilizon.Storage.Page alias Oban.Job require Logger @impl Oban.Worker @spec perform(Oban.Job.t()) :: :ok def perform(%Job{}) do refresh_participant_stats() end def refresh_participant_stats do Logger.info("Launching RefreshParticipantStats job") %Page{elements: future_events} = Events.list_events(1, 100_000_000) updated_events_count = Enum.reduce(future_events, 0, fn %Event{} = event, updated_events_count -> participants = Events.list_all_participants_for_event(event.id) participant_stats = Enum.reduce( participants, %{ not_approved: 0, not_confirmed: 0, rejected: 0, participant: 0, moderator: 0, administrator: 0, creator: 0 }, fn %Participant{role: role}, acc -> Map.update(acc, role, 1, &(&1 + 1)) end ) if participant_stats != Map.from_struct(event.participant_stats) do Logger.debug("Uupdating event #{event.id} because of wrong participant_stats") Events.update_event(event, %{ participant_stats: participant_stats }) updated_events_count + 1 else Logger.debug("Skipped updating event #{event.id}") updated_events_count end end) Logger.info("Updated #{updated_events_count} events on #{length(future_events)}") end end