Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto-archival of unclaimed asciicasts (GC) #333

Merged
merged 16 commits into from Dec 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env.production.sample
Expand Up @@ -25,6 +25,11 @@ SECRET_KEY_BASE=
## Default: first public asciicast
# HOME_ASCIICAST_ID=1

## Enable auto-archival of recordings uploaded by anonymous users.
## Set this variable to number of days after which the recordings are archived.
## Default: unset (no auto-archival)
# ASCIICAST_GC_DAYS=7

### E-mail delivery

## Outgoing mail hostname, used by namshi/smtp container.
Expand Down
5 changes: 5 additions & 0 deletions config/config.exs
Expand Up @@ -60,6 +60,11 @@ config :exq_ui, server: false
config :scrivener_html,
view_style: :bootstrap_v4

config :asciinema, Asciinema.Scheduler,
jobs: [
{"0 * * * *", {Asciinema.GC, :run, []}}
]

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env}.exs"
4 changes: 4 additions & 0 deletions config/dev.exs
Expand Up @@ -49,5 +49,9 @@ config :asciinema, Asciinema.Mailer,
config :asciinema, Asciinema.Vt.Worker,
vt_script_path: "vt/main.js"

if gc_days = System.get_env("ASCIICAST_GC_DAYS") do
config :asciinema, :asciicast_gc_days, String.to_integer(gc_days)
end

# Import custom config.
import_config "custom*.exs"
8 changes: 7 additions & 1 deletion lib/asciinema/accounts/accounts.ex
Expand Up @@ -43,6 +43,12 @@ defmodule Asciinema.Accounts do
|> Repo.update
end

def temporary_user?(user), do: user.email == nil

def temporary_users(q \\ User) do
from(u in q, where: is_nil(u.email))
end

def send_login_email(email_or_username) do
with {:ok, %User{} = user} <- lookup_user(email_or_username) do
do_send_login_email(user)
Expand Down Expand Up @@ -249,7 +255,7 @@ defmodule Asciinema.Accounts do
end

def asciicasts(user, visibility \\ :all) do
q = assoc(user, :asciicasts)
q = from(a in assoc(user, :asciicasts), where: is_nil(a.archived_at))

case visibility do
:all -> q
Expand Down
1 change: 1 addition & 0 deletions lib/asciinema/application.ex
Expand Up @@ -17,6 +17,7 @@ defmodule Asciinema.Application do
:poolboy.child_spec(:worker, Asciinema.PngGenerator.Rsvg.poolboy_config(), []),
supervisor(Asciinema.Vt.Pool, []),
supervisor(Exq, []),
Asciinema.Scheduler
]

:ok = :error_logger.add_report_handler(Sentry.Logger)
Expand Down
1 change: 1 addition & 0 deletions lib/asciinema/asciicasts/asciicast.ex
Expand Up @@ -34,6 +34,7 @@ defmodule Asciinema.Asciicasts.Asciicast do
field :recorded_at, Timex.Ecto.DateTime
field :idle_time_limit, :float
field :views_count, :integer, default: 0
field :archived_at, Timex.Ecto.DateTime

timestamps(inserted_at: :created_at)

Expand Down
28 changes: 25 additions & 3 deletions lib/asciinema/asciicasts/asciicasts.ex
Expand Up @@ -74,9 +74,17 @@ defmodule Asciinema.Asciicasts do
|> filter(category)
end

defp filter(q, :featured), do: where(q, [a], a.featured == true and a.private == false)
defp filter(q, :public), do: where(q, [a], a.private == false)
defp filter(q, :all), do: q
defp filter(q, :featured) do
where(q, [a], a.featured == true and a.private == false and is_nil(a.archived_at))
end

defp filter(q, :public) do
where(q, [a], a.private == false and is_nil(a.archived_at))
end

defp filter(q, :all) do
where(q, [a], is_nil(a.archived_at))
end

defp sort(q, :date), do: order_by(q, desc: :id)
defp sort(q, :popularity), do: order_by(q, desc: :views_count)
Expand Down Expand Up @@ -557,4 +565,18 @@ defmodule Asciinema.Asciicasts do

