Skip to content

Commit ebeef24

Browse files
committed
Fix oban
1 parent 877a63c commit ebeef24

4 files changed

Lines changed: 65 additions & 20 deletions

File tree

apps/codebattle/lib/codebattle/user_group_tournament/context.ex

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -567,26 +567,28 @@ defmodule Codebattle.UserGroupTournament.Context do
567567
|> Enum.uniq()
568568
end
569569

570-
@hide_unveil_chunk_size 500
570+
@default_hide_unveil_chunk_size 500
571571

572572
@doc """
573-
Enqueues `RepoHideWorker` jobs in chunks of #{@hide_unveil_chunk_size} repo IDs each.
573+
Enqueues `RepoHideWorker` jobs in chunks of repo IDs.
574574
Returns the number of repo IDs that were enqueued (not the number of jobs).
575575
"""
576-
@spec enqueue_bulk_hide(GroupTournament.t()) :: non_neg_integer()
577-
def enqueue_bulk_hide(%GroupTournament{} = group_tournament) do
578-
enqueue_repo_id_chunks(group_tournament, &Codebattle.Workers.RepoHideWorker.new/2)
576+
@spec enqueue_bulk_hide(GroupTournament.t(), pos_integer()) :: non_neg_integer()
577+
def enqueue_bulk_hide(%GroupTournament{} = group_tournament, batch_size \\ @default_hide_unveil_chunk_size) do
578+
enqueue_repo_id_chunks(group_tournament, batch_size, &Codebattle.Workers.RepoHideWorker.new/2)
579579
end
580580

581-
@spec enqueue_bulk_unveil(GroupTournament.t()) :: non_neg_integer()
582-
def enqueue_bulk_unveil(%GroupTournament{} = group_tournament) do
583-
enqueue_repo_id_chunks(group_tournament, &Codebattle.Workers.RepoUnveilWorker.new/2)
581+
@spec enqueue_bulk_unveil(GroupTournament.t(), pos_integer()) :: non_neg_integer()
582+
def enqueue_bulk_unveil(%GroupTournament{} = group_tournament, batch_size \\ @default_hide_unveil_chunk_size) do
583+
enqueue_repo_id_chunks(group_tournament, batch_size, &Codebattle.Workers.RepoUnveilWorker.new/2)
584584
end
585585

586-
defp enqueue_repo_id_chunks(%GroupTournament{} = group_tournament, build_job) do
586+
defp enqueue_repo_id_chunks(%GroupTournament{} = group_tournament, batch_size, build_job) do
587+
safe_batch_size = max(batch_size, 1)
588+
587589
group_tournament
588590
|> list_repo_ids()
589-
|> Enum.chunk_every(@hide_unveil_chunk_size)
591+
|> Enum.chunk_every(safe_batch_size)
590592
|> Enum.with_index()
591593
|> Enum.reduce(0, fn {chunk, idx}, count ->
592594
args = %{repo_ids: chunk, group_tournament_id: group_tournament.id}

apps/codebattle/lib/codebattle_web/controllers/admin/group_tournament_controller.ex

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ defmodule CodebattleWeb.Admin.GroupTournamentController do
295295

296296
defp enqueue_bulk_op(conn, id, params, action) do
297297
group_tournament = Context.get_group_tournament!(id)
298-
batch_size = parse_batch_size(get_in(params, ["bulk_repo", "batch_size"]))
298+
batch_size = parse_bulk_op_batch_size(action, get_in(params, ["bulk_repo", "batch_size"]))
299299
{label, unit, enqueued, rate_note} = run_bulk_op(action, group_tournament, batch_size)
300300
{kind, message} = bulk_op_flash(label, unit, enqueued, rate_note)
301301

@@ -312,11 +312,11 @@ defmodule CodebattleWeb.Admin.GroupTournamentController do
312312
add_viewer_roles: {"add-viewer-role", &UserGroupTournamentContext.enqueue_bulk_add_viewer_roles/2}
313313
}
314314

315-
defp run_bulk_op(:hide, gt, _batch_size),
316-
do: {"hide", "repos", UserGroupTournamentContext.enqueue_bulk_hide(gt), :chunked}
315+
defp run_bulk_op(:hide, gt, chunk_size),
316+
do: {"hide", "repos", UserGroupTournamentContext.enqueue_bulk_hide(gt, chunk_size), {:chunked, chunk_size}}
317317

318-
defp run_bulk_op(:unveil, gt, _batch_size),
319-
do: {"unveil", "repos", UserGroupTournamentContext.enqueue_bulk_unveil(gt), :chunked}
318+
defp run_bulk_op(:unveil, gt, chunk_size),
319+
do: {"unveil", "repos", UserGroupTournamentContext.enqueue_bulk_unveil(gt, chunk_size), {:chunked, chunk_size}}
320320

321321
defp run_bulk_op(action, gt, batch_size) do
322322
{label, fun} = Map.fetch!(@bulk_per_user_ops, action)
@@ -325,8 +325,8 @@ defmodule CodebattleWeb.Admin.GroupTournamentController do
325325

326326
defp bulk_op_flash(label, _unit, 0, _rate_note), do: {:error, "Nothing to enqueue for #{label}."}
327327

328-
defp bulk_op_flash(label, unit, enqueued, :chunked),
329-
do: {:info, "Enqueued #{label} jobs covering #{enqueued} #{unit} (chunks of 500 per bulk call)."}
328+
defp bulk_op_flash(label, unit, enqueued, {:chunked, chunk_size}),
329+
do: {:info, "Enqueued #{label} jobs covering #{enqueued} #{unit} (chunks of #{chunk_size} per bulk call)."}
330330

