mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-10 14:52:57 +00:00
Refactor loadOwnProfile to use Promise.race and clean up relay fetching logic.
Extracts `fetchProfileFromRelay` helper method in `AuthService` to encapsulate timeout logic and event validation. This simplifies `loadOwnProfile` and makes it more readable and maintainable. Also adds comprehensive tests for `loadOwnProfile` in `tests/auth-service.test.mjs`. Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
1fbee4219b
commit
dcb8424535
2 files changed
+177
-61
No files matched your search
+82
-61
@@ -1030,8 +1030,63 @@ export default class AuthService {
|
||||
return { switched: true, detail };
|
||||
}
|
||||
|
||||
async fetchProfileFromRelay(
|
||||
relayUrl,
|
||||
filter,
|
||||
normalizedPubkey,
|
||||
timeoutMs,
|
||||
requireEvent,
|
||||
) {
|
||||
const fetchPromise = this.nostrClient.pool.list([relayUrl], filter);
|
||||
let timeoutId;
|
||||
|
||||
const timeoutPromise = new Promise((_, reject) => {
|
||||
timeoutId = setTimeout(() => {
|
||||
const timeoutError = new Error(
|
||||
`Timed out fetching profile from ${relayUrl} after ${timeoutMs}ms`,
|
||||
);
|
||||
timeoutError.code = "timeout";
|
||||
timeoutError.relay = relayUrl;
|
||||
timeoutError.timeoutMs = timeoutMs;
|
||||
reject(timeoutError);
|
||||
}, timeoutMs);
|
||||
});
|
||||
|
||||
try {
|
||||
const result = await Promise.race([fetchPromise, timeoutPromise]);
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
const events = Array.isArray(result)
|
||||
? result.filter((event) => event && event.pubkey === normalizedPubkey)
|
||||
: [];
|
||||
|
||||
if (requireEvent && !events.length) {
|
||||
const emptyError = new Error(
|
||||
`No profile events returned from ${relayUrl}`,
|
||||
);
|
||||
emptyError.code = "empty";
|
||||
emptyError.relay = relayUrl;
|
||||
throw emptyError;
|
||||
}
|
||||
|
||||
return { relayUrl, events };
|
||||
} catch (error) {
|
||||
clearTimeout(timeoutId);
|
||||
// Suppress unhandled rejection from fetchPromise if it's still running
|
||||
fetchPromise.catch(() => {});
|
||||
|
||||
if (error.relay) {
|
||||
throw error;
|
||||
}
|
||||
const wrapped = error instanceof Error ? error : new Error(String(error));
|
||||
wrapped.relay = relayUrl;
|
||||
throw wrapped;
|
||||
}
|
||||
}
|
||||
|
||||
async loadOwnProfile(pubkey) {
|
||||
const normalized = this.normalizeHexPubkey(pubkey) ||
|
||||
const normalized =
|
||||
this.normalizeHexPubkey(pubkey) ||
|
||||
(typeof pubkey === "string" ? pubkey.trim() : "");
|
||||
if (!normalized) {
|
||||
return FALLBACK_PROFILE;
|
||||
@@ -1074,13 +1129,20 @@ export default class AuthService {
|
||||
return {
|
||||
name: data.display_name || data.name || FALLBACK_PROFILE.name,
|
||||
picture: data.picture || FALLBACK_PROFILE.picture,
|
||||
about: typeof data.about === "string" ? data.about : FALLBACK_PROFILE.about,
|
||||
about:
|
||||
typeof data.about === "string" ? data.about : FALLBACK_PROFILE.about,
|
||||
website:
|
||||
typeof data.website === "string" ? data.website : FALLBACK_PROFILE.website,
|
||||
typeof data.website === "string"
|
||||
? data.website
|
||||
: FALLBACK_PROFILE.website,
|
||||
banner:
|
||||
typeof data.banner === "string" ? data.banner : FALLBACK_PROFILE.banner,
|
||||
lud16: typeof data.lud16 === "string" ? data.lud16 : FALLBACK_PROFILE.lud16,
|
||||
lud06: typeof data.lud06 === "string" ? data.lud06 : FALLBACK_PROFILE.lud06,
|
||||
typeof data.banner === "string"
|
||||
? data.banner
|
||||
: FALLBACK_PROFILE.banner,
|
||||
lud16:
|
||||
typeof data.lud16 === "string" ? data.lud16 : FALLBACK_PROFILE.lud16,
|
||||
lud06:
|
||||
typeof data.lud06 === "string" ? data.lud06 : FALLBACK_PROFILE.lud06,
|
||||
};
|
||||
} catch (error) {
|
||||
this.log("[AuthService] Failed to parse profile metadata", error);
|
||||
@@ -1088,67 +1150,26 @@ export default class AuthService {
|
||||
}
|
||||
};
|
||||
|
||||
const fetchFromRelay = (relayUrl, timeoutMs, requireEvent) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let settled = false;
|
||||
const timer = setTimeout(() => {
|
||||
if (settled) {
|
||||
return;
|
||||
}
|
||||
settled = true;
|
||||
const timeoutError = new Error(
|
||||
`Timed out fetching profile from ${relayUrl} after ${timeoutMs}ms`
|
||||
);
|
||||
timeoutError.code = "timeout";
|
||||
timeoutError.relay = relayUrl;
|
||||
timeoutError.timeoutMs = timeoutMs;
|
||||
reject(timeoutError);
|
||||
}, timeoutMs);
|
||||
|
||||
Promise.resolve()
|
||||
.then(() => this.nostrClient.pool.list([relayUrl], filter))
|
||||
.then((result) => {
|
||||
if (settled) {
|
||||
return;
|
||||
}
|
||||
settled = true;
|
||||
clearTimeout(timer);
|
||||
const events = Array.isArray(result)
|
||||
? result.filter((event) => event && event.pubkey === normalized)
|
||||
: [];
|
||||
if (requireEvent && !events.length) {
|
||||
const emptyError = new Error(
|
||||
`No profile events returned from ${relayUrl}`
|
||||
);
|
||||
emptyError.code = "empty";
|
||||
emptyError.relay = relayUrl;
|
||||
reject(emptyError);
|
||||
return;
|
||||
}
|
||||
resolve({ relayUrl, events });
|
||||
})
|
||||
.catch((error) => {
|
||||
if (settled) {
|
||||
return;
|
||||
}
|
||||
settled = true;
|
||||
clearTimeout(timer);
|
||||
const wrapped =
|
||||
error instanceof Error ? error : new Error(String(error));
|
||||
wrapped.relay = relayUrl;
|
||||
reject(wrapped);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const fastRelays = relays.slice(0, FAST_PROFILE_RELAY_LIMIT);
|
||||
const backgroundRelays = relays.slice(fastRelays.length);
|
||||
|
||||
const fastPromises = fastRelays.map((relayUrl) =>
|
||||
fetchFromRelay(relayUrl, FAST_PROFILE_TIMEOUT_MS, true)
|
||||
this.fetchProfileFromRelay(
|
||||
relayUrl,
|
||||
filter,
|
||||
normalized,
|
||||
FAST_PROFILE_TIMEOUT_MS,
|
||||
true,
|
||||
),
|
||||
);
|
||||
const backgroundPromises = backgroundRelays.map((relayUrl) =>
|
||||
fetchFromRelay(relayUrl, BACKGROUND_PROFILE_TIMEOUT_MS, false)
|
||||
this.fetchProfileFromRelay(
|
||||
relayUrl,
|
||||
filter,
|
||||
normalized,
|
||||
BACKGROUND_PROFILE_TIMEOUT_MS,
|
||||
false,
|
||||
),
|
||||
);
|
||||
|
||||
const background = Promise.allSettled([
|
||||
|
||||
Reference in new issue
Block a user