tmp_path
end

def gc_days do
Application.get_env(:asciinema, :asciicast_gc_days)
end

def archive_asciicasts(users_query, dt) do
query = from a in Asciicast,
join: u in ^users_query,
on: a.user_id == u.id,
where: is_nil(a.archived_at) and a.created_at < ^dt

{count, _} = Repo.update_all(query, set: [archived_at: Timex.now()])
count
end
end
14 changes: 14 additions & 0 deletions lib/asciinema/gc.ex
@@ -0,0 +1,14 @@
defmodule Asciinema.GC do
alias Asciinema.Accounts
alias Asciinema.Asciicasts
require Logger

def run do
if days = Asciicasts.gc_days() do
Logger.info("archiving unclaimed asciicasts...")
dt = Timex.shift(Timex.now(), days: -days)
count = Asciicasts.archive_asciicasts(Accounts.temporary_users(), dt)
Logger.info("archived #{count} asciicasts")
end
end
end
3 changes: 3 additions & 0 deletions lib/asciinema/scheduler.ex
@@ -0,0 +1,3 @@
defmodule Asciinema.Scheduler do
use Quantum.Scheduler, otp_app: :asciinema
end
6 changes: 6 additions & 0 deletions lib/asciinema_web.ex
Expand Up @@ -79,4 +79,10 @@ defmodule AsciinemaWeb do
defmacro __using__(which) when is_atom(which) do
apply(__MODULE__, which, [])
end

def instance_hostname do
AsciinemaWeb.Endpoint.url()
|> URI.parse()
|> Map.get(:host)
end
end
6 changes: 4 additions & 2 deletions lib/asciinema_web/controllers/api/asciicast_controller.ex
Expand Up @@ -28,7 +28,7 @@ defmodule AsciinemaWeb.Api.AsciicastController do
conn
|> put_status(:created)
|> put_resp_header("location", url)
|> render(:created, url: url)
|> render(:created, url: url, install_id: conn.assigns.install_id)

{:error, :unknown_format} ->
conn
Expand Down Expand Up @@ -69,7 +69,9 @@ defmodule AsciinemaWeb.Api.AsciicastController do
defp authenticate(conn, _opts) do
with {username, api_token} <- get_basic_auth(conn),
{:ok, %User{} = user} <- Accounts.get_user_with_api_token(api_token, username) do
assign(conn, :current_user, user)
conn
|> assign(:install_id, api_token)
|> assign(:current_user, user)
else
_otherwise ->
conn
Expand Down
49 changes: 35 additions & 14 deletions lib/asciinema_web/controllers/asciicast_controller.ex
Expand Up @@ -5,7 +5,7 @@ defmodule AsciinemaWeb.AsciicastController do

plug :put_layout, "app2.html"
plug :clear_main_class
plug :load_asciicast when action in [:show, :edit, :update, :delete]
plug :load_asciicast when action in [:show, :edit, :update, :delete, :example, :iframe, :embed]
plug :require_current_user when action in [:edit, :update, :delete]
plug :authorize, :asciicast when action in [:edit, :update, :delete]

Expand Down Expand Up @@ -37,7 +37,13 @@ defmodule AsciinemaWeb.AsciicastController do
end

def show(conn, _params) do
do_show(conn, get_format(conn), conn.assigns.asciicast)
asciicast = conn.assigns.asciicast

if asciicast.archived_at do
render_archived(conn)
else
do_show(conn, get_format(conn), asciicast)
end
end

def do_show(conn, "html", asciicast) do
Expand Down Expand Up @@ -133,35 +139,50 @@ defmodule AsciinemaWeb.AsciicastController do
end
end

def iframe(conn, %{"id" => id}) do
asciicast = Asciicasts.get_asciicast!(id)
def iframe(conn, _params) do
url = asciicast_file_url(conn, conn.assigns.asciicast)

conn
|> put_layout("iframe.html")
|> delete_resp_header("x-frame-options")
|> render("iframe.html", file_url: asciicast_file_url(conn, asciicast))
|> render_asciicast("iframe.html", file_url: url)
end

