Skip to content

Commit

Permalink
Merge pull request #53 from mbta/ph-off-switch
Browse files Browse the repository at this point in the history
feat: "Off switch" config in S3
  • Loading branch information
handorff authored Mar 6, 2020
2 parents e64d370 + 5ea3f97 commit 7cdb94b
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 3 deletions.
5 changes: 4 additions & 1 deletion lib/screens/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ defmodule Screens.Application do
use Application

def start(_type, _args) do
import Supervisor.Spec, warn: false

# List all child processes to be supervised
children = [
# Start the endpoint when the application starts
ScreensWeb.Endpoint
ScreensWeb.Endpoint,
# Starts a worker by calling: Screens.Worker.start_link(arg)
# {Screens.Worker, arg},
Screens.Override.Supervisor
]

# See https://hexdocs.pm/elixir/Supervisor.html
Expand Down
31 changes: 31 additions & 0 deletions lib/screens/override/fetch.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
defmodule Screens.Override.Fetch do
@moduledoc false

@default_opts [timeout: 2000, recv_timeout: 2000]

def fetch_config_from_s3(opts \\ []) do
url = "https://mbta-dotcom.s3.amazonaws.com/screens/config/" <> config_path_for_environment()
headers = []

with {:ok, response} <- HTTPoison.get(url, headers, Keyword.merge(@default_opts, opts)),
%{status_code: 200, body: body} <- response,
{:ok, parsed} <- Jason.decode(body),
%{"disabled_screen_ids" => disabled_screen_ids, "globally_disabled" => globally_disabled} <-
parsed do
{:ok,
%{
globally_disabled: globally_disabled,
disabled_screen_ids: MapSet.new(disabled_screen_ids)
}}
else
_ -> :error
end
end

defp config_path_for_environment do
case Application.get_env(:screens, :environment_name) do
"prod" -> "prod.json"
_ -> "dev.json"
end
end
end
55 changes: 55 additions & 0 deletions lib/screens/override/state.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
defmodule Screens.Override.State do
@moduledoc false

@initial_fetch_wait_ms 500
@refresh_ms 15 * 1000
@default_config %{globally_disabled: false, disabled_screen_ids: MapSet.new()}

use GenServer

def start_link(opts \\ []) do
GenServer.start_link(__MODULE__, :ok, opts)
end

def lookup(pid \\ __MODULE__, screen_id) do
GenServer.call(pid, {:lookup, screen_id})
end

def schedule_refresh(pid, ms \\ @refresh_ms) do
Process.send_after(pid, :refresh, ms)
:ok
end

###

@impl true
def init(:ok) do
schedule_refresh(self(), @initial_fetch_wait_ms)
{:ok, @default_config}
end

@impl true
def handle_call({:lookup, _screen_id}, _from, %{globally_disabled: true} = state) do
{:reply, true, state}
end

def handle_call(
{:lookup, screen_id},
_from,
%{globally_disabled: false, disabled_screen_ids: disabled_screen_ids} = state
) do
{:reply, MapSet.member?(disabled_screen_ids, screen_id), state}
end

@impl true
def handle_info(:refresh, _state) do
new_state =
case Screens.Override.Fetch.fetch_config_from_s3() do
{:ok, config} -> config
:error -> @default_config
end

schedule_refresh(self())
{:noreply, new_state}
end
end
17 changes: 17 additions & 0 deletions lib/screens/override/supervisor.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defmodule Screens.Override.Supervisor do
@moduledoc false

use Supervisor

def start_link([]) do
Supervisor.start_link(__MODULE__, :ok, name: __MODULE__)
end

def init(:ok) do
children = [
worker(Screens.Override.State, [[name: Screens.Override.State]])
]

supervise(children, strategy: :one_for_one)
end
end
13 changes: 12 additions & 1 deletion lib/screens/screen_data.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,18 @@ defmodule Screens.ScreenData do
alias Screens.Departures.Departure
alias Screens.NearbyConnections

def by_stop_id_with_version(stop_id, client_version) do
def by_stop_id_with_override_and_version(stop_id, screen_id, client_version) do
if Screens.Override.State.lookup(String.to_integer(screen_id)) do
%{
force_reload: false,
success: false
}
else
by_stop_id_with_version(stop_id, client_version)
end
end

defp by_stop_id_with_version(stop_id, client_version) do
api_version = Application.get_env(:screens, :api_version)

if api_version == client_version do
Expand Down
2 changes: 1 addition & 1 deletion lib/screens_web/controllers/screen_api_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ defmodule ScreensWeb.ScreenApiController do
|> Application.get_env(:screen_data)
|> Map.get(screen_id)
|> Map.get(:stop_id)
|> Screens.ScreenData.by_stop_id_with_version(version)
|> Screens.ScreenData.by_stop_id_with_override_and_version(screen_id, version)

json(conn, data)
end
Expand Down

0 comments on commit 7cdb94b

Please sign in to comment.