1.0 KiB · text 5af55d9
defmodule GitGud.Repositories.Numbering do
@moduledoc """
Allocates the next `#N` for a repository. The number space is shared
between issues and pull requests, matching GitHub semantics.
Call inside a transaction; the two MAX(...) queries lock nothing on
their own, so concurrent inserts can race. The per-repo
`unique_index(:issues, [:repository_id, :number])` and the matching
one on `:pull_requests` are the safety net — on conflict, retry.
"""
import Ecto.Query, warn: false
alias GitGud.Issues.Issue
alias GitGud.PullRequests.PullRequest
alias GitGud.Repo
@doc "Returns the next free `number` for the repo (≥ 1)."
def next_for(repository_id) when is_integer(repository_id) do
issue_max =
from(i in Issue, where: i.repository_id == ^repository_id, select: max(i.number))
|> Repo.one()
pr_max =
from(p in PullRequest, where: p.repository_id == ^repository_id, select: max(p.number))
|> Repo.one()
Enum.max([issue_max || 0, pr_max || 0]) + 1
end
end