From 33ba5d79b635f44041113680e7666e798f36a481 Mon Sep 17 00:00:00 2001 From: Uku Taht <Uku.taht@gmail.com> Date: Mon, 6 Sep 2021 13:54:51 +0300 Subject: [PATCH] Memoize has_stats? (#1302) * Memoize has_stats? * Remove unused alias --- lib/plausible/auth/auth.ex | 7 ++-- lib/plausible/site/schema.ex | 5 +++ lib/plausible/sites.ex | 17 ++++++++++ lib/plausible/stats/clickhouse.ex | 4 ++- .../controllers/stats_controller.ex | 7 ++-- .../stats/waiting_first_pageview.html.eex | 2 +- lib/workers/send_site_setup_emails.ex | 5 ++- .../20210906102736_memoize_setup_complete.exs | 9 ++++++ test/plausible/sites_test.exs | 32 +++++++++++++++++++ 9 files changed, 75 insertions(+), 13 deletions(-) create mode 100644 priv/repo/migrations/20210906102736_memoize_setup_complete.exs diff --git a/lib/plausible/auth/auth.ex b/lib/plausible/auth/auth.ex index ac3c7864..3dd82504 100644 --- a/lib/plausible/auth/auth.ex +++ b/lib/plausible/auth/auth.ex @@ -1,7 +1,6 @@ defmodule Plausible.Auth do use Plausible.Repo alias Plausible.Auth - alias Plausible.Stats.Clickhouse, as: Stats def issue_email_verification(user) do Repo.update_all(from(c in "email_verification_codes", where: c.user_id == ^user.id), @@ -68,7 +67,7 @@ defmodule Plausible.Auth do end def has_active_sites?(user, roles \\ [:owner, :admin, :viewer]) do - domains = + sites = Repo.all( from u in Plausible.Auth.User, where: u.id == ^user.id, @@ -77,10 +76,10 @@ defmodule Plausible.Auth do where: sm.role in ^roles, join: s in Plausible.Site, on: s.id == sm.site_id, - select: s.domain + select: s ) - Stats.has_pageviews?(domains) + Enum.any?(sites, &Plausible.Sites.has_stats?/1) end def user_owns_sites?(user) do diff --git a/lib/plausible/site/schema.ex b/lib/plausible/site/schema.ex index ade0ffc2..625c5bcd 100644 --- a/lib/plausible/site/schema.ex +++ b/lib/plausible/site/schema.ex @@ -10,6 +10,7 @@ defmodule Plausible.Site do field :timezone, :string, default: "Etc/UTC" field :public, :boolean field :locked, :boolean + field :has_stats, :boolean many_to_many :members, User, join_through: Plausible.Site.Membership has_many :memberships, Plausible.Site.Membership @@ -42,6 +43,10 @@ defmodule Plausible.Site do change(site, public: false) end + def set_has_stats(site, has_stats_val) do + change(site, has_stats: has_stats_val) + end + defp clean_domain(changeset) do clean_domain = (get_field(changeset, :domain) || "") diff --git a/lib/plausible/sites.ex b/lib/plausible/sites.ex index f50f034d..e073fc7f 100644 --- a/lib/plausible/sites.ex +++ b/lib/plausible/sites.ex @@ -26,6 +26,23 @@ defmodule Plausible.Sites do end end + def has_stats?(site) do + if site.has_stats do + true + else + has_stats = Plausible.Stats.Clickhouse.has_pageviews?(site) + + if has_stats do + Plausible.Site.set_has_stats(site, true) + |> Repo.update() + + true + else + false + end + end + end + def create_shared_link(site, name, password \\ nil) do changes = SharedLink.changeset( diff --git a/lib/plausible/stats/clickhouse.ex b/lib/plausible/stats/clickhouse.ex index 60607f6a..ac5b2a67 100644 --- a/lib/plausible/stats/clickhouse.ex +++ b/lib/plausible/stats/clickhouse.ex @@ -892,7 +892,9 @@ defmodule Plausible.Stats.Clickhouse do end def has_pageviews?(site) do - ClickhouseRepo.exists?(from e in "events", where: e.domain == ^site.domain) + ClickhouseRepo.exists?( + from e in "events", where: e.domain == ^site.domain and e.name == "pageview" + ) end def all_props(site, %Query{filters: %{"props" => meta}} = query) when is_map(meta) do diff --git a/lib/plausible_web/controllers/stats_controller.ex b/lib/plausible_web/controllers/stats_controller.ex index cdd2023f..00c0e9ae 100644 --- a/lib/plausible_web/controllers/stats_controller.ex +++ b/lib/plausible_web/controllers/stats_controller.ex @@ -1,16 +1,15 @@ defmodule PlausibleWeb.StatsController do use PlausibleWeb, :controller use Plausible.Repo - alias Plausible.Stats.Clickhouse, as: Stats alias Plausible.Stats.Query plug PlausibleWeb.AuthorizeSiteAccess when action in [:stats, :csv_export] def stats(%{assigns: %{site: site}} = conn, _params) do - has_pageviews = Stats.has_pageviews?(site) + has_stats = Plausible.Sites.has_stats?(site) cond do - !site.locked && has_pageviews -> + !site.locked && has_stats -> demo = site.domain == PlausibleWeb.Endpoint.host() offer_email_report = get_session(conn, site.domain <> "_offer_email_report") @@ -26,7 +25,7 @@ defmodule PlausibleWeb.StatsController do demo: demo ) - !site.locked && !has_pageviews -> + !site.locked && !has_stats -> conn |> assign(:skip_plausible_tracking, true) |> render("waiting_first_pageview.html", site: site) diff --git a/lib/plausible_web/templates/stats/waiting_first_pageview.html.eex b/lib/plausible_web/templates/stats/waiting_first_pageview.html.eex index b262ca0b..e66ebf68 100644 --- a/lib/plausible_web/templates/stats/waiting_first_pageview.html.eex +++ b/lib/plausible_web/templates/stats/waiting_first_pageview.html.eex @@ -10,7 +10,7 @@ }) } - setInterval(updateStatus, 1500) + setInterval(updateStatus, 5000) </script> <div class="w-full max-w-md mx-auto mt-8"> diff --git a/lib/workers/send_site_setup_emails.ex b/lib/workers/send_site_setup_emails.ex index 74c95546..d4250aac 100644 --- a/lib/workers/send_site_setup_emails.ex +++ b/lib/workers/send_site_setup_emails.ex @@ -2,7 +2,6 @@ defmodule Plausible.Workers.SendSiteSetupEmails do use Plausible.Repo use Oban.Worker, queue: :site_setup_emails require Logger - alias Plausible.Stats.Clickhouse, as: Stats @impl Oban.Worker def perform(_job) do @@ -46,7 +45,7 @@ defmodule Plausible.Workers.SendSiteSetupEmails do Plausible.Sites.owner_for(site) |> Repo.preload(:subscription) - setup_completed = Stats.has_pageviews?(site) + setup_completed = Plausible.Sites.has_stats?(site) hours_passed = Timex.diff(Timex.now(), site.inserted_at, :hours) if !setup_completed && hours_passed > 47 do @@ -69,7 +68,7 @@ defmodule Plausible.Workers.SendSiteSetupEmails do Plausible.Sites.owner_for(site) |> Repo.preload(:subscription) - if Stats.has_pageviews?(site) do + if Plausible.Sites.has_stats?(site) do send_setup_success_email(owner, site) end end diff --git a/priv/repo/migrations/20210906102736_memoize_setup_complete.exs b/priv/repo/migrations/20210906102736_memoize_setup_complete.exs new file mode 100644 index 00000000..a1b5ebc0 --- /dev/null +++ b/priv/repo/migrations/20210906102736_memoize_setup_complete.exs @@ -0,0 +1,9 @@ +defmodule Plausible.Repo.Migrations.MemoizeSetupComplete do + use Ecto.Migration + + def change do + alter table(:sites) do + add :has_stats, :boolean, null: false, default: false + end + end +end diff --git a/test/plausible/sites_test.exs b/test/plausible/sites_test.exs index b4f4be59..077c694d 100644 --- a/test/plausible/sites_test.exs +++ b/test/plausible/sites_test.exs @@ -1,5 +1,6 @@ defmodule Plausible.SitesTest do use Plausible.DataCase + import Plausible.TestUtils alias Plausible.Sites describe "is_member?" do @@ -17,4 +18,35 @@ defmodule Plausible.SitesTest do refute Sites.is_member?(user.id, site) end end + + describe "has_stats?" do + test "is false if site has no stats" do + site = insert(:site) + + refute Sites.has_stats?(site) + end + + test "is true if site has stats" do + site = insert(:site) + + populate_stats(site, [ + build(:pageview) + ]) + + assert Sites.has_stats?(site) + end + + test "memoizes has_stats value" do + site = insert(:site) + + populate_stats(site, [ + build(:pageview) + ]) + + refute site.has_stats + + assert Sites.has_stats?(site) + assert Repo.reload!(site).has_stats + end + end end -- GitLab