Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lib/bob/artifacts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ defmodule Bob.Artifacts do
@erlang_arch_repos ~w(hexpm/erlang-amd64 hexpm/erlang-arm64)
@docker_cleanup_per_arch_repos ~w(hexpm/elixir-amd64 hexpm/elixir-arm64) ++ @erlang_arch_repos

# The CDN purge sleeps 4 seconds between each of its three requests, so it is
# queued rather than run in the agent's POST /api/artifacts/add.
def add(attrs) do
upsert(attrs)
generate_builds_txt(attrs.arch, attrs.os)
Bob.Fastly.purge_builds(purge_keys(attrs.arch, attrs.os, attrs.name))
:ok
Bob.Queue.add(Bob.Job.PurgeBuilds, [purge_keys(attrs.arch, attrs.os, attrs.name)])
end

def add_docker_tag(repo, tag, archs, built_at \\ DateTime.utc_now()) do
Expand Down
9 changes: 9 additions & 0 deletions lib/bob/job/purge_builds.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule Bob.Job.PurgeBuilds do
def run(keys) do
Bob.Fastly.purge_builds(keys)
end

def priority(), do: 1
def weight(), do: 1
def concurrency(), do: :shared
end
6 changes: 5 additions & 1 deletion lib/bob/queue.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@ defmodule Bob.Queue do

# Periodic scheduler jobs re-run every interval and must not be suppressed by
# backoff after a transient failure; only the build jobs they enqueue back off.
# A builds purge is queued once per uploaded artifact and nothing re-queues it,
# so backing off after a failed purge would skip the next build's purge of the
# same keys.
@no_backoff [
Bob.Job.OTPChecker,
Bob.Job.DockerChecker,
Bob.Job.Reconcile,
Bob.Job.ReconcileBaseImages,
Bob.Job.DockerCleanup
Bob.Job.DockerCleanup,
Bob.Job.PurgeBuilds
]

@dedup_conflict_target {:unsafe_fragment,
Expand Down
9 changes: 8 additions & 1 deletion test/bob/artifacts_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ defmodule Bob.ArtifactsTest do
end

describe "add/1" do
test "upserts and regenerates builds.txt" do
test "upserts, regenerates builds.txt and queues the CDN purge" do
Bob.FakeHttpClient.reset()

Bob.FakeHttpClient.stub(
Expand All @@ -175,6 +175,13 @@ defmodule Bob.ArtifactsTest do

assert Artifacts.add(attrs()) == :ok
assert [%Artifact{name: "OTP-27.0"}] = Repo.all(Artifact)

assert Bob.Queue.queued() == [
{Bob.Job.PurgeBuilds,
[
"builds/otp/amd64/ubuntu-24.04/txt builds/otp/amd64/ubuntu-24.04/OTP-27.0"
]}
]
end
end

Expand Down
18 changes: 18 additions & 0 deletions test/bob/job/purge_builds_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defmodule Bob.Job.PurgeBuildsTest do
use ExUnit.Case

alias Bob.Job.PurgeBuilds

test "exposes the runner callbacks" do
assert PurgeBuilds.priority() == 1
assert PurgeBuilds.weight() == 1
assert PurgeBuilds.concurrency() == :shared
end

test "run/1 purges the keys, a no-op when Fastly is not configured" do
System.delete_env("BOB_FASTLY_KEY")
System.delete_env("BOB_FASTLY_SERVICE_BUILDS")

assert PurgeBuilds.run("builds/otp/amd64/ubuntu-24.04/txt") == :ok
end
end
11 changes: 11 additions & 0 deletions test/bob/queue_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,17 @@ defmodule Bob.QueueTest do
end
end

test "a failed builds purge does not back off the next purge of the same keys" do
keys = "builds/otp/amd64/ubuntu-24.04/txt builds/otp/amd64/ubuntu-24.04/master"

Queue.add(Bob.Job.PurgeBuilds, [keys])
{:ok, {id, [^keys]}} = Queue.start(Bob.Job.PurgeBuilds)
Queue.failure(id)
Queue.add(Bob.Job.PurgeBuilds, [keys])

assert size(Bob.Job.PurgeBuilds) == 1
end

test "success clears any existing backoff for the job" do
# Set up a previously-failed job that is now running again, by inserting
# the rows directly (a backed-off job will not re-enter the queue on its own).
Expand Down
Loading