All files / src/server/repositories allocateWithRetry.ts

87.5% Statements 7/8
100% Branches 5/5
100% Functions 1/1
83.33% Lines 5/6

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21                  1320x 1331x 1331x   33x 22x            
// Bounded retry for allocating a per-parent unique value (MAX+1 number, unique
// slug) with an INSERT/UPDATE that races other writers: recompute inside
// `attempt`, retry only the constraint that a fresh value can actually resolve.
// Bounded so a persistent conflict surfaces instead of looping forever.
export async function allocateWithRetry<T>(
  attempt: () => Promise<T>,
  isRetryableConflict: (error: unknown) => boolean,
  attempts = 5,
): Promise<T> {
  for (let i = 0; i < attempts; i++) {
    try {
      return await attempt();
    } catch (error) {
      if (isRetryableConflict(error) && i < attempts - 1) continue;
      throw error;
    }
  }
  // Unreachable: the final attempt either returns or throws above.
  throw new Error("allocateWithRetry: no attempts");
}