@@ -36,6 +36,7 @@ import {
3636 promiseWithResolvers ,
3737} from "@/utils" ;
3838import { createHttpSocket } from "./conn/drivers/http" ;
39+ import { createRawWebSocketSocket } from "./conn/drivers/raw-websocket" ;
3940import { createWebSocketSocket } from "./conn/drivers/websocket" ;
4041import type { ActorDriver } from "./driver" ;
4142import { loggerWithoutContext } from "./log" ;
@@ -383,12 +384,19 @@ export async function handleRawWebSocketHandler(
383384) : Promise < UpgradeWebSocketArgs > {
384385 const actor = await actorDriver . loadActor ( actorId ) ;
385386
387+ // Promise used to wait for the websocket close in `disconnect`
388+ const closePromiseResolvers = promiseWithResolvers < void > ( ) ;
389+
390+ // Track connection outside of scope for cleanup
391+ let createdConn : AnyConn | undefined ;
392+
386393 // Return WebSocket event handlers
387394 return {
388- onOpen : ( evt : any , ws : any ) => {
395+ onOpen : async ( evt : any , ws : any ) => {
389396 // Extract rivetRequestId provided by engine runner
390397 const rivetRequestId = evt ?. rivetRequestId ;
391398 const isHibernatable =
399+ ! ! rivetRequestId &&
392400 actor [
393401 ACTOR_INSTANCE_PERSIST_SYMBOL
394402 ] . hibernatableConns . findIndex ( ( conn ) =>
@@ -424,10 +432,36 @@ export async function handleRawWebSocketHandler(
424432 toUrl : newRequest . url ,
425433 } ) ;
426434
427- // Call the actor's onWebSocket handler with the adapted WebSocket
428- actor . handleWebSocket ( adapter , {
429- request : newRequest ,
430- } ) ;
435+ try {
436+ // Create connection using actor.createConn - this handles deduplication for hibernatable connections
437+ const requestId = rivetRequestId
438+ ? String ( rivetRequestId )
439+ : crypto . randomUUID ( ) ;
440+ const conn = await actor . createConn (
441+ createRawWebSocketSocket (
442+ requestId ,
443+ rivetRequestId ,
444+ isHibernatable ,
445+ adapter ,
446+ closePromiseResolvers . promise ,
447+ ) ,
448+ { } , // No parameters for raw WebSocket
449+ newRequest ,
450+ ) ;
451+
452+ createdConn = conn ;
453+
454+ // Call the actor's onWebSocket handler with the adapted WebSocket
455+ actor . handleWebSocket ( adapter , {
456+ request : newRequest ,
457+ } ) ;
458+ } catch ( error ) {
459+ actor . rLog . error ( {
460+ msg : "failed to create raw WebSocket connection" ,
461+ error : String ( error ) ,
462+ } ) ;
463+ ws . close ( 1011 , "Failed to create connection" ) ;
464+ }
431465 } ,
432466 onMessage : ( event : any , ws : any ) => {
433467 // Find the adapter for this WebSocket
@@ -442,6 +476,15 @@ export async function handleRawWebSocketHandler(
442476 if ( adapter ) {
443477 adapter . _handleClose ( evt ?. code || 1006 , evt ?. reason || "" ) ;
444478 }
479+
480+ // Resolve the close promise
481+ closePromiseResolvers . resolve ( ) ;
482+
483+ // Clean up the connection
484+ if ( createdConn ) {
485+ const wasClean = evt ?. wasClean || evt ?. code === 1000 ;
486+ actor . connDisconnected ( createdConn , wasClean ) ;
487+ }
445488 } ,
446489 onError : ( error : any , ws : any ) => {
447490 // Find the adapter for this WebSocket
0 commit comments