analytics/lib/workers/import_analytics.ex
Adrian Gruntkowski 41fef85d29
Implement resumable GA4 imports to work around rate limiting (#4049)
* Add support for resuming import to GA4 importer

* Handle rate limiting gracefully for all remainig GA4 HTTP requests

* Show notice tooltip for long running imports

* Bump resume job schedule delay to 65 minutes

* Fix tooltip styling
2024-04-30 18:06:18 +02:00

98 lines
2.3 KiB
Elixir

defmodule Plausible.Workers.ImportAnalytics do
@moduledoc """
Worker for running analytics import jobs.
"""
use Plausible.Repo
require Logger
use Oban.Worker,
queue: :analytics_imports,
max_attempts: 3,
unique: [fields: [:args], keys: [:import_id], period: 60]
alias Plausible.Imported.ImportSources
alias Plausible.Imported.Importer
alias Plausible.Imported.SiteImport
@impl Oban.Worker
def perform(%Oban.Job{
args: %{"import_id" => import_id} = args
}) do
site_import =
SiteImport
|> Repo.get!(import_id)
|> Repo.preload(:site)
import_api = ImportSources.by_name(site_import.source)
case import_api.run_import(site_import, args) do
{:ok, site_import} ->
import_complete(site_import)
:ok
{:error, error, error_opts} ->
Sentry.capture_message("Failed to import from #{site_import.source}",
extra: %{
import_id: site_import.id,
site: site_import.site.domain,
error: inspect(error)
}
)
import_fail(site_import, error_opts)
{:discard, error}
end
end
@impl Oban.Worker
def backoff(_job) do
# 5 minutes
300
end
def import_complete(site_import) do
site_import = Repo.preload(site_import, [:site, :imported_by])
PlausibleWeb.Email.import_success(site_import, site_import.imported_by)
|> Plausible.Mailer.send()
Plausible.Sites.clear_stats_start_date!(site_import.site)
Importer.notify(site_import, :complete)
:ok
end
def import_fail_transient(site_import) do
Plausible.Purge.delete_imported_stats!(site_import)
Importer.notify(site_import, :transient_fail)
end
def import_fail(site_import, opts) do
skip_purge? = Keyword.get(opts, :skip_purge?, false)
skip_mark_failed? = Keyword.get(opts, :skip_mark_failed?, false)
if not skip_purge? do
Plausible.Purge.delete_imported_stats!(site_import)
end
if not skip_mark_failed? do
import_api = ImportSources.by_name(site_import.source)
site_import =
site_import
|> import_api.mark_failed()
|> Repo.preload([:site, :imported_by])
Importer.notify(site_import, :fail)
PlausibleWeb.Email.import_failure(site_import, site_import.imported_by)
|> Plausible.Mailer.send()
end
end
end