diff --git a/CHANGELOG.md b/CHANGELOG.md index 77a86e20..1bb94985 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +- changed: Increase NYM mixFetch timeout to 120s for improved XMR makeSpend reliability. +- changed: Remove NYM mixFetch per-host request queue now that `@nymproject/mix-fetch` handles concurrency natively. + ## 2.43.1 (2026-02-23) - changed: Upgrade `@nymproject/mix-fetch` to improve performance with new concurrency changes. diff --git a/src/io/browser/browser-io.ts b/src/io/browser/browser-io.ts index 80fa556e..b66fbf09 100644 --- a/src/io/browser/browser-io.ts +++ b/src/io/browser/browser-io.ts @@ -1,9 +1,10 @@ +import { mixFetch } from '@nymproject/mix-fetch' import { makeLocalStorageDisklet } from 'disklet' import { LogBackend, makeLog } from '../../core/log/log' import { EdgeFetchOptions, EdgeFetchResponse, EdgeIo } from '../../types/types' import { scrypt } from '../../util/crypto/scrypt' -import { initMixFetch, queueMixFetch } from '../../util/nym' +import { initMixFetch, mixFetchOptions } from '../../util/nym' import { fetchCorsProxy } from './fetch-cors-proxy' // Only try CORS proxy/bridge techniques up to 5 times @@ -51,11 +52,14 @@ export function makeBrowserIo(logBackend: LogBackend): EdgeIo { if (privacy === 'nym') { // Ensure mixFetch is initialized before use await initMixFetch(log) - // Use queued fetch to handle mixFetch's one-request-per-host limitation - return await queueMixFetch(uri, { - ...opts, - mode: 'unsafe-ignore-cors' as RequestMode - }) + return await mixFetch( + uri, + { + ...opts, + mode: 'unsafe-ignore-cors' as RequestMode + }, + mixFetchOptions + ) } if (corsBypass === 'always') { return await fetchCorsProxy(uri, opts) diff --git a/src/io/react-native/react-native-worker.ts b/src/io/react-native/react-native-worker.ts index a71b31a1..f7cd2c54 100644 --- a/src/io/react-native/react-native-worker.ts +++ b/src/io/react-native/react-native-worker.ts @@ -1,3 +1,4 @@ +import { mixFetch } from '@nymproject/mix-fetch' import hashjs from 'hash.js' import HmacDRBG from 'hmac-drbg' import { base64 } from 'rfc4648' @@ -17,7 +18,7 @@ import { EdgeFetchResponse, EdgeIo } from '../../types/types' -import { initMixFetch, queueMixFetch } from '../../util/nym' +import { initMixFetch, mixFetchOptions } from '../../util/nym' import { hideProperties } from '../hidden-properties' import { makeNativeBridge } from './native-bridge' import { WorkerApi, YAOB_THROTTLE_MS } from './react-native-types' @@ -178,11 +179,14 @@ async function makeIo(logBackend: LogBackend): Promise { if (privacy === 'nym') { // Ensure mixFetch is initialized before use await initMixFetch(log) - // Use queued fetch to handle mixFetch's one-request-per-host limitation - const response = await queueMixFetch(uri, { - ...opts, - mode: 'unsafe-ignore-cors' as RequestMode - }) + const response = await mixFetch( + uri, + { + ...opts, + mode: 'unsafe-ignore-cors' as RequestMode + }, + mixFetchOptions + ) return response } if (corsBypass === 'always') { diff --git a/src/util/nym.ts b/src/util/nym.ts index b1bee731..fc623823 100644 --- a/src/util/nym.ts +++ b/src/util/nym.ts @@ -1,7 +1,6 @@ import { createMixFetch, IMixFetch, - mixFetch, SetupMixFetchOps } from '@nymproject/mix-fetch' @@ -11,30 +10,15 @@ import { EdgeLog } from '../types/types' * Configuration options for the NYM mixFetch client. */ export const mixFetchOptions: SetupMixFetchOps = { - forceTls: true // force WSS + forceTls: true, // force WSS + mixFetchOverride: { + requestTimeoutMs: 120000 + } } // MixFetch initialization state let mixFetchInitPromise: Promise | null = null -// Per-host request queue to handle mixFetch's one-request-per-host limitation -// Maps host -> Promise that resolves when current request completes (for chaining) -const hostRequestChains = new Map>() - -/** - * Extract the host:port from a URI for queue keying - */ -function getHostKey(uri: string): string { - try { - const url = new URL(uri) - const port = - url.port !== '' ? url.port : url.protocol === 'https:' ? '443' : '80' - return `${url.hostname}:${port}` - } catch { - return uri - } -} - /** * Initialize the NYM mixFetch client. Must be called before using mixFetch. * Safe to call multiple times - subsequent calls return the same promise. @@ -56,33 +40,3 @@ export async function initMixFetch(log: EdgeLog): Promise { } return await mixFetchInitPromise } - -/** - * Queue-wrapped mixFetch that serializes requests per host. - * mixFetch only allows one concurrent request per host, so we chain them. - */ -export async function queueMixFetch( - uri: string, - opts: RequestInit & { mode?: string } -): Promise { - const hostKey = getHostKey(uri) - - // Get the current chain for this host (or resolved promise if none) - const previousChain = hostRequestChains.get(hostKey) ?? Promise.resolve() - - // Chain our request after the previous one - const ourWork = previousChain - .catch(() => {}) // Ignore errors from previous request - .then(async () => await mixFetch(uri, opts, mixFetchOptions)) - .finally(() => { - // Clean up if we're still the chain tail - if (hostRequestChains.get(hostKey) === ourWork) { - hostRequestChains.delete(hostKey) - } - }) - - // Store our chain BEFORE awaiting - ensures subsequent requests wait for us - hostRequestChains.set(hostKey, ourWork) - - return await ourWork -}