MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / claimPorts

Function claimPorts

e2e/src/ports.ts:157–218  ·  view source on GitHub ↗
(claims: ReadonlyArray<PortClaim>)

Source from the content-addressed store, hash-verified

155 * one vitest run) shares the block via disjoint offsets.
156 */
157export const claimPorts = async (claims: ReadonlyArray<PortClaim>): Promise<ClaimedPorts> => {
158 const ports: Record<string, number> = {};
159 const unpinned = claims.filter((claim) => {
160 const pinned = process.env[claim.envVar];
161 if (pinned) ports[claim.envVar] = Number(pinned);
162 return !pinned;
163 });
164 if (unpinned.length === 0) return { ports, release: async () => {} };
165
166 for (let attempt = 0; attempt < BLOCK_COUNT; attempt++) {
167 const block =
168 BLOCK_BASE + ((portBlock - BLOCK_BASE + attempt * BLOCK_SIZE) % (BLOCK_COUNT * BLOCK_SIZE));
169 // This process may already hold the block's lock (the other target's
170 // globalsetup in the same vitest run); reuse it instead of re-locking.
171 let lock = heldLocks.get(block);
172 if (!lock) {
173 lock = await tryLockBlock(block);
174 if (!lock) {
175 console.warn(`[e2e] port block ${block} is locked by another suite; trying next block`);
176 continue;
177 }
178 heldLocks.set(block, lock);
179 }
180 // BIND-probe every claimed port, holding all probe servers open until the
181 // whole block is proven free. A bind (unlike a connect-probe) also detects
182 // an ephemeral outbound socket squatting the port, and keeping the probes
183 // open means nothing can slip into these ports between the check and the
184 // moment we close them just before the services bind.
185 const probes = await Promise.all(unpinned.map((claim) => bindProbe(block + claim.offset)));
186 const held = probes.flatMap((probe) => probe ?? []);
187 if (probes.some((probe) => probe === undefined)) {
188 const taken = unpinned
189 .filter((_, index) => probes[index] === undefined)
190 .map((claim) => `${block + claim.offset} (${claim.label})`);
191 await Promise.all(held.map(closeServer)); // Free the ports we did grab.
192 console.warn(
193 `[e2e] port block ${block} has squatters — ${taken.join(", ")}; trying next block`,
194 );
195 continue; // Keep the lock: a half-busy block is still ours, just unusable now.
196 }
197 for (const claim of unpinned) {
198 const port = block + claim.offset;
199 ports[claim.envVar] = port;
200 // Workers spawn after globalsetup, so they inherit these and agree.
201 process.env[claim.envVar] = String(port);
202 }
203 // Release the probe listeners the instant before we return: the caller boots
204 // its services immediately, so the ports go from probe-held to service-held
205 // with only a microsecond gap (vs. the seconds a pre-boot probe left open).
206 await Promise.all(held.map(closeServer));
207 return {
208 ports,
209 release: async () => {
210 const held = heldLocks.get(block);
211 if (!held) return;
212 heldLocks.delete(block);
213 await new Promise<void>((done) => held.close(() => done()));
214 },

Callers 2

claimAndBootFunction · 0.85
runFunction · 0.85

Calls 7

tryLockBlockFunction · 0.85
bindProbeFunction · 0.85
warnMethod · 0.80
setMethod · 0.80
getMethod · 0.65
deleteMethod · 0.65
closeMethod · 0.65

Tested by

no test coverage detected