Skip to content

Commit 7ed67a3

Browse files
dylanjeffersclaude
andcommitted
fix(identity): bound SDK getUserAccount lookup in authMiddleware
authMiddleware backfills blockchainUserId/handle via a blocking audiusSdk.full.users.getUserAccount() call whenever the identity user row is missing those fields - the exact state of a user mid-signup. During signup the on-chain user is often not yet indexed by discovery, so the SDK blocks on its internal node selection + retries. The surrounding try/catch only handles rejection, not a hang, so the whole request (e.g. POST /users/update) stalls until the client times out. This path went live in prod on 6/15 once #14474 shipped loadAudiusSdk.cjs into the build, activating the SDK in authMiddleware for the first time. Wrap the lookup in a 3s timeout so a slow/hanging discovery lookup degrades gracefully (logged, then next()) instead of stalling auth on every authenticated endpoint. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 0f000be commit 7ed67a3

1 file changed

Lines changed: 32 additions & 10 deletions

File tree

packages/identity-service/src/authMiddleware.js

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,20 @@ const models = require('./models')
1111
const audiusLibsWrapper = require('./audiusLibsInstance')
1212
const { encodeHashId, decodeHashId } = require('./utils/hashIds')
1313

14+
// Upper bound on the discovery/SDK lookup used to backfill blockchainUserId/handle.
15+
// During signup the on-chain user is often not yet indexed by discovery, so this
16+
// call can block on the SDK's internal node selection + retries. Without a bound it
17+
// stalls the entire request (e.g. /users/update) until the client times out.
18+
const SDK_USER_LOOKUP_TIMEOUT_MS = 3000
19+
20+
const withTimeout = (promise, ms, message) =>
21+
Promise.race([
22+
promise,
23+
new Promise((_resolve, reject) =>
24+
setTimeout(() => reject(new Error(message)), ms)
25+
)
26+
])
27+
1428
/**
1529
* Queries for whether the wallet address has privilege to act as actingUserId
1630
* @param {number} managerWalletAddress
@@ -114,11 +128,15 @@ async function authMiddleware(req, res, next) {
114128
// ensuring that the user.handle always represents the latest state on chain
115129
if (!user.blockchainUserId || !user.handle) {
116130
try {
117-
const res = await req.app.get('audiusSdk').full.users.getUserAccount({
118-
wallet: walletAddress,
119-
encodedDataMessage,
120-
encodedDataSignature: signature
121-
})
131+
const res = await withTimeout(
132+
req.app.get('audiusSdk').full.users.getUserAccount({
133+
wallet: walletAddress,
134+
encodedDataMessage,
135+
encodedDataSignature: signature
136+
}),
137+
SDK_USER_LOOKUP_TIMEOUT_MS,
138+
'audiusSdk.getUserAccount timed out'
139+
)
122140
const discprovUser = res.data.user
123141
const userId = decodeHashId(discprovUser.id)
124142
const handle = discprovUser.handle
@@ -181,11 +199,15 @@ const parameterizedAuthMiddleware = ({ shouldRespondBadRequest }) => {
181199

182200
if (!user.blockchainUserId || !user.handle) {
183201
try {
184-
const res = await req.app.get('audiusSdk').full.users.getUserAccount({
185-
wallet: walletAddress,
186-
encodedDataMessage,
187-
encodedDataSignature: signature
188-
})
202+
const res = await withTimeout(
203+
req.app.get('audiusSdk').full.users.getUserAccount({
204+
wallet: walletAddress,
205+
encodedDataMessage,
206+
encodedDataSignature: signature
207+
}),
208+
SDK_USER_LOOKUP_TIMEOUT_MS,
209+
'audiusSdk.getUserAccount timed out'
210+
)
189211
const discprovUser = res.data.user
190212
const userId = decodeHashId(discprovUser.id)
191213
const handle = discprovUser.handle

0 commit comments

Comments
 (0)