Skip to content

Commit

Permalink
add a catch-all for handling unexpected messages on the genserver
Browse files Browse the repository at this point in the history
We're seeing something similar to
benoitc/hackney#464 that is causing the
genserver to crash, because it's not handling a message that seems to be
leaking from hackney / httpoison. This change should prevent that crash
from happening.
  • Loading branch information
peburrows committed Sep 26, 2024
1 parent d0a4e11 commit 95044dd
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 33 deletions.
22 changes: 22 additions & 0 deletions lib/statsig_ex.ex
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
defmodule StatsigEx do
use GenServer
require Logger
alias StatsigEx.Utils

# default intervals
@flush_interval 60_000
@reload_interval 60_000

@moduledoc """
`StatsigEx` is the module through which all interaction with flags and configs
should flow. At a high level, it works like this:
* at startup, a `GenServer` is created that stores the most recent flag and config
definitions.
* (either via `check_gate` or )
* every `@reload_interval` milliseconds, the server pulls any recent changes to
flag or config definitions and updates its copy.
* every `@flush_interval` milliseconds, the server pushes exposure logs to statsig.
"""

def start_link(opts \\ []) do
opts =
opts
Expand Down Expand Up @@ -42,6 +55,9 @@ defmodule StatsigEx do
# end
end

@doc """
For a user, check a gate.
"""
def check_gate(user, gate, server \\ __MODULE__)
def check_gate(nil, _gate, _server), do: {:error, :no_user}

Expand Down Expand Up @@ -116,6 +132,12 @@ defmodule StatsigEx do
{:noreply, Map.put(state, :events, remaining)}
end

# might want to log these messages
def handle_info(msg, state) do
Logger.info("unhandled message: #{inspect(msg)}")
{:noreply, state}
end

def terminate(_reason, %{api_key: key, events: events}),
do: flush_events(key, events)

Expand Down
4 changes: 4 additions & 0 deletions lib/statsig_ex/evaluator.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
defmodule StatsigEx.Evaluator do
@unsupported ["ip_based"]

@moduledoc """
It is rare, but there may be a case where you need to get an evaluation result directly
"""

defmodule Result do
defstruct exposures: [],
secondary_exposures: [],
Expand Down
37 changes: 4 additions & 33 deletions test/consistency_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,9 @@ defmodule StatsigEx.ConsistencyTest do
|> Map.get("data")
|> generate_all_tests()

@tag :skip
test "one test" do
result =
StatsigEx.Evaluator.eval(
%{
"appVersion" => "1.3",
"ip" => "1.0.0.0",
"locale" => "en_US",
"statsigEnvironment" => %{"tier" => "DEVELOPMENT"},
"userAgent" =>
"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1",
"userID" => "123"
},
"test_gate_with_targeting_gate",
:gate,
:test
)

secondary = [
%{
"gate" => "global_holdout",
"gateValue" => "false",
"ruleID" => "3QoA4ncNdVGBaMt3N1KYjz:0.50:1"
},
%{
"gate" => "test_targeting_gate_with_no_rules",
"gateValue" => "false",
"ruleID" => "default"
}
]

[_ | sec] = result.exposures
assert Enum.sort(secondary) == Enum.sort(sec)
test "random messages are properly handled" do
assert :ok = Process.send(:test, {:ssl_closed, {:sslsocket, {:gen_tcp, :etc}}}, [])
# give the server time to handle the message
Process.sleep(100)
end
end

0 comments on commit 95044dd

Please sign in to comment.