feat: add Pi provider managed resources

This commit is contained in:
2026-08-22 21:48:00 +08:00
parent 81d8ad1b6b
commit 161f3f471b
31 changed files with 1581 additions and 40 deletions

View File

@@ -0,0 +1,44 @@
export interface PiProviderAuthRecoveryOptions<T> {
accountId: string;
operation: (attempt: 0 | 1) => Promise<T>;
isAuthenticationError: (error: unknown) => boolean;
refreshCredential: () => Promise<void>;
reopenWorker: () => Promise<void>;
}
export class PiProviderRefreshCoordinator {
private readonly refreshes = new Map<string, Promise<void>>();
get pendingAccountCount(): number {
return this.refreshes.size;
}
async refreshAccount(accountId: string, refresh: () => Promise<void>): Promise<void> {
const normalizedAccountId = accountId.trim();
if (!normalizedAccountId) throw new Error('Provider account id is required');
let pending = this.refreshes.get(normalizedAccountId);
if (!pending) {
pending = Promise.resolve()
.then(refresh)
.finally(() => {
if (this.refreshes.get(normalizedAccountId) === pending) {
this.refreshes.delete(normalizedAccountId);
}
});
this.refreshes.set(normalizedAccountId, pending);
}
await pending;
}
async withSingleAuthRecovery<T>(options: PiProviderAuthRecoveryOptions<T>): Promise<T> {
try {
return await options.operation(0);
} catch (error) {
if (!options.isAuthenticationError(error)) throw error;
}
await this.refreshAccount(options.accountId, options.refreshCredential);
await options.reopenWorker();
return await options.operation(1);
}
}