@@ -133,6 +133,37 @@ const dateWorkflow = DBOS.registerWorkflow(
133133 } ,
134134) ;
135135
136+ // Re-sets one event key twice with different formats; the second setEvent must overwrite value AND serialization.
137+ const reSetEventWorkflow = DBOS . registerWorkflow (
138+ async ( ) => {
139+ await DBOS . setEvent ( 'rekey' , 10n , { serializationType : 'portable' } ) ;
140+ await DBOS . setEvent ( 'rekey' , 10n , { serializationType : 'native' } ) ;
141+ } ,
142+ { name : 'reSetEventWorkflow' } ,
143+ ) ;
144+
145+ // Workflows for the OAOO replay test: recv/getEvent must keep their recorded serialization across replay.
146+ const portableEventSetterWF = DBOS . registerWorkflow (
147+ async ( input : string ) => {
148+ await DBOS . setEvent ( 'evt' , input , { serializationType : 'portable' } ) ;
149+ } ,
150+ { name : 'portableEventSetterWF' } ,
151+ ) ;
152+
153+ const eventGetterWF = DBOS . registerWorkflow (
154+ async ( setterId : string ) => {
155+ return await DBOS . getEvent < string > ( setterId , 'evt' ) ;
156+ } ,
157+ { name : 'eventGetterWF' } ,
158+ ) ;
159+
160+ const portableRecvWF = DBOS . registerWorkflow (
161+ async ( ) => {
162+ return await DBOS . recv < string > ( 'topic' ) ;
163+ } ,
164+ { name : 'portableRecvWF' } ,
165+ ) ;
166+
136167describe ( 'portable-serizlization-tests' , ( ) => {
137168 let config : DBOSConfig ;
138169 let systemDBClient : Client ;
@@ -333,6 +364,20 @@ describe('portable-serizlization-tests', () => {
333364 }
334365 } ) ;
335366
367+ test ( 'test-setevent-reset-updates-serialization' , async ( ) => {
368+ // Re-set portable then native: the native format must win so getEvent recovers 10n, not the superjson envelope.
369+ const handle = await DBOS . startWorkflow ( reSetEventWorkflow ) ( ) ;
370+ await handle . getResult ( ) ;
371+
372+ const row = await systemDBClient . query < workflow_events > (
373+ `SELECT * FROM dbos.workflow_events WHERE workflow_uuid = $1 AND key = $2` ,
374+ [ handle . workflowID , 'rekey' ] ,
375+ ) ;
376+ expect ( row . rows [ 0 ] . serialization ) . toBe ( DBOSJSON . name ( ) ) ;
377+
378+ expect ( await DBOS . getEvent ( handle . workflowID , 'rekey' ) ) . toBe ( 10n ) ;
379+ } ) ;
380+
336381 // Reproduces https://github.com/dbos-inc/dbos-transact-ts/issues/1208
337382 test ( 'test-portable-void-workflow' , async ( ) => {
338383 // A portable workflow that returns undefined should succeed, not throw
@@ -958,6 +1003,44 @@ describe('custom-serializer-restart-tests', () => {
9581003
9591004 process . env . DBOS__APPVERSION = undefined ;
9601005 } ) ;
1006+
1007+ test ( 'test-recv-getevent-preserve-serialization-on-replay' , async ( ) => {
1008+ // Under the base64 global serializer, replayed recv/getEvent must use the stored portable format or deserialization throws.
1009+ process . env . DBOS__APPVERSION = 'v0' ;
1010+ await setUpDBOSTestSysDb ( config ) ;
1011+ config . serializer = base64Serializer ;
1012+ DBOS . setConfig ( config ) ;
1013+ await DBOS . launch ( ) ;
1014+
1015+ systemDBClient = new Client ( { connectionString : config . systemDatabaseUrl } ) ;
1016+ await systemDBClient . connect ( ) ;
1017+
1018+ // --- getEvent path ---
1019+ const setter = await DBOS . startWorkflow ( portableEventSetterWF ) ( 'event-payload' ) ;
1020+ await setter . getResult ( ) ;
1021+ // Sanity check: the event was stored in portable format, not base64.
1022+ const evtRow = await systemDBClient . query < workflow_events > (
1023+ `SELECT * FROM dbos.workflow_events WHERE workflow_uuid = $1 AND key = $2` ,
1024+ [ setter . workflowID , 'evt' ] ,
1025+ ) ;
1026+ expect ( evtRow . rows [ 0 ] . serialization ) . toBe ( DBOSPortableJSON . name ( ) ) ;
1027+
1028+ const getter = await DBOS . startWorkflow ( eventGetterWF ) ( setter . workflowID ) ;
1029+ expect ( await getter . getResult ( ) ) . toBe ( 'event-payload' ) ;
1030+ // Replay the getter: getEvent hits OAOO and must still return the value.
1031+ const reGetter = await reexecuteWorkflowById ( getter . workflowID ) ;
1032+ expect ( await reGetter ?. getResult ( ) ) . toBe ( 'event-payload' ) ;
1033+
1034+ // --- recv path ---
1035+ const receiver = await DBOS . startWorkflow ( portableRecvWF ) ( ) ;
1036+ await DBOS . send ( receiver . workflowID , 'msg-payload' , 'topic' , undefined , { serializationType : 'portable' } ) ;
1037+ expect ( await receiver . getResult ( ) ) . toBe ( 'msg-payload' ) ;
1038+ // Replay the receiver: recv hits OAOO and must still return the message.
1039+ const reReceiver = await reexecuteWorkflowById ( receiver . workflowID ) ;
1040+ expect ( await reReceiver ?. getResult ( ) ) . toBe ( 'msg-payload' ) ;
1041+
1042+ process . env . DBOS__APPVERSION = undefined ;
1043+ } ) ;
9611044} ) ;
9621045
9631046// Workflows for async-serializer tests (registered at module level)
0 commit comments