331331
defp bulk_op_flash(label, unit, enqueued, batch_size),
332332
do: {:info, "Enqueued #{label} jobs for #{enqueued} #{unit} (rate: #{batch_size} jobs/sec)."}
@@ -531,6 +531,11 @@ defmodule CodebattleWeb.Admin.GroupTournamentController do
531531
# even with concurrent runs from other tournaments.
532532
@default_batch_size 50
533533
@max_batch_size 100
534+
@default_repo_chunk_size 500
535+
@repo_chunk_sizes [1, 10, 100, 500]
536+
537+
defp parse_bulk_op_batch_size(action, value) when action in [:hide, :unveil], do: parse_repo_chunk_size(value)
538+
defp parse_bulk_op_batch_size(_action, value), do: parse_batch_size(value)
534539

535540
defp parse_batch_size(nil), do: @default_batch_size
536541

@@ -544,6 +549,18 @@ defmodule CodebattleWeb.Admin.GroupTournamentController do
544549
defp parse_batch_size(value) when is_integer(value) and value >= 1 and value <= @max_batch_size, do: value
545550
defp parse_batch_size(_), do: @default_batch_size
546551

552+
defp parse_repo_chunk_size(nil), do: @default_repo_chunk_size
553+
554+
defp parse_repo_chunk_size(value) when is_binary(value) do
555+
case value |> String.trim() |> Integer.parse() do
556+
{n, ""} when n in @repo_chunk_sizes -> n
557+
_ -> @default_repo_chunk_size
558+
end
559+
end
560+
561+
defp parse_repo_chunk_size(value) when value in @repo_chunk_sizes, do: value
562+
defp parse_repo_chunk_size(_), do: @default_repo_chunk_size
563+
547564
def create_token(conn, %{"id" => id, "group_tournament_token" => token_params}) do
548565
group_tournament = Context.get_group_tournament!(id)
549566

apps/codebattle/lib/codebattle_web/templates/admin/group_tournament/show.html.heex

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,14 +314,27 @@
314314
<h4 class="text-white">Hide Repos</h4>
315315
<p class="cb-text small mb-3">
316316
Enqueues <code>RepoHideWorker</code>
317-
jobs that batch all tournament repos into chunks of 500 per <code>/repos/hide</code>
317+
jobs that batch all tournament repos into configurable chunks per <code>/repos/hide</code>
318318
call. One job per chunk, scheduled 1 second apart, retried by Oban on failure.
319319
</p>
320320
<form
321321
action={Routes.admin_group_tournament_path(@conn, :hide_repos, @group_tournament)}
322322
method="post"
323+
class="d-flex align-items-end flex-wrap"
323324
>
324325
<input type="hidden" name="_csrf_token" value={Plug.CSRFProtection.get_csrf_token()} />
326+
<div class="form-group mb-0 mr-3" style="max-width: 240px;">
327+
<label class="text-white">Batch size</label>
328+
<select
329+
name="bulk_repo[batch_size]"
330+
class="form-control cb-bg-panel cb-border-color text-white mt-2"
331+
>
332+
<option value="1">1 repo per call</option>
333+
<option value="10">10 repos per call</option>
334+
<option value="100">100 repos per call</option>
335+
<option value="500" selected>500 repos per call</option>
336+
</select>
337+
</div>
325338
<button
326339
type="submit"
327340
class="btn btn-outline-warning cb-rounded"
@@ -336,15 +349,28 @@
336349
<h4 class="text-white">Unveil Repos</h4>
337350
<p class="cb-text small mb-3">
338351
Enqueues <code>RepoUnveilWorker</code>
339-
jobs that batch all hidden tournament repos into chunks of 500 per
352+
jobs that batch all hidden tournament repos into configurable chunks per
340353
<code>/repos/unveil</code>
341354
call.
342355
</p>
343356
<form
344357
action={Routes.admin_group_tournament_path(@conn, :unveil_repos, @group_tournament)}
345358
method="post"
359+
class="d-flex align-items-end flex-wrap"
346360
>
347361
<input type="hidden" name="_csrf_token" value={Plug.CSRFProtection.get_csrf_token()} />
362+
<div class="form-group mb-0 mr-3" style="max-width: 240px;">
363+
<label class="text-white">Batch size</label>
364+
<select
365+
name="bulk_repo[batch_size]"
366+
class="form-control cb-bg-panel cb-border-color text-white mt-2"
367+
>
368+
<option value="1">1 repo per call</option>
369+
<option value="10">10 repos per call</option>
370+
<option value="100">100 repos per call</option>
371+
<option value="500" selected>500 repos per call</option>
372+
</select>
373+
</div>
348374
<button
349375
type="submit"
350376
class="btn btn-outline-success cb-rounded"

config/config.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ config :codebattle, Oban,
3636
# `bot_detection` is intentionally low-concurrency: the analysis is CPU-bound
3737
# (telemetry aggregation + code parsing) and runs after every finished game,
3838
# so we cap parallelism to keep the box responsive under bursts.
39-
queues: [default: 10, bot_detection: 2]
39+
queues: [default: 40, bot_detection: 2]
4040

4141
config :codebattle, :api_key, "x-key"
4242
config :codebattle, :app_subtitle, "by Hexlet’s community"

0 commit comments

Comments
 (0)