fix(socket-handler): Fix socket handler race condition by differentiating between async and sync handlers. Now, async socket handlers complete their setup before initial data is emitted, ensuring that no data is lost. Documentation and tests have been updated to reflect this change.
This commit is contained in:
@ -155,4 +155,41 @@ Deferred certificate provisioning until after ports are ready:
|
||||
- `test/test.acme-timing-simple.ts` - Verifies proper timing sequence
|
||||
|
||||
### Migration
|
||||
Update to v19.3.9+, no configuration changes needed.
|
||||
Update to v19.3.9+, no configuration changes needed.
|
||||
|
||||
## Socket Handler Race Condition Fix (v19.5.0)
|
||||
|
||||
### Issue
|
||||
Initial data chunks were being emitted before async socket handlers had completed setup, causing data loss when handlers performed async operations before setting up data listeners.
|
||||
|
||||
### Root Cause
|
||||
The `handleSocketHandlerAction` method was using `process.nextTick` to emit initial chunks regardless of whether the handler was sync or async. This created a race condition where async handlers might not have their listeners ready when the initial data was emitted.
|
||||
|
||||
### Solution
|
||||
Differentiated between sync and async handlers:
|
||||
```typescript
|
||||
const result = route.action.socketHandler(socket);
|
||||
|
||||
if (result instanceof Promise) {
|
||||
// Async handler - wait for completion before emitting initial data
|
||||
result.then(() => {
|
||||
if (initialChunk && initialChunk.length > 0) {
|
||||
socket.emit('data', initialChunk);
|
||||
}
|
||||
}).catch(/*...*/);
|
||||
} else {
|
||||
// Sync handler - use process.nextTick as before
|
||||
if (initialChunk && initialChunk.length > 0) {
|
||||
process.nextTick(() => {
|
||||
socket.emit('data', initialChunk);
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Test Coverage
|
||||
- `test/test.socket-handler-race.ts` - Specifically tests async handlers with delayed listener setup
|
||||
- Verifies that initial data is received even when handler sets up listeners after async work
|
||||
|
||||
### Usage Note
|
||||
Socket handlers require initial data from the client to trigger routing (not just a TLS handshake). Clients must send at least one byte of data for the handler to be invoked.
|
Reference in New Issue
Block a user