| defmodule Plausible.Session.TransferTest do |
| use ExUnit.Case |
| import Plausible.Factory |
| import Plausible.TestUtils, only: [tmp_dir: 0] |
|
|
| @tag :slow |
| test "it works" do |
| tmp_dir = tmp_dir() |
|
|
| old = start_another_plausible(tmp_dir) |
| await_transfer(old) |
|
|
| Enum.each(1..250, fn _ -> process_event(old, build(:event, name: "pageview")) end) |
|
|
| new = start_another_plausible(tmp_dir) |
| await_transfer(new) |
|
|
| assert all_sessions_sorted(new) == all_sessions_sorted(old) |
| end |
|
|
| defp start_another_plausible(tmp_dir) do |
| {:ok, pid, _node} = :peer.start_link(%{connection: {{127, 0, 0, 1}, 0}}) |
| add_code_paths(pid) |
| transfer_configuration(pid) |
| :ok = :peer.call(pid, Application, :put_env, [:plausible, :session_transfer_dir, tmp_dir]) |
| ensure_applications_started(pid) |
| pid |
| end |
|
|
| defp add_code_paths(pid) do |
| :ok = :peer.call(pid, :code, :add_paths, [:code.get_path()]) |
| end |
|
|
| defp transfer_configuration(pid) do |
| for {app_name, _, _} <- Application.loaded_applications() do |
| for {key, val} <- Application.get_all_env(app_name) do |
| :ok = :peer.call(pid, Application, :put_env, [app_name, key, val]) |
| end |
| end |
| end |
|
|
| defp ensure_applications_started(pid) do |
| {:ok, _apps} = :peer.call(pid, Application, :ensure_all_started, [:mix]) |
| :ok = :peer.call(pid, Mix, :env, [Mix.env()]) |
|
|
| for {app_name, _, _} <- Application.loaded_applications(), app_name != :dialyxir do |
| {:ok, _apps} = :peer.call(pid, Application, :ensure_all_started, [app_name]) |
| end |
| end |
|
|
| @session_params %{ |
| referrer: "ref", |
| referrer_source: "refsource", |
| utm_medium: "medium", |
| utm_source: "source", |
| utm_campaign: "campaign", |
| utm_content: "content", |
| utm_term: "term", |
| browser: "browser", |
| browser_version: "55", |
| country_code: "EE", |
| screen_size: "Desktop", |
| operating_system: "Mac", |
| operating_system_version: "11" |
| } |
|
|
| defp process_event(pid, event) do |
| :peer.call(pid, Plausible.Session.CacheStore, :on_event, [ |
| event, |
| @session_params, |
| _prev_user_id = nil, |
| [buffer_insert: &Function.identity/1] |
| ]) |
| end |
|
|
| defp all_sessions_sorted(pid) do |
| cache_names = :peer.call(pid, Plausible.Cache.Adapter, :get_names, [:sessions]) |
|
|
| records = |
| Enum.flat_map(cache_names, fn cache_name -> |
| tab = :peer.call(pid, ConCache, :ets, [cache_name]) |
| :peer.call(pid, :ets, :tab2list, [tab]) |
| end) |
|
|
| Enum.sort_by(records, fn {key, _} -> key end) |
| end |
|
|
| defp await_transfer(pid, timeout \\ :timer.seconds(1)) do |
| test = self() |
|
|
| spawn_link(fn -> |
| await_loop(fn -> :peer.call(pid, Plausible.Session.Transfer, :attempted?, []) end) |
| send(test, :took) |
| end) |
|
|
| assert_receive :took, timeout |
| end |
|
|
| defp await_loop(f) do |
| :timer.sleep(100) |
|
|
| case f.() do |
| true -> :done |
| false -> await_loop(f) |
| end |
| end |
| end |
|
|