Skip to content

Commit 57f48b5

Browse files
mltheuserku76uh
andauthored
Fixed unsafe cast in SensoryEventResponseHandler.scala (#1931)
Co-authored-by: ku76uh <malte.heuser@ing.com>
1 parent e804b74 commit 57f48b5

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

core/akka-runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/SensoryEventResponseHandler.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,10 @@ class SensoryEventResponseHandler(receiver: ActorRef, command: ProcessEvent)
147147
def streaming(runningJobs: Set[Long], cache: List[Any]): Receive = {
148148
command.reaction match {
149149
case FireSensoryEventReaction.NotifyOnEvent(_, onEvent)
150-
if Option(cache.head.asInstanceOf[TransitionFired].output.asInstanceOf[EventInstance]).exists(_.name == onEvent) =>
150+
if (cache.head match {
151+
case fired: TransitionFired => Option(fired.output).collect { case e: EventInstance => e }.exists(_.name == onEvent)
152+
case _ => false
153+
}) =>
151154
notifyComplete(cache.reverse)
152155
Actor.ignoringBehavior
153156

core/akka-runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_index/SensoryEventResponseHandlerSpec.scala

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,29 @@ class SensoryEventResponseHandlerSpec extends AkkaTestBase("SensoryEventResponse
118118
client.expectNoMessage(100.millis)
119119
}
120120

121+
"not crash when a TransitionFailed is received while awaiting NotifyOnEvent" in {
122+
val client = TestProbe()
123+
val sensoryEvent = EventInstance(webshop.orderPlaced.name, Map.empty)
124+
val cmd = ProcessEvent("", sensoryEvent, None, 1 second, NotifyOnEvent(waitForRetries = true, "event2"))
125+
val handler = system.actorOf(SensoryEventResponseHandler(client.ref, cmd))
126+
val event1 = EventInstance("event1", Map("ingredient1" -> PrimitiveValue("value1")))
127+
val event2 = EventInstance("event2", Map("ingredient2" -> PrimitiveValue("value2")))
128+
handler ! webShopRecipe
129+
client.expectNoMessage(100.millis)
130+
// First event fires, spawns job 2
131+
handler ! TransitionFired(1, 1, None, Map.empty, Map.empty, Set(2), event1)
132+
client.expectNoMessage(100.millis)
133+
// Job 2 FAILS - this should NOT cause a ClassCastException
134+
handler ! TransitionFailed(2, 2, None, Map.empty, null, "some error", ProcessInstanceProtocol.ExceptionStrategy.BlockTransition)
135+
client.expectNoMessage(100.millis)
136+
// Now the actual event2 fires on a new job - this should complete
137+
handler ! TransitionFired(3, 3, None, Map.empty, Map.empty, Set.empty, event2)
138+
// We expect a response with event1 and event2, excluding the failed job's output
139+
val expectedEventNames = List(event1.name, event2.name)
140+
val expectedIngredients = event1.providedIngredients ++ event2.providedIngredients
141+
client.expectMsg(ProcessEventCompletedResponse(SensoryEventResult(SensoryEventStatus.Completed, expectedEventNames, expectedIngredients)))
142+
}
143+
121144

122145
"wait for the completion of all jobs even if one fails with TransitionFailed" in {
123146
val client = TestProbe()

0 commit comments

Comments
 (0)