Problem
In src/utils/lock.ts line 9, the default lock TTL is 30 seconds. Stellar network transactions can take 5-30 seconds depending on network congestion. The lock heartbeat fires at ttlMs / 2 = 15 seconds.
If the Stellar transaction takes longer than 30 seconds and the heartbeat fails (e.g., a transient Redis blip), the lock expires, and another request could enter the critical section.
Impact
- Duplicate Stellar transactions possible
- Lock expires during long operations
- Potential double-spending
Fix
Increase default TTL and make it configurable:
export async function withLock<T>(
key: string,
fn: () => Promise<T>,
ttlMs: number = 60_000, // 60 seconds default
): Promise<T> {
Also update callers to pass appropriate TTLs:
await withLock(`reward:${submissionId}`, async () => {
// Stellar transaction
}, 90_000); // 90 seconds for Stellar operations
Scope
src/utils/lock.ts -- update default TTL
- Update callers to pass appropriate TTLs
Acceptance Criteria
- Default TTL is 60 seconds
- Stellar operations use 90+ second TTL
- Lock does not expire during normal operations
- Existing tests pass
Technical Context
src/utils/lock.ts:9 -- default TTL
src/modules/rewards/reward.service.ts:207 -- Stellar lock usage
Problem
In
src/utils/lock.tsline 9, the default lock TTL is 30 seconds. Stellar network transactions can take 5-30 seconds depending on network congestion. The lock heartbeat fires atttlMs / 2 = 15 seconds.If the Stellar transaction takes longer than 30 seconds and the heartbeat fails (e.g., a transient Redis blip), the lock expires, and another request could enter the critical section.
Impact
Fix
Increase default TTL and make it configurable:
Also update callers to pass appropriate TTLs:
Scope
src/utils/lock.ts-- update default TTLAcceptance Criteria
Technical Context
src/utils/lock.ts:9-- default TTLsrc/modules/rewards/reward.service.ts:207-- Stellar lock usage