File size: 2,683 Bytes
c27e67a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | defmodule Plausible.Workers.ScheduleEmailReports do
@moduledoc """
Job scheduling dispatch of weekly and monthly email reports.
"""
use Plausible.Repo
use Oban.Worker, queue: :schedule_email_reports
alias Plausible.Workers.SendEmailReport
@impl Oban.Worker
@doc """
Email reports should be sent on Monday at 9am according to the timezone
of a site.
"""
def perform(_job) do
schedule_weekly_emails()
schedule_monthly_emails()
end
defp schedule_weekly_emails() do
weekly_jobs =
from(
j in Oban.Job,
where:
j.worker == "Plausible.Workers.SendEmailReport" and
fragment("(? ->> 'interval')", j.args) == "weekly"
)
sites =
Repo.all(
from s in Plausible.Site,
inner_join: t in assoc(s, :team),
join: wr in Plausible.Site.WeeklyReport,
on: wr.site_id == s.id,
left_join: job in subquery(weekly_jobs),
on:
fragment("(? -> 'site_id')::int", job.args) == s.id and
job.state not in ["completed", "discarded"],
where: is_nil(job),
where: not t.locked,
preload: [weekly_report: wr]
)
for site <- sites do
SendEmailReport.new(%{site_id: site.id, interval: "weekly"},
scheduled_at: monday_9am(site.timezone)
)
|> Oban.insert!()
end
:ok
end
def monday_9am(timezone) do
DateTime.now!(timezone)
|> DateTime.shift(week: 1)
|> Plausible.Times.beginning_of_week()
|> DateTime.shift(hour: 9)
end
defp schedule_monthly_emails() do
monthly_jobs =
from(
j in Oban.Job,
where:
j.worker == "Plausible.Workers.SendEmailReport" and
fragment("(? ->> 'interval')", j.args) == "monthly"
)
sites =
Repo.all(
from s in Plausible.Site,
inner_join: t in assoc(s, :team),
join: mr in Plausible.Site.MonthlyReport,
on: mr.site_id == s.id,
left_join: job in subquery(monthly_jobs),
on:
fragment("(? -> 'site_id')::int", job.args) == s.id and
job.state not in ["completed", "discarded"],
where: is_nil(job),
where: not t.locked,
preload: [monthly_report: mr]
)
for site <- sites do
SendEmailReport.new(%{site_id: site.id, interval: "monthly"},
scheduled_at: first_of_month_9am(site.timezone)
)
|> Oban.insert!()
end
:ok
end
def first_of_month_9am(timezone) do
DateTime.now!(timezone)
|> DateTime.shift(month: 1)
|> Plausible.Times.beginning_of_month()
|> DateTime.shift(hour: 9)
end
end
|