Class: Agentilda::Adoption
- Inherits:
-
Object
- Object
- Agentilda::Adoption
- Defined in:
- lib/agentilda/adoption.rb
Overview
Gives a plan folder to every pull request that has no plan to point at.
resync prs can resolve most pull requests from their branch or their
diff. What it cannot resolve it used to flag for a human — "diff touches
021.00, 022.00, 024.00 and none is obviously primary" — and stop. That is
honest but not useful: the work exists, it is unspecified, and leaving it
unnumbered means it never appears in the index at all.
So an orphan is adopted instead. It gets a retroactive plan of its own, numbered in the gap after the furthest plan it can see, holding the pull request that produced it.
Why the numbering is allocated serially
The obvious parallel design — every worker reads the highest number and
adds .01 — is deterministic but not unique, and the collision is the
common case rather than the rare one. Fifteen open pull requests branched
off the same main all see the same highest number and all compute the same
slot. Determinism is not the property that matters here; distinctness is.
So the pipeline is gather in parallel, allocate serially, apply in parallel. The allocation is pure arithmetic over an array that is already in memory, so the serial section costs microseconds; the two expensive phases — reading each branch and writing each folder — keep the whole fan-out. And because the slots are handed out before any worker starts, no worker can want a number another worker holds: no locks, no retries, and the same input produces the same numbers every run.
Defined Under Namespace
Classes: Adoptee
Instance Attribute Summary collapse
- #github ⇒ Agentilda::GitHub readonly
- #jobs ⇒ Integer readonly
- #root ⇒ String readonly
- #tree ⇒ Agentilda::Tree readonly
Instance Method Summary collapse
-
#call(pulls) ⇒ Array<Agentilda::Adoption::Adoptee>
Adopt every orphan: create its folder and record its pull request.
-
#initialize(tree:, github: GitHub.new, root: nil, jobs: UI.default_jobs) ⇒ Adoption
constructor
A new instance of Adoption.
-
#plan(pulls) ⇒ Array<Agentilda::Adoption::Adoptee>
Work out what each orphan would be given, without creating anything.
Constructor Details
#initialize(tree:, github: GitHub.new, root: nil, jobs: UI.default_jobs) ⇒ Adoption
Returns a new instance of Adoption.
59 60 61 62 63 64 |
# File 'lib/agentilda/adoption.rb', line 59 def initialize(tree:, github: GitHub.new, root: nil, jobs: UI.default_jobs) @tree = tree @github = github @root = root || File.dirname(tree.dir) @jobs = jobs end |
Instance Attribute Details
#github ⇒ Agentilda::GitHub (readonly)
70 71 72 |
# File 'lib/agentilda/adoption.rb', line 70 def github @github end |
#jobs ⇒ Integer (readonly)
76 77 78 |
# File 'lib/agentilda/adoption.rb', line 76 def jobs @jobs end |
#tree ⇒ Agentilda::Tree (readonly)
67 68 69 |
# File 'lib/agentilda/adoption.rb', line 67 def tree @tree end |
Instance Method Details
#call(pulls) ⇒ Array<Agentilda::Adoption::Adoptee>
Adopt every orphan: create its folder and record its pull request.
90 91 92 93 94 95 96 97 |
# File 'lib/agentilda/adoption.rb', line 90 def call(pulls) adoptees = plan(pulls) return adoptees if adoptees.empty? created = Parallel.map(adoptees, in_threads: jobs) { |adoptee| adopt(adoptee) } tree.reload created end |
#plan(pulls) ⇒ Array<Agentilda::Adoption::Adoptee>
Work out what each orphan would be given, without creating anything.
82 83 84 |
# File 'lib/agentilda/adoption.rb', line 82 def plan(pulls) allocate(gather(pulls)) end |