503 + Retry-After
This commit is contained in:
parent
e0511053a4
commit
a754c0fdc2
@ -45,9 +45,9 @@ else
|
|||||||
end
|
end
|
||||||
|
|
||||||
config :asciinema, :png_generator, Asciinema.PngGenerator.A2png
|
config :asciinema, :png_generator, Asciinema.PngGenerator.A2png
|
||||||
config :asciinema, Asciinema.PngGenerator.A2png, bin_path: "./a2png/a2png.sh"
|
config :asciinema, Asciinema.PngGenerator.A2png,
|
||||||
|
bin_path: System.get_env("A2PNG_BIN_PATH") || "./a2png/a2png.sh",
|
||||||
config :porcelain, goon_warn_if_missing: false
|
pool_size: String.to_integer(System.get_env("A2PNG_POOL_SIZE") || "2")
|
||||||
|
|
||||||
# Import environment specific config. This must remain at the bottom
|
# Import environment specific config. This must remain at the bottom
|
||||||
# of this file so it overrides the configuration defined above.
|
# of this file so it overrides the configuration defined above.
|
||||||
|
@ -14,7 +14,7 @@ defmodule Asciinema do
|
|||||||
supervisor(Asciinema.Endpoint, []),
|
supervisor(Asciinema.Endpoint, []),
|
||||||
# Start your own worker by calling: Asciinema.Worker.start_link(arg1, arg2, arg3)
|
# Start your own worker by calling: Asciinema.Worker.start_link(arg1, arg2, arg3)
|
||||||
# worker(Asciinema.Worker, [arg1, arg2, arg3]),
|
# worker(Asciinema.Worker, [arg1, arg2, arg3]),
|
||||||
:poolboy.child_spec(:worker, poolboy_config(), []),
|
:poolboy.child_spec(:worker, Asciinema.PngGenerator.A2png.poolboy_config(), []),
|
||||||
]
|
]
|
||||||
|
|
||||||
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
|
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
|
||||||
@ -29,11 +29,4 @@ defmodule Asciinema do
|
|||||||
Asciinema.Endpoint.config_change(changed, removed)
|
Asciinema.Endpoint.config_change(changed, removed)
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
defp poolboy_config do
|
|
||||||
[{:name, {:local, :worker}},
|
|
||||||
{:worker_module, Asciinema.PngGenerator.A2png},
|
|
||||||
{:size, 2},
|
|
||||||
{:max_overflow, 0}]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
@ -3,16 +3,31 @@ defmodule Asciinema.PngGenerator.A2png do
|
|||||||
use GenServer
|
use GenServer
|
||||||
alias Asciinema.Asciicast
|
alias Asciinema.Asciicast
|
||||||
|
|
||||||
@result_timeout 30000
|
@pool_name :worker
|
||||||
@acquire_timeout 5000
|
@acquire_timeout 5000
|
||||||
|
@a2png_timeout 30000
|
||||||
|
@result_timeout 35000
|
||||||
|
|
||||||
def generate(%Asciicast{} = asciicast) do
|
def generate(%Asciicast{} = asciicast) do
|
||||||
{:ok, tmp_dir_path} = Briefly.create(directory: true)
|
{:ok, tmp_dir_path} = Briefly.create(directory: true)
|
||||||
|
|
||||||
:poolboy.transaction(
|
try do
|
||||||
:worker,
|
:poolboy.transaction(
|
||||||
&GenServer.call(&1, {:gen_png, asciicast, tmp_dir_path}, @result_timeout), @acquire_timeout
|
@pool_name,
|
||||||
)
|
(fn pid ->
|
||||||
|
try do
|
||||||
|
GenServer.call(pid, {:generate, asciicast, tmp_dir_path}, @result_timeout)
|
||||||
|
catch
|
||||||
|
:exit, {:timeout, _} ->
|
||||||
|
{:error, :timeout}
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
@acquire_timeout
|
||||||
|
)
|
||||||
|
catch
|
||||||
|
:exit, {:timeout, _} ->
|
||||||
|
{:error, :busy}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# GenServer API
|
# GenServer API
|
||||||
@ -25,11 +40,18 @@ defmodule Asciinema.PngGenerator.A2png do
|
|||||||
{:ok, nil}
|
{:ok, nil}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_call({:gen_png, asciicast, tmp_dir_path}, _from, state) do
|
def handle_call({:generate, asciicast, tmp_dir_path}, _from, state) do
|
||||||
{:reply, do_gen(asciicast, tmp_dir_path), state}
|
{:reply, do_generate(asciicast, tmp_dir_path), state}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_gen(asciicast, tmp_dir_path) do
|
def poolboy_config do
|
||||||
|
[{:name, {:local, @pool_name}},
|
||||||
|
{:worker_module, __MODULE__},
|
||||||
|
{:size, pool_size()},
|
||||||
|
{:max_overflow, 0}]
|
||||||
|
end
|
||||||
|
|
||||||
|
defp do_generate(asciicast, tmp_dir_path) do
|
||||||
path = Asciicast.json_store_path(asciicast)
|
path = Asciicast.json_store_path(asciicast)
|
||||||
json_path = Path.join(tmp_dir_path, "tmp.json")
|
json_path = Path.join(tmp_dir_path, "tmp.json")
|
||||||
png_path = Path.join(tmp_dir_path, "tmp.png")
|
png_path = Path.join(tmp_dir_path, "tmp.png")
|
||||||
@ -37,7 +59,8 @@ defmodule Asciinema.PngGenerator.A2png do
|
|||||||
|
|
||||||
with {:ok, file} <- file_store().open(path),
|
with {:ok, file} <- file_store().open(path),
|
||||||
{:ok, _} <- :file.copy(file, json_path),
|
{:ok, _} <- :file.copy(file, json_path),
|
||||||
%{status: 0} <- Porcelain.exec(bin_path(), [json_path, png_path, snapshot_at]) do
|
process <- Porcelain.spawn(bin_path(), [json_path, png_path, snapshot_at]),
|
||||||
|
{:ok, %{status: 0}} <- Porcelain.Process.await(process, @a2png_timeout) do
|
||||||
{:ok, png_path}
|
{:ok, png_path}
|
||||||
else
|
else
|
||||||
otherwise ->
|
otherwise ->
|
||||||
@ -45,10 +68,14 @@ defmodule Asciinema.PngGenerator.A2png do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def bin_path do
|
defp bin_path do
|
||||||
Keyword.get(Application.get_env(:asciinema, __MODULE__), :bin_path)
|
Keyword.get(Application.get_env(:asciinema, __MODULE__), :bin_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp pool_size do
|
||||||
|
Keyword.get(Application.get_env(:asciinema, __MODULE__), :pool_size)
|
||||||
|
end
|
||||||
|
|
||||||
defp file_store do
|
defp file_store do
|
||||||
Application.get_env(:asciinema, :file_store)
|
Application.get_env(:asciinema, :file_store)
|
||||||
end
|
end
|
||||||
|
@ -5,11 +5,17 @@ defmodule Asciinema.AsciicastImageController do
|
|||||||
|
|
||||||
def show(conn, %{"id" => id} = _params) do
|
def show(conn, %{"id" => id} = _params) do
|
||||||
asciicast = Repo.one!(Asciicast.by_id_or_secret_token(id))
|
asciicast = Repo.one!(Asciicast.by_id_or_secret_token(id))
|
||||||
{:ok, png_path} = PngGenerator.generate(asciicast)
|
|
||||||
|
|
||||||
conn
|
case PngGenerator.generate(asciicast) do
|
||||||
|> put_resp_header("content-type", MIME.path(png_path))
|
{:ok, png_path} ->
|
||||||
|> send_file(200, png_path)
|
conn
|
||||||
|> halt
|
|> put_resp_header("content-type", MIME.path(png_path))
|
||||||
|
|> send_file(200, png_path)
|
||||||
|
|> halt
|
||||||
|
{:error, :busy} ->
|
||||||
|
conn
|
||||||
|
|> put_resp_header("retry-after", "5")
|
||||||
|
|> send_resp(503, "")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user