@@ -30,6 +30,8 @@ import * as Entity from "./Entity.ts"
3030import * as EntityAddress from "./EntityAddress.ts"
3131import * as EntityId from "./EntityId.ts"
3232import * as EntityType from "./EntityType.ts"
33+ import * as Envelope from "./Envelope.ts"
34+ import * as Message from "./Message.ts"
3335import { MessageStorage } from "./MessageStorage.ts"
3436import type { WithExitEncoded } from "./Reply.ts"
3537import * as Reply from "./Reply.ts"
@@ -131,22 +133,30 @@ export const make = Effect.gen(function*() {
131133 } )
132134 const clockClient = yield * ClockEntity . client
133135
134- const requestIdFor = Effect . fnUntraced ( function * ( options : {
136+ const entityAddressFor = ( options : {
135137 readonly workflow : Workflow . Any
136138 readonly entityType : string
137139 readonly executionId : string
138- readonly tag : string
139- readonly id : string
140- } ) {
140+ } ) => {
141141 const shardGroup = ServiceMap . get ( options . workflow . annotations , ClusterSchema . ShardGroup ) (
142142 options . executionId as EntityId . EntityId
143143 )
144144 const entityId = EntityId . make ( options . executionId )
145- const address = EntityAddress . make ( {
145+ return EntityAddress . make ( {
146146 entityType : EntityType . make ( options . entityType ) ,
147147 entityId,
148148 shardId : sharding . getShardId ( entityId , shardGroup )
149149 } )
150+ }
151+
152+ const requestIdFor = Effect . fnUntraced ( function * ( options : {
153+ readonly workflow : Workflow . Any
154+ readonly entityType : string
155+ readonly executionId : string
156+ readonly tag : string
157+ readonly id : string
158+ } ) {
159+ const address = entityAddressFor ( options )
150160 return yield * storage . requestIdForPrimaryKey ( { address, tag : options . tag , id : options . id } )
151161 } )
152162
@@ -253,6 +263,46 @@ export const make = Effect.gen(function*() {
253263 yield * sharding . reset ( requestId . value )
254264 } , Effect . scoped )
255265
266+ const interrupt = Effect . fnUntraced (
267+ function * ( workflow : Workflow . Any , executionId : string ) {
268+ ensureEntity ( workflow )
269+ const requestId = yield * requestIdFor ( {
270+ workflow,
271+ entityType : `Workflow/${ workflow . name } ` ,
272+ executionId,
273+ tag : "run" ,
274+ id : ""
275+ } )
276+ if ( Option . isNone ( requestId ) ) {
277+ return Option . none ( )
278+ }
279+ const reply = yield * replyForRequestId ( requestId . value )
280+
281+ const nonSuspendedReply = Option . filter (
282+ reply ,
283+ ( reply ) => reply . exit . _tag !== "Success" || reply . exit . value . _tag !== "Suspended"
284+ )
285+ if ( Option . isSome ( nonSuspendedReply ) ) {
286+ return Option . none ( )
287+ }
288+
289+ yield * engine . deferredDone ( InterruptSignal , {
290+ workflowName : workflow . name ,
291+ executionId,
292+ deferredName : InterruptSignal . name ,
293+ exit : Exit . void
294+ } )
295+
296+ return requestId
297+ } ,
298+ Effect . retry ( {
299+ while : ( e ) => e . _tag === "PersistenceError" ,
300+ times : 3 ,
301+ schedule : Schedule . exponential ( 250 )
302+ } ) ,
303+ Effect . orDie
304+ )
305+
256306 const engine = WorkflowEngine . makeUnsafe ( {
257307 register : ( workflow , execute ) =>
258308 Effect . suspend ( ( ) =>
@@ -386,39 +436,28 @@ export const make = Effect.gen(function*() {
386436 return Option . some ( yield * exit )
387437 } , Effect . orDie ) ,
388438
389- interrupt : Effect . fnUntraced (
390- function * ( workflow , executionId ) {
391- ensureEntity ( workflow )
392- const reply = yield * requestReply ( {
393- workflow,
394- entityType : `Workflow/${ workflow . name } ` ,
395- executionId,
396- tag : "run" ,
397- id : ""
398- } )
399-
400- const nonSuspendedReply = Option . filter (
401- reply ,
402- ( reply ) => reply . exit . _tag !== "Success" || reply . exit . value . _tag !== "Suspended"
403- )
404- if ( Option . isSome ( nonSuspendedReply ) ) {
405- return
406- }
407-
408- yield * engine . deferredDone ( InterruptSignal , {
409- workflowName : workflow . name ,
410- executionId,
411- deferredName : InterruptSignal . name ,
412- exit : Exit . void
413- } )
414- } ,
415- Effect . retry ( {
416- while : ( e ) => e . _tag === "PersistenceError" ,
417- times : 3 ,
418- schedule : Schedule . exponential ( 250 )
419- } ) ,
420- Effect . orDie
421- ) ,
439+ interrupt : ( workflow , executionId ) => Effect . asVoid ( interrupt ( workflow , executionId ) ) ,
440+ interruptUnsafe : Effect . fnUntraced ( function * ( workflow , executionId ) {
441+ const requestId = yield * interrupt ( workflow , executionId )
442+ if ( Option . isNone ( requestId ) ) return
443+ const entity = ensureEntity ( workflow )
444+ const runRpc = entity . protocol . requests . get ( "run" ) !
445+ yield * Effect . orDie ( sharding . sendOutgoing (
446+ new Message . OutgoingEnvelope ( {
447+ rpc : runRpc ,
448+ envelope : new Envelope . Interrupt ( {
449+ id : yield * sharding . getSnowflake ,
450+ address : entityAddressFor ( {
451+ workflow,
452+ entityType : `Workflow/${ workflow . name } ` ,
453+ executionId
454+ } ) ,
455+ requestId : requestId . value
456+ } )
457+ } ) ,
458+ false
459+ ) )
460+ } ) ,
422461
423462 resume : ( workflow , executionId ) => ensureSuccess ( resume ( workflow , executionId ) ) ,
424463
0 commit comments