Skip to content
This repository was archived by the owner on Jul 16, 2026. It is now read-only.

Commit cccd7c8

Browse files
authored
Allow disabling the Preview queue consumer (#181)
1 parent 6b3a60e commit cccd7c8

4 files changed

Lines changed: 163 additions & 18 deletions

File tree

config/config.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ config :preview,
44
queue_id: "dummy",
55
queue_producer: Broadway.DummyProducer,
66
queue_concurrency: 2,
7+
queue_enabled: true,
78
package_store_impl: Preview.Package.DefaultStore,
89
package_updater_impl: Preview.Package.Updater,
910
hex_impl: Preview.Hex.HTTP,

config/runtime.exs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,39 @@
11
import Config
22

33
if config_env() == :prod do
4+
queue_enabled =
5+
case System.get_env("PREVIEW_QUEUE_ENABLED", "true") do
6+
"true" ->
7+
true
8+
9+
"false" ->
10+
false
11+
12+
value ->
13+
raise "invalid PREVIEW_QUEUE_ENABLED #{inspect(value)}; expected \"true\" or \"false\""
14+
end
15+
416
config :preview,
517
host: System.fetch_env!("PREVIEW_HOST"),
618
repo_url: System.fetch_env!("PREVIEW_REPO_URL"),
719
repo_public_key: System.fetch_env!("PREVIEW_REPO_PUBLIC_KEY"),
8-
queue_id: System.fetch_env!("PREVIEW_QUEUE_ID"),
9-
queue_concurrency: String.to_integer(System.fetch_env!("PREVIEW_QUEUE_CONCURRENCY")),
10-
fastly_key: System.fetch_env!("PREVIEW_FASTLY_KEY"),
11-
fastly_repo: System.fetch_env!("PREVIEW_FASTLY_REPO")
20+
queue_enabled: queue_enabled
1221

13-
config :preview, :repo_bucket,
14-
implementation: Preview.Storage.S3,
15-
name: System.fetch_env!("PREVIEW_REPO_BUCKET")
22+
if queue_enabled do
23+
config :preview,
24+
queue_id: System.fetch_env!("PREVIEW_QUEUE_ID"),
25+
queue_concurrency: String.to_integer(System.fetch_env!("PREVIEW_QUEUE_CONCURRENCY")),
26+
fastly_key: System.fetch_env!("PREVIEW_FASTLY_KEY"),
27+
fastly_repo: System.fetch_env!("PREVIEW_FASTLY_REPO")
28+
29+
config :preview, :repo_bucket,
30+
implementation: Preview.Storage.S3,
31+
name: System.fetch_env!("PREVIEW_REPO_BUCKET")
32+
33+
config :ex_aws,
34+
access_key_id: System.fetch_env!("PREVIEW_AWS_ACCESS_KEY_ID"),
35+
secret_access_key: System.fetch_env!("PREVIEW_AWS_ACCESS_KEY_SECRET")
36+
end
1637

1738
config :preview, :preview_bucket,
1839
implementation: Preview.Storage.GCS,
@@ -23,10 +44,6 @@ if config_env() == :prod do
2344
url: [host: System.fetch_env!("PREVIEW_HOST")],
2445
secret_key_base: System.fetch_env!("PREVIEW_SECRET_KEY_BASE")
2546

26-
config :ex_aws,
27-
access_key_id: System.fetch_env!("PREVIEW_AWS_ACCESS_KEY_ID"),
28-
secret_access_key: System.fetch_env!("PREVIEW_AWS_ACCESS_KEY_SECRET")
29-
3047
config :sentry,
3148
dsn: System.fetch_env!("PREVIEW_SENTRY_DSN"),
3249
environment_name: System.fetch_env!("PREVIEW_ENV")

lib/preview/application.ex

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,26 @@ defmodule Preview.Application do
99
:logger.add_handler(:my_sentry_handler, Sentry.LoggerHandler, %{})
1010
setup_tmp_dir()
1111

12-
children = [
12+
children = children(Application.fetch_env!(:preview, :queue_enabled))
13+
14+
opts = [strategy: :one_for_one, name: Preview.Supervisor]
15+
Supervisor.start_link(children, opts)
16+
end
17+
18+
def children(queue_enabled) when is_boolean(queue_enabled) do
19+
common = [
1320
Preview.TmpDir,
1421
PreviewWeb.Telemetry,
1522
{Phoenix.PubSub, name: Preview.PubSub},
1623
{Task.Supervisor, name: Preview.Tasks},
1724
{Finch, name: Preview.Finch, pools: finch_pools()},
1825
goth_spec(),
19-
{Preview.Debouncer, name: Preview.Debouncer},
20-
Preview.Queue,
2126
PreviewWeb.Endpoint,
2227
package_spec()
2328
]
2429

25-
# See https://hexdocs.pm/elixir/Supervisor.html
26-
# for other strategies and supported options
27-
opts = [strategy: :one_for_one, name: Preview.Supervisor]
28-
Supervisor.start_link(children, opts)
30+
queue = [{Preview.Debouncer, name: Preview.Debouncer}, Preview.Queue]
31+
common ++ if(queue_enabled, do: queue, else: [])
2932
end
3033

3134
# Tell Phoenix to update the endpoint configuration

test/preview/application_test.exs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
defmodule Preview.ApplicationTest do
2+
use ExUnit.Case, async: true
3+
4+
alias Preview.Application
5+
6+
test "queue children can be disabled without removing the web endpoint" do
7+
enabled = child_ids(Application.children(true))
8+
disabled = child_ids(Application.children(false))
9+
10+
assert Preview.Queue in enabled
11+
assert Preview.Debouncer in enabled
12+
refute Preview.Queue in disabled
13+
refute Preview.Debouncer in disabled
14+
assert PreviewWeb.Endpoint in enabled
15+
assert PreviewWeb.Endpoint in disabled
16+
end
17+
18+
test "disabled production configuration does not require queue credentials" do
19+
elixir = System.find_executable("elixir")
20+
erl = System.find_executable("erl")
21+
path = [Path.dirname(elixir), Path.dirname(erl), "/usr/bin", "/bin"] |> Enum.uniq()
22+
23+
env = [
24+
"PATH=#{Enum.join(path, ":")}",
25+
"PREVIEW_QUEUE_ENABLED=false",
26+
"PREVIEW_HOST=preview.hex.pm",
27+
"PREVIEW_REPO_URL=https://repo.hex.pm",
28+
"PREVIEW_REPO_PUBLIC_KEY=public-key",
29+
"PREVIEW_BUCKET=preview-bucket",
30+
"PREVIEW_PORT=4005",
31+
"PREVIEW_SECRET_KEY_BASE=secret-key-base",
32+
"PREVIEW_SENTRY_DSN=sentry-dsn",
33+
"PREVIEW_ENV=prod",
34+
"BEAM_PORT=14005"
35+
]
36+
37+
expression = ~S|Config.Reader.read!("config/runtime.exs", env: :prod); IO.write("configured")|
38+
39+
assert {"configured", 0} =
40+
System.cmd(System.find_executable("env"), ["-i" | env] ++ [elixir, "-e", expression])
41+
end
42+
43+
test "production configuration defaults to an enabled queue" do
44+
env = runtime_env() ++ queue_env()
45+
46+
expression =
47+
~S"""
48+
config = Config.Reader.read!("config/runtime.exs", env: :prod)
49+
preview = config[:preview]
50+
ex_aws = config[:ex_aws]
51+
52+
IO.write(
53+
Enum.join(
54+
[
55+
preview[:queue_id],
56+
preview[:queue_concurrency],
57+
preview[:fastly_key],
58+
preview[:fastly_repo],
59+
preview[:repo_bucket][:name],
60+
ex_aws[:access_key_id],
61+
ex_aws[:secret_access_key]
62+
],
63+
"|"
64+
)
65+
)
66+
"""
67+
68+
assert {"queue|10|fastly-key|fastly-repo|repo-bucket|aws-key|aws-secret", 0} =
69+
System.cmd(
70+
System.find_executable("env"),
71+
["-i" | env] ++ [System.find_executable("elixir"), "-e", expression]
72+
)
73+
end
74+
75+
test "production configuration rejects invalid queue settings" do
76+
env = ["PREVIEW_QUEUE_ENABLED=invalid" | runtime_env()]
77+
expression = ~S|Config.Reader.read!("config/runtime.exs", env: :prod)|
78+
79+
assert {output, status} =
80+
System.cmd(
81+
System.find_executable("env"),
82+
["-i" | env] ++ [System.find_executable("elixir"), "-e", expression],
83+
stderr_to_stdout: true
84+
)
85+
86+
assert status != 0
87+
assert output =~ "invalid PREVIEW_QUEUE_ENABLED"
88+
end
89+
90+
defp runtime_env do
91+
elixir = System.find_executable("elixir")
92+
erl = System.find_executable("erl")
93+
path = [Path.dirname(elixir), Path.dirname(erl), "/usr/bin", "/bin"] |> Enum.uniq()
94+
95+
[
96+
"PATH=#{Enum.join(path, ":")}",
97+
"PREVIEW_HOST=preview.hex.pm",
98+
"PREVIEW_REPO_URL=https://repo.hex.pm",
99+
"PREVIEW_REPO_PUBLIC_KEY=public-key",
100+
"PREVIEW_BUCKET=preview-bucket",
101+
"PREVIEW_PORT=4005",
102+
"PREVIEW_SECRET_KEY_BASE=secret-key-base",
103+
"PREVIEW_SENTRY_DSN=sentry-dsn",
104+
"PREVIEW_ENV=prod",
105+
"BEAM_PORT=14005"
106+
]
107+
end
108+
109+
defp queue_env do
110+
[
111+
"PREVIEW_QUEUE_ID=queue",
112+
"PREVIEW_QUEUE_CONCURRENCY=10",
113+
"PREVIEW_FASTLY_KEY=fastly-key",
114+
"PREVIEW_FASTLY_REPO=fastly-repo",
115+
"PREVIEW_REPO_BUCKET=repo-bucket",
116+
"PREVIEW_AWS_ACCESS_KEY_ID=aws-key",
117+
"PREVIEW_AWS_ACCESS_KEY_SECRET=aws-secret"
118+
]
119+
end
120+
121+
defp child_ids(children) do
122+
MapSet.new(children, fn child -> Supervisor.child_spec(child, []).id end)
123+
end
124+
end

0 commit comments

Comments
 (0)