Address code review suggestions

- Update README.md example to match new OfferFactory signature
- Add error handling and RTCPeerConnection cleanup on factory failure
- Document setupIceCandidateHandler() method usage
- Use undefined instead of null for offerId variable

Co-authored-by: Bas <bvdaakster@users.noreply.github.com>
This commit is contained in:
claude[bot]
2025-12-14 10:21:43 +00:00
parent df231c192d
commit a0dc9ddad0
2 changed files with 19 additions and 5 deletions

View File

@@ -49,8 +49,8 @@ const rondevu = await Rondevu.connect({
await rondevu.publishService({ await rondevu.publishService({
service: 'chat:1.0.0', service: 'chat:1.0.0',
maxOffers: 5, // Maintain up to 5 concurrent offers maxOffers: 5, // Maintain up to 5 concurrent offers
offerFactory: async (rtcConfig) => { offerFactory: async (pc) => {
const pc = new RTCPeerConnection(rtcConfig) // pc is created by Rondevu with ICE handlers already attached
const dc = pc.createDataChannel('chat') const dc = pc.createDataChannel('chat')
dc.addEventListener('open', () => { dc.addEventListener('open', () => {
@@ -64,7 +64,7 @@ await rondevu.publishService({
const offer = await pc.createOffer() const offer = await pc.createOffer()
await pc.setLocalDescription(offer) await pc.setLocalDescription(offer)
return { pc, dc, offer } return { dc, offer }
} }
}) })

View File

@@ -382,6 +382,10 @@ export class Rondevu {
/** /**
* Set up ICE candidate handler to send candidates to the server * Set up ICE candidate handler to send candidates to the server
*
* Note: This is used by connectToService() where the offerId is already known.
* For createOffer(), we use inline ICE handling with early candidate queuing
* since the offerId isn't available until after the factory completes.
*/ */
private setupIceCandidateHandler( private setupIceCandidateHandler(
pc: RTCPeerConnection, pc: RTCPeerConnection,
@@ -434,7 +438,7 @@ export class Rondevu {
// This ensures we capture all candidates, even those generated immediately // This ensures we capture all candidates, even those generated immediately
// when setLocalDescription() is called in the factory // when setLocalDescription() is called in the factory
const earlyIceCandidates: RTCIceCandidateInit[] = [] const earlyIceCandidates: RTCIceCandidateInit[] = []
let offerId: string | null = null let offerId: string | undefined
pc.onicecandidate = async (event) => { pc.onicecandidate = async (event) => {
if (event.candidate) { if (event.candidate) {
@@ -461,7 +465,17 @@ export class Rondevu {
// 3. Call the factory with the pc - factory creates data channel and offer // 3. Call the factory with the pc - factory creates data channel and offer
// When factory calls setLocalDescription(), ICE gathering starts and // When factory calls setLocalDescription(), ICE gathering starts and
// candidates are captured by the handler we set up above // candidates are captured by the handler we set up above
const { dc, offer } = await this.offerFactory(pc) let dc: RTCDataChannel | undefined
let offer: RTCSessionDescriptionInit
try {
const factoryResult = await this.offerFactory(pc)
dc = factoryResult.dc
offer = factoryResult.offer
} catch (err) {
// Clean up the connection if factory fails
pc.close()
throw err
}
// 4. Publish to server to get offerId // 4. Publish to server to get offerId
const result = await this.api.publishService({ const result = await this.api.publishService({