1 /*
2  *  Make.org Core API
3  *  Copyright (C) 2018 Make.org
4  *
5  * This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  *
18  */
19 
20 package org.make.api.technical.job
21 
22 import akka.actor.typed.scaladsl.Behaviors
23 import akka.actor.typed.{ActorRef, Behavior}
24 import akka.persistence.typed.PersistenceId
25 import akka.persistence.typed.scaladsl.{Effect, EventSourcedBehavior, RetentionCriteria}
26 import eu.timepit.refined.auto._
27 import org.make.api.technical.job.JobActor.Protocol.Command._
28 import org.make.api.technical.job.JobActor.Protocol.Response._
29 import org.make.api.technical.job.JobEvent._
30 import org.make.api.technical.{ActorCommand, ActorProtocol}
31 import org.make.core.job.Job
32 import org.make.core.job.Job.{JobId, JobStatus, Progress}
33 import org.make.core.{DateHelper, MakeSerializable}
34 import spray.json.{DefaultJsonProtocol, JsString, JsValue, RootJsonFormat}
35 
36 import scala.concurrent.duration.Duration
37 
38 object JobActor {
39 
40   sealed trait JobState extends MakeSerializable {
41     def isStopped: Boolean
42     def isStuck(heartRate: Duration): Boolean
43     def handleCommand(heartRate: Duration): JobActor.Protocol.Command => Effect[JobEvent, JobState]
44     def handleEvent: JobEvent                                         => JobState
45   }
46 
47   case object EmptyJob extends JobState {
48     override def isStopped: Boolean = true
49     override def isStuck(heartRate: Duration): Boolean = false
50 
51     override def handleCommand(heartRate: Duration): JobActor.Protocol.Command => Effect[JobEvent, JobState] = {
52       case Start(id, replyTo: ActorRef[JobAcceptance]) =>
53         Effect.persist(Started(id, DateHelper.now())).thenReply(replyTo)(_ => JobAcceptance(true))
54       case command: StatusCommand => Effect.reply(command.replyTo)(NotRunning)
55       case Get(_, replyTo)        => Effect.reply(replyTo)(State(None))
56       case Kill(_)                => Effect.stop().thenStop()
57     }
58 
59     override def handleEvent: JobEvent => JobState = {
60       case Started(id, date) => DefinedJob(Job(id, JobStatus.Running(0d), Some(date), Some(date)))
61       case _                 => this
62     }
63 
64     implicit val emptyJobJsonFormat: RootJsonFormat[EmptyJob.type] = new RootJsonFormat[EmptyJob.type] {
65       private val Key = "empty"
66 
67       @SuppressWarnings(Array("org.wartremover.warts.Throw"))
68       override def read(json: JsValue): EmptyJob.type = json match {
69         case JsString(Key) => EmptyJob
70         case other         => throw new IllegalStateException(s"$other is not an EmptyJob.")
71       }
72 
73       override def write(obj: EmptyJob.type): JsValue = JsString(Key)
74     }
75   }
76 
77   final case class DefinedJob(job: Job) extends JobState {
78     private def persistIfRunning(replyTo: ActorRef[Process], event: JobEvent): Effect[JobEvent, JobState] = {
79       if (isStopped) {
80         Effect.reply(replyTo)(NotRunning)
81       } else {
82         Effect.persist(event).thenReply(replyTo)(_ => Ack)
83       }
84     }
85 
86     override def isStopped: Boolean = {
87       job.status match {
88         case JobStatus.Running(_) => false
89         case _                    => true
90       }
91     }
92 
93     override def isStuck(heartRate: Duration): Boolean = job.isStuck(heartRate)
94 
95     override def handleCommand(heartRate: Duration): JobActor.Protocol.Command => Effect[JobEvent, JobState] = {
96       case Start(id, replyTo: ActorRef[JobAcceptance]) =>
97         if (isStopped || isStuck(heartRate)) {
98           Effect.persist(Started(id, DateHelper.now())).thenReply(replyTo)(_ => JobAcceptance(true))
99         } else {
100           Effect.reply(replyTo)(JobAcceptance(false))
101         }
102       case Heartbeat(id, replyTo) => persistIfRunning(replyTo, HeartbeatReceived(id, DateHelper.now()))
103       case Report(id, progress, replyTo) =>
104         persistIfRunning(replyTo, Progressed(id, DateHelper.now(), progress))
105       case Finish(id, outcome, replyTo) =>
106         persistIfRunning(replyTo, Finished(id, DateHelper.now(), outcome.flatMap(e => Option(e.getMessage))))
107       case Get(_, replyTo) => Effect.reply(replyTo)(State(Some(job)))
108       case Kill(_)         => Effect.stop().thenStop()
109     }
110 
111     override def handleEvent: JobEvent => JobState = {
112       case Started(id, date) => DefinedJob(Job(id, JobStatus.Running(0d), Some(date), Some(date)))
113       case HeartbeatReceived(_, date) =>
114         DefinedJob(job.copy(updatedAt = Some(date)))
115       case Progressed(_, date, progress) =>
116         DefinedJob(job.copy(status = JobStatus.Running(progress), updatedAt = Some(date)))
117       case Finished(_, date, outcome) =>
118         DefinedJob(job.copy(status = JobStatus.Finished(outcome), updatedAt = Some(date)))
119     }
120   }
121 
122   object DefinedJob {
123     implicit val jsonFormat: RootJsonFormat[DefinedJob] = DefaultJsonProtocol.jsonFormat1(DefinedJob.apply)
124   }
125 
126   sealed abstract class Protocol extends ActorProtocol
127 
128   object Protocol {
129     sealed abstract class Command extends Protocol with ActorCommand[JobId]
130 
131     object Command {
132       sealed trait StatusCommand {
133         def replyTo: ActorRef[Process]
134       }
135 
136       final case class Start(id: JobId, replyTo: ActorRef[JobAcceptance]) extends Command
137       final case class Heartbeat(id: JobId, replyTo: ActorRef[Process]) extends Command with StatusCommand
138       final case class Report(id: JobId, progress: Progress, replyTo: ActorRef[Process])
139           extends Command
140           with StatusCommand
141       final case class Finish(id: JobId, failure: Option[Throwable], replyTo: ActorRef[Process])
142           extends Command
143           with StatusCommand
144       final case class Get(id: JobId, replyTo: ActorRef[State]) extends Command
145       final case class Kill(id: JobId) extends Command
146     }
147 
148     sealed abstract class Response extends Protocol
149 
150     object Response {
151       final case class JobAcceptance(isAccepted: Boolean) extends Response
152       final case class State(value: Option[Job]) extends Response
153 
154       sealed trait Process extends Response
155       final case object Ack extends Process
156       final case object NotRunning extends Process
157     }
158   }
159 
160   val JournalPluginId: String = "make-api.event-sourcing.jobs.journal"
161   val SnapshotPluginId: String = "make-api.event-sourcing.jobs.snapshot"
162 
163   def apply(heartRate: Duration): Behavior[Protocol.Command] = {
164     Behaviors.setup { context =>
165       val id: JobId = JobId(context.self.path.name)
166       val persistenceId: PersistenceId = PersistenceId.ofUniqueId(id.value)
167       EventSourcedBehavior[Protocol.Command, JobEvent, JobState](
168         persistenceId,
169         emptyState = EmptyJob,
170         commandHandler(heartRate),
171         eventHandler
172       ).withJournalPluginId(JournalPluginId)
173         .withSnapshotPluginId(SnapshotPluginId)
174         .withRetention(RetentionCriteria.snapshotEvery(numberOfEvents = 10, keepNSnapshots = 50))
175     }
176   }
177 
178   def commandHandler(heartRate: Duration)(state: JobState, command: Protocol.Command): Effect[JobEvent, JobState] = {
179     state.handleCommand(heartRate)(command)
180   }
181 
182   def eventHandler(state: JobState, event: JobEvent): JobState = state.handleEvent(event)
183 
184 }
Line Stmt Id Pos Tree Symbol Tests Code
48 13175 1933 - 1937 Literal <nosymbol> true
49 9585 1995 - 2000 Literal <nosymbol> false
53 15652 2208 - 2224 Apply org.make.core.DefaultDateHelper.now org.make.core.DateHelper.now()
53 16465 2181 - 2271 Apply akka.persistence.typed.scaladsl.EffectBuilder.thenReply akka.persistence.typed.scaladsl.Effect.persist[org.make.api.technical.job.JobEvent.Started, org.make.api.technical.job.JobActor.JobState](org.make.api.technical.job.JobEvent.Started.apply(id, org.make.core.DateHelper.now())).thenReply[org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance](replyTo)(((x$1: org.make.api.technical.job.JobActor.JobState) => org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance.apply(true)))
53 11958 2196 - 2225 Apply org.make.api.technical.job.JobEvent.Started.apply org.make.api.technical.job.JobEvent.Started.apply(id, org.make.core.DateHelper.now())
53 17920 2251 - 2270 Apply org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance.apply org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance.apply(true)
54 12575 2322 - 2337 Select org.make.api.technical.job.JobActor.Protocol.Command.StatusCommand.replyTo command.replyTo
54 14964 2309 - 2350 Apply akka.persistence.typed.scaladsl.Effect.reply akka.persistence.typed.scaladsl.Effect.reply[org.make.api.technical.job.JobActor.Protocol.Response.Process, Nothing, org.make.api.technical.job.JobActor.JobState](command.replyTo)(org.make.api.technical.job.JobActor.Protocol.Response.NotRunning)
54 9457 2339 - 2349 Select org.make.api.technical.job.JobActor.Protocol.Response.NotRunning org.make.api.technical.job.JobActor.Protocol.Response.NotRunning
55 15670 2388 - 2422 Apply akka.persistence.typed.scaladsl.Effect.reply akka.persistence.typed.scaladsl.Effect.reply[org.make.api.technical.job.JobActor.Protocol.Response.State, Nothing, org.make.api.technical.job.JobActor.JobState](replyTo)(org.make.api.technical.job.JobActor.Protocol.Response.State.apply(scala.None))
55 11372 2416 - 2420 Select scala.None scala.None
55 9893 2410 - 2421 Apply org.make.api.technical.job.JobActor.Protocol.Response.State.apply org.make.api.technical.job.JobActor.Protocol.Response.State.apply(scala.None)
56 12456 2460 - 2484 Apply akka.persistence.typed.scaladsl.EffectBuilder.thenStop akka.persistence.typed.scaladsl.Effect.stop[Nothing, org.make.api.technical.job.JobActor.JobState]().thenStop()
60 16361 2621 - 2631 Apply scala.Some.apply scala.Some.apply[java.time.ZonedDateTime](date)
60 12900 2633 - 2643 Apply scala.Some.apply scala.Some.apply[java.time.ZonedDateTime](date)
60 15442 2579 - 2645 Apply org.make.api.technical.job.JobActor.DefinedJob.apply JobActor.this.DefinedJob.apply(org.make.core.job.Job.apply(id, org.make.core.job.Job.JobStatus.Running.apply((api.this.RefType.refinedRefType.unsafeWrap[Double, org.make.core.job.Job.ProgressRefinement](0.0): eu.timepit.refined.api.Refined[Double,org.make.core.job.Job.ProgressRefinement])), scala.Some.apply[java.time.ZonedDateTime](date), scala.Some.apply[java.time.ZonedDateTime](date)))
60 17939 2598 - 2619 Apply org.make.core.job.Job.JobStatus.Running.apply org.make.core.job.Job.JobStatus.Running.apply((api.this.RefType.refinedRefType.unsafeWrap[Double, org.make.core.job.Job.ProgressRefinement](0.0): eu.timepit.refined.api.Refined[Double,org.make.core.job.Job.ProgressRefinement]))
60 8865 2590 - 2644 Apply org.make.core.job.Job.apply org.make.core.job.Job.apply(id, org.make.core.job.Job.JobStatus.Running.apply((api.this.RefType.refinedRefType.unsafeWrap[Double, org.make.core.job.Job.ProgressRefinement](0.0): eu.timepit.refined.api.Refined[Double,org.make.core.job.Job.ProgressRefinement])), scala.Some.apply[java.time.ZonedDateTime](date), scala.Some.apply[java.time.ZonedDateTime](date))
64 16375 2759 - 2762 Apply org.make.api.technical.job.JobActor.EmptyJob.$anon.<init> org.make.api.sessionhistory.sessionhistorycoordinatortest,org.make.api.technical.crm.crmservicecomponenttest new $anon()
65 11723 2819 - 2826 Literal <nosymbol> org.make.api.sessionhistory.sessionhistorycoordinatortest,org.make.api.technical.crm.crmservicecomponenttest "empty"
69 9914 2989 - 2997 Select org.make.api.technical.job.JobActor.EmptyJob org.scalatest.testsuite JobActor.this.EmptyJob
70 15635 3028 - 3090 Throw <nosymbol> throw new java.lang.IllegalStateException(("".+(other).+(" is not an EmptyJob."): String))
73 18412 3156 - 3169 Apply spray.json.JsString.apply org.scalatest.testsuite spray.json.JsString.apply($anon.this.Key)
73 11871 3165 - 3168 Select org.make.api.technical.job.JobActor.EmptyJob.$anon.Key org.scalatest.testsuite $anon.this.Key
79 12921 3360 - 3369 Select org.make.api.technical.job.JobActor.DefinedJob.isStopped DefinedJob.this.isStopped
80 11626 3381 - 3414 Block akka.persistence.typed.scaladsl.Effect.reply akka.persistence.typed.scaladsl.Effect.reply[org.make.api.technical.job.JobActor.Protocol.Response.Process, Nothing, org.make.api.technical.job.JobActor.JobState](replyTo)(org.make.api.technical.job.JobActor.Protocol.Response.NotRunning)
80 9059 3403 - 3413 Select org.make.api.technical.job.JobActor.Protocol.Response.NotRunning org.make.api.technical.job.JobActor.Protocol.Response.NotRunning
80 14866 3381 - 3414 Apply akka.persistence.typed.scaladsl.Effect.reply akka.persistence.typed.scaladsl.Effect.reply[org.make.api.technical.job.JobActor.Protocol.Response.Process, Nothing, org.make.api.technical.job.JobActor.JobState](replyTo)(org.make.api.technical.job.JobActor.Protocol.Response.NotRunning)
82 12083 3438 - 3488 Block akka.persistence.typed.scaladsl.EffectBuilder.thenReply akka.persistence.typed.scaladsl.Effect.persist[org.make.api.technical.job.JobEvent, org.make.api.technical.job.JobActor.JobState](event).thenReply[org.make.api.technical.job.JobActor.Protocol.Response.Process](replyTo)(((x$2: org.make.api.technical.job.JobActor.JobState) => org.make.api.technical.job.JobActor.Protocol.Response.Ack))
82 15648 3438 - 3488 Apply akka.persistence.typed.scaladsl.EffectBuilder.thenReply akka.persistence.typed.scaladsl.Effect.persist[org.make.api.technical.job.JobEvent, org.make.api.technical.job.JobActor.JobState](event).thenReply[org.make.api.technical.job.JobActor.Protocol.Response.Process](replyTo)(((x$2: org.make.api.technical.job.JobActor.JobState) => org.make.api.technical.job.JobActor.Protocol.Response.Ack))
82 9795 3484 - 3487 Select org.make.api.technical.job.JobActor.Protocol.Response.Ack org.make.api.technical.job.JobActor.Protocol.Response.Ack
87 18205 3550 - 3560 Select org.make.core.job.Job.status DefinedJob.this.job.status
88 14720 3606 - 3611 Literal <nosymbol> false
89 12569 3649 - 3653 Literal <nosymbol> true
93 9078 3726 - 3748 Apply org.make.core.job.Job.isStuck DefinedJob.this.job.isStuck(heartRate)
97 11641 3933 - 3964 Apply scala.Boolean.|| DefinedJob.this.isStopped.||(DefinedJob.this.isStuck(heartRate))
97 15095 3946 - 3964 Apply org.make.api.technical.job.JobActor.DefinedJob.isStuck DefinedJob.this.isStuck(heartRate)
98 14614 3978 - 4068 Block akka.persistence.typed.scaladsl.EffectBuilder.thenReply akka.persistence.typed.scaladsl.Effect.persist[org.make.api.technical.job.JobEvent.Started, org.make.api.technical.job.JobActor.JobState](org.make.api.technical.job.JobEvent.Started.apply(id, org.make.core.DateHelper.now())).thenReply[org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance](replyTo)(((x$3: org.make.api.technical.job.JobActor.JobState) => org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance.apply(true)))
98 12098 4048 - 4067 Apply org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance.apply org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance.apply(true)
98 17930 3978 - 4068 Apply akka.persistence.typed.scaladsl.EffectBuilder.thenReply akka.persistence.typed.scaladsl.Effect.persist[org.make.api.technical.job.JobEvent.Started, org.make.api.technical.job.JobActor.JobState](org.make.api.technical.job.JobEvent.Started.apply(id, org.make.core.DateHelper.now())).thenReply[org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance](replyTo)(((x$3: org.make.api.technical.job.JobActor.JobState) => org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance.apply(true)))
98 15549 3993 - 4022 Apply org.make.api.technical.job.JobEvent.Started.apply org.make.api.technical.job.JobEvent.Started.apply(id, org.make.core.DateHelper.now())
98 9812 4005 - 4021 Apply org.make.core.DefaultDateHelper.now org.make.core.DateHelper.now()
100 15437 4096 - 4139 Block akka.persistence.typed.scaladsl.Effect.reply akka.persistence.typed.scaladsl.Effect.reply[org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance, Nothing, org.make.api.technical.job.JobActor.JobState](replyTo)(org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance.apply(false))
100 12582 4118 - 4138 Apply org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance.apply org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance.apply(false)
100 8963 4096 - 4139 Apply akka.persistence.typed.scaladsl.Effect.reply akka.persistence.typed.scaladsl.Effect.reply[org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance, Nothing, org.make.api.technical.job.JobActor.JobState](replyTo)(org.make.api.technical.job.JobActor.Protocol.Response.JobAcceptance.apply(false))
102 11384 4235 - 4251 Apply org.make.core.DefaultDateHelper.now org.make.core.DateHelper.now()
102 9712 4213 - 4252 Apply org.make.api.technical.job.JobEvent.HeartbeatReceived.apply org.make.api.technical.job.JobEvent.HeartbeatReceived.apply(id, org.make.core.DateHelper.now())
102 15560 4187 - 4253 Apply org.make.api.technical.job.JobActor.DefinedJob.persistIfRunning DefinedJob.this.persistIfRunning(replyTo, org.make.api.technical.job.JobEvent.HeartbeatReceived.apply(id, org.make.core.DateHelper.now()))
104 14369 4306 - 4375 Apply org.make.api.technical.job.JobActor.DefinedJob.persistIfRunning DefinedJob.this.persistIfRunning(replyTo, org.make.api.technical.job.JobEvent.Progressed.apply(id, org.make.core.DateHelper.now(), progress))
104 18406 4332 - 4374 Apply org.make.api.technical.job.JobEvent.Progressed.apply org.make.api.technical.job.JobEvent.Progressed.apply(id, org.make.core.DateHelper.now(), progress)
104 11981 4347 - 4363 Apply org.make.core.DefaultDateHelper.now org.make.core.DateHelper.now()
106 14860 4505 - 4525 Apply scala.Option.apply scala.Option.apply[String](e.getMessage())
106 15464 4427 - 4528 Apply org.make.api.technical.job.JobActor.DefinedJob.persistIfRunning DefinedJob.this.persistIfRunning(replyTo, org.make.api.technical.job.JobEvent.Finished.apply(id, org.make.core.DateHelper.now(), outcome.flatMap[String](((e: Throwable) => scala.Option.apply[String](e.getMessage())))))
106 17658 4453 - 4527 Apply org.make.api.technical.job.JobEvent.Finished.apply org.make.api.technical.job.JobEvent.Finished.apply(id, org.make.core.DateHelper.now(), outcome.flatMap[String](((e: Throwable) => scala.Option.apply[String](e.getMessage()))))
106 11856 4484 - 4526 Apply scala.Option.flatMap outcome.flatMap[String](((e: Throwable) => scala.Option.apply[String](e.getMessage())))
106 8976 4512 - 4524 Apply java.lang.Throwable.getMessage e.getMessage()
106 12478 4466 - 4482 Apply org.make.core.DefaultDateHelper.now org.make.core.DateHelper.now()
107 17826 4587 - 4596 Apply scala.Some.apply scala.Some.apply[org.make.core.job.Job](DefinedJob.this.job)
107 14847 4581 - 4597 Apply org.make.api.technical.job.JobActor.Protocol.Response.State.apply org.make.api.technical.job.JobActor.Protocol.Response.State.apply(scala.Some.apply[org.make.core.job.Job](DefinedJob.this.job))
107 12791 4559 - 4598 Apply akka.persistence.typed.scaladsl.Effect.reply akka.persistence.typed.scaladsl.Effect.reply[org.make.api.technical.job.JobActor.Protocol.Response.State, Nothing, org.make.api.technical.job.JobActor.JobState](replyTo)(org.make.api.technical.job.JobActor.Protocol.Response.State.apply(scala.Some.apply[org.make.core.job.Job](DefinedJob.this.job)))
107 12378 4592 - 4595 Select org.make.api.technical.job.JobActor.DefinedJob.job DefinedJob.this.job
108 8880 4629 - 4653 Apply akka.persistence.typed.scaladsl.EffectBuilder.thenStop akka.persistence.typed.scaladsl.Effect.stop[Nothing, org.make.api.technical.job.JobActor.JobState]().thenStop()
112 11271 4790 - 4800 Apply scala.Some.apply scala.Some.apply[java.time.ZonedDateTime](date)
112 17533 4802 - 4812 Apply scala.Some.apply scala.Some.apply[java.time.ZonedDateTime](date)
112 15788 4759 - 4813 Apply org.make.core.job.Job.apply org.make.core.job.Job.apply(id, org.make.core.job.Job.JobStatus.Running.apply((api.this.RefType.refinedRefType.unsafeWrap[Double, org.make.core.job.Job.ProgressRefinement](0.0): eu.timepit.refined.api.Refined[Double,org.make.core.job.Job.ProgressRefinement])), scala.Some.apply[java.time.ZonedDateTime](date), scala.Some.apply[java.time.ZonedDateTime](date))
112 15360 4767 - 4788 Apply org.make.core.job.Job.JobStatus.Running.apply org.make.core.job.Job.JobStatus.Running.apply((api.this.RefType.refinedRefType.unsafeWrap[Double, org.make.core.job.Job.ProgressRefinement](0.0): eu.timepit.refined.api.Refined[Double,org.make.core.job.Job.ProgressRefinement]))
112 12390 4748 - 4814 Apply org.make.api.technical.job.JobActor.DefinedJob.apply JobActor.this.DefinedJob.apply(org.make.core.job.Job.apply(id, org.make.core.job.Job.JobStatus.Running.apply((api.this.RefType.refinedRefType.unsafeWrap[Double, org.make.core.job.Job.ProgressRefinement](0.0): eu.timepit.refined.api.Refined[Double,org.make.core.job.Job.ProgressRefinement])), scala.Some.apply[java.time.ZonedDateTime](date), scala.Some.apply[java.time.ZonedDateTime](date)))
114 10978 4879 - 4879 Select org.make.core.job.Job.copy$default$2 DefinedJob.this.job.copy$default$2
114 15370 4875 - 4907 Apply org.make.core.job.Job.copy DefinedJob.this.job.copy(x$2, x$3, x$4, x$1)
114 14607 4879 - 4879 Select org.make.core.job.Job.copy$default$1 DefinedJob.this.job.copy$default$1
114 11754 4864 - 4908 Apply org.make.api.technical.job.JobActor.DefinedJob.apply JobActor.this.DefinedJob.apply({ <artifact> val x$1: Some[java.time.ZonedDateTime] @scala.reflect.internal.annotations.uncheckedBounds = scala.Some.apply[java.time.ZonedDateTime](date); <artifact> val x$2: org.make.core.job.Job.JobId = DefinedJob.this.job.copy$default$1; <artifact> val x$3: org.make.core.job.Job.JobStatus = DefinedJob.this.job.copy$default$2; <artifact> val x$4: Option[java.time.ZonedDateTime] @scala.reflect.internal.annotations.uncheckedBounds = DefinedJob.this.job.copy$default$3; DefinedJob.this.job.copy(x$2, x$3, x$4, x$1) })
114 18312 4896 - 4906 Apply scala.Some.apply scala.Some.apply[java.time.ZonedDateTime](date)
114 8957 4879 - 4879 Select org.make.core.job.Job.copy$default$3 DefinedJob.this.job.copy$default$3
116 18325 4976 - 4976 Select org.make.core.job.Job.copy$default$3 DefinedJob.this.job.copy$default$3
116 15813 5031 - 5041 Apply scala.Some.apply scala.Some.apply[java.time.ZonedDateTime](date)
116 11975 4976 - 4976 Select org.make.core.job.Job.copy$default$1 DefinedJob.this.job.copy$default$1
116 10997 4961 - 5043 Apply org.make.api.technical.job.JobActor.DefinedJob.apply JobActor.this.DefinedJob.apply({ <artifact> val x$5: org.make.core.job.Job.JobStatus.Running = org.make.core.job.Job.JobStatus.Running.apply(progress); <artifact> val x$6: Some[java.time.ZonedDateTime] @scala.reflect.internal.annotations.uncheckedBounds = scala.Some.apply[java.time.ZonedDateTime](date); <artifact> val x$7: org.make.core.job.Job.JobId = DefinedJob.this.job.copy$default$1; <artifact> val x$8: Option[java.time.ZonedDateTime] @scala.reflect.internal.annotations.uncheckedBounds = DefinedJob.this.job.copy$default$3; DefinedJob.this.job.copy(x$7, x$5, x$8, x$6) })
116 17549 4990 - 5017 Apply org.make.core.job.Job.JobStatus.Running.apply org.make.core.job.Job.JobStatus.Running.apply(progress)
116 14507 4972 - 5042 Apply org.make.core.job.Job.copy DefinedJob.this.job.copy(x$7, x$5, x$8, x$6)
118 11555 5108 - 5108 Select org.make.core.job.Job.copy$default$1 DefinedJob.this.job.copy$default$1
118 11991 5093 - 5175 Apply org.make.api.technical.job.JobActor.DefinedJob.apply JobActor.this.DefinedJob.apply({ <artifact> val x$9: org.make.core.job.Job.JobStatus.Finished = org.make.core.job.Job.JobStatus.Finished.apply(outcome); <artifact> val x$10: Some[java.time.ZonedDateTime] @scala.reflect.internal.annotations.uncheckedBounds = scala.Some.apply[java.time.ZonedDateTime](date); <artifact> val x$11: org.make.core.job.Job.JobId = DefinedJob.this.job.copy$default$1; <artifact> val x$12: Option[java.time.ZonedDateTime] @scala.reflect.internal.annotations.uncheckedBounds = DefinedJob.this.job.copy$default$3; DefinedJob.this.job.copy(x$11, x$9, x$12, x$10) })
118 15457 5104 - 5174 Apply org.make.core.job.Job.copy DefinedJob.this.job.copy(x$11, x$9, x$12, x$10)
118 8973 5122 - 5149 Apply org.make.core.job.Job.JobStatus.Finished.apply org.make.core.job.Job.JobStatus.Finished.apply(outcome)
118 14981 5163 - 5173 Apply scala.Some.apply scala.Some.apply[java.time.ZonedDateTime](date)
118 17438 5108 - 5108 Select org.make.core.job.Job.copy$default$3 DefinedJob.this.job.copy$default$3
123 17955 5299 - 5315 Apply org.make.api.technical.job.JobActor.DefinedJob.apply org.scalatest.testsuite JobActor.this.DefinedJob.apply(job)
123 14519 5298 - 5298 Select org.make.core.job.Job.jobJsonFormat org.make.api.sessionhistory.sessionhistorycoordinatortest,org.make.api.technical.crm.crmservicecomponenttest job.this.Job.jobJsonFormat
123 11009 5267 - 5316 ApplyToImplicitArgs spray.json.ProductFormatsInstances.jsonFormat1 org.make.api.sessionhistory.sessionhistorycoordinatortest,org.make.api.technical.crm.crmservicecomponenttest spray.json.DefaultJsonProtocol.jsonFormat1[org.make.core.job.Job, org.make.api.technical.job.JobActor.DefinedJob](((job: org.make.core.job.Job) => JobActor.this.DefinedJob.apply(job)))(job.this.Job.jobJsonFormat, (ClassTag.apply[org.make.api.technical.job.JobActor.DefinedJob](classOf[org.make.api.technical.job.JobActor$$DefinedJob]): scala.reflect.ClassTag[org.make.api.technical.job.JobActor.DefinedJob]))
160 8872 6613 - 6651 Literal <nosymbol> "make-api.event-sourcing.jobs.journal"
161 15002 6685 - 6724 Literal <nosymbol> "make-api.event-sourcing.jobs.snapshot"
164 13681 6795 - 7324 Apply akka.actor.typed.scaladsl.Behaviors.setup akka.actor.typed.scaladsl.Behaviors.setup[org.make.api.technical.job.JobActor.Protocol.Command](((context: akka.actor.typed.scaladsl.ActorContext[org.make.api.technical.job.JobActor.Protocol.Command]) => { val id: org.make.core.job.Job.JobId = org.make.core.job.Job.JobId.apply(context.self.path.name); val persistenceId: akka.persistence.typed.PersistenceId = akka.persistence.typed.PersistenceId.ofUniqueId(id.value); akka.persistence.typed.scaladsl.EventSourcedBehavior.apply[org.make.api.technical.job.JobActor.Protocol.Command, org.make.api.technical.job.JobEvent, org.make.api.technical.job.JobActor.JobState](persistenceId, JobActor.this.EmptyJob, ((state: org.make.api.technical.job.JobActor.JobState, command: org.make.api.technical.job.JobActor.Protocol.Command) => JobActor.this.commandHandler(heartRate)(state, command)), ((state: org.make.api.technical.job.JobActor.JobState, event: org.make.api.technical.job.JobEvent) => JobActor.this.eventHandler(state, event))).withJournalPluginId(JobActor.this.JournalPluginId).withSnapshotPluginId(JobActor.this.SnapshotPluginId).withRetention(akka.persistence.typed.scaladsl.RetentionCriteria.snapshotEvery(10, 50)) }))
165 17457 6846 - 6875 Apply org.make.core.job.Job.JobId.apply org.make.core.job.Job.JobId.apply(context.self.path.name)
165 11736 6852 - 6874 Select akka.actor.ActorPath.name context.self.path.name
166 11884 6917 - 6951 Apply akka.persistence.typed.PersistenceId.ofUniqueId akka.persistence.typed.PersistenceId.ofUniqueId(id.value)
166 13777 6942 - 6950 Select org.make.core.job.Job.JobId.value id.value
169 18309 7062 - 7070 Select org.make.api.technical.job.JobActor.EmptyJob JobActor.this.EmptyJob
170 14719 7080 - 7105 Apply org.make.api.technical.job.JobActor.commandHandler JobActor.this.commandHandler(heartRate)(state, command)
171 10677 7115 - 7127 Apply org.make.api.technical.job.JobActor.eventHandler JobActor.this.eventHandler(state, event)
172 8888 7156 - 7171 Select org.make.api.technical.job.JobActor.JournalPluginId JobActor.this.JournalPluginId
173 14882 7203 - 7219 Select org.make.api.technical.job.JobActor.SnapshotPluginId JobActor.this.SnapshotPluginId
174 17225 6958 - 7318 Apply akka.persistence.typed.scaladsl.EventSourcedBehavior.withRetention akka.persistence.typed.scaladsl.EventSourcedBehavior.apply[org.make.api.technical.job.JobActor.Protocol.Command, org.make.api.technical.job.JobEvent, org.make.api.technical.job.JobActor.JobState](persistenceId, JobActor.this.EmptyJob, ((state: org.make.api.technical.job.JobActor.JobState, command: org.make.api.technical.job.JobActor.Protocol.Command) => JobActor.this.commandHandler(heartRate)(state, command)), ((state: org.make.api.technical.job.JobActor.JobState, event: org.make.api.technical.job.JobEvent) => JobActor.this.eventHandler(state, event))).withJournalPluginId(JobActor.this.JournalPluginId).withSnapshotPluginId(JobActor.this.SnapshotPluginId).withRetention(akka.persistence.typed.scaladsl.RetentionCriteria.snapshotEvery(10, 50))
174 11748 7244 - 7317 Apply akka.persistence.typed.scaladsl.RetentionCriteria.snapshotEvery akka.persistence.typed.scaladsl.RetentionCriteria.snapshotEvery(10, 50)
179 11899 7452 - 7491 Apply scala.Function1.apply state.handleCommand(heartRate).apply(command)
182 18218 7562 - 7586 Apply scala.Function1.apply state.handleEvent.apply(event)