All files ensureUniqueCounter.ts

87.5% Statements 21/24
83.33% Branches 5/6
66.66% Functions 4/6
91.3% Lines 21/23

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 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 7627x                         56x 56x   56x 7x 7x     56x 56x                               56x                 56x   56x 56x   56x     56x   56x   56x   56x 56x             56x 56x 55x        
const uniqueCounterScopes = new WeakMap<object, Promise<void>>()
 
async function runEnsureUniqueCounterValue<T>({
  initialValue,
  isTaken,
  reserve,
  nextValue,
}: {
  initialValue: T
  isTaken: (candidate: T) => Promise<boolean> | boolean
  reserve: (candidate: T) => void
  nextValue: (counter: number) => T
}): Promise<T> {
  let candidate = initialValue
  let counter = 1
 
  while (await isTaken(candidate)) {
    candidate = nextValue(counter)
    counter += 1
  }
 
  reserve(candidate)
  return candidate
}
 
export async function ensureUniqueCounterValue<T>({
  initialValue,
  isTaken,
  reserve,
  nextValue,
  scope,
}: {
  initialValue: T
  isTaken: (candidate: T) => Promise<boolean> | boolean
  reserve: (candidate: T) => void
  nextValue: (counter: number) => T
  scope?: object
}): Promise<T> {
  Iif (scope == null) {
    return await runEnsureUniqueCounterValue({
      initialValue,
      isTaken,
      reserve,
      nextValue,
    })
  }
 
  const previous = uniqueCounterScopes.get(scope) ?? Promise.resolve()
  let releaseScope: (() => void) | undefined
  const pendingScope = new Promise<void>((resolve) => {
    releaseScope = resolve
  })
  const currentScope = previous
    .catch(() => undefined)
    .then(async () => {
      await pendingScope
    })
  uniqueCounterScopes.set(scope, currentScope)
 
  await previous.catch(() => undefined)
 
  try {
    return await runEnsureUniqueCounterValue({
      initialValue,
      isTaken,
      reserve,
      nextValue,
    })
  } finally {
    releaseScope?.()
    if (uniqueCounterScopes.get(scope) === currentScope) {
      uniqueCounterScopes.delete(scope)
    }
  }
}