fix(admin): resolve tunnel owner emails via one listUsers scan
The upstream admin gateway deterministically truncates the first per-row getUserById that immediately follows a request's auth check, yielding an empty body the per-call retry cannot clear — so a couple of tunnel rows showed owner_email '—' on every load regardless of retry or concurrency. Replace the per-row getUserById fan-out with a single bounded listUsers scan (same transient retry) that builds an id->email map and stops early once every owner on the page is resolved. A single listUsers read does not hit the truncation pattern, eliminating the dashes. Remove the now-unused mapWithConcurrency helper and OWNER_EMAIL_CONCURRENCY constant.
This commit is contained in:
@@ -126,33 +126,3 @@ export async function withAdminRetry<R extends { error: MaybeError }>(
|
||||
if (threw) throw lastThrown;
|
||||
return lastResult as R;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map over `items` running at most `concurrency` async tasks at a time, while
|
||||
* preserving result order.
|
||||
*
|
||||
* Firing every GoTrue admin lookup at once (e.g. one `getUserById` per tunnel
|
||||
* row) can self-inflict an upstream throttle: the proxy truncates the tail of a
|
||||
* large concurrent burst, producing the very empty-body responses we retry on —
|
||||
* and because the retries fire back into the same saturated window, a few rows
|
||||
* can still fail. Bounding the concurrency keeps each lookup inside the
|
||||
* throttle's allowance so {@link withAdminRetry} reliably resolves every row.
|
||||
*/
|
||||
export async function mapWithConcurrency<T, R>(
|
||||
items: readonly T[],
|
||||
concurrency: number,
|
||||
task: (item: T, index: number) => Promise<R>,
|
||||
): Promise<R[]> {
|
||||
const results = new Array<R>(items.length);
|
||||
const limit = Math.max(1, Math.min(concurrency, items.length || 1));
|
||||
let next = 0;
|
||||
async function worker(): Promise<void> {
|
||||
for (;;) {
|
||||
const i = next++;
|
||||
if (i >= items.length) return;
|
||||
results[i] = await task(items[i], i);
|
||||
}
|
||||
}
|
||||
await Promise.all(Array.from({ length: limit }, () => worker()));
|
||||
return results;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user