Browse Source

speed up startup

imwald
Silberengel 1 month ago
parent
commit
c799256298
  1. 4
      package-lock.json
  2. 2
      package.json
  3. 7
      src/lib/logger.ts
  4. 6
      src/main.tsx
  5. 22
      src/services/client.service.ts

4
package-lock.json generated

@ -1,12 +1,12 @@
{ {
"name": "jumble-imwald", "name": "jumble-imwald",
"version": "18.0.0", "version": "18.0.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "jumble-imwald", "name": "jumble-imwald",
"version": "18.0.0", "version": "18.0.1",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@asciidoctor/core": "^3.0.4", "@asciidoctor/core": "^3.0.4",

2
package.json

@ -1,6 +1,6 @@
{ {
"name": "jumble-imwald", "name": "jumble-imwald",
"version": "18.0.0", "version": "18.0.1",
"description": "A user-friendly Nostr client focused on relay feed browsing and relay discovery, forked from Jumble", "description": "A user-friendly Nostr client focused on relay feed browsing and relay discovery, forked from Jumble",
"private": true, "private": true,
"type": "module", "type": "module",

7
src/lib/logger.ts

@ -61,8 +61,11 @@ class Logger {
private formatMessage(level: LogLevel, message: string, ...args: any[]): [string, ...any[]] { private formatMessage(level: LogLevel, message: string, ...args: any[]): [string, ...any[]] {
const timestamp = new Date().toISOString().substring(11, 23) // HH:mm:ss.SSS const timestamp = new Date().toISOString().substring(11, 23) // HH:mm:ss.SSS
const caller = this.getCallerInfo() // Stack capture is expensive (main-thread jank, especially on mobile). Only when deep debug is on.
const prefix = `[${timestamp}] [${level.toUpperCase()}] [${caller}]` const caller = this.config.enableDebug ? this.getCallerInfo() : ''
const prefix = caller
? `[${timestamp}] [${level.toUpperCase()}] [${caller}]`
: `[${timestamp}] [${level.toUpperCase()}]`
return [`${prefix} ${message}`, ...args] return [`${prefix} ${message}`, ...args]
} }

6
src/main.tsx

@ -30,6 +30,9 @@ const SESSION_STORAGE_KEY = 'jumble:session'
async function bootstrap() { async function bootstrap() {
// Always defined: fetch does not throw on 4xx/5xx, so non-OK responses must not leave this unset. // Always defined: fetch does not throw on 4xx/5xx, so non-OK responses must not leave this unset.
window.__RUNTIME_CONFIG__ = {} window.__RUNTIME_CONFIG__ = {}
await Promise.all([
storage.initAsync(),
(async () => {
try { try {
const r = await fetch('/config.json') const r = await fetch('/config.json')
if (r.ok) { if (r.ok) {
@ -38,13 +41,14 @@ async function bootstrap() {
} catch { } catch {
window.__RUNTIME_CONFIG__ = {} window.__RUNTIME_CONFIG__ = {}
} }
})()
])
// Mark session storage as used so it's visible in DevTools; VersionUpdateBanner and NotePage also use it. // Mark session storage as used so it's visible in DevTools; VersionUpdateBanner and NotePage also use it.
try { try {
sessionStorage.setItem(SESSION_STORAGE_KEY, String(Date.now())) sessionStorage.setItem(SESSION_STORAGE_KEY, String(Date.now()))
} catch { } catch {
// ignore quota or private browsing // ignore quota or private browsing
} }
await storage.initAsync()
publishMonitorAnnouncementOnce() publishMonitorAnnouncementOnce()
createRoot(document.getElementById('root')!).render( createRoot(document.getElementById('root')!).render(
<StrictMode> <StrictMode>

22
src/services/client.service.ts

@ -97,7 +97,13 @@ class ClientService extends EventTarget {
async init() { async init() {
await indexedDb.iterateProfileEvents((profileEvent) => this.addUsernameToIndex(profileEvent)) await indexedDb.iterateProfileEvents((profileEvent) => this.addUsernameToIndex(profileEvent))
this.fetchNip66RelayDiscovery().catch(() => {}) // Defer NIP-66 discovery so the first WebSocket slots go to login, relay list, and feed — not background search.
const runNip66 = () => this.fetchNip66RelayDiscovery().catch(() => {})
if (typeof requestIdleCallback !== 'undefined') {
requestIdleCallback(() => runNip66(), { timeout: 8000 })
} else {
setTimeout(runNip66, 2500)
}
} }
/** NIP-66: fetch relay discovery events (30166) in background to supplement search/NIP support. */ /** NIP-66: fetch relay discovery events (30166) in background to supplement search/NIP support. */
@ -1291,7 +1297,7 @@ class ClientService extends EventTarget {
const isExternalSearch = eoseTimeout > 1000 // Consider it external search if timeout > 1s const isExternalSearch = eoseTimeout > 1000 // Consider it external search if timeout > 1s
if (isExternalSearch) { if (isExternalSearch) {
logger.info('query: Starting external relay search', { logger.debug('query: Starting external relay search', {
relayCount: urls.length, relayCount: urls.length,
relays: urls, relays: urls,
eoseTimeout, eoseTimeout,
@ -1301,7 +1307,7 @@ class ClientService extends EventTarget {
} }
/** Once one relay returns results, give others this long (ms) then resolve with what we have */ /** Once one relay returns results, give others this long (ms) then resolve with what we have */
const FIRST_RESULT_GRACE_MS = 2000 const FIRST_RESULT_GRACE_MS = 1200
return await new Promise<NEvent[]>((resolve) => { return await new Promise<NEvent[]>((resolve) => {
const events: NEvent[] = [] const events: NEvent[] = []
@ -1331,7 +1337,7 @@ class ClientService extends EventTarget {
} }
const duration = eoseTime ? Date.now() - eoseTime : 0 const duration = eoseTime ? Date.now() - eoseTime : 0
if (isExternalSearch) { if (isExternalSearch) {
logger.info('query: Resolving external search', { logger.debug('query: Resolving external search', {
eventsFound: events.length, eventsFound: events.length,
eventCount, eventCount,
allEosed, allEosed,
@ -1346,7 +1352,7 @@ class ClientService extends EventTarget {
onevent(evt) { onevent(evt) {
eventCount++ eventCount++
if (isExternalSearch && eventCount <= 3) { if (isExternalSearch && eventCount <= 3) {
logger.info('query: Received event', { logger.debug('query: Received event', {
eventId: evt.id.substring(0, 8), eventId: evt.id.substring(0, 8),
eventCount, eventCount,
timeSinceEose: eoseTime ? Date.now() - eoseTime : null timeSinceEose: eoseTime ? Date.now() - eoseTime : null
@ -1393,7 +1399,7 @@ class ClientService extends EventTarget {
allEosed = true allEosed = true
eoseTime = Date.now() eoseTime = Date.now()
if (isExternalSearch) { if (isExternalSearch) {
logger.info('query: Received EOSE from all relays', { logger.debug('query: Received EOSE from all relays', {
eventsSoFar: events.length, eventsSoFar: events.length,
eventCount, eventCount,
willWait: eoseTimeout willWait: eoseTimeout
@ -1418,7 +1424,7 @@ class ClientService extends EventTarget {
}, },
onclose: (url, reason) => { onclose: (url, reason) => {
if (isExternalSearch) { if (isExternalSearch) {
logger.info('query: Relay connection closed', { url, reason, eventsSoFar: events.length, allEosed }) logger.debug('query: Relay connection closed', { url, reason, eventsSoFar: events.length, allEosed })
} }
// If we've received EOSE, we have a timeout set - let it handle resolution // If we've received EOSE, we have a timeout set - let it handle resolution
// This gives searchable relays time to search their databases // This gives searchable relays time to search their databases
@ -1447,7 +1453,7 @@ class ClientService extends EventTarget {
// Fallback timeout: resolve after globalTimeout to prevent hanging // Fallback timeout: resolve after globalTimeout to prevent hanging
globalTimeoutId = setTimeout(() => { globalTimeoutId = setTimeout(() => {
if (isExternalSearch) { if (isExternalSearch) {
logger.info('query: Global timeout reached', { logger.debug('query: Global timeout reached', {
eventsFound: events.length, eventsFound: events.length,
eventCount, eventCount,
allEosed allEosed

Loading…
Cancel
Save