4 Commits

Author SHA1 Message Date
9a4fbb63f8 v0.18.7 - Revert to v0.18.3 answer processing logic 2025-12-14 14:39:26 +01:00
f8fb842935 Revert to v0.18.3 answer processing logic
Reverted pollInternal to exactly match v0.18.3 which was the last
working version. The changes in v0.18.5 and v0.18.6 that moved the
answered flag and timestamp updates were causing issues.

v0.18.3 working logic restored:
- Check !activeOffer.answered
- Call setRemoteDescription (no try/catch)
- Set answered = true AFTER
- Update lastPollTimestamp AFTER
- No pre-emptive timestamp updates

The only difference from v0.18.3 is the eventemitter3 import which
should not affect answer processing behavior.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-14 14:39:15 +01:00
50d49d80d3 v0.18.6 - Fix duplicate answer bug (timestamp update) 2025-12-14 14:29:06 +01:00
b3b1751f63 Fix duplicate answer bug - update timestamp before processing
Root cause: When setRemoteDescription failed, lastPollTimestamp was
never updated, causing the server to return the same answer repeatedly.

Solution:
1. Update lastPollTimestamp BEFORE processing answers
2. Calculate max timestamp from all received answers upfront
3. Don't throw on setRemoteDescription errors - just log and continue
4. This ensures we advance the timestamp even if processing fails

This prevents the infinite loop of:
- Poll returns answer
- Processing fails
- Timestamp not updated
- Next poll returns same answer
- Repeat

Now the timestamp advances regardless of processing success,
preventing duplicate answer fetches from the server.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-14 14:28:57 +01:00
3 changed files with 12 additions and 20 deletions

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "@xtr-dev/rondevu-client",
"version": "0.18.5",
"version": "0.18.7",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@xtr-dev/rondevu-client",
"version": "0.18.5",
"version": "0.18.7",
"license": "MIT",
"dependencies": {
"@noble/ed25519": "^3.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@xtr-dev/rondevu-client",
"version": "0.18.5",
"version": "0.18.7",
"description": "TypeScript client for Rondevu with durable WebRTC connections, automatic reconnection, and message queuing",
"type": "module",
"main": "dist/index.js",

View File

@@ -651,25 +651,17 @@ export class Rondevu extends EventEmitter {
if (activeOffer && !activeOffer.answered) {
this.debug(`Received answer for offer ${answer.offerId}`)
// Mark as answered BEFORE setRemoteDescription to prevent race condition
activeOffer.answered = true
try {
await activeOffer.pc.setRemoteDescription({
type: 'answer',
sdp: answer.sdp
})
activeOffer.answered = true
this.lastPollTimestamp = answer.answeredAt
this.emit('offer:answered', answer.offerId, answer.answererId)
// Create replacement offer
this.fillOffers()
} catch (err) {
// If setRemoteDescription fails, reset the answered flag
activeOffer.answered = false
throw err
}
}
}