def embed(conn, %{"id" => id} = params) do
asciicast = Asciicasts.get_asciicast!(id)
def embed(conn, params) do
opts = Asciicasts.PlaybackOpts.parse(params)

conn
|> put_layout("embed.html")
|> delete_resp_header("x-frame-options")
|> render("embed.html",
asciicast: asciicast,
playback_options: opts
)
|> render_asciicast("embed.html", playback_options: opts)
end

def example(conn, %{"id" => id}) do
asciicast = Asciicasts.get_asciicast!(id)
def example(conn, _params) do
home_asciicast = Asciicasts.get_homepage_asciicast()

conn
|> put_layout("example.html")
|> render("example.html", asciicast: asciicast, home_asciicast: home_asciicast)
|> render_asciicast("example.html", home_asciicast: home_asciicast)
end

defp render_asciicast(conn, template, assigns) do
if conn.assigns.asciicast.archived_at do
render_archived(conn)
else
render(conn, template, assigns)
end
end

defp render_archived(conn) do
case get_format(conn) do
"html" ->
conn
|> put_status(410)
|> render("archived.html")

_ ->
send_resp(conn, 410, "")
end
end

defp download_filename(%Asciicast{version: version, id: id}, %{"dl" => _}) do
Expand Down
14 changes: 14 additions & 0 deletions lib/asciinema_web/templates/asciicast/archived.html.eex
@@ -0,0 +1,14 @@
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>This recording has been archived</h2>

<%= if days = asciicast_gc_days() do %>
<p>
All unclaimed recordings (the ones not linked to any user account) are
automatically archived <%= days %> days after upload.
</p>
<% end %>
</div>
</div>
</div>
40 changes: 36 additions & 4 deletions lib/asciinema_web/views/api/asciicast_view.ex
@@ -1,18 +1,50 @@
defmodule AsciinemaWeb.Api.AsciicastView do
use AsciinemaWeb, :view

def render("created.text", %{url: url}) do
url
def render("created.text", assigns) do
message(assigns)
end

def render("created.json", %{url: url}) do
%{url: url}
def render("created.json", assigns) do
%{
url: assigns.url,
message: message(assigns)
}
end

def render("error.json", %{changeset: changeset}) do
%{errors: translate_errors(changeset)}
end

defp message(%{conn: conn, url: url, install_id: install_id}) do
message = """
View the recording at:

#{url}
"""

is_tmp_user = Asciinema.Accounts.temporary_user?(conn.assigns.current_user)
gc_days = Asciinema.Asciicasts.gc_days()

if is_tmp_user && gc_days do
hostname = AsciinemaWeb.instance_hostname()

"""
#{message}
This installation of asciinema recorder hasn't been linked to any #{hostname}
account. All unclaimed recordings (from unknown installations like this one)
are automatically archived #{gc_days} days after upload.

If you want to preserve all recordings made on this machine, connect this
installation with #{hostname} account by opening the following link:

#{connect_url(conn, :show, install_id)}
"""
else
message
end
end

def translate_errors(changeset) do
Ecto.Changeset.traverse_errors(changeset, &translate_error/1)
end
Expand Down
4 changes: 4 additions & 0 deletions lib/asciinema_web/views/asciicast_view.ex
Expand Up @@ -461,4 +461,8 @@ defmodule AsciinemaWeb.AsciicastView do
def percent(float) do
"#{Decimal.round(Decimal.new(float), 3)}%"
end

