Problem
agent.sh and preview.sh both duplicate the IP slot allocation logic: used_slots(), next_slot(), slot_to_ips(), claim_slot(), and shared constants (MAX_SLOT, SUBNET_PREFIX). This duplication already caused a divergent merge conflict where both files had to be resolved independently with the same fix.
Proposal
Extract a slot-lib.sh that both scripts source, containing:
- Constants:
SUBNET_PREFIX, MAX_SLOT, SLOT_LOCK
- Functions:
used_slots(), next_slot(), slot_to_ips()
claim_slot <tracking_file> [extra_fields...] — atomically finds the next slot under flock, writes "${slot} ${host_ip} ${local_ip} ${extra_fields...}" to the given tracking file path, and echoes the slot number
Callers would become:
# agent.sh
slot=$(claim_slot "$AGENT_DIR/$name")
# preview.sh
slot=$(claim_slot "$PREVIEW_DIR/$slug" "$repo" "$branch")
The only difference between the two call sites is the tracking file path and extra fields appended to the line — claim_slot can accept these as arguments.
Context
This came up while resolving merge conflicts between feat/automated-intake-pipeline (which added flock-based locking) and main (which added slot recycling via PR #150). Both changes touched the same duplicated code in both files.
Problem
agent.shandpreview.shboth duplicate the IP slot allocation logic:used_slots(),next_slot(),slot_to_ips(),claim_slot(), and shared constants (MAX_SLOT,SUBNET_PREFIX). This duplication already caused a divergent merge conflict where both files had to be resolved independently with the same fix.Proposal
Extract a
slot-lib.shthat both scripts source, containing:SUBNET_PREFIX,MAX_SLOT,SLOT_LOCKused_slots(),next_slot(),slot_to_ips()claim_slot <tracking_file> [extra_fields...]— atomically finds the next slot underflock, writes"${slot} ${host_ip} ${local_ip} ${extra_fields...}"to the given tracking file path, and echoes the slot numberCallers would become:
The only difference between the two call sites is the tracking file path and extra fields appended to the line —
claim_slotcan accept these as arguments.Context
This came up while resolving merge conflicts between
feat/automated-intake-pipeline(which addedflock-based locking) andmain(which added slot recycling via PR #150). Both changes touched the same duplicated code in both files.