def asciicast_gc_days do
Asciinema.Asciicasts.gc_days()
end
end
1 change: 1 addition & 0 deletions mix.exs
Expand Up @@ -54,6 +54,7 @@ defmodule Asciinema.Mixfile do
{:poison, "~> 3.1"},
{:poolboy, "~> 1.5"},
{:postgrex, ">= 0.0.0"},
{:quantum, "~> 2.3"},
{:redix, ">= 0.6.1"},
{:scrivener_ecto, "~> 1.0"},
{:scrivener_html, "~> 1.7"},
Expand Down
6 changes: 6 additions & 0 deletions mix.lock
Expand Up @@ -10,6 +10,7 @@
"cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm"},
"credo": {:hex, :credo, "0.10.0", "66234a95effaf9067edb19fc5d0cd5c6b461ad841baac42467afed96c78e5e9e", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
"crontab": {:hex, :crontab, "1.1.5", "2c9439506ceb0e9045de75879e994b88d6f0be88bfe017d58cb356c66c4a5482", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},
"db_connection": {:hex, :db_connection, "1.1.3", "89b30ca1ef0a3b469b1c779579590688561d586694a3ce8792985d4d7e575a61", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
"decimal": {:hex, :decimal, "1.5.0", "b0433a36d0e2430e3d50291b1c65f53c37d56f83665b43d79963684865beab68", [:mix], [], "hexpm"},
"distillery": {:hex, :distillery, "2.0.11", "9259399cb64c88e2df6bbaef29e09b0a81d16d0155203ebf65c6be7b95f7b744", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm"},
Expand All @@ -22,12 +23,15 @@
"exq_ui": {:hex, :exq_ui, "0.9.0", "e97e9fa9009f30d2926b51a166e40a3a521e83f61f3f333fede8335b2aa57f09", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, repo: "hexpm", optional: false]}, {:exq, "~> 0.9", [hex: :exq, repo: "hexpm", optional: false]}, {:plug, ">= 0.8.1 and < 2.0.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"file_system": {:hex, :file_system, "0.2.2", "7f1e9de4746f4eb8a4ca8f2fbab582d84a4e40fa394cce7bfcb068b988625b06", [:mix], [], "hexpm"},
"gen_smtp": {:hex, :gen_smtp, "0.12.0", "97d44903f5ca18ca85cb39aee7d9c77e98d79804bbdef56078adcf905cb2ef00", [:rebar3], [], "hexpm"},
"gen_stage": {:hex, :gen_stage, "0.14.1", "9d46723fda072d4f4bb31a102560013f7960f5d80ea44dcb96fd6304ed61e7a4", [:mix], [], "hexpm"},
"gen_state_machine": {:hex, :gen_state_machine, "2.0.4", "cc31749b8ee50d42c8db7d96c85637c4c9fdc7a007145c8aa2f371c89148a6ca", [:mix], [], "hexpm"},
"gettext": {:hex, :gettext, "0.13.1", "5e0daf4e7636d771c4c71ad5f3f53ba09a9ae5c250e1ab9c42ba9edccc476263", [:mix], [], "hexpm"},
"hackney": {:hex, :hackney, "1.13.0", "24edc8cd2b28e1c652593833862435c80661834f6c9344e84b6a2255e7aeef03", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.2", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
"html_sanitize_ex": {:hex, :html_sanitize_ex, "1.3.0", "f005ad692b717691203f940c686208aa3d8ffd9dd4bb3699240096a51fa9564e", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"},
"idna": {:hex, :idna, "5.1.2", "e21cb58a09f0228a9e0b95eaa1217f1bcfc31a1aaa6e1fdf2f53a33f7dbd9494", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
"inflex": {:hex, :inflex, "1.9.0", "2bef01a84437bca0a12fc107821ae7771b0ba847dccab5d1cd61f35972e66813", [:mix], [], "hexpm"},
"jason": {:hex, :jason, "1.1.1", "d3ccb840dfb06f2f90a6d335b536dd074db748b3e7f5b11ab61d239506585eb2", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
"libring": {:hex, :libring, "1.4.0", "41246ba2f3fbc76b3971f6bce83119dfec1eee17e977a48d8a9cfaaf58c2a8d6", [:mix], [], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
"mime": {:hex, :mime, "1.3.0", "5e8d45a39e95c650900d03f897fbf99ae04f60ab1daa4a34c7a20a5151b7a5fe", [:mix], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
Expand All @@ -43,13 +47,15 @@
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"},
"poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [:rebar], [], "hexpm"},
"postgrex": {:hex, :postgrex, "0.13.5", "3d931aba29363e1443da167a4b12f06dcd171103c424de15e5f3fc2ba3e6d9c5", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm"},
"quantum": {:hex, :quantum, "2.3.3", "83f565de81ac43b8fda4dd4266b209eaed29545d1c41e17aa6b75b08736c80f6", [:mix], [{:calendar, "~> 0.17", [hex: :calendar, repo: "hexpm", optional: true]}, {:crontab, "~> 1.1", [hex: :crontab, repo: "hexpm", optional: false]}, {:gen_stage, "~> 0.12", [hex: :gen_stage, repo: "hexpm", optional: false]}, {:swarm, "~> 3.3", [hex: :swarm, repo: "hexpm", optional: false]}, {:timex, "~> 3.1", [hex: :timex, repo: "hexpm", optional: true]}], "hexpm"},
"ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm"},
"redix": {:hex, :redix, "0.7.1", "25a6c1c0d9b2d12a35aef759f9e49bd9bca00e0cd857ce766412f08fdda72163", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"},
"scrivener": {:hex, :scrivener, "2.5.0", "e1f78c62b6806d91cc9c4778deef1ea4e80aa9fadfce2c16831afe0468cc8a2c", [:mix], [], "hexpm"},
"scrivener_ecto": {:hex, :scrivener_ecto, "1.3.0", "69698428e22810ac8a47abc12d1df5b2f5d8f6b36dc5d5bfe6dd93fde857c576", [:mix], [{:ecto, "~> 2.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.11.0 or ~> 0.12.0 or ~> 0.13.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:scrivener, "~> 2.4", [hex: :scrivener, repo: "hexpm", optional: false]}], "hexpm"},
"scrivener_html": {:hex, :scrivener_html, "1.7.1", "afa35128fb36184bc469e4531bb1ef61b2d91bb29e373157068c62332291485f", [:mix], [{:phoenix, "~> 1.0-pre and < 1.4.0", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.1", [hex: :plug, repo: "hexpm", optional: false]}, {:scrivener, "~> 1.2 or ~> 2.0", [hex: :scrivener, repo: "hexpm", optional: false]}], "hexpm"},
"sentry": {:hex, :sentry, "6.4.2", "71b3cf8ce6dbf7816b8086eb8f221fd7fd71cefdbf7461094c628785cae6a67c", [:mix], [{:hackney, "~> 1.8 or 1.6.5", [hex: :hackney, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:poison, "~> 1.5 or ~> 2.0 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"},
"swarm": {:hex, :swarm, "3.3.1", "b4d29c49310b92b4a84bd3be6a51d9616eaeda1899b7619201d0908d8d789bd8", [:mix], [{:gen_state_machine, "~> 2.0", [hex: :gen_state_machine, repo: "hexpm", optional: false]}, {:libring, "~> 1.0", [hex: :libring, repo: "hexpm", optional: false]}], "hexpm"},
"timex": {:hex, :timex, "3.1.24", "d198ae9783ac807721cca0c5535384ebdf99da4976be8cefb9665a9262a1e9e3", [:mix], [{:combine, "~> 0.7", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"},
"timex_ecto": {:hex, :timex_ecto, "3.2.1", "461140751026e1ca03298fab628f78ab189e78784175f5e301eefa034ee530aa", [:mix], [{:ecto, "~> 2.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:timex, "~> 3.1", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm"},
"tzdata": {:hex, :tzdata, "0.5.13", "dfd6a10c1c9ed2b4c6493e35af5da6c37058c9578b2e413d37242d6943ed07d9", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
Expand Down
@@ -0,0 +1,9 @@
defmodule Asciinema.Repo.Migrations.AddArchivedAtToAsciicasts do
use Ecto.Migration

def change do
alter table(:asciicasts) do
add :archived_at, :naive_datetime
end
end
end
8 changes: 8 additions & 0 deletions rel/config/config.exs
Expand Up @@ -44,3 +44,11 @@ if dsn = env.("SENTRY_DSN") do
else
config :sentry, included_environments: []
end

if gc_days = env.("ASCIICAST_GC_DAYS") do
config :asciinema, :asciicast_gc_days, String.to_integer(gc_days)
end

if String.downcase("#{env.("CRON")}") in ["0", "false", "no"] do
config :asciinema, Asciinema.Scheduler, jobs: []
end