From b0afeb6efade722c2bdcfaa3ee3d1a6745ca6ab0 Mon Sep 17 00:00:00 2001 From: Tim Linschoten Date: Mon, 26 Aug 2019 16:33:25 +0200 Subject: [PATCH 01/86] Start on making the InteractionInstances be called via an Actor to allow for remoting --- .../InteractionAgentDescriptor.scala | 8 +++++ .../InteractionAgentProtocol.scala | 32 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentDescriptor.scala create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentProtocol.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentDescriptor.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentDescriptor.scala new file mode 100644 index 000000000..f3c8cdc78 --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentDescriptor.scala @@ -0,0 +1,8 @@ +package com.ing.baker.runtime.akka.actor.interaction_agent + +import com.ing.baker.types.Type + +case class InteractionAgentDescriptor( + name: String, + input: Seq[Type], + output: Option[Map[String, Map[String, Type]]]) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentProtocol.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentProtocol.scala new file mode 100644 index 000000000..33872bce2 --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentProtocol.scala @@ -0,0 +1,32 @@ +package com.ing.baker.runtime.akka.actor.interaction_agent + +import akka.remote.ContainerFormats.ActorRef +import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable +import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance} + +class InteractionAgentProtocol { + sealed trait ProcessIndexMessage extends BakerSerializable + + case class Register(interactionAgentDescriptor: InteractionAgentDescriptor, + agentRef: ActorRef) extends ProcessIndexMessage + + case class ExecuteInstance(input: Seq[IngredientInstance]) + + sealed trait ExecuteInstanceResponse extends BakerSerializable + + /** + * Instance executed successfully + * @param result the EventInstance that is created, empty if interaction does not return an Event + */ + case class InstanceExecutedSuccessfully(result: Option[EventInstance]) extends ExecuteInstanceResponse + + /** + * Technical failure of the interaction + */ + case class InstanceExecutionFailed() extends ExecuteInstanceResponse + + /** + * Invalid request, bad ingredients given + */ + case class InstanceExecutedInvalid() extends ExecuteInstanceResponse +} From 76ede3dba7828d25055a4c47b99b5a603ce5f1cd Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Mon, 26 Aug 2019 17:50:03 +0200 Subject: [PATCH 02/86] Added the new InteractionManager protocol and a first implementation of the InteractionAgent --- .../interaction_agent/InteractionAgent.scala | 46 +++++++++++++++++++ .../InteractionAgentProtocol.scala | 9 ++-- .../InteractionManagerProtocol.scala | 25 ++++++++++ 3 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgent.scala create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManagerProtocol.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgent.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgent.scala new file mode 100644 index 000000000..ccb54e561 --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgent.scala @@ -0,0 +1,46 @@ +package com.ing.baker.runtime.akka.actor.interaction_agent + +import akka.actor.{Actor, ActorRef, Props} +import akka.util.Timeout +import com.ing.baker.runtime.scaladsl.{EventInstance, InteractionInstance} + +import scala.concurrent.{ExecutionContext, Future} +import scala.util.{Failure, Success} + +object InteractionAgent { + + def apply(instance: InteractionInstance)(implicit timeout: Timeout): Props = + Props(new InteractionAgent(instance)) + + /** + * Closes over the agent and manager actor references, just like the pipe pattern does, except it sends a more expressive + * message in the case of failure. + * + * TODO: Handle invalid ingredients scenario + * + * @param agent actor reference + * @param manager actor reference + * @param result outcome of invoking the interaction instance + * @param ec execution context to use + */ + private[interaction_agent] def pipeExecutionResponse(agent: ActorRef, manager: ActorRef)(result: Future[Option[EventInstance]])(implicit ec: ExecutionContext): Unit = { + result.onComplete { + case Success(value) => + manager.tell(InteractionAgentProtocol.InstanceExecutedSuccessfully(value), agent) + case Failure(exception) => + manager.tell(InteractionAgentProtocol.InstanceExecutionFailed(), agent) + } + } +} + +class InteractionAgent(instance: InteractionInstance)(implicit timeout: Timeout) extends Actor { + + import context.dispatcher + + // TODO: Register to manager on creation + + def receive: Receive = { + case InteractionAgentProtocol.ExecuteInstance(input) => + InteractionAgent.pipeExecutionResponse(self, sender)(instance.run(input)) + } +} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentProtocol.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentProtocol.scala index 33872bce2..189d1ab22 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentProtocol.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentProtocol.scala @@ -4,15 +4,16 @@ import akka.remote.ContainerFormats.ActorRef import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance} -class InteractionAgentProtocol { - sealed trait ProcessIndexMessage extends BakerSerializable +object InteractionAgentProtocol { + + sealed trait InteractionAgentMessage extends BakerSerializable case class Register(interactionAgentDescriptor: InteractionAgentDescriptor, - agentRef: ActorRef) extends ProcessIndexMessage + agentRef: ActorRef) extends InteractionAgentMessage case class ExecuteInstance(input: Seq[IngredientInstance]) - sealed trait ExecuteInstanceResponse extends BakerSerializable + sealed trait ExecuteInstanceResponse extends InteractionAgentMessage /** * Instance executed successfully diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManagerProtocol.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManagerProtocol.scala new file mode 100644 index 000000000..e050cc3f8 --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManagerProtocol.scala @@ -0,0 +1,25 @@ +package com.ing.baker.runtime.akka.actor.interaction_manager + +import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable +import com.ing.baker.runtime.javadsl.EventInstance + +object InteractionManagerProtocol { + + sealed trait InteractionManagerMessage extends BakerSerializable + + case class ExecuteTransition() extends InteractionManagerMessage + + sealed trait ExecuteTransitionResponse extends InteractionManagerMessage + + case class ExecuteTransitionSuccessful(result: Option[EventInstance]) + + /** + * Technical failure of the interaction + */ + case class InstanceExecutionFailed() extends ExecuteTransitionResponse + + /** + * Invalid request, bad ingredients given + */ + case class InstanceExecutedInvalid() extends ExecuteTransitionResponse +} From 0a535293a974ded8038d73dfb7d240857171bf7e Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Wed, 11 Sep 2019 12:10:14 +0200 Subject: [PATCH 03/86] Algorithm work --- build.sbt | 2 + docs/specs/GuildsAndAdventurers.tla | 116 ++++++++++++++++++ project/Dependencies.scala | 2 + .../interaction_agent/InteractionAgent.scala | 12 +- .../InteractionManager.scala | 10 ++ .../InteractionQuestboard.scala | 20 +++ .../InteractionQuestboardProtocol.scala | 14 +++ 7 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 docs/specs/GuildsAndAdventurers.tla create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManager.scala create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboard.scala create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboardProtocol.scala diff --git a/build.sbt b/build.sbt index 968a647a0..d0fa53724 100644 --- a/build.sbt +++ b/build.sbt @@ -90,6 +90,8 @@ lazy val runtime = project.in(file("runtime")) akkaPersistence, akkaPersistenceQuery, akkaCluster, + akkaClusterTools, + akkaDistributedData, akkaClusterSharding, akkaBoostrap, akkaInmemoryJournal, diff --git a/docs/specs/GuildsAndAdventurers.tla b/docs/specs/GuildsAndAdventurers.tla new file mode 100644 index 000000000..871a61802 --- /dev/null +++ b/docs/specs/GuildsAndAdventurers.tla @@ -0,0 +1,116 @@ +---------------------- MODULE InteractionManagerAgent ---------------------- + +CONSTANTS GUILDS, ADVENTURERS + +VARIABLES guildsState, adventurersState + +---------------------------------------------------------------------------- + +TypeOk == TRUE + /\ guildsState \in [GUILDS -> UNION {{ <<"requesting", "">>, <<"completed", "">>, <<"committed", adv>>} : adv \in ADVENTURERS}] + /\ adventurersState \in [ADVENTURERS -> UNION {{<<"looking-for-quest", "">>, <<"considering", guild>>, <<"committed", guild>>} : guild \in GUILDS}] + +Init == + /\ guildsState = [guild \in GUILDS |-> <<"requesting", "">>] + /\ adventurersState = [adventurers \in ADVENTURERS |-> <<"looking-for-quest", "">>] + +AdventurerIsConsideringGuild(guild, adv) == + adventurersState[adv] = <<"considering", guild>> + +AdventurerIsCommittedWithGuild(guild, adv) == + adventurersState[adv] = <<"committed", guild>> + +GuildIsCommittedWithAdventurer(guild, adv) == + guildsState[guild] = <<"committed", adv>> + +AreCommitted(guild, adv) == + /\ GuildIsCommittedWithAdventurer(guild, adv) + /\ AdventurerIsCommittedWithGuild(guild, adv) + +MatchExistsBetween(guild, adv) == + /\ guildsState[guild] = <<"requesting", "">> + /\ adventurersState[adv] = <<"looking-for-quest", "">> + +AdventurerIsReadyOk(guild, adv) == + /\ guildsState[guild] = <<"requesting", "">> + /\ adventurersState[adv] = <<"considering", guild>> + +GuildIsReadyOk(guild, adv) == + /\ guildsState[guild] = <<"committed", adv>> + /\ adventurersState[adv] = <<"considering", guild>> + +QuestInProgress(guild, adv) == + AreCommitted(guild, adv) + +QuestWasAlreadyTakenByAdv1(guild, adv1, adv2) == + /\ adv1 # adv2 + /\ ( guildsState[guild] = <<"committed", adv1>> \/ guildsState[guild] = <<"completed", "">> ) + /\ adventurersState[adv2] = <<"considering", guild>> + +---------------------------------------------------------------------------- + +AdventurerConsidersAQuest == + /\ \E <> \in GUILDS \X ADVENTURERS : MatchExistsBetween(guild, adv) + /\ LET guildAdv == CHOOSE <> \in GUILDS \X ADVENTURERS : MatchExistsBetween(guild, adv) + guild == guildAdv[1] + adv == guildAdv[2] + IN /\ adventurersState' = [adventurersState EXCEPT ![adv] = <<"considering", guild>>] + /\ UNCHANGED guildsState + +GuildCommitsToAnAdventurer == + /\ \E <> \in GUILDS \X ADVENTURERS : AdventurerIsReadyOk(guild, adv) + /\ LET guildAdv == CHOOSE <> \in GUILDS \X ADVENTURERS : AdventurerIsReadyOk(guild, adv) + guild == guildAdv[1] + adv == guildAdv[2] + IN /\ guildsState' = [guildsState EXCEPT ![guild] = <<"committed", adv>>] + /\ UNCHANGED adventurersState + +AdventurerCommitsToAGuild == + /\ \E <> \in GUILDS \X ADVENTURERS : GuildIsReadyOk(guild, adv) + /\ LET guildAdv == CHOOSE <> \in GUILDS \X ADVENTURERS : GuildIsReadyOk(guild, adv) + guild == guildAdv[1] + adv == guildAdv[2] + IN /\ adventurersState' = [adventurersState EXCEPT ![adv] = <<"committed", guild>>] + /\ UNCHANGED guildsState + +AdventurerDropsTakenQuest == + /\ \E <> \in GUILDS \X ADVENTURERS \X ADVENTURERS: QuestWasAlreadyTakenByAdv1(guild, adv1, adv2) + /\ LET guildAdv == CHOOSE <> \in GUILDS \X ADVENTURERS \X ADVENTURERS : QuestWasAlreadyTakenByAdv1(guild, adv1, adv2) + guild == guildAdv[1] + adv == guildAdv[3] + IN /\ adventurersState' = [adventurersState EXCEPT ![adv] = <<"looking-for-quest", "">>] + /\ UNCHANGED guildsState + +AdventurerFinishesTheQuest == + /\ \E <> \in GUILDS \X ADVENTURERS : QuestInProgress(guild, adv) + /\ LET guildAdv == CHOOSE <> \in GUILDS \X ADVENTURERS : QuestInProgress(guild, adv) + guild == guildAdv[1] + adv == guildAdv[2] + IN /\ adventurersState' = [adventurersState EXCEPT ![adv] = <<"looking-for-quest", "">>] + /\ guildsState' = [guildsState EXCEPT ![guild] = <<"completed", "">>] + +Next == + \/ AdventurerConsidersAQuest + \/ GuildCommitsToAnAdventurer + \/ AdventurerCommitsToAGuild + \/ AdventurerFinishesTheQuest + \/ AdventurerDropsTakenQuest + +Spec == + Init /\ [][Next]_<> + +Consistent == + /\ \A <> \in GUILDS \X ADVENTURERS : + /\ GuildIsCommittedWithAdventurer(guild, adv) => ( AdventurerIsCommittedWithGuild(guild, adv) \/ AdventurerIsConsideringGuild(guild, adv) ) + /\ AdventurerIsCommittedWithGuild(guild, adv) => GuildIsCommittedWithAdventurer(guild, adv) + /\ \A <> \in ADVENTURERS \X ADVENTURERS \X GUILDS : + ~ AreCommitted(guild, adv1) \/ ~ AreCommitted(guild, adv2) \/ adv1 = adv2 + +---------------------------------------------------------------------------- + +THEOREM Spec => [](TypeOk /\ Consistent) + +============================================================================= +\* Modification History +\* Last modified Mon Sep 09 16:41:00 CEST 2019 by atfm0 +\* Created Thu Sep 05 16:24:49 CEST 2019 by atfm0 diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 080ec8787..ab3db1470 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -30,6 +30,8 @@ object Dependencies { val akkaPersistenceCassandra = "com.typesafe.akka" %% "akka-persistence-cassandra" % "0.54" val akkaCluster = "com.typesafe.akka" %% "akka-cluster" % akkaVersion val akkaClusterSharding = "com.typesafe.akka" %% "akka-cluster-sharding" % akkaVersion + val akkaDistributedData = "com.typesafe.akka" %% "akka-distributed-data" % akkaVersion + val akkaClusterTools = "com.typesafe.akka" %% "akka-cluster-tools" % akkaVersion val akkaSlf4j = "com.typesafe.akka" %% "akka-slf4j" % akkaVersion val akkaTestKit = "com.typesafe.akka" %% "akka-testkit" % akkaVersion val akkaStreamTestKit = "com.typesafe.akka" %% "akka-stream-testkit" % akkaVersion diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgent.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgent.scala index ccb54e561..5154bb1d2 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgent.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgent.scala @@ -1,6 +1,8 @@ package com.ing.baker.runtime.akka.actor.interaction_agent import akka.actor.{Actor, ActorRef, Props} +import akka.cluster.pubsub.DistributedPubSub +import akka.cluster.pubsub.DistributedPubSubMediator import akka.util.Timeout import com.ing.baker.runtime.scaladsl.{EventInstance, InteractionInstance} @@ -9,8 +11,8 @@ import scala.util.{Failure, Success} object InteractionAgent { - def apply(instance: InteractionInstance)(implicit timeout: Timeout): Props = - Props(new InteractionAgent(instance)) + def apply(recipeName: String, instance: InteractionInstance)(implicit timeout: Timeout): Props = + Props(new InteractionAgent(recipeName, instance)) /** * Closes over the agent and manager actor references, just like the pipe pattern does, except it sends a more expressive @@ -33,10 +35,14 @@ object InteractionAgent { } } -class InteractionAgent(instance: InteractionInstance)(implicit timeout: Timeout) extends Actor { +class InteractionAgent(recipeName: String, instance: InteractionInstance)(implicit timeout: Timeout) extends Actor { import context.dispatcher + val mediator = DistributedPubSub(context.system).mediator + + mediator ! DistributedPubSubMediator.Subscribe(s"Compute|:|$recipeName|:|$instance|:|v0", self) + // TODO: Register to manager on creation def receive: Receive = { diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManager.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManager.scala new file mode 100644 index 000000000..67b7386af --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManager.scala @@ -0,0 +1,10 @@ +package com.ing.baker.runtime.akka.actor.interaction_manager + +import akka.actor.Actor +import akka.cluster.pubsub.DistributedPubSub +import akka.cluster.pubsub.DistributedPubSubMediator.Subscribe + +class InteractionManager extends Actor { + + def receive: Receive = ??? +} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboard.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboard.scala new file mode 100644 index 000000000..c8b543daa --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboard.scala @@ -0,0 +1,20 @@ +package com.ing.baker.runtime.akka.actor.interaction_questboard + +import akka.actor.Actor +import akka.cluster.ddata.DistributedData + +class InteractionQuestboard extends Actor { + + val replicator = DistributedData(context.system).replicator + + def receive: Receive = { + case InteractionQuestboardProtocol.PostQuest(namespace, guild) => + ??? + + case InteractionQuestboardProtocol.GetQuest(namespace) => + ??? + + case InteractionQuestboardProtocol.RemoveQuest(namespace, guild) => + ??? + } +} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboardProtocol.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboardProtocol.scala new file mode 100644 index 000000000..18f51264e --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboardProtocol.scala @@ -0,0 +1,14 @@ +package com.ing.baker.runtime.akka.actor.interaction_questboard + +import akka.actor.ActorRef + +object InteractionQuestboardProtocol { + + case class GetQuest(namespace: String) + + case class GetQuestResponse(guild: ActorRef) + + case class PostQuest(namespace: String, guild: ActorRef) + + case class RemoveQuest(namespace: String, guild: ActorRef) +} From 04c2cc8af5dbf724b168b2507f0ab21acbba2c23 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Tue, 17 Sep 2019 11:41:07 +0200 Subject: [PATCH 04/86] InteractionAgent concept finished --- .../interaction_agent/InteractionAgent.scala | 52 ---------- .../InteractionAgentDescriptor.scala | 8 -- .../InteractionAgentProtocol.scala | 33 ------- .../InteractionManager.scala | 10 -- .../InteractionManagerProtocol.scala | 25 ----- .../InteractionQuestboard.scala | 20 ---- .../InteractionQuestboardProtocol.scala | 14 --- .../InteractionAgent.scala | 95 +++++++++++++++++++ .../ProtocolInteractionExecution.scala | 36 +++++++ .../ProtocolPushPullMatching.scala | 24 +++++ .../ProtocolQuestCommit.scala | 18 ++++ .../QuestMandated.scala | 53 +++++++++++ .../InstanceSchedulingSpec.scala | 91 ++++++++++++++++++ 13 files changed, 317 insertions(+), 162 deletions(-) delete mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgent.scala delete mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentDescriptor.scala delete mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentProtocol.scala delete mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManager.scala delete mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManagerProtocol.scala delete mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboard.scala delete mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboardProtocol.scala create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolQuestCommit.scala create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala create mode 100644 runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InstanceSchedulingSpec.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgent.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgent.scala deleted file mode 100644 index 5154bb1d2..000000000 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgent.scala +++ /dev/null @@ -1,52 +0,0 @@ -package com.ing.baker.runtime.akka.actor.interaction_agent - -import akka.actor.{Actor, ActorRef, Props} -import akka.cluster.pubsub.DistributedPubSub -import akka.cluster.pubsub.DistributedPubSubMediator -import akka.util.Timeout -import com.ing.baker.runtime.scaladsl.{EventInstance, InteractionInstance} - -import scala.concurrent.{ExecutionContext, Future} -import scala.util.{Failure, Success} - -object InteractionAgent { - - def apply(recipeName: String, instance: InteractionInstance)(implicit timeout: Timeout): Props = - Props(new InteractionAgent(recipeName, instance)) - - /** - * Closes over the agent and manager actor references, just like the pipe pattern does, except it sends a more expressive - * message in the case of failure. - * - * TODO: Handle invalid ingredients scenario - * - * @param agent actor reference - * @param manager actor reference - * @param result outcome of invoking the interaction instance - * @param ec execution context to use - */ - private[interaction_agent] def pipeExecutionResponse(agent: ActorRef, manager: ActorRef)(result: Future[Option[EventInstance]])(implicit ec: ExecutionContext): Unit = { - result.onComplete { - case Success(value) => - manager.tell(InteractionAgentProtocol.InstanceExecutedSuccessfully(value), agent) - case Failure(exception) => - manager.tell(InteractionAgentProtocol.InstanceExecutionFailed(), agent) - } - } -} - -class InteractionAgent(recipeName: String, instance: InteractionInstance)(implicit timeout: Timeout) extends Actor { - - import context.dispatcher - - val mediator = DistributedPubSub(context.system).mediator - - mediator ! DistributedPubSubMediator.Subscribe(s"Compute|:|$recipeName|:|$instance|:|v0", self) - - // TODO: Register to manager on creation - - def receive: Receive = { - case InteractionAgentProtocol.ExecuteInstance(input) => - InteractionAgent.pipeExecutionResponse(self, sender)(instance.run(input)) - } -} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentDescriptor.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentDescriptor.scala deleted file mode 100644 index f3c8cdc78..000000000 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentDescriptor.scala +++ /dev/null @@ -1,8 +0,0 @@ -package com.ing.baker.runtime.akka.actor.interaction_agent - -import com.ing.baker.types.Type - -case class InteractionAgentDescriptor( - name: String, - input: Seq[Type], - output: Option[Map[String, Map[String, Type]]]) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentProtocol.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentProtocol.scala deleted file mode 100644 index 189d1ab22..000000000 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_agent/InteractionAgentProtocol.scala +++ /dev/null @@ -1,33 +0,0 @@ -package com.ing.baker.runtime.akka.actor.interaction_agent - -import akka.remote.ContainerFormats.ActorRef -import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable -import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance} - -object InteractionAgentProtocol { - - sealed trait InteractionAgentMessage extends BakerSerializable - - case class Register(interactionAgentDescriptor: InteractionAgentDescriptor, - agentRef: ActorRef) extends InteractionAgentMessage - - case class ExecuteInstance(input: Seq[IngredientInstance]) - - sealed trait ExecuteInstanceResponse extends InteractionAgentMessage - - /** - * Instance executed successfully - * @param result the EventInstance that is created, empty if interaction does not return an Event - */ - case class InstanceExecutedSuccessfully(result: Option[EventInstance]) extends ExecuteInstanceResponse - - /** - * Technical failure of the interaction - */ - case class InstanceExecutionFailed() extends ExecuteInstanceResponse - - /** - * Invalid request, bad ingredients given - */ - case class InstanceExecutedInvalid() extends ExecuteInstanceResponse -} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManager.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManager.scala deleted file mode 100644 index 67b7386af..000000000 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManager.scala +++ /dev/null @@ -1,10 +0,0 @@ -package com.ing.baker.runtime.akka.actor.interaction_manager - -import akka.actor.Actor -import akka.cluster.pubsub.DistributedPubSub -import akka.cluster.pubsub.DistributedPubSubMediator.Subscribe - -class InteractionManager extends Actor { - - def receive: Receive = ??? -} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManagerProtocol.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManagerProtocol.scala deleted file mode 100644 index e050cc3f8..000000000 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_manager/InteractionManagerProtocol.scala +++ /dev/null @@ -1,25 +0,0 @@ -package com.ing.baker.runtime.akka.actor.interaction_manager - -import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable -import com.ing.baker.runtime.javadsl.EventInstance - -object InteractionManagerProtocol { - - sealed trait InteractionManagerMessage extends BakerSerializable - - case class ExecuteTransition() extends InteractionManagerMessage - - sealed trait ExecuteTransitionResponse extends InteractionManagerMessage - - case class ExecuteTransitionSuccessful(result: Option[EventInstance]) - - /** - * Technical failure of the interaction - */ - case class InstanceExecutionFailed() extends ExecuteTransitionResponse - - /** - * Invalid request, bad ingredients given - */ - case class InstanceExecutedInvalid() extends ExecuteTransitionResponse -} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboard.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboard.scala deleted file mode 100644 index c8b543daa..000000000 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboard.scala +++ /dev/null @@ -1,20 +0,0 @@ -package com.ing.baker.runtime.akka.actor.interaction_questboard - -import akka.actor.Actor -import akka.cluster.ddata.DistributedData - -class InteractionQuestboard extends Actor { - - val replicator = DistributedData(context.system).replicator - - def receive: Receive = { - case InteractionQuestboardProtocol.PostQuest(namespace, guild) => - ??? - - case InteractionQuestboardProtocol.GetQuest(namespace) => - ??? - - case InteractionQuestboardProtocol.RemoveQuest(namespace, guild) => - ??? - } -} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboardProtocol.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboardProtocol.scala deleted file mode 100644 index 18f51264e..000000000 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_questboard/InteractionQuestboardProtocol.scala +++ /dev/null @@ -1,14 +0,0 @@ -package com.ing.baker.runtime.akka.actor.interaction_questboard - -import akka.actor.ActorRef - -object InteractionQuestboardProtocol { - - case class GetQuest(namespace: String) - - case class GetQuestResponse(guild: ActorRef) - - case class PostQuest(namespace: String, guild: ActorRef) - - case class RemoveQuest(namespace: String, guild: ActorRef) -} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala new file mode 100644 index 000000000..70fffde26 --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala @@ -0,0 +1,95 @@ +package com.ing.baker.runtime.akka.actor.interaction_schedulling + +import akka.actor.{Actor, ActorRef, Props} +import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} +import com.ing.baker.runtime.scaladsl.{EventInstance, InteractionInstance} + +import scala.concurrent.{ExecutionContext, Future} +import scala.util.{Failure, Success} + +object InteractionAgent { + + def apply(recipeName: String, instance: InteractionInstance, version: String = "v0"): Props = + Props(new InteractionAgent(recipeName, instance, version)) + + /** + * Closes over the agent actor references, just like the pipe pattern does, except it sends a more expressive + * message in the case of failure. + * + * TODO: Handle invalid ingredients scenario + * + * @param agent actor reference + * @param result outcome of invoking the interaction instance + * @param ec execution context to use + */ + private[interaction_schedulling] def pipeBackExecutionResponse(agent: ActorRef)(result: Future[Option[EventInstance]])(implicit ec: ExecutionContext): Unit = { + result.onComplete { + case Success(value) => + agent.tell(ProtocolInteractionExecution.InstanceExecutedSuccessfully(value), agent) + case Failure(exception) => + agent.tell(ProtocolInteractionExecution.InstanceExecutionFailed(), agent) + } + } +} + +class InteractionAgent(recipeName: String, interaction: InteractionInstance, version: String) extends Actor { + + import context.dispatcher + + val mediator: ActorRef = DistributedPubSub(context.system).mediator + + val pullTopic: String = + ProtocolPushPullMatching.pullTopic(recipeName, interaction.name, version) + + val pushTopic: String = + ProtocolPushPullMatching.pushTopic(recipeName, interaction.name, version) + + def pull(): Unit = + mediator ! DistributedPubSubMediator.Publish(pullTopic, ProtocolPushPullMatching.Pull(self)) + + def subscribePush(): Unit = + mediator ! DistributedPubSubMediator.Subscribe(pushTopic, self) + + def unsubscribePush(): Unit = + mediator ! DistributedPubSubMediator.Unsubscribe(pushTopic, self) + + subscribePush() + pull() + + def receive: Receive = { + case ProtocolPushPullMatching.Push(mandated) => + // start Quest commit protocol + mandated ! ProtocolQuestCommit.Considering(self) + unsubscribePush() + context.become(considering) + + case ProtocolPushPullMatching.AvailableQuest(mandated) => + // start Quest commit protocol + mandated ! ProtocolQuestCommit.Considering(self) + unsubscribePush() + context.become(considering) + } + + def considering: Receive = { + case ProtocolQuestCommit.Commit(mandated, executeMessage) => + // start the execution protocol by already starting the computation and become committed + InteractionAgent.pipeBackExecutionResponse(self)(interaction.run(executeMessage.input)) + context.become(committed(mandated)) + + case ProtocolQuestCommit.QuestTaken => + // quest taken, start all over again + subscribePush() + pull() + context.become(receive) + } + + def committed(mandated: ActorRef): Receive = { + case message: ProtocolInteractionExecution => + // Forward the result + mandated ! message + // Start all over again + subscribePush() + pull() + context.become(receive) + } +} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala new file mode 100644 index 000000000..953c3fbb9 --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala @@ -0,0 +1,36 @@ +package com.ing.baker.runtime.akka.actor.interaction_schedulling + +import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable +import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance} + +/** + * Protocol executed after a match between a QuestMandate and InteractionAgent has been made and after both + * have committed. + * + * A simple request from the manager to the agent for execution with specific ingredients is done using the + * ExecuteInstance message, the outcome comes in the form of either the response messages InstanceExecutedSuccessfully, + * InstanceExecutionFailed or InvalidExecution + * + */ +sealed trait ProtocolInteractionExecution extends BakerSerializable + +object ProtocolInteractionExecution { + + case class ExecuteInstance(input: Seq[IngredientInstance]) extends ProtocolInteractionExecution + + /** + * Instance executed successfully + * @param result the EventInstance that is created, empty if interaction does not return an Event + */ + case class InstanceExecutedSuccessfully(result: Option[EventInstance]) extends ProtocolInteractionExecution + + /** + * Technical failure of the interaction + */ + case class InstanceExecutionFailed() extends ProtocolInteractionExecution + + /** + * Invalid request, bad ingredients given + */ + case class InvalidExecution() extends ProtocolInteractionExecution +} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala new file mode 100644 index 000000000..89fa0a2ed --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala @@ -0,0 +1,24 @@ +package com.ing.baker.runtime.akka.actor.interaction_schedulling + +import akka.actor.ActorRef + +/** + * Protocol done to find a possible matching between a QuestMandated and an available InteractionAgent + */ +sealed trait ProtocolPushPullMatching + +object ProtocolPushPullMatching { + + def pushTopic(recipeName: String, interactionName: String, version: String): String = + s"Push|:|$recipeName|:|$interactionName|:|$version" + + def pullTopic(recipeName: String, interactionName: String, version: String): String = + s"Pull|:|$recipeName|:|$interactionName|:|$version" + + case class Push(mandated: ActorRef) extends ProtocolPushPullMatching + + case class Pull(agent: ActorRef) extends ProtocolPushPullMatching + + case class AvailableQuest(mandated: ActorRef) extends ProtocolPushPullMatching + +} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolQuestCommit.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolQuestCommit.scala new file mode 100644 index 000000000..28af28a0e --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolQuestCommit.scala @@ -0,0 +1,18 @@ +package com.ing.baker.runtime.akka.actor.interaction_schedulling + +import akka.actor.ActorRef + +/** + * A Protocol executed after finding a candidate match between a QuestMandated and an InteractionAgent, it makes sure + * that 1 QuestMandated commits with 1 InteractionAgent only and vice versa, without leaving orphan agents. + */ +sealed trait ProtocolQuestCommit + +object ProtocolQuestCommit { + + case class Considering(agent: ActorRef) extends ProtocolQuestCommit + + case class Commit(mandated: ActorRef, execute: ProtocolInteractionExecution.ExecuteInstance) extends ProtocolQuestCommit + + case object QuestTaken extends ProtocolQuestCommit +} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala new file mode 100644 index 000000000..6c3577a88 --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala @@ -0,0 +1,53 @@ +package com.ing.baker.runtime.akka.actor.interaction_schedulling + +import akka.actor.{Actor, ActorRef, PoisonPill, Props} +import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} +import com.ing.baker.runtime.scaladsl.IngredientInstance + +object QuestMandated { + + def apply(manager: ActorRef, ingredients: Seq[IngredientInstance], recipeName: String, interactionName: String, version: String = "v0"): Props = + Props(new QuestMandated(manager, ingredients, recipeName, interactionName, version)) +} + +class QuestMandated(manager: ActorRef, ingredients: Seq[IngredientInstance], recipeName: String, interactionName: String, version: String) extends Actor { + + val mediator: ActorRef = DistributedPubSub(context.system).mediator + + val pullTopic: String = + ProtocolPushPullMatching.pullTopic(recipeName, interactionName, version) + + val pushTopic: String = + ProtocolPushPullMatching.pushTopic(recipeName, interactionName, version) + + def push(): Unit = + mediator ! DistributedPubSubMediator.Publish(pushTopic, ProtocolPushPullMatching.Push(self)) + + def start(): Unit = + mediator ! DistributedPubSubMediator.Subscribe(pullTopic, self); push() + + start() + + def receive: Receive = { + case ProtocolPushPullMatching.Pull(agent) => + // respond with available quest + agent ! ProtocolPushPullMatching.AvailableQuest(self) + + case ProtocolQuestCommit.Considering(agent) => + // start the interaction execution protocol by responding with a commit message + agent ! ProtocolQuestCommit.Commit(self, ProtocolInteractionExecution.ExecuteInstance(ingredients)) + context.become(committed) + } + + def committed: Receive = { + + case message: ProtocolInteractionExecution => + // report and kill himself + manager ! message + self ! PoisonPill + + case ProtocolQuestCommit.Considering(agent) => + agent ! ProtocolQuestCommit.QuestTaken + } + +} diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InstanceSchedulingSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InstanceSchedulingSpec.scala new file mode 100644 index 000000000..7106a57e5 --- /dev/null +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InstanceSchedulingSpec.scala @@ -0,0 +1,91 @@ +package com.ing.baker.runtime.akka.actor.interaction_schedulling + +import akka.actor.{ActorRef, ActorSystem} +import akka.testkit.{ImplicitSender, TestKit} +import com.ing.baker.runtime.akka.actor.interaction_schedulling.ProtocolInteractionExecution.InstanceExecutedSuccessfully +import com.ing.baker.runtime.scaladsl.IngredientInstance +import com.ing.baker.runtime.scaladsl.EventInstance +import com.ing.baker.runtime.scaladsl.InteractionInstance +import com.ing.baker.types.{CharArray, PrimitiveValue} +import com.typesafe.config.{Config, ConfigFactory} +import org.scalatest.{BeforeAndAfter, BeforeAndAfterAll, Matchers, WordSpecLike} +import org.scalatest.concurrent.Eventually +import org.scalatest.mockito.MockitoSugar + +import scala.concurrent.Future + +object InstanceSchedulingSpec { + + val config: Config = ConfigFactory.parseString( + """ + |akka { + | actor { + | provider = "cluster" + | } + | remote { + | log-remote-lifecycle-events = off + | netty.tcp { + | hostname = "127.0.0.1" + | port = 2551 + | } + | } + | + | cluster { + | seed-nodes = ["akka.tcp://InstanceSchedulingSpec@127.0.0.1:2551"] + | auto-down-unreachable-after = 10s + | } + |} + """.stripMargin) +} + +class InstanceSchedulingSpec extends TestKit(ActorSystem("InstanceSchedulingSpec", config = InstanceSchedulingSpec.config)) + with ImplicitSender + with WordSpecLike + with Matchers + with BeforeAndAfterAll + with BeforeAndAfter + with MockitoSugar + with Eventually { + + import system.dispatcher + + val recipeName: String = "TestRecipe" + + val interaction: InteractionInstance = + InteractionInstance( + "TestInstance", + Seq(CharArray), + ingredients => Future (Some { + val computed = PrimitiveValue(ingredients.head.value.as[String].toUpperCase()) + EventInstance("TestDone", Map("upper" -> computed)) + }) + ) + + val jobs: List[String] = + List.fill(10000)("hello") + + def buildAgents(): List[ActorRef] = + List( + system.actorOf(InteractionAgent(recipeName, interaction)), + system.actorOf(InteractionAgent(recipeName, interaction)) + ) + + def buildMandated(job: String, manager: ActorRef): ActorRef = + system.actorOf(QuestMandated(manager, Seq(IngredientInstance("test-ingredient", PrimitiveValue(job))), recipeName, interaction.name)) + + "The Instance scheduling protocol" should { + "simple run success" in { + buildAgents() + jobs.foreach(buildMandated(_, self)) + buildAgents() + receiveN(jobs.length).foreach { job => + job.asInstanceOf[InstanceExecutedSuccessfully] match { + case InstanceExecutedSuccessfully(Some(EventInstance("TestDone", map))) => + map("upper").as[String] shouldBe "HELLO" + case other => + fail(other + " is not a successful execution result") + } + } + } + } +} From ccae2cd14131bbf6ad5930af336e7d93131a0c52 Mon Sep 17 00:00:00 2001 From: Tim Linschoten Date: Tue, 17 Sep 2019 17:16:06 +0200 Subject: [PATCH 05/86] Connected the new quest mechanism to Baker and allow for remote interactions. Now has a very very very very naive binding between Instance and descriptor of interactions. --- .../ing/baker/runtime/akka/AkkaBaker.scala | 2 +- .../baker/runtime/akka/AkkaBakerConfig.scala | 16 +++-- .../InteractionAgent.scala | 10 +-- .../ProtocolInteractionExecution.scala | 10 +++ .../ProtocolPushPullMatching.scala | 8 +-- .../QuestMandated.scala | 45 ++++++++++--- .../akka/internal/InteractionManager.scala | 63 ++++++++++++++++++- .../runtime/akka/internal/RecipeRuntime.scala | 6 +- runtime/src/test/resources/application.conf | 2 + .../runtime/akka/BakerExecutionSpec.scala | 57 ++++++++++++++++- .../InstanceSchedulingSpec.scala | 37 ++++++----- .../process_index/ProcessIndexSpec.scala | 28 +++++---- .../internal/InteractionManagerSpec.scala | 18 +++--- 13 files changed, 228 insertions(+), 74 deletions(-) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala index 49793eb4d..2f1b36c85 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala @@ -60,7 +60,7 @@ class AkkaBaker private[runtime](config: AkkaBakerConfig) extends Baker { } private def getImplementationErrors(compiledRecipe: CompiledRecipe): Set[String] = { - compiledRecipe.interactionTransitions.filterNot(config.interactionManager.getImplementation(_).isDefined) + compiledRecipe.interactionTransitions.filterNot(config.interactionManager.hasImplementation) .map(s => s"No implementation provided for interaction: ${s.originalInteractionName}") } diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala index b904bddaa..3f9654de6 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala @@ -1,15 +1,16 @@ package com.ing.baker.runtime.akka -import akka.actor.{ ActorSystem, Address, AddressFromURIString } +import akka.actor.{ActorSystem, Address, AddressFromURIString} import akka.persistence.query.PersistenceQuery -import akka.persistence.query.scaladsl.{ CurrentEventsByPersistenceIdQuery, CurrentPersistenceIdsQuery, PersistenceIdsQuery } +import akka.persistence.query.scaladsl.{CurrentEventsByPersistenceIdQuery, CurrentPersistenceIdsQuery, PersistenceIdsQuery} import cats.data.NonEmptyList import com.ing.baker.runtime.akka.AkkaBakerConfig.BakerPersistenceQuery import com.ing.baker.runtime.akka.actor.serialization.Encryption -import com.ing.baker.runtime.akka.actor.{ BakerActorProvider, ClusterBakerActorProvider, LocalBakerActorProvider } -import com.ing.baker.runtime.akka.internal.InteractionManager +import com.ing.baker.runtime.akka.actor.{BakerActorProvider, ClusterBakerActorProvider, LocalBakerActorProvider} +import com.ing.baker.runtime.akka.internal.{InteractionManager, InteractionManagerDis, InteractionManagerLocal} import com.typesafe.config.Config import net.ceedubs.ficus.Ficus._ + import scala.concurrent.duration._ case class AkkaBakerConfig( @@ -58,7 +59,7 @@ object AkkaBakerConfig { defaultShutdownTimeout = 30.seconds, defaultAddRecipeTimeout = 10.seconds, bakerActorProvider = provider, - interactionManager = new InteractionManager(), + interactionManager = new InteractionManagerLocal(), readJournal = PersistenceQuery(actorSystem) .readJournalFor[BakerPersistenceQuery]("inmemory-read-journal") )(actorSystem) @@ -106,7 +107,10 @@ object AkkaBakerConfig { case Some(other) => throw new IllegalArgumentException(s"Unsupported actor provider: $other") } }, - interactionManager = new InteractionManager, + interactionManager = config.as[Option[String]]("baker.interaction-manager") match { + case Some("remote") => new InteractionManagerDis(actorSystem, 10 seconds, 600 seconds) //TODO read timeout from config //TODO 2 remore computation timeout + case _ => new InteractionManagerLocal() + }, readJournal = PersistenceQuery(actorSystem) .readJournalFor[BakerPersistenceQuery](config.as[String]("baker.actor.read-journal-plugin")) )(actorSystem) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala index 70fffde26..0c66ec6cb 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala @@ -9,8 +9,8 @@ import scala.util.{Failure, Success} object InteractionAgent { - def apply(recipeName: String, instance: InteractionInstance, version: String = "v0"): Props = - Props(new InteractionAgent(recipeName, instance, version)) + def apply(instance: InteractionInstance): Props = + Props(new InteractionAgent(instance)) /** * Closes over the agent actor references, just like the pipe pattern does, except it sends a more expressive @@ -32,17 +32,17 @@ object InteractionAgent { } } -class InteractionAgent(recipeName: String, interaction: InteractionInstance, version: String) extends Actor { +class InteractionAgent(interaction: InteractionInstance) extends Actor { import context.dispatcher val mediator: ActorRef = DistributedPubSub(context.system).mediator val pullTopic: String = - ProtocolPushPullMatching.pullTopic(recipeName, interaction.name, version) + ProtocolPushPullMatching.pullTopic(interaction.name) val pushTopic: String = - ProtocolPushPullMatching.pushTopic(recipeName, interaction.name, version) + ProtocolPushPullMatching.pushTopic(interaction.name) def pull(): Unit = mediator ! DistributedPubSubMediator.Publish(pullTopic, ProtocolPushPullMatching.Pull(self)) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala index 953c3fbb9..1508c876d 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala @@ -29,6 +29,16 @@ object ProtocolInteractionExecution { */ case class InstanceExecutionFailed() extends ProtocolInteractionExecution + /** + * Technical failure of the interaction + */ + case class InstanceExecutionTimedOut() extends ProtocolInteractionExecution + + /** + * Technical failure of the interaction + */ + case class NoInstanceFound() extends ProtocolInteractionExecution + /** * Invalid request, bad ingredients given */ diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala index 89fa0a2ed..bd60142b7 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala @@ -9,11 +9,11 @@ sealed trait ProtocolPushPullMatching object ProtocolPushPullMatching { - def pushTopic(recipeName: String, interactionName: String, version: String): String = - s"Push|:|$recipeName|:|$interactionName|:|$version" + def pushTopic(interactionName: String): String = + s"Push|:||:|$interactionName|:|" - def pullTopic(recipeName: String, interactionName: String, version: String): String = - s"Pull|:|$recipeName|:|$interactionName|:|$version" + def pullTopic(interactionName: String): String = + s"Pull|:||:|$interactionName|:|" case class Push(mandated: ActorRef) extends ProtocolPushPullMatching diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala index 6c3577a88..0704e25a8 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala @@ -2,33 +2,49 @@ package com.ing.baker.runtime.akka.actor.interaction_schedulling import akka.actor.{Actor, ActorRef, PoisonPill, Props} import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} +import akka.util.Timeout +import com.ing.baker.runtime.akka.actor.interaction_schedulling.QuestMandated.{ComputationTimeout, PostTimeout, Start} import com.ing.baker.runtime.scaladsl.IngredientInstance object QuestMandated { - def apply(manager: ActorRef, ingredients: Seq[IngredientInstance], recipeName: String, interactionName: String, version: String = "v0"): Props = - Props(new QuestMandated(manager, ingredients, recipeName, interactionName, version)) + case object Start + + case object PostTimeout + + case object ComputationTimeout + + def apply(ingredients: Seq[IngredientInstance], interactionName: String, postTimeout: Timeout, computationTimeout: Timeout): Props = + Props(new QuestMandated(ingredients, interactionName, postTimeout, computationTimeout)) } -class QuestMandated(manager: ActorRef, ingredients: Seq[IngredientInstance], recipeName: String, interactionName: String, version: String) extends Actor { +class QuestMandated(ingredients: Seq[IngredientInstance], interactionName: String, postTimeout: Timeout, computationTimeout: Timeout) extends Actor { val mediator: ActorRef = DistributedPubSub(context.system).mediator val pullTopic: String = - ProtocolPushPullMatching.pullTopic(recipeName, interactionName, version) + ProtocolPushPullMatching.pullTopic(interactionName) val pushTopic: String = - ProtocolPushPullMatching.pushTopic(recipeName, interactionName, version) + ProtocolPushPullMatching.pushTopic(interactionName) def push(): Unit = mediator ! DistributedPubSubMediator.Publish(pushTopic, ProtocolPushPullMatching.Push(self)) - def start(): Unit = - mediator ! DistributedPubSubMediator.Subscribe(pullTopic, self); push() + def start(): Unit = { + mediator ! DistributedPubSubMediator.Subscribe(pullTopic, self) + push() + context.system.scheduler.scheduleOnce(postTimeout.duration, self, PostTimeout)(context.dispatcher, self) + } - start() def receive: Receive = { + case Start => + start() + context.become(running(sender)) + } + + def running(manager: ActorRef): Receive = { case ProtocolPushPullMatching.Pull(agent) => // respond with available quest agent ! ProtocolPushPullMatching.AvailableQuest(self) @@ -36,10 +52,15 @@ class QuestMandated(manager: ActorRef, ingredients: Seq[IngredientInstance], rec case ProtocolQuestCommit.Considering(agent) => // start the interaction execution protocol by responding with a commit message agent ! ProtocolQuestCommit.Commit(self, ProtocolInteractionExecution.ExecuteInstance(ingredients)) - context.become(committed) + context.system.scheduler.scheduleOnce(computationTimeout.duration, self, ComputationTimeout)(context.dispatcher, self) + context.become(committed(manager)) + + case PostTimeout => + manager ! ProtocolInteractionExecution.NoInstanceFound + self ! PoisonPill } - def committed: Receive = { + def committed(manager: ActorRef): Receive = { case message: ProtocolInteractionExecution => // report and kill himself @@ -48,6 +69,10 @@ class QuestMandated(manager: ActorRef, ingredients: Seq[IngredientInstance], rec case ProtocolQuestCommit.Considering(agent) => agent ! ProtocolQuestCommit.QuestTaken + + case ComputationTimeout => + manager ! ProtocolInteractionExecution.InstanceExecutionTimedOut + self ! PoisonPill } } diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala index 19a0c9a82..72f633a28 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala @@ -2,10 +2,57 @@ package com.ing.baker.runtime.akka.internal import java.util.concurrent.ConcurrentHashMap +import akka.actor.ActorSystem +import akka.pattern.ask +import akka.util.Timeout import com.ing.baker.il.petrinet.InteractionTransition -import com.ing.baker.runtime.scaladsl.InteractionInstance +import com.ing.baker.runtime.akka.actor.interaction_schedulling.QuestMandated.Start +import com.ing.baker.runtime.akka.actor.interaction_schedulling.{InteractionAgent, ProtocolInteractionExecution, QuestMandated} +import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance, InteractionInstance} import scala.compat.java8.FunctionConverters._ +import scala.concurrent.Future + + + +trait InteractionManager { + def hasImplementation(interaction: InteractionTransition): Boolean + + def executeImplementation(interaction: InteractionTransition, input: Seq[IngredientInstance]): Future[Option[EventInstance]] + + /** + * Add an implementation to the InteractionManager + * + * @param implementation + */ + def addImplementation(implementation: InteractionInstance): Unit + +} + +class InteractionManagerDis(system: ActorSystem, postTimeout: Timeout, computationTimeout: Timeout) extends InteractionManager { + + import system.dispatcher + + override def executeImplementation(interaction: InteractionTransition, input: Seq[IngredientInstance]): Future[Option[EventInstance]] = { + val a = system.actorOf(QuestMandated(input, interaction.interactionName, postTimeout, computationTimeout)) + a.ask(Start)(Timeout.durationToTimeout(postTimeout.duration + computationTimeout.duration)).flatMap { + case ProtocolInteractionExecution.InstanceExecutedSuccessfully(result) => Future.successful(result) + //What if there is no implementation available???? + case ProtocolInteractionExecution.InstanceExecutionFailed() => Future.failed(new RuntimeException("Remote execution of interaction failed")) + } + } + + /** + * Add an implementation to the InteractionManager + * + * @param implementation + */ + override def addImplementation(implementation: InteractionInstance): Unit = { + system.actorOf(InteractionAgent(implementation)) + } + + override def hasImplementation(interaction: InteractionTransition): Boolean = true +} /** * The InteractionManager is responsible for all implementation of interactions. @@ -13,7 +60,7 @@ import scala.compat.java8.FunctionConverters._ * * @param interactionImplementations All */ -class InteractionManager(private var interactionImplementations: Seq[InteractionInstance] = Seq.empty) { +class InteractionManagerLocal(private var interactionImplementations: Seq[InteractionInstance] = Seq.empty) extends InteractionManager { private val implementationCache: ConcurrentHashMap[InteractionTransition, InteractionInstance] = new ConcurrentHashMap[InteractionTransition, InteractionInstance] @@ -53,6 +100,16 @@ class InteractionManager(private var interactionImplementations: Seq[Interaction * @param interaction The interaction to check * @return An option containing the implementation if available */ - def getImplementation(interaction: InteractionTransition): Option[InteractionInstance] = + private[internal] def getImplementation(interaction: InteractionTransition): Option[InteractionInstance] = Option(implementationCache.computeIfAbsent(interaction, (findInteractionImplementation _).asJava)) + + def hasImplementation(interaction: InteractionTransition): Boolean = + getImplementation(interaction).isDefined + + override def executeImplementation(interaction: InteractionTransition, input: Seq[IngredientInstance]): Future[Option[EventInstance]] = { + this.getImplementation(interaction) match { + case Some(implementation) => implementation.run(input) + case None => Future.failed(new FatalInteractionException("No implementation available for interaction")) + } + } } diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/RecipeRuntime.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/RecipeRuntime.scala index 81b5b1e9d..ff4b38781 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/RecipeRuntime.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/RecipeRuntime.scala @@ -193,10 +193,6 @@ class RecipeRuntime(recipe: CompiledRecipe, interactionManager: InteractionManag try { - // obtain the interaction implementation - val implementation = interactionManager.getImplementation(interaction).getOrElse { - throw new FatalInteractionException("No implementation available for interaction") - } // create the interaction input val input = createInteractionInput(interaction, processState) @@ -207,7 +203,7 @@ class RecipeRuntime(recipe: CompiledRecipe, interactionManager: InteractionManag eventStream.publish(InteractionStarted(timeStarted, recipe.name, recipe.recipeId, processState.recipeInstanceId, interaction.interactionName)) // executes the interaction and obtain the (optional) output event - implementation.execute(input).map { interactionOutput => + interactionManager.executeImplementation(interaction, input).map { interactionOutput => // validates the event, throws a FatalInteraction exception if invalid RecipeRuntime.validateInteractionOutput(interaction, interactionOutput).foreach { validationError => diff --git a/runtime/src/test/resources/application.conf b/runtime/src/test/resources/application.conf index e2f6863b6..57233a150 100644 --- a/runtime/src/test/resources/application.conf +++ b/runtime/src/test/resources/application.conf @@ -27,6 +27,8 @@ akka { logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" } +baker.interaction-manager = local + inmemory-read-journal { write-plugin = "inmemory-journal" offset-mode = "sequence" diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala index d2b2a99d7..0f42f5624 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala @@ -23,6 +23,12 @@ import org.mockito.Matchers.{eq => mockitoEq, _} import org.mockito.Mockito._ import org.mockito.invocation.InvocationOnMock import org.slf4j.{Logger, LoggerFactory} +import com.typesafe.config.{Config, ConfigFactory} +import org.mockito.Matchers.{eq => mockitoEq, _} +import org.mockito.Mockito._ +import org.mockito.invocation.InvocationOnMock +import org.mockito.stubbing.Answer +import org.slf4j.LoggerFactory import scala.concurrent.Future import scala.concurrent.duration._ @@ -199,7 +205,56 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { "interactionOneOriginalIngredient" -> interactionOneIngredientValue) } - "correctly notify on event" in { + "execute an interaction when its ingredient is provided in cluster" in { + val recipe = + Recipe("IngredientProvidedRecipeCluster") + .withInteraction(interactionOne) + .withSensoryEvent(initialEvent) + + + val config: Config = ConfigFactory.parseString( + """ + |include "baker.conf" + | + |akka { + | actor { + | provider = "cluster" + | } + | remote { + | log-remote-lifecycle-events = off + | netty.tcp { + | hostname = "127.0.0.1" + | port = 2555 + | } + | } + | + | cluster { + | seed-nodes = ["akka.tcp://remoteTest@127.0.0.1:2555"] + | auto-down-unreachable-after = 10s + | } + |} + |baker.interaction-manager = remote + """.stripMargin).withFallback(ConfigFactory.load()) + + val baker = Baker.akka(config, ActorSystem.apply("remoteTest", config)) + + for { + _ <- baker.addInteractionInstances(mockImplementations) + recipeId <- baker.addRecipe(RecipeCompiler.compileRecipe(recipe)) + _ = when(testInteractionOneMock.apply(anyString(), anyString())).thenReturn(Future.successful(InteractionOneSuccessful(interactionOneIngredientValue))) + recipeInstanceId = UUID.randomUUID().toString + _ <- baker.bake(recipeId, recipeInstanceId) + _ <- baker.fireEventAndResolveWhenCompleted(recipeInstanceId, EventInstance.unsafeFrom(EventInstance.unsafeFrom(InitialEvent(initialIngredientValue)))) + _ = verify(testInteractionOneMock).apply(recipeInstanceId.toString, "initialIngredient") + state <- baker.getRecipeInstanceState(recipeInstanceId) + } yield + state.ingredients shouldBe + ingredientMap( + "initialIngredient" -> initialIngredientValue, + "interactionOneOriginalIngredient" -> interactionOneIngredientValue) + } + + "Correctly notify on event" in { val sensoryEvent = Event( name = "sensory-event", diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InstanceSchedulingSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InstanceSchedulingSpec.scala index 7106a57e5..8b81a0089 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InstanceSchedulingSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InstanceSchedulingSpec.scala @@ -2,17 +2,18 @@ package com.ing.baker.runtime.akka.actor.interaction_schedulling import akka.actor.{ActorRef, ActorSystem} import akka.testkit.{ImplicitSender, TestKit} +import akka.util.Timeout +import cats.effect.{IO, Timer} import com.ing.baker.runtime.akka.actor.interaction_schedulling.ProtocolInteractionExecution.InstanceExecutedSuccessfully -import com.ing.baker.runtime.scaladsl.IngredientInstance -import com.ing.baker.runtime.scaladsl.EventInstance -import com.ing.baker.runtime.scaladsl.InteractionInstance +import com.ing.baker.runtime.akka.actor.interaction_schedulling.QuestMandated.Start +import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance, InteractionInstance} import com.ing.baker.types.{CharArray, PrimitiveValue} import com.typesafe.config.{Config, ConfigFactory} -import org.scalatest.{BeforeAndAfter, BeforeAndAfterAll, Matchers, WordSpecLike} import org.scalatest.concurrent.Eventually import org.scalatest.mockito.MockitoSugar +import org.scalatest.{BeforeAndAfter, BeforeAndAfterAll, Matchers, WordSpecLike} -import scala.concurrent.Future +import scala.concurrent.duration._ object InstanceSchedulingSpec { @@ -47,37 +48,39 @@ class InstanceSchedulingSpec extends TestKit(ActorSystem("InstanceSchedulingSpec with MockitoSugar with Eventually { - import system.dispatcher + implicit val timer: Timer[IO] = IO.timer(system.dispatcher) val recipeName: String = "TestRecipe" + def work(str: String): IO[String] = + IO.sleep(1 millis).map(_ => str.toUpperCase()) + val interaction: InteractionInstance = InteractionInstance( "TestInstance", Seq(CharArray), - ingredients => Future (Some { - val computed = PrimitiveValue(ingredients.head.value.as[String].toUpperCase()) - EventInstance("TestDone", Map("upper" -> computed)) - }) - ) + ingredients => + work(ingredients.head.value.as[String]).map(res => { + Some(EventInstance("TestDone", Map("upper" -> PrimitiveValue(res)))) + }).unsafeToFuture() + ) val jobs: List[String] = - List.fill(10000)("hello") + List.fill(1000)("hello") def buildAgents(): List[ActorRef] = List( - system.actorOf(InteractionAgent(recipeName, interaction)), - system.actorOf(InteractionAgent(recipeName, interaction)) + system.actorOf(InteractionAgent(interaction)), + system.actorOf(InteractionAgent(interaction)) ) def buildMandated(job: String, manager: ActorRef): ActorRef = - system.actorOf(QuestMandated(manager, Seq(IngredientInstance("test-ingredient", PrimitiveValue(job))), recipeName, interaction.name)) + system.actorOf(QuestMandated(Seq(IngredientInstance("test-ingredient", PrimitiveValue(job))), interaction.name, Timeout.durationToTimeout(10 seconds), Timeout.durationToTimeout(60 seconds))) "The Instance scheduling protocol" should { "simple run success" in { buildAgents() - jobs.foreach(buildMandated(_, self)) - buildAgents() + jobs.foreach(buildMandated(_, self) ! Start) receiveN(jobs.length).foreach { job => job.asInstanceOf[InstanceExecutedSuccessfully] match { case InstanceExecutedSuccessfully(Some(EventInstance("TestDone", map))) => diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexSpec.scala index 78ddadc49..40377019a 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexSpec.scala @@ -1,32 +1,34 @@ package com.ing.baker.runtime.akka.actor.process_index -import akka.actor.{ Actor, ActorRef, ActorSystem, Props } -import akka.testkit.{ ImplicitSender, TestKit, TestProbe } -import com.ing.baker.il.petrinet.{ EventTransition, Place, RecipePetriNet, Transition } -import com.ing.baker.il.{ CompiledRecipe, EventDescriptor, IngredientDescriptor } -import com.ing.baker.petrinet.api.{ Marking, PetriNet } +import java.util.UUID + +import akka.actor.{Actor, ActorRef, ActorSystem, Props} +import akka.testkit.{ImplicitSender, TestKit, TestProbe} +import com.ing.baker.il.petrinet.{EventTransition, Place, RecipePetriNet, Transition} +import com.ing.baker.il.{CompiledRecipe, EventDescriptor, IngredientDescriptor} +import com.ing.baker.petrinet.api.{Marking, PetriNet} import com.ing.baker.runtime.akka.actor.process_index.ProcessIndex.CheckForProcessesToBeDeleted import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProtocol.FireSensoryEventReaction.NotifyWhenReceived import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProtocol._ import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol._ import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProtocol -import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProtocol.{ AllRecipes, GetAllRecipes, RecipeInformation } +import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProtocol.{AllRecipes, GetAllRecipes, RecipeInformation} import com.ing.baker.runtime.akka.actor.serialization.Encryption -import com.ing.baker.runtime.akka.internal.InteractionManager -import com.ing.baker.runtime.scaladsl.{ EventInstance, RecipeInstanceState } +import com.ing.baker.runtime.akka.internal.InteractionManagerLocal +import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeInstanceState} import com.ing.baker.types import com.ing.baker.types.Value -import com.typesafe.config.{ Config, ConfigFactory } -import java.util.UUID +import com.typesafe.config.{Config, ConfigFactory} import org.mockito.Mockito import org.mockito.Mockito.when import org.scalatest.concurrent.Eventually import org.scalatest.mockito.MockitoSugar -import org.scalatest.{ BeforeAndAfter, BeforeAndAfterAll, Matchers, WordSpecLike } -import scala.concurrent.duration._ +import org.scalatest.{BeforeAndAfter, BeforeAndAfterAll, Matchers, WordSpecLike} import scalax.collection.immutable.Graph +import scala.concurrent.duration._ + object ProcessIndexSpec { val config: Config = ConfigFactory.parseString( """ @@ -281,7 +283,7 @@ class ProcessIndexSpec extends TestKit(ActorSystem("ProcessIndexSpec", ProcessIn recipeInstanceIdleTimeout = None, retentionCheckInterval = None, configuredEncryption = Encryption.NoEncryption, - interactionManager = new InteractionManager(), + interactionManager = new InteractionManagerLocal(), recipeManager = recipeManager, Seq.empty) { override def createProcessActor(id: String, compiledRecipe: CompiledRecipe) = petriNetActorRef diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/internal/InteractionManagerSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/internal/InteractionManagerSpec.scala index 7721355d4..908d1bde2 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/internal/InteractionManagerSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/internal/InteractionManagerSpec.scala @@ -9,7 +9,7 @@ import org.mockito.Mockito.when import org.scalatest.mockito.MockitoSugar import org.scalatest.{Matchers, WordSpecLike} -class InteractionManagerSpec extends WordSpecLike with Matchers with MockitoSugar { +class InteractionManagerLocalSpec extends WordSpecLike with Matchers with MockitoSugar { "getImplementation" should { "return Some" when { "an interaction implementation is available" in { @@ -17,7 +17,7 @@ class InteractionManagerSpec extends WordSpecLike with Matchers with MockitoSuga when(interactionImplementation.name).thenReturn("InteractionName") when(interactionImplementation.input).thenReturn(Seq(types.Int32)) - val interactionManager: InteractionManager = new InteractionManager(Seq(interactionImplementation)) + val interactionManager: InteractionManagerLocal = new InteractionManagerLocal(Seq(interactionImplementation)) val interactionTransition = mock[InteractionTransition] when(interactionTransition.originalInteractionName).thenReturn("InteractionName") val ingredientDescriptor: IngredientDescriptor = IngredientDescriptor("ingredientName", types.Int32) @@ -35,7 +35,7 @@ class InteractionManagerSpec extends WordSpecLike with Matchers with MockitoSuga when(interactionImplementation2.name).thenReturn("InteractionName2") when(interactionImplementation2.input).thenReturn(Seq(types.Int32)) - val interactionManager: InteractionManager = new InteractionManager(Seq(interactionImplementation1, interactionImplementation2)) + val interactionManager: InteractionManagerLocal = new InteractionManagerLocal(Seq(interactionImplementation1, interactionImplementation2)) val interactionTransition = mock[InteractionTransition] when(interactionTransition.originalInteractionName).thenReturn("InteractionName") val ingredientDescriptor: IngredientDescriptor = IngredientDescriptor("ingredientName", types.Int32) @@ -53,7 +53,7 @@ class InteractionManagerSpec extends WordSpecLike with Matchers with MockitoSuga when(interactionImplementation2.name).thenReturn("InteractionName") when(interactionImplementation2.input).thenReturn(Seq(types.Int32)) - val interactionManager: InteractionManager = new InteractionManager(Seq(interactionImplementation1, interactionImplementation2)) + val interactionManager: InteractionManagerLocal = new InteractionManagerLocal(Seq(interactionImplementation1, interactionImplementation2)) val interactionTransition = mock[InteractionTransition] when(interactionTransition.originalInteractionName).thenReturn("InteractionName") val ingredientDescriptor: IngredientDescriptor = IngredientDescriptor("ingredientName", types.Int32) @@ -69,7 +69,7 @@ class InteractionManagerSpec extends WordSpecLike with Matchers with MockitoSuga when(interactionImplementation.name).thenReturn("InteractionName") when(interactionImplementation.input).thenReturn(Seq(types.Int32)) - val interactionManager: InteractionManager = new InteractionManager(Seq(interactionImplementation)) + val interactionManager: InteractionManagerLocal = new InteractionManagerLocal(Seq(interactionImplementation)) val interactionTransition = mock[InteractionTransition] when(interactionTransition.originalInteractionName).thenReturn("WrongInteractionName") val ingredientDescriptor: IngredientDescriptor = IngredientDescriptor("ingredientName", types.Int32) @@ -83,7 +83,7 @@ class InteractionManagerSpec extends WordSpecLike with Matchers with MockitoSuga when(interactionImplementation.name).thenReturn("InteractionName") when(interactionImplementation.input).thenReturn(Seq(types.Int32)) - val interactionManager: InteractionManager = new InteractionManager(Seq(interactionImplementation)) + val interactionManager: InteractionManagerLocal = new InteractionManagerLocal(Seq(interactionImplementation)) val interactionTransition = mock[InteractionTransition] when(interactionTransition.originalInteractionName).thenReturn("InteractionName") val ingredientDescriptor: IngredientDescriptor = IngredientDescriptor("ingredientName", types.CharArray) @@ -97,7 +97,7 @@ class InteractionManagerSpec extends WordSpecLike with Matchers with MockitoSuga when(interactionImplementation.name).thenReturn("InteractionName") when(interactionImplementation.input).thenReturn(Seq(types.Int32, types.CharArray)) - val interactionManager: InteractionManager = new InteractionManager(Seq(interactionImplementation)) + val interactionManager: InteractionManagerLocal = new InteractionManagerLocal(Seq(interactionImplementation)) val interactionTransition = mock[InteractionTransition] when(interactionTransition.originalInteractionName).thenReturn("InteractionName") val ingredientDescriptor: IngredientDescriptor = IngredientDescriptor("ingredientName", types.Int32) @@ -111,7 +111,7 @@ class InteractionManagerSpec extends WordSpecLike with Matchers with MockitoSuga when(interactionImplementation.name).thenReturn("InteractionName") when(interactionImplementation.input).thenReturn(Seq(types.Int32)) - val interactionManager: InteractionManager = new InteractionManager(Seq(interactionImplementation)) + val interactionManager: InteractionManagerLocal = new InteractionManagerLocal(Seq(interactionImplementation)) val interactionTransition = mock[InteractionTransition] when(interactionTransition.originalInteractionName).thenReturn("InteractionName") val ingredientDescriptor: IngredientDescriptor = IngredientDescriptor("ingredientName", types.Int32) @@ -122,7 +122,7 @@ class InteractionManagerSpec extends WordSpecLike with Matchers with MockitoSuga } "empty interaction seq" in { - val interactionManager: InteractionManager = new InteractionManager(Seq.empty) + val interactionManager: InteractionManagerLocal = new InteractionManagerLocal(Seq.empty) val interactionTransition: InteractionTransition = mock[InteractionTransition] interactionManager.getImplementation(interactionTransition) should equal(None) From df2c65899ef5422175b6597cd20e4a257135b96d Mon Sep 17 00:00:00 2001 From: Tim Linschoten Date: Tue, 17 Sep 2019 17:27:10 +0200 Subject: [PATCH 06/86] Fixed unit test by changing node. --- .../com/ing/baker/runtime/akka/BakerExecutionSpec.scala | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala index 0f42f5624..7da203f5f 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala @@ -18,17 +18,11 @@ import com.ing.baker.runtime.common.BakerException._ import com.ing.baker.runtime.common._ import com.ing.baker.runtime.scaladsl.{Baker, EventInstance, InteractionInstance} import com.ing.baker.types.{CharArray, Int32, PrimitiveValue} -import com.typesafe.config.ConfigFactory -import org.mockito.Matchers.{eq => mockitoEq, _} -import org.mockito.Mockito._ -import org.mockito.invocation.InvocationOnMock -import org.slf4j.{Logger, LoggerFactory} import com.typesafe.config.{Config, ConfigFactory} import org.mockito.Matchers.{eq => mockitoEq, _} import org.mockito.Mockito._ import org.mockito.invocation.InvocationOnMock -import org.mockito.stubbing.Answer -import org.slf4j.LoggerFactory +import org.slf4j.{Logger, LoggerFactory} import scala.concurrent.Future import scala.concurrent.duration._ From add20042e8195e6b8a621fb0461438e16f416757 Mon Sep 17 00:00:00 2001 From: Tim Linschoten Date: Wed, 18 Sep 2019 14:00:51 +0200 Subject: [PATCH 07/86] Added basic logging for the new components --- .../interaction_schedulling/InteractionAgent.scala | 11 ++++++++++- .../actor/interaction_schedulling/QuestMandated.scala | 11 +++++++++++ .../runtime/akka/internal/InteractionManager.scala | 6 ++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala index 0c66ec6cb..3a5a76702 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala @@ -3,6 +3,8 @@ package com.ing.baker.runtime.akka.actor.interaction_schedulling import akka.actor.{Actor, ActorRef, Props} import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} import com.ing.baker.runtime.scaladsl.{EventInstance, InteractionInstance} +import org.slf4j.LoggerFactory +import InteractionAgent._ import scala.concurrent.{ExecutionContext, Future} import scala.util.{Failure, Success} @@ -30,6 +32,8 @@ object InteractionAgent { agent.tell(ProtocolInteractionExecution.InstanceExecutionFailed(), agent) } } + + private val log = LoggerFactory.getLogger(classOf[InteractionAgent]) } class InteractionAgent(interaction: InteractionInstance) extends Actor { @@ -59,12 +63,14 @@ class InteractionAgent(interaction: InteractionInstance) extends Actor { def receive: Receive = { case ProtocolPushPullMatching.Push(mandated) => // start Quest commit protocol + log.info(s"${interaction.name}: Considering quest from $mandated") mandated ! ProtocolQuestCommit.Considering(self) unsubscribePush() context.become(considering) case ProtocolPushPullMatching.AvailableQuest(mandated) => // start Quest commit protocol + log.info(s"${interaction.name}: Considering quest from $mandated") mandated ! ProtocolQuestCommit.Considering(self) unsubscribePush() context.become(considering) @@ -72,12 +78,14 @@ class InteractionAgent(interaction: InteractionInstance) extends Actor { def considering: Receive = { case ProtocolQuestCommit.Commit(mandated, executeMessage) => + log.info(s"${interaction.name}: Commited to quest from $mandated") // start the execution protocol by already starting the computation and become committed InteractionAgent.pipeBackExecutionResponse(self)(interaction.run(executeMessage.input)) context.become(committed(mandated)) case ProtocolQuestCommit.QuestTaken => - // quest taken, start all over again + log.info(s"${interaction.name}: Quest taken, starting the protocol again") + // quest taIken, start all over again subscribePush() pull() context.become(receive) @@ -85,6 +93,7 @@ class InteractionAgent(interaction: InteractionInstance) extends Actor { def committed(mandated: ActorRef): Receive = { case message: ProtocolInteractionExecution => + log.info(s"${interaction.name}: Considering quest from $mandated") // Forward the result mandated ! message // Start all over again diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala index 0704e25a8..98dbb05a8 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala @@ -5,6 +5,8 @@ import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} import akka.util.Timeout import com.ing.baker.runtime.akka.actor.interaction_schedulling.QuestMandated.{ComputationTimeout, PostTimeout, Start} import com.ing.baker.runtime.scaladsl.IngredientInstance +import org.slf4j.LoggerFactory +import QuestMandated._ object QuestMandated { @@ -16,6 +18,8 @@ object QuestMandated { def apply(ingredients: Seq[IngredientInstance], interactionName: String, postTimeout: Timeout, computationTimeout: Timeout): Props = Props(new QuestMandated(ingredients, interactionName, postTimeout, computationTimeout)) + + private val log = LoggerFactory.getLogger(classOf[QuestMandated]) } class QuestMandated(ingredients: Seq[IngredientInstance], interactionName: String, postTimeout: Timeout, computationTimeout: Timeout) extends Actor { @@ -40,6 +44,7 @@ class QuestMandated(ingredients: Seq[IngredientInstance], interactionName: Strin def receive: Receive = { case Start => + log.info(s"$interactionName: Starting Quest for interaction") start() context.become(running(sender)) } @@ -47,15 +52,18 @@ class QuestMandated(ingredients: Seq[IngredientInstance], interactionName: Strin def running(manager: ActorRef): Receive = { case ProtocolPushPullMatching.Pull(agent) => // respond with available quest + log.info(s"$interactionName: responding to pull of available agent") agent ! ProtocolPushPullMatching.AvailableQuest(self) case ProtocolQuestCommit.Considering(agent) => + log.info(s"$interactionName: Mandate Quest for agent: $agent") // start the interaction execution protocol by responding with a commit message agent ! ProtocolQuestCommit.Commit(self, ProtocolInteractionExecution.ExecuteInstance(ingredients)) context.system.scheduler.scheduleOnce(computationTimeout.duration, self, ComputationTimeout)(context.dispatcher, self) context.become(committed(manager)) case PostTimeout => + log.info(s"$interactionName: Timed out on waiting for response when trying to find agent") manager ! ProtocolInteractionExecution.NoInstanceFound self ! PoisonPill } @@ -63,14 +71,17 @@ class QuestMandated(ingredients: Seq[IngredientInstance], interactionName: Strin def committed(manager: ActorRef): Receive = { case message: ProtocolInteractionExecution => + log.info(s"$interactionName: Quest executed") // report and kill himself manager ! message self ! PoisonPill case ProtocolQuestCommit.Considering(agent) => + log.info(s"$interactionName: rejecting other agent: $agent") agent ! ProtocolQuestCommit.QuestTaken case ComputationTimeout => + log.info(s"$interactionName: Timed out on waiting for response of agent after commited") manager ! ProtocolInteractionExecution.InstanceExecutionTimedOut self ! PoisonPill } diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala index 72f633a28..cf162e4eb 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala @@ -34,11 +34,13 @@ class InteractionManagerDis(system: ActorSystem, postTimeout: Timeout, computati import system.dispatcher override def executeImplementation(interaction: InteractionTransition, input: Seq[IngredientInstance]): Future[Option[EventInstance]] = { - val a = system.actorOf(QuestMandated(input, interaction.interactionName, postTimeout, computationTimeout)) + val a = system.actorOf(QuestMandated(input, interaction.originalInteractionName, postTimeout, computationTimeout)) a.ask(Start)(Timeout.durationToTimeout(postTimeout.duration + computationTimeout.duration)).flatMap { case ProtocolInteractionExecution.InstanceExecutedSuccessfully(result) => Future.successful(result) - //What if there is no implementation available???? case ProtocolInteractionExecution.InstanceExecutionFailed() => Future.failed(new RuntimeException("Remote execution of interaction failed")) + case ProtocolInteractionExecution.NoInstanceFound() => executeImplementation(interaction, input) + case ProtocolInteractionExecution.InstanceExecutionTimedOut() => Future.failed(new RuntimeException("Execution of interaction timed out")) + case ProtocolInteractionExecution.InvalidExecution() => Future.failed(new RuntimeException("Execution of interaction failed because of invalid ingredient input")) } } From 3c3c6f91c8170a6c46e2b487410a0ffb47eb19be Mon Sep 17 00:00:00 2001 From: Tim Linschoten Date: Wed, 18 Sep 2019 14:44:14 +0200 Subject: [PATCH 08/86] Added some trace UUID information to the logs. --- .../InteractionAgent.scala | 26 ++++++++++--------- .../ProtocolPushPullMatching.scala | 6 +++-- .../QuestMandated.scala | 24 +++++++++-------- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala index 3a5a76702..3cf0c5e0b 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala @@ -1,5 +1,7 @@ package com.ing.baker.runtime.akka.actor.interaction_schedulling +import java.util.UUID + import akka.actor.{Actor, ActorRef, Props} import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} import com.ing.baker.runtime.scaladsl.{EventInstance, InteractionInstance} @@ -61,39 +63,39 @@ class InteractionAgent(interaction: InteractionInstance) extends Actor { pull() def receive: Receive = { - case ProtocolPushPullMatching.Push(mandated) => + case ProtocolPushPullMatching.Push(mandated, uuid) => // start Quest commit protocol - log.info(s"${interaction.name}: Considering quest from $mandated") + log.info(s"${interaction.name}:$uuid: Considering quest from $mandated") mandated ! ProtocolQuestCommit.Considering(self) unsubscribePush() - context.become(considering) + context.become(considering(uuid)) - case ProtocolPushPullMatching.AvailableQuest(mandated) => + case ProtocolPushPullMatching.AvailableQuest(mandated, uuid) => // start Quest commit protocol - log.info(s"${interaction.name}: Considering quest from $mandated") + log.info(s"${interaction.name}:$uuid: Considering quest from $mandated") mandated ! ProtocolQuestCommit.Considering(self) unsubscribePush() - context.become(considering) + context.become(considering(uuid)) } - def considering: Receive = { + def considering(uuid: UUID): Receive = { case ProtocolQuestCommit.Commit(mandated, executeMessage) => - log.info(s"${interaction.name}: Commited to quest from $mandated") + log.info(s"${interaction.name}:$uuid: Commited to quest from $mandated") // start the execution protocol by already starting the computation and become committed InteractionAgent.pipeBackExecutionResponse(self)(interaction.run(executeMessage.input)) - context.become(committed(mandated)) + context.become(committed(mandated, uuid)) case ProtocolQuestCommit.QuestTaken => - log.info(s"${interaction.name}: Quest taken, starting the protocol again") + log.info(s"${interaction.name}:$uuid: Quest taken, starting the protocol again") // quest taIken, start all over again subscribePush() pull() context.become(receive) } - def committed(mandated: ActorRef): Receive = { + def committed(mandated: ActorRef, uuid: UUID): Receive = { case message: ProtocolInteractionExecution => - log.info(s"${interaction.name}: Considering quest from $mandated") + log.info(s"${interaction.name}:$uuid: Considering quest from $mandated") // Forward the result mandated ! message // Start all over again diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala index bd60142b7..3a3682a22 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala @@ -1,5 +1,7 @@ package com.ing.baker.runtime.akka.actor.interaction_schedulling +import java.util.UUID + import akka.actor.ActorRef /** @@ -15,10 +17,10 @@ object ProtocolPushPullMatching { def pullTopic(interactionName: String): String = s"Pull|:||:|$interactionName|:|" - case class Push(mandated: ActorRef) extends ProtocolPushPullMatching + case class Push(mandated: ActorRef, uuid: UUID) extends ProtocolPushPullMatching case class Pull(agent: ActorRef) extends ProtocolPushPullMatching - case class AvailableQuest(mandated: ActorRef) extends ProtocolPushPullMatching + case class AvailableQuest(mandated: ActorRef, uuid: UUID) extends ProtocolPushPullMatching } diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala index 98dbb05a8..34231238f 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala @@ -1,5 +1,7 @@ package com.ing.baker.runtime.akka.actor.interaction_schedulling +import java.util.UUID + import akka.actor.{Actor, ActorRef, PoisonPill, Props} import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} import akka.util.Timeout @@ -17,12 +19,12 @@ object QuestMandated { case object ComputationTimeout def apply(ingredients: Seq[IngredientInstance], interactionName: String, postTimeout: Timeout, computationTimeout: Timeout): Props = - Props(new QuestMandated(ingredients, interactionName, postTimeout, computationTimeout)) + Props(new QuestMandated(UUID.randomUUID(), ingredients, interactionName, postTimeout, computationTimeout)) private val log = LoggerFactory.getLogger(classOf[QuestMandated]) } -class QuestMandated(ingredients: Seq[IngredientInstance], interactionName: String, postTimeout: Timeout, computationTimeout: Timeout) extends Actor { +class QuestMandated(uuid: UUID, ingredients: Seq[IngredientInstance], interactionName: String, postTimeout: Timeout, computationTimeout: Timeout) extends Actor { val mediator: ActorRef = DistributedPubSub(context.system).mediator @@ -33,7 +35,7 @@ class QuestMandated(ingredients: Seq[IngredientInstance], interactionName: Strin ProtocolPushPullMatching.pushTopic(interactionName) def push(): Unit = - mediator ! DistributedPubSubMediator.Publish(pushTopic, ProtocolPushPullMatching.Push(self)) + mediator ! DistributedPubSubMediator.Publish(pushTopic, ProtocolPushPullMatching.Push(self, uuid)) def start(): Unit = { mediator ! DistributedPubSubMediator.Subscribe(pullTopic, self) @@ -44,7 +46,7 @@ class QuestMandated(ingredients: Seq[IngredientInstance], interactionName: Strin def receive: Receive = { case Start => - log.info(s"$interactionName: Starting Quest for interaction") + log.info(s"$interactionName:$uuid: Starting Quest for interaction") start() context.become(running(sender)) } @@ -52,18 +54,18 @@ class QuestMandated(ingredients: Seq[IngredientInstance], interactionName: Strin def running(manager: ActorRef): Receive = { case ProtocolPushPullMatching.Pull(agent) => // respond with available quest - log.info(s"$interactionName: responding to pull of available agent") - agent ! ProtocolPushPullMatching.AvailableQuest(self) + log.info(s"$interactionName:$uuid: responding to pull of available agent") + agent ! ProtocolPushPullMatching.AvailableQuest(self, uuid) case ProtocolQuestCommit.Considering(agent) => - log.info(s"$interactionName: Mandate Quest for agent: $agent") + log.info(s"$interactionName:$uuid: Mandate Quest for agent: $agent") // start the interaction execution protocol by responding with a commit message agent ! ProtocolQuestCommit.Commit(self, ProtocolInteractionExecution.ExecuteInstance(ingredients)) context.system.scheduler.scheduleOnce(computationTimeout.duration, self, ComputationTimeout)(context.dispatcher, self) context.become(committed(manager)) case PostTimeout => - log.info(s"$interactionName: Timed out on waiting for response when trying to find agent") + log.info(s"$interactionName:$uuid: Timed out on waiting for response when trying to find agent") manager ! ProtocolInteractionExecution.NoInstanceFound self ! PoisonPill } @@ -71,17 +73,17 @@ class QuestMandated(ingredients: Seq[IngredientInstance], interactionName: Strin def committed(manager: ActorRef): Receive = { case message: ProtocolInteractionExecution => - log.info(s"$interactionName: Quest executed") + log.info(s"$interactionName:$uuid: Quest executed") // report and kill himself manager ! message self ! PoisonPill case ProtocolQuestCommit.Considering(agent) => - log.info(s"$interactionName: rejecting other agent: $agent") + log.info(s"$interactionName:$uuid: rejecting other agent: $agent") agent ! ProtocolQuestCommit.QuestTaken case ComputationTimeout => - log.info(s"$interactionName: Timed out on waiting for response of agent after commited") + log.info(s"$interactionName:$uuid: Timed out on waiting for response of agent after commited") manager ! ProtocolInteractionExecution.InstanceExecutionTimedOut self ! PoisonPill } From 99c382ab2723ccb855758c2eca628e7f8004bc8f Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Wed, 18 Sep 2019 15:08:29 +0200 Subject: [PATCH 09/86] Tests updated --- examples/src/main/resources/application.conf | 5 +++++ examples/src/main/resources/docker-compose.yaml | 14 +++++++------- .../ProtocolInteractionExecution.scala | 2 +- .../runtime/akka/internal/InteractionManager.scala | 2 +- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/examples/src/main/resources/application.conf b/examples/src/main/resources/application.conf index 873a3c06b..60aab476d 100644 --- a/examples/src/main/resources/application.conf +++ b/examples/src/main/resources/application.conf @@ -25,6 +25,9 @@ service { } baker { + + interaction-manager = "remote" + actor { provider = "cluster-sharded" idle-timeout = 1 minute @@ -43,6 +46,8 @@ cassandra-journal.contact-points.0 = ${?CASSANDRA_CONTACT_POINTS_0} cassandra-snapshot-store.contact-points.0 = "127.0.0.1" cassandra-snapshot-store.contact-points.0 = ${?CASSANDRA_CONTACT_POINTS_0} +akka.actor.allow-java-serialization = on + akka { actor { diff --git a/examples/src/main/resources/docker-compose.yaml b/examples/src/main/resources/docker-compose.yaml index 674ae8b65..e42c4dc89 100644 --- a/examples/src/main/resources/docker-compose.yaml +++ b/examples/src/main/resources/docker-compose.yaml @@ -1,7 +1,7 @@ version: '3' services: node1: - image: "checkout-service-baker-example:3.0.0-SNAPSHOT" + image: "checkout-service-baker-example:3.0.1-SNAPSHOT" ports: - "8081:8080" - "5261:5266" @@ -14,26 +14,26 @@ services: CLUSTER_SEED_HOST: node1 CLUSTER_SEED_PORT: 2551 node2: - image: "checkout-service-baker-example:3.0.0-SNAPSHOT" + image: "checkout-service-baker-example:3.0.1-SNAPSHOT" ports: - "8082:8080" - "5262:5266" - "9092:9095" - logging: - driver: none + #logging: + # driver: none environment: CLUSTER_HOST: node2 CLUSTER_PORT: 2551 CLUSTER_SEED_HOST: node1 CLUSTER_SEED_PORT: 2551 node3: - image: "checkout-service-baker-example:3.0.0-SNAPSHOT" + image: "checkout-service-baker-example:3.0.1-SNAPSHOT" ports: - "8083:8080" - "5263:526" - "9093:9095" - logging: - driver: none + #logging: + # driver: none environment: CLUSTER_HOST: node3 CLUSTER_PORT: 2551 diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala index 1508c876d..c2f0ba927 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala @@ -37,7 +37,7 @@ object ProtocolInteractionExecution { /** * Technical failure of the interaction */ - case class NoInstanceFound() extends ProtocolInteractionExecution + case object NoInstanceFound extends ProtocolInteractionExecution /** * Invalid request, bad ingredients given diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala index cf162e4eb..db42627e2 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala @@ -38,7 +38,7 @@ class InteractionManagerDis(system: ActorSystem, postTimeout: Timeout, computati a.ask(Start)(Timeout.durationToTimeout(postTimeout.duration + computationTimeout.duration)).flatMap { case ProtocolInteractionExecution.InstanceExecutedSuccessfully(result) => Future.successful(result) case ProtocolInteractionExecution.InstanceExecutionFailed() => Future.failed(new RuntimeException("Remote execution of interaction failed")) - case ProtocolInteractionExecution.NoInstanceFound() => executeImplementation(interaction, input) + case ProtocolInteractionExecution.NoInstanceFound => executeImplementation(interaction, input) case ProtocolInteractionExecution.InstanceExecutionTimedOut() => Future.failed(new RuntimeException("Execution of interaction timed out")) case ProtocolInteractionExecution.InvalidExecution() => Future.failed(new RuntimeException("Execution of interaction failed because of invalid ingredient input")) } From 8c1faab873ff10f7aa37dd726893515074a2e7fb Mon Sep 17 00:00:00 2001 From: Tim Linschoten Date: Wed, 18 Sep 2019 17:08:39 +0200 Subject: [PATCH 10/86] Added timeout for how long a agent can be considering. Removed the committed state and go into receive state directly. --- .../InteractionAgent.scala | 45 ++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala index 3cf0c5e0b..5798bce98 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala @@ -4,15 +4,18 @@ import java.util.UUID import akka.actor.{Actor, ActorRef, Props} import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} +import com.ing.baker.runtime.akka.actor.interaction_schedulling.InteractionAgent._ import com.ing.baker.runtime.scaladsl.{EventInstance, InteractionInstance} import org.slf4j.LoggerFactory -import InteractionAgent._ import scala.concurrent.{ExecutionContext, Future} import scala.util.{Failure, Success} +import scala.concurrent.duration._ object InteractionAgent { + case object CommitTimeout + def apply(instance: InteractionInstance): Props = Props(new InteractionAgent(instance)) @@ -22,16 +25,16 @@ object InteractionAgent { * * TODO: Handle invalid ingredients scenario * - * @param agent actor reference + * @param agent actor reference * @param result outcome of invoking the interaction instance - * @param ec execution context to use + * @param ec execution context to use */ - private[interaction_schedulling] def pipeBackExecutionResponse(agent: ActorRef)(result: Future[Option[EventInstance]])(implicit ec: ExecutionContext): Unit = { + private[interaction_schedulling] def pipeBackExecutionResponse(agent: ActorRef, mandated: ActorRef)(result: Future[Option[EventInstance]])(implicit ec: ExecutionContext): Unit = { result.onComplete { case Success(value) => - agent.tell(ProtocolInteractionExecution.InstanceExecutedSuccessfully(value), agent) + mandated.tell(ProtocolInteractionExecution.InstanceExecutedSuccessfully(value), agent) case Failure(exception) => - agent.tell(ProtocolInteractionExecution.InstanceExecutionFailed(), agent) + mandated.tell(ProtocolInteractionExecution.InstanceExecutionFailed(), agent) } } @@ -68,6 +71,7 @@ class InteractionAgent(interaction: InteractionInstance) extends Actor { log.info(s"${interaction.name}:$uuid: Considering quest from $mandated") mandated ! ProtocolQuestCommit.Considering(self) unsubscribePush() + context.system.scheduler.scheduleOnce(10 seconds, self, CommitTimeout)(context.dispatcher, self) context.become(considering(uuid)) case ProtocolPushPullMatching.AvailableQuest(mandated, uuid) => @@ -75,6 +79,7 @@ class InteractionAgent(interaction: InteractionInstance) extends Actor { log.info(s"${interaction.name}:$uuid: Considering quest from $mandated") mandated ! ProtocolQuestCommit.Considering(self) unsubscribePush() + context.system.scheduler.scheduleOnce(10 seconds, self, CommitTimeout)(context.dispatcher, self) context.become(considering(uuid)) } @@ -82,8 +87,11 @@ class InteractionAgent(interaction: InteractionInstance) extends Actor { case ProtocolQuestCommit.Commit(mandated, executeMessage) => log.info(s"${interaction.name}:$uuid: Commited to quest from $mandated") // start the execution protocol by already starting the computation and become committed - InteractionAgent.pipeBackExecutionResponse(self)(interaction.run(executeMessage.input)) - context.become(committed(mandated, uuid)) + InteractionAgent.pipeBackExecutionResponse(self, mandated)(interaction.run(executeMessage.input)) + subscribePush() + pull() + context.become(receive) + // context.become(committed(mandated, uuid)) case ProtocolQuestCommit.QuestTaken => log.info(s"${interaction.name}:$uuid: Quest taken, starting the protocol again") @@ -91,16 +99,23 @@ class InteractionAgent(interaction: InteractionInstance) extends Actor { subscribePush() pull() context.become(receive) - } - def committed(mandated: ActorRef, uuid: UUID): Receive = { - case message: ProtocolInteractionExecution => - log.info(s"${interaction.name}:$uuid: Considering quest from $mandated") - // Forward the result - mandated ! message - // Start all over again + case CommitTimeout => + log.info(s"${interaction.name}:$uuid: not received a response after commit timeout") subscribePush() pull() context.become(receive) + } + +// def committed(mandated: ActorRef, uuid: UUID): Receive = { +// case message: ProtocolInteractionExecution => +// log.info(s"${interaction.name}:$uuid: Considering quest from $mandated") +// // Forward the result +// mandated ! message +// // Start all over again +// subscribePush() +// pull() +// context.become(receive) +// } } From 27a75ba829526b6bbf9faa0f12e4c6ad8a9bf988 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Fri, 20 Sep 2019 18:26:56 +0200 Subject: [PATCH 11/86] Added proto serialization to scheduling messages --- .../protobuf/interaction_schedulling.proto | 61 ++++++ .../InteractionAgent.scala | 6 +- .../InteractionSchedulingProto.scala | 184 ++++++++++++++++++ .../ProtocolInteractionExecution.scala | 2 +- .../ProtocolPushPullMatching.scala | 5 +- .../ProtocolQuestCommit.scala | 5 +- .../QuestMandated.scala | 4 +- .../BakerTypedProtobufSerializer.scala | 32 ++- .../akka/actor/serialization/ProtoMap.scala | 5 +- .../IngredientInstanceMapping.scala | 24 +++ .../akka/internal/InteractionManager.scala | 4 +- .../InstanceSchedulingSpec.scala | 6 +- 12 files changed, 320 insertions(+), 18 deletions(-) create mode 100644 runtime/src/main/protobuf/interaction_schedulling.proto rename runtime/src/main/scala/com/ing/baker/runtime/akka/actor/{interaction_schedulling => interaction_scheduling}/InteractionAgent.scala (92%) create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala rename runtime/src/main/scala/com/ing/baker/runtime/akka/actor/{interaction_schedulling => interaction_scheduling}/ProtocolInteractionExecution.scala (96%) rename runtime/src/main/scala/com/ing/baker/runtime/akka/actor/{interaction_schedulling => interaction_scheduling}/ProtocolPushPullMatching.scala (75%) rename runtime/src/main/scala/com/ing/baker/runtime/akka/actor/{interaction_schedulling => interaction_scheduling}/ProtocolQuestCommit.scala (73%) rename runtime/src/main/scala/com/ing/baker/runtime/akka/actor/{interaction_schedulling => interaction_scheduling}/QuestMandated.scala (94%) create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/IngredientInstanceMapping.scala rename runtime/src/test/scala/com/ing/baker/runtime/akka/actor/{interaction_schedulling => interaction_scheduling}/InstanceSchedulingSpec.scala (91%) diff --git a/runtime/src/main/protobuf/interaction_schedulling.proto b/runtime/src/main/protobuf/interaction_schedulling.proto new file mode 100644 index 000000000..38b658e8d --- /dev/null +++ b/runtime/src/main/protobuf/interaction_schedulling.proto @@ -0,0 +1,61 @@ +syntax = "proto2"; + +import "scalapb/scalapb.proto"; +import "common.proto"; + +option java_package = "com.ing.baker.runtime.akka.actor.interaction_scheduling.protobuf"; +option (scalapb.options) = { + flat_package: true +}; + +message ExecuteInstance { + repeated Ingredient input = 1; +} + +message InstanceExecutedSuccessfully { + optional RuntimeEvent result = 1; +} + +message InstanceExecutionFailed { + +} + +message InstanceExecutionTimedOut { + +} + +message NoInstanceFound { + +} + +message InvalidExecution { + +} + +message Push { + optional ActorRefId mandated = 1; + optional string uuid = 2; +} + +message Pull { + optional ActorRefId agent = 1; +} + +message AvailableQuest { + optional ActorRefId mandated = 1; + optional string uuid = 2; +} + +message Considering { + optional ActorRefId agent = 1; +} + +message Commit { + optional ActorRefId mandated = 1; + optional ExecuteInstance execute = 2; +} + +message QuestTaken { + +} + diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionAgent.scala similarity index 92% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala rename to runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionAgent.scala index 5798bce98..1221bea31 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InteractionAgent.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionAgent.scala @@ -1,10 +1,10 @@ -package com.ing.baker.runtime.akka.actor.interaction_schedulling +package com.ing.baker.runtime.akka.actor.interaction_scheduling import java.util.UUID import akka.actor.{Actor, ActorRef, Props} import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} -import com.ing.baker.runtime.akka.actor.interaction_schedulling.InteractionAgent._ +import com.ing.baker.runtime.akka.actor.interaction_scheduling.InteractionAgent._ import com.ing.baker.runtime.scaladsl.{EventInstance, InteractionInstance} import org.slf4j.LoggerFactory @@ -29,7 +29,7 @@ object InteractionAgent { * @param result outcome of invoking the interaction instance * @param ec execution context to use */ - private[interaction_schedulling] def pipeBackExecutionResponse(agent: ActorRef, mandated: ActorRef)(result: Future[Option[EventInstance]])(implicit ec: ExecutionContext): Unit = { + private[interaction_scheduling] def pipeBackExecutionResponse(agent: ActorRef, mandated: ActorRef)(result: Future[Option[EventInstance]])(implicit ec: ExecutionContext): Unit = { result.onComplete { case Success(value) => mandated.tell(ProtocolInteractionExecution.InstanceExecutedSuccessfully(value), agent) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala new file mode 100644 index 000000000..816316b80 --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala @@ -0,0 +1,184 @@ +package com.ing.baker.runtime.akka.actor.interaction_scheduling + +import java.util.UUID + +import cats.implicits._ +import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolInteractionExecution.{ExecuteInstance, InstanceExecutedSuccessfully, InstanceExecutionFailed, InstanceExecutionTimedOut, InvalidExecution, NoInstanceFound} +import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolPushPullMatching.{AvailableQuest, Pull, Push} +import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolQuestCommit.{Commit, Considering, QuestTaken} +import com.ing.baker.runtime.akka.actor.serialization.{ProtoMap, SerializersProvider} +import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} + +import scala.util.{Success, Try} + +object InteractionSchedulingProto { + + implicit def executeInstanceProto: ProtoMap[ExecuteInstance, protobuf.ExecuteInstance] = + new ProtoMap[ExecuteInstance, protobuf.ExecuteInstance] { + + val companion = protobuf.ExecuteInstance + + def toProto(a: ExecuteInstance): protobuf.ExecuteInstance = + protobuf.ExecuteInstance(a.input.map(ctxToProto(_))) + + def fromProto(message: protobuf.ExecuteInstance): Try[ExecuteInstance] = + for { + result <- message.input.toList.traverse(ctxFromProto(_)) + } yield ExecuteInstance(result) + } + + implicit def instanceExcutedSuccessfullyProto: ProtoMap[InstanceExecutedSuccessfully, protobuf.InstanceExecutedSuccessfully] = + new ProtoMap[InstanceExecutedSuccessfully, protobuf.InstanceExecutedSuccessfully] { + + val companion = protobuf.InstanceExecutedSuccessfully + + def toProto(a: InstanceExecutedSuccessfully): protobuf.InstanceExecutedSuccessfully = + protobuf.InstanceExecutedSuccessfully(a.result.map(ctxToProto(_))) + + def fromProto(message: protobuf.InstanceExecutedSuccessfully): Try[InstanceExecutedSuccessfully] = + for { + result <- message.result.traverse(ctxFromProto(_)) + } yield InstanceExecutedSuccessfully(result) + } + + implicit def instanceExecutionFailedProto: ProtoMap[InstanceExecutionFailed, protobuf.InstanceExecutionFailed] = + new ProtoMap[InstanceExecutionFailed, protobuf.InstanceExecutionFailed] { + + val companion = protobuf.InstanceExecutionFailed + + def toProto(a: InstanceExecutionFailed): protobuf.InstanceExecutionFailed = + protobuf.InstanceExecutionFailed() + + def fromProto(message: protobuf.InstanceExecutionFailed): Try[InstanceExecutionFailed] = + Success(InstanceExecutionFailed()) + } + + implicit def instanceExecutionTimedOutProto: ProtoMap[InstanceExecutionTimedOut, protobuf.InstanceExecutionTimedOut] = + new ProtoMap[InstanceExecutionTimedOut, protobuf.InstanceExecutionTimedOut] { + + val companion = protobuf.InstanceExecutionTimedOut + + def toProto(a: InstanceExecutionTimedOut): protobuf.InstanceExecutionTimedOut = + protobuf.InstanceExecutionTimedOut() + + def fromProto(message: protobuf.InstanceExecutionTimedOut): Try[InstanceExecutionTimedOut] = + Success(InstanceExecutionTimedOut()) + } + + implicit def noInstanceFoundProto: ProtoMap[NoInstanceFound.type, protobuf.NoInstanceFound] = + new ProtoMap[NoInstanceFound.type, protobuf.NoInstanceFound] { + + val companion = protobuf.NoInstanceFound + + def toProto(a: NoInstanceFound.type): protobuf.NoInstanceFound = + protobuf.NoInstanceFound() + + def fromProto(message: protobuf.NoInstanceFound): Try[NoInstanceFound.type] = + Success(NoInstanceFound) + } + + implicit def invalidExecutionProto: ProtoMap[InvalidExecution, protobuf.InvalidExecution] = + new ProtoMap[InvalidExecution, protobuf.InvalidExecution] { + + val companion = protobuf.InvalidExecution + + def toProto(a: InvalidExecution): protobuf.InvalidExecution = + protobuf.InvalidExecution() + + def fromProto(message: protobuf.InvalidExecution): Try[InvalidExecution] = + Success(InvalidExecution()) + } + + implicit def pushProto(implicit ev0: SerializersProvider): ProtoMap[Push, protobuf.Push] = + new ProtoMap[Push, protobuf.Push] { + + val companion = protobuf.Push + + def toProto(a: Push): protobuf.Push = + protobuf.Push(Some(ctxToProto(a.mandated)), Some(a.uuid.toString)) + + def fromProto(message: protobuf.Push): Try[Push] = + for { + mandatedId <- versioned(message.mandated, "mandated") + mandated <- ctxFromProto(mandatedId) + uuidRaw <- versioned(message.uuid, "uuid") + uuid <- Try(UUID.fromString(uuidRaw)) + } yield Push(mandated, uuid) + } + + implicit def pullProto(implicit ev0: SerializersProvider): ProtoMap[Pull, protobuf.Pull] = + new ProtoMap[Pull, protobuf.Pull] { + + val companion = protobuf.Pull + + def toProto(a: Pull): protobuf.Pull = + protobuf.Pull(Some(ctxToProto(a.agent))) + + def fromProto(message: protobuf.Pull): Try[Pull] = + for { + agentId <- versioned(message.agent, "agent") + agent <- ctxFromProto(agentId) + } yield Pull(agent) + } + + implicit def availableQuestProto(implicit ev0: SerializersProvider): ProtoMap[AvailableQuest, protobuf.AvailableQuest] = + new ProtoMap[AvailableQuest, protobuf.AvailableQuest] { + + val companion = protobuf.AvailableQuest + + def toProto(a: AvailableQuest): protobuf.AvailableQuest = + protobuf.AvailableQuest(Some(ctxToProto(a.mandated)), Some(a.uuid.toString)) + + def fromProto(message: protobuf.AvailableQuest): Try[AvailableQuest] = + for { + mandatedId <- versioned(message.mandated, "mandated") + mandated <- ctxFromProto(mandatedId) + uuidRaw <- versioned(message.uuid, "uuid") + uuid <- Try(UUID.fromString(uuidRaw)) + } yield AvailableQuest(mandated, uuid) + } + + implicit def consideringProto(implicit ev0: SerializersProvider): ProtoMap[Considering, protobuf.Considering] = + new ProtoMap[Considering, protobuf.Considering] { + + val companion = protobuf.Considering + + def toProto(a: Considering): protobuf.Considering = + protobuf.Considering(Some(ctxToProto(a.agent))) + + def fromProto(message: protobuf.Considering): Try[Considering] = + for { + agentId <- versioned(message.agent, "agent") + agent <- ctxFromProto(agentId) + } yield Considering(agent) + } + + implicit def commitProto(implicit ev0: SerializersProvider): ProtoMap[Commit, protobuf.Commit] = + new ProtoMap[Commit, protobuf.Commit] { + + val companion = protobuf.Commit + + def toProto(a: Commit): protobuf.Commit = + protobuf.Commit(Some(ctxToProto(a.mandated)), Some(ctxToProto(a.execute))) + + def fromProto(message: protobuf.Commit): Try[Commit] = + for { + mandatedId <- versioned(message.mandated, "mandated") + mandated <- ctxFromProto(mandatedId) + executeProto <- versioned(message.execute, "execute") + execute <- ctxFromProto(executeProto) + } yield Commit(mandated, execute) + } + + implicit def questTakenProto: ProtoMap[QuestTaken.type, protobuf.QuestTaken] = + new ProtoMap[QuestTaken.type, protobuf.QuestTaken] { + + val companion = protobuf.QuestTaken + + def toProto(a: QuestTaken.type): protobuf.QuestTaken = + protobuf.QuestTaken() + + def fromProto(message: protobuf.QuestTaken): Try[QuestTaken.type] = + Success(QuestTaken) + } +} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolInteractionExecution.scala similarity index 96% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala rename to runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolInteractionExecution.scala index c2f0ba927..681ed7ae4 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolInteractionExecution.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolInteractionExecution.scala @@ -1,4 +1,4 @@ -package com.ing.baker.runtime.akka.actor.interaction_schedulling +package com.ing.baker.runtime.akka.actor.interaction_scheduling import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolPushPullMatching.scala similarity index 75% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala rename to runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolPushPullMatching.scala index 3a3682a22..87efb392a 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolPushPullMatching.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolPushPullMatching.scala @@ -1,13 +1,14 @@ -package com.ing.baker.runtime.akka.actor.interaction_schedulling +package com.ing.baker.runtime.akka.actor.interaction_scheduling import java.util.UUID import akka.actor.ActorRef +import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable /** * Protocol done to find a possible matching between a QuestMandated and an available InteractionAgent */ -sealed trait ProtocolPushPullMatching +sealed trait ProtocolPushPullMatching extends BakerSerializable object ProtocolPushPullMatching { diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolQuestCommit.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolQuestCommit.scala similarity index 73% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolQuestCommit.scala rename to runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolQuestCommit.scala index 28af28a0e..894eacfd6 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/ProtocolQuestCommit.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolQuestCommit.scala @@ -1,12 +1,13 @@ -package com.ing.baker.runtime.akka.actor.interaction_schedulling +package com.ing.baker.runtime.akka.actor.interaction_scheduling import akka.actor.ActorRef +import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable /** * A Protocol executed after finding a candidate match between a QuestMandated and an InteractionAgent, it makes sure * that 1 QuestMandated commits with 1 InteractionAgent only and vice versa, without leaving orphan agents. */ -sealed trait ProtocolQuestCommit +sealed trait ProtocolQuestCommit extends BakerSerializable object ProtocolQuestCommit { diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/QuestMandated.scala similarity index 94% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala rename to runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/QuestMandated.scala index 34231238f..b0c20f9bc 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/QuestMandated.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/QuestMandated.scala @@ -1,11 +1,11 @@ -package com.ing.baker.runtime.akka.actor.interaction_schedulling +package com.ing.baker.runtime.akka.actor.interaction_scheduling import java.util.UUID import akka.actor.{Actor, ActorRef, PoisonPill, Props} import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} import akka.util.Timeout -import com.ing.baker.runtime.akka.actor.interaction_schedulling.QuestMandated.{ComputationTimeout, PostTimeout, Start} +import com.ing.baker.runtime.akka.actor.interaction_scheduling.QuestMandated.{ComputationTimeout, PostTimeout, Start} import com.ing.baker.runtime.scaladsl.IngredientInstance import org.slf4j.LoggerFactory import QuestMandated._ diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala index 47a17f740..d740c2f2c 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala @@ -2,8 +2,9 @@ package com.ing.baker.runtime.akka.actor.serialization import akka.actor.ExtendedActorSystem import akka.serialization.SerializerWithStringManifest -import com.ing.baker.{il, runtime} import com.ing.baker.runtime.akka.actor.ClusterBakerActorProvider +import com.ing.baker.runtime.akka.actor.interaction_scheduling.InteractionSchedulingProto._ +import com.ing.baker.runtime.akka.actor.interaction_scheduling.{ProtocolInteractionExecution, ProtocolPushPullMatching, ProtocolQuestCommit} import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProto._ import com.ing.baker.runtime.akka.actor.process_index.{ProcessIndex, ProcessIndexProtocol} import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProto._ @@ -11,6 +12,7 @@ import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProto._ import com.ing.baker.runtime.akka.actor.recipe_manager.{RecipeManager, RecipeManagerProtocol} import com.ing.baker.runtime.akka.actor.serialization.BakerTypedProtobufSerializer.BinarySerializable +import com.ing.baker.{il, runtime} import org.slf4j.LoggerFactory import scala.reflect.ClassTag @@ -26,7 +28,7 @@ object BakerTypedProtobufSerializer { val identifier = 101 def entries(implicit ev0: SerializersProvider): List[BinarySerializable] = - commonEntries ++ processIndexEntries ++ processInstanceEntries ++ recipeManagerEntries + commonEntries ++ processIndexEntries ++ processInstanceEntries ++ recipeManagerEntries ++ interactionSchedulingEntries def commonEntries(implicit ev0: SerializersProvider): List[BinarySerializable] = List( @@ -158,6 +160,32 @@ object BakerTypedProtobufSerializer { .register("RecipeManager.RecipeAdded") ) + def interactionSchedulingEntries(implicit ev0: SerializersProvider): List[BinarySerializable] = + List( + forType[ProtocolInteractionExecution.InstanceExecutedSuccessfully] + .register("InteractionSchedulingProtocols.InstanceExecutedSuccessfully"), + forType[ProtocolInteractionExecution.InstanceExecutionFailed] + .register("InteractionSchedulingProtocols.InstanceExecutionFailed"), + forType[ProtocolInteractionExecution.InstanceExecutionTimedOut] + .register("InteractionSchedulingProtocols.InstanceExecutionTimedOut"), + forType[ProtocolInteractionExecution.NoInstanceFound.type] + .register("InteractionSchedulingProtocols.NoInstanceFound"), + forType[ProtocolInteractionExecution.InvalidExecution] + .register("InteractionSchedulingProtocols.InvalidExecution"), + forType[ProtocolPushPullMatching.Push] + .register("InteractionSchedulingProtocols.Push"), + forType[ProtocolPushPullMatching.Pull] + .register("InteractionSchedulingProtocols.Pull"), + forType[ProtocolPushPullMatching.AvailableQuest] + .register("InteractionSchedulingProtocols.AvailableQuest"), + forType[ProtocolQuestCommit.Considering] + .register("InteractionSchedulingProtocols.Considering"), + forType[ProtocolQuestCommit.Commit] + .register("InteractionSchedulingProtocols.Commit"), + forType[ProtocolQuestCommit.QuestTaken.type] + .register("InteractionSchedulingProtocols.QuestTaken") + ) + def forType[A <: AnyRef](implicit tag: ClassTag[A]): RegisterFor[A] = new RegisterFor[A](tag) class RegisterFor[A <: AnyRef](classTag: ClassTag[A]) { diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala index 3fed2ef5d..c51f3b341 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala @@ -5,7 +5,7 @@ import com.ing.baker.il import com.ing.baker.types import com.ing.baker.runtime.akka.actor.protobuf import com.ing.baker.runtime.akka.actor.serialization.protomappings._ -import com.ing.baker.runtime.scaladsl.{EventMoment, RecipeInstanceState, EventInstance, SensoryEventResult} +import com.ing.baker.runtime.scaladsl.{EventInstance, EventMoment, IngredientInstance, RecipeInstanceState, SensoryEventResult} import scalapb.GeneratedMessageCompanion import scala.util.{Success, Try} @@ -50,6 +50,9 @@ object ProtoMap { implicit val ingredientDescriptorMapping: ProtoMap[il.IngredientDescriptor, protobuf.IngredientDescriptor] = new IngredientDescriptorMapping + implicit val ingredientInstanceMapping: ProtoMap[IngredientInstance, protobuf.Ingredient] = + new IngredientInstanceMapping + implicit val bakerTypeMapping: ProtoMap[types.Type, protobuf.Type] = new BakerTypesMapping diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/IngredientInstanceMapping.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/IngredientInstanceMapping.scala new file mode 100644 index 000000000..a2b40b417 --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/IngredientInstanceMapping.scala @@ -0,0 +1,24 @@ +package com.ing.baker.runtime.akka.actor.serialization.protomappings + +import com.ing.baker.runtime.akka.actor.serialization.ProtoMap +import com.ing.baker.runtime.akka.actor.protobuf +import com.ing.baker.runtime.scaladsl.IngredientInstance +import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} + +import scala.util.Try + +class IngredientInstanceMapping extends ProtoMap[IngredientInstance, protobuf.Ingredient] { + + val companion = protobuf.Ingredient + + override def toProto(data: IngredientInstance): protobuf.Ingredient = + protobuf.Ingredient(Option(data.name), None, Some(ctxToProto(data.value))) + + override def fromProto(message: protobuf.Ingredient): Try[IngredientInstance] = + for { + name <- versioned(message.name, "name") + valueProto <- versioned(message.value, "value") + value <- ctxFromProto(valueProto) + } yield IngredientInstance(name, value) + +} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala index db42627e2..e2e85d6b1 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala @@ -6,8 +6,8 @@ import akka.actor.ActorSystem import akka.pattern.ask import akka.util.Timeout import com.ing.baker.il.petrinet.InteractionTransition -import com.ing.baker.runtime.akka.actor.interaction_schedulling.QuestMandated.Start -import com.ing.baker.runtime.akka.actor.interaction_schedulling.{InteractionAgent, ProtocolInteractionExecution, QuestMandated} +import com.ing.baker.runtime.akka.actor.interaction_scheduling.QuestMandated.Start +import com.ing.baker.runtime.akka.actor.interaction_scheduling.{InteractionAgent, ProtocolInteractionExecution, QuestMandated} import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance, InteractionInstance} import scala.compat.java8.FunctionConverters._ diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InstanceSchedulingSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InstanceSchedulingSpec.scala similarity index 91% rename from runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InstanceSchedulingSpec.scala rename to runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InstanceSchedulingSpec.scala index 8b81a0089..b9cf18030 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_schedulling/InstanceSchedulingSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InstanceSchedulingSpec.scala @@ -1,11 +1,11 @@ -package com.ing.baker.runtime.akka.actor.interaction_schedulling +package com.ing.baker.runtime.akka.actor.interaction_scheduling import akka.actor.{ActorRef, ActorSystem} import akka.testkit.{ImplicitSender, TestKit} import akka.util.Timeout import cats.effect.{IO, Timer} -import com.ing.baker.runtime.akka.actor.interaction_schedulling.ProtocolInteractionExecution.InstanceExecutedSuccessfully -import com.ing.baker.runtime.akka.actor.interaction_schedulling.QuestMandated.Start +import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolInteractionExecution.InstanceExecutedSuccessfully +import com.ing.baker.runtime.akka.actor.interaction_scheduling.QuestMandated.Start import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance, InteractionInstance} import com.ing.baker.types.{CharArray, PrimitiveValue} import com.typesafe.config.{Config, ConfigFactory} From 4c9338745d6cf8812d896f066c8d7dc215e3c944 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Mon, 23 Sep 2019 17:09:25 +0200 Subject: [PATCH 12/86] Implemented client and server for BaaS (only 1 method) --- baas/src/main/protobuf/baas.proto | 48 +--- baas/src/main/resources/reference.conf | 21 +- .../ing/baker/runtime/baas/BaaSProto.scala | 54 ++++ .../ing/baker/runtime/baas/BaaSProtocol.scala | 12 + .../ing/baker/runtime/baas/BaaSServer.scala | 38 +++ .../baker/runtime/baas/MarshallingUtils.scala | 17 ++ .../baker/runtime/baas/scaladsl/Baker.scala | 243 ++++++++++++++++++ .../baas/common/CheckoutFlowRecipe.scala | 122 +++++++++ .../common/CommonBaaSServerClientSpec.scala | 57 ++++ .../baas/common/MakePaymentInstance.scala | 18 ++ .../baas/common/ReserveItemsInstance.scala | 19 ++ .../baas/common/ShipItemsInstance.scala | 20 ++ .../ScalaDSLBaaSServerClientSpec.scala | 33 +++ .../ProcessInstanceEventSourcing.scala | 4 +- .../serialization/SerializersProvider.scala | 14 +- 15 files changed, 650 insertions(+), 70 deletions(-) create mode 100644 baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala create mode 100644 baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala create mode 100644 baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala create mode 100644 baas/src/main/scala/com/ing/baker/runtime/baas/MarshallingUtils.scala create mode 100644 baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala create mode 100644 baas/src/test/scala/com/ing/baker/runtime/baas/common/CheckoutFlowRecipe.scala create mode 100644 baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala create mode 100644 baas/src/test/scala/com/ing/baker/runtime/baas/common/MakePaymentInstance.scala create mode 100644 baas/src/test/scala/com/ing/baker/runtime/baas/common/ReserveItemsInstance.scala create mode 100644 baas/src/test/scala/com/ing/baker/runtime/baas/common/ShipItemsInstance.scala create mode 100644 baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala diff --git a/baas/src/main/protobuf/baas.proto b/baas/src/main/protobuf/baas.proto index 97400fc0a..d25dab6bd 100644 --- a/baas/src/main/protobuf/baas.proto +++ b/baas/src/main/protobuf/baas.proto @@ -8,13 +8,7 @@ option (scalapb.options) = { flat_package: true }; -message AddInteractionHTTPRequest { - optional string name = 1; - optional string uri = 2; - repeated Type input = 3; -} - -message AddInteractionHTTPResponse { +message BaaSRemoteFailure { optional string message = 1; } @@ -25,43 +19,3 @@ message AddRecipeRequest { message AddRecipeResponse { optional string recipeId = 1; } - -message BakeRequest { - optional string recipeId= 1; -} - -message BakeResponse { - optional ProcessState processState= 1; -} - -message EventsResponse { - repeated RuntimeEvent runtimeEvent = 1; -} - -message IngredientsResponse { - map ingredients = 1; -} - -message ProcessEventRequest { - optional RuntimeEvent runtimeEvent = 1; -} - -message ProcessEventResponse { - optional SensoryEventStatus sensoryEventStatus = 1; -} - -message StateResponse { - optional ProcessState processState= 1; -} - -message VisualStateResponse { - optional string VisualStateResponse = 1; -} - -message ExecuteInteractionHTTPRequest { - repeated Ingredient ingredient = 1; -} - -message ExecuteInteractionHTTPResponse { - optional RuntimeEvent runtimeEvent = 1; -} \ No newline at end of file diff --git a/baas/src/main/resources/reference.conf b/baas/src/main/resources/reference.conf index b4faba05f..12d38ea5d 100644 --- a/baas/src/main/resources/reference.conf +++ b/baas/src/main/resources/reference.conf @@ -1,20 +1 @@ -baker.engine.baas { - client-host = "localhost" - client-port = 8081 - baas-host = "localhost" - baas-port = 8091 -} - -akka { - actor { - serializers { - baas-protobuf = "com.ing.baker.baas.serialization.BaasProtobufSerializer" - } - - serialization-bindings { - // map baker classes to use protobuf serialization - "com.ing.baker.baas.server.protocol.BaasRequest" = baas-protobuf - "com.ing.baker.baas.server.protocol.BaasResponse" = baas-protobuf - } - } -} \ No newline at end of file +include "baker.conf" diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala new file mode 100644 index 000000000..75c25adb3 --- /dev/null +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala @@ -0,0 +1,54 @@ +package com.ing.baker.runtime.baas + +import BaaSProtocol._ +import com.ing.baker.runtime.akka.actor.serialization.{ProtoMap, SerializersProvider} +import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import scalapb.GeneratedMessageCompanion + +import scala.util.Try + +object BaaSProto { + + implicit val baaSRemoteFailureProto: ProtoMap[BaaSRemoteFailure, protobuf.BaaSRemoteFailure] = + new ProtoMap[BaaSRemoteFailure, protobuf.BaaSRemoteFailure] { + + override def companion: GeneratedMessageCompanion[protobuf.BaaSRemoteFailure] = + protobuf.BaaSRemoteFailure + + override def toProto(a: BaaSRemoteFailure): protobuf.BaaSRemoteFailure = + protobuf.BaaSRemoteFailure(Some(a.message)) + + override def fromProto(message: protobuf.BaaSRemoteFailure): Try[BaaSRemoteFailure] = + versioned(message.message, "message") + .map(BaaSRemoteFailure) + } + + implicit def addRecipeRequestProto(implicit ev0: SerializersProvider): ProtoMap[AddRecipeRequest, protobuf.AddRecipeRequest] = + new ProtoMap[AddRecipeRequest, protobuf.AddRecipeRequest] { + + override def companion: GeneratedMessageCompanion[protobuf.AddRecipeRequest] = + protobuf.AddRecipeRequest + + override def toProto(a: AddRecipeRequest): protobuf.AddRecipeRequest = + protobuf.AddRecipeRequest(Some(ctxToProto(a.compiledRecipe))) + + override def fromProto(message: protobuf.AddRecipeRequest): Try[AddRecipeRequest] = + versioned(message.compiledRecipe, "compiledRecipe") + .flatMap(ctxFromProto(_)) + .map(AddRecipeRequest) + } + + implicit def addRecipeResponseProto: ProtoMap[AddRecipeResponse, protobuf.AddRecipeResponse] = + new ProtoMap[AddRecipeResponse, protobuf.AddRecipeResponse] { + + override def companion: GeneratedMessageCompanion[protobuf.AddRecipeResponse] = + protobuf.AddRecipeResponse + + override def toProto(a: AddRecipeResponse): protobuf.AddRecipeResponse = + protobuf.AddRecipeResponse(Some(a.recipeId)) + + override def fromProto(message: protobuf.AddRecipeResponse): Try[AddRecipeResponse] = + versioned(message.recipeId, "recipeId") + .map(AddRecipeResponse) + } +} diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala new file mode 100644 index 000000000..8e8524d0f --- /dev/null +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala @@ -0,0 +1,12 @@ +package com.ing.baker.runtime.baas + +import com.ing.baker.il.CompiledRecipe + +object BaaSProtocol { + + case class BaaSRemoteFailure(message: String) + + case class AddRecipeRequest(compiledRecipe: CompiledRecipe) + + case class AddRecipeResponse(recipeId: String) +} diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala new file mode 100644 index 000000000..836a8b792 --- /dev/null +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala @@ -0,0 +1,38 @@ +package com.ing.baker.runtime.baas + +import akka.actor.ActorSystem +import akka.http.scaladsl.Http +import akka.http.scaladsl.server.Directives._ +import akka.http.scaladsl.server.Route +import akka.stream.Materializer +import com.ing.baker.runtime.akka.actor.serialization.{Encryption, SerializersProvider} +import com.ing.baker.runtime.baas.BaaSProto._ +import com.ing.baker.runtime.baas.MarshallingUtils._ +import com.ing.baker.runtime.scaladsl.Baker + +import scala.concurrent.Future + +object BaaSServer { + + def run(baker: Baker, host: String, port: Int)(implicit system: ActorSystem, mat: Materializer): Future[Http.ServerBinding] = { + val encryption = Encryption.NoEncryption + val server = new BaaSServer()(system, mat, baker, encryption) + Http().bindAndHandle(server.route, host, port) + } +} + +class BaaSServer(implicit system: ActorSystem, mat: Materializer, baker: Baker, encryption: Encryption) { + + import system.dispatcher + + implicit val serializersProvider: SerializersProvider = + SerializersProvider(system, encryption) + + def route: Route = pathPrefix("api" / "v3")(concat(addRecipe)) + + def addRecipe: Route = post(path("addRecipe") { + entity(as[BaaSProtocol.AddRecipeRequest]) { request => + complete(baker.addRecipe(request.compiledRecipe).map(BaaSProtocol.AddRecipeResponse)) + } + }) +} diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/MarshallingUtils.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/MarshallingUtils.scala new file mode 100644 index 000000000..aceabff95 --- /dev/null +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/MarshallingUtils.scala @@ -0,0 +1,17 @@ +package com.ing.baker.runtime.baas + +import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller} +import akka.http.scaladsl.model.{ContentTypes, MediaTypes} +import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller} +import com.ing.baker.runtime.akka.actor.serialization.ProtoMap + +object MarshallingUtils { + + type ProtoMessage[A] = scalapb.GeneratedMessage with scalapb.Message[A] + + implicit def protoMarshaller[A, P <: ProtoMessage[P]](implicit mapping: ProtoMap[A, P]): ToEntityMarshaller[A] = + Marshaller.ByteArrayMarshaller.wrap(MediaTypes.`application/octet-stream`)(mapping.toByteArray) + + implicit def protoUnmarshaller[A, P <: ProtoMessage[P]](implicit mapping: ProtoMap[A, P]): FromEntityUnmarshaller[A] = + Unmarshaller.byteArrayUnmarshaller.map(mapping.fromByteArray(_).get) +} diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala new file mode 100644 index 000000000..3ce94105d --- /dev/null +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala @@ -0,0 +1,243 @@ +package com.ing.baker.runtime.baas.scaladsl + +import akka.actor.ActorSystem +import akka.http.scaladsl.Http +import akka.http.scaladsl.marshalling.Marshal +import akka.http.scaladsl.model.Uri.Path +import akka.http.scaladsl.model.{HttpMethods, HttpRequest, MessageEntity, Uri} +import akka.http.scaladsl.unmarshalling.Unmarshal +import akka.stream.Materializer +import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} +import com.ing.baker.runtime.akka.actor.serialization.{Encryption, SerializersProvider} +import com.ing.baker.runtime.baas.BaaSProto._ +import com.ing.baker.runtime.baas.BaaSProtocol +import com.ing.baker.runtime.baas.MarshallingUtils._ +import com.ing.baker.runtime.common.SensoryEventStatus +import com.ing.baker.runtime.scaladsl.{BakerEvent, EventInstance, EventMoment, EventResolutions, InteractionInstance, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult, Baker => ScalaBaker} +import com.ing.baker.types.Value + +import scala.concurrent.Future + +class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(implicit system: ActorSystem, mat: Materializer) extends ScalaBaker { + + import system.dispatcher + + implicit val serializersProvider: SerializersProvider = + SerializersProvider(system, encryption) + + val root: Path = Path./("api")./("v3") + + def withPath(path: Path): Uri = hostname.withPath(path) + + /** + * Adds a recipe to baker and returns a recipeId for the recipe. + * + * This function is idempotent, if the same (equal) recipe was added earlier this will return the same recipeId + * + * @param compiledRecipe The compiled recipe. + * @return A recipeId + */ + override def addRecipe(compiledRecipe: CompiledRecipe): Future[String] = + for { + encoded <- Marshal(BaaSProtocol.AddRecipeRequest(compiledRecipe)).to[MessageEntity] + request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("addRecipe")), entity = encoded) //, entity = encoded.withContentType(ContentTypes.`application/octet-stream`)) + response <- Http().singleRequest(request) + decoded <- Unmarshal(response).to[BaaSProtocol.AddRecipeResponse] + } yield decoded.recipeId + + /** + * Returns the recipe information for the given RecipeId + * + * @param recipeId + * @return + */ + override def getRecipe(recipeId: String): Future[RecipeInformation] = ??? + + /** + * Returns all recipes added to this baker instance. + * + * @return All recipes in the form of map of recipeId -> CompiledRecipe + */ + override def getAllRecipes: Future[Map[String, RecipeInformation]] = ??? + + /** + * Creates a process instance for the given recipeId with the given RecipeInstanceId as identifier + * + * @param recipeId The recipeId for the recipe to bake + * @param recipeInstanceId The identifier for the newly baked process + * @return + */ + override def bake(recipeId: String, recipeInstanceId: String): Future[Unit] = ??? + + /** + * Notifies Baker that an event has happened and waits until the event was accepted but not executed by the process. + * + * Possible failures: + * `NoSuchProcessException` -> When no process exists for the given id + * `ProcessDeletedException` -> If the process is already deleted + * + * @param recipeInstanceId The process identifier + * @param event The event object + * @param correlationId Id used to ensure the process instance handles unique events + */ + override def fireEventAndResolveWhenReceived(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): Future[SensoryEventStatus] = ??? + + /** + * Notifies Baker that an event has happened and waits until all the actions which depend on this event are executed. + * + * Possible failures: + * `NoSuchProcessException` -> When no process exists for the given id + * `ProcessDeletedException` -> If the process is already deleted + * + * @param recipeInstanceId The process identifier + * @param event The event object + * @param correlationId Id used to ensure the process instance handles unique events + */ + override def fireEventAndResolveWhenCompleted(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): Future[SensoryEventResult] = ??? + + /** + * Notifies Baker that an event has happened and waits until an specific event has executed. + * + * Possible failures: + * `NoSuchProcessException` -> When no process exists for the given id + * `ProcessDeletedException` -> If the process is already deleted + * + * @param recipeInstanceId The process identifier + * @param event The event object + * @param onEvent The name of the event to wait for + * @param correlationId Id used to ensure the process instance handles unique events + */ + override def fireEventAndResolveOnEvent(recipeInstanceId: String, event: EventInstance, onEvent: String, correlationId: Option[String]): Future[SensoryEventResult] = ??? + + /** + * Notifies Baker that an event has happened and provides 2 async handlers, one for when the event was accepted by + * the process, and another for when the event was fully executed by the process. + * + * Possible failures: + * `NoSuchProcessException` -> When no process exists for the given id + * `ProcessDeletedException` -> If the process is already deleted + * + * @param recipeInstanceId The process identifier + * @param event The event object + * @param correlationId Id used to ensure the process instance handles unique events + */ + override def fireEvent(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): EventResolutions = ??? + + /** + * Returns an index of all running processes. + * + * Can potentially return a partial index when baker runs in cluster mode + * and not all shards can be reached within the given timeout. + * + * Does not include deleted processes. + * + * @return An index of all processes + */ + override def getAllRecipeInstancesMetadata: Future[Set[RecipeInstanceMetadata]] = ??? + + /** + * Returns the process state. + * + * @param recipeInstanceId The process identifier + * @return The process state. + */ + override def getRecipeInstanceState(recipeInstanceId: String): Future[RecipeInstanceState] = ??? + + /** + * Returns all provided ingredients for a given RecipeInstance id. + * + * @param recipeInstanceId The process id. + * @return The provided ingredients. + */ + override def getIngredients(recipeInstanceId: String): Future[Map[String, Value]] = ??? + + /** + * Returns all fired events for a given RecipeInstance id. + * + * @param recipeInstanceId The process id. + * @return The events + */ + override def getEvents(recipeInstanceId: String): Future[Seq[EventMoment]] = ??? + + /** + * Returns all names of fired events for a given RecipeInstance id. + * + * @param recipeInstanceId The process id. + * @return The event names + */ + override def getEventNames(recipeInstanceId: String): Future[Seq[String]] = ??? + + /** + * Returns the visual state (.dot) for a given process. + * + * @param recipeInstanceId The process identifier. + * @return A visual (.dot) representation of the process state. + */ + override def getVisualState(recipeInstanceId: String, style: RecipeVisualStyle): Future[String] = ??? + + /** + * Registers a listener to all runtime events for recipes with the given name run in this baker instance. + * + * Note that the delivery guarantee is *AT MOST ONCE*. Do not use it for critical functionality + */ + override def registerEventListener(recipeName: String, listenerFunction: (String, EventInstance) => Unit): Future[Unit] = ??? + + /** + * Registers a listener to all runtime events for all recipes that run in this Baker instance. + * + * Note that the delivery guarantee is *AT MOST ONCE*. Do not use it for critical functionality + */ + override def registerEventListener(listenerFunction: (String, EventInstance) => Unit): Future[Unit] = ??? + + /** + * Registers a listener function that listens to all BakerEvents + * + * Note that the delivery guarantee is *AT MOST ONCE*. Do not use it for critical functionality + * + * @param listenerFunction + * @return + */ + override def registerBakerEventListener(listenerFunction: BakerEvent => Unit): Future[Unit] = ??? + + /** + * Adds an interaction implementation to baker. + * + * @param implementation The implementation object + */ + override def addInteractionInstance(implementation: InteractionInstance): Future[Unit] = ??? + + /** + * Adds a sequence of interaction implementation to baker. + * + * @param implementations The implementation object + */ + override def addInteractionInstances(implementations: Seq[InteractionInstance]): Future[Unit] = ??? + + /** + * Attempts to gracefully shutdown the baker system. + */ + override def gracefulShutdown(): Future[Unit] = ??? + + /** + * Retries a blocked interaction. + * + * @return + */ + override def retryInteraction(recipeInstanceId: String, interactionName: String): Future[Unit] = ??? + + /** + * Resolves a blocked interaction by specifying it's output. + * + * !!! You should provide an event of the original interaction. Event / ingredient renames are done by Baker. + * + * @return + */ + override def resolveInteraction(recipeInstanceId: String, interactionName: String, event: EventInstance): Future[Unit] = ??? + + /** + * Stops the retrying of an interaction. + * + * @return + */ + override def stopRetryingInteraction(recipeInstanceId: String, interactionName: String): Future[Unit] = ??? +} diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CheckoutFlowRecipe.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CheckoutFlowRecipe.scala new file mode 100644 index 000000000..bc0ab7a7b --- /dev/null +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CheckoutFlowRecipe.scala @@ -0,0 +1,122 @@ +package com.ing.baker.runtime.baas.common + +import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff +import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff.UntilDeadline +import com.ing.baker.recipe.scaladsl.{Event, Ingredient, Interaction, Recipe} +import CheckoutFlowIngredients._ +import CheckoutFlowEvents._ +import CheckoutFlowInteractions._ + +import scala.concurrent.Future +import scala.concurrent.duration._ + +object CheckoutFlowIngredients { + + case class OrderId(orderId: String) + + case class Item(itemId: String) + + case class ReservedItems(items: List[Item], data: Array[Byte]) + + case class ShippingAddress(address: String) + + case class PaymentInformation(info: String) + + case class ShippingOrder(items: List[Item], data: Array[Byte], address: ShippingAddress) +} + +object CheckoutFlowEvents { + + case class OrderPlaced(orderId: OrderId, items: List[Item]) + + case class PaymentInformationReceived(paymentInformation: PaymentInformation) + + case class ShippingAddressReceived(shippingAddress: ShippingAddress) + + sealed trait ReserveItemsOutput + + case class OrderHadUnavailableItems(unavailableItems: List[Item]) extends ReserveItemsOutput + + case class ItemsReserved(reservedItems: ReservedItems) extends ReserveItemsOutput + + sealed trait MakePaymentOutput + + case class PaymentSuccessful(shippingOrder: ShippingOrder) extends MakePaymentOutput + + case class PaymentFailed() extends MakePaymentOutput + + case class ShippingConfirmed() +} + +object CheckoutFlowInteractions { + + trait ReserveItems { + + def apply(orderId: OrderId, items: List[Item]): Future[ReserveItemsOutput] + } + + def ReserveItemsInteraction = Interaction( + name = "ReserveItems", + inputIngredients = Seq( + Ingredient[OrderId]("orderId"), + Ingredient[List[Item]]("items") + ), + output = Seq( + Event[OrderHadUnavailableItems], + Event[ItemsReserved] + ) + ) + + trait MakePayment { + + def apply(items: ReservedItems, address: ShippingAddress, payment: PaymentInformation): Future[MakePaymentOutput] + } + + def MakePaymentInteraction = Interaction( + name = "MakePayment", + inputIngredients = Seq( + Ingredient[ReservedItems]("reservedItems"), + Ingredient[ShippingAddress]("shippingAddress"), + Ingredient[PaymentInformation]("paymentInformation") + ), + output = Seq( + Event[PaymentSuccessful], + Event[PaymentFailed] + ) + ) + + trait ShipItems { + + def apply(order: ShippingOrder): Future[ShippingConfirmed] + } + + def ShipItemsInteraction = Interaction( + name = "ShipItems", + inputIngredients = Seq( + Ingredient[ShippingOrder]("shippingOrder") + ), + output = Seq( + Event[ShippingConfirmed] + ) + ) +} + +object CheckoutFlowRecipe { + + def recipe: Recipe = Recipe("Webshop") + .withSensoryEvents( + Event[OrderPlaced], + Event[PaymentInformationReceived], + Event[ShippingAddressReceived]) + .withInteractions( + ReserveItemsInteraction, + MakePaymentInteraction, + ShipItemsInteraction) + .withDefaultFailureStrategy( + RetryWithIncrementalBackoff + .builder() + .withInitialDelay(100 milliseconds) + .withUntil(Some(UntilDeadline(24 hours))) + .withMaxTimeBetweenRetries(Some(10 minutes)) + .build()) +} diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala new file mode 100644 index 000000000..e93fc78cf --- /dev/null +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala @@ -0,0 +1,57 @@ +package com.ing.baker.runtime.baas.common + +import akka.actor.ActorSystem +import akka.http.scaladsl.Http +import akka.stream.Materializer +import cats.effect.{IO, Timer} +import cats.~> +import com.ing.baker.compiler.RecipeCompiler +import com.ing.baker.runtime.baas.BaaSServer +import com.ing.baker.runtime.common.Baker +import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi +import com.ing.baker.runtime.scaladsl.{InteractionInstance, Baker => ScalaBaker} +import org.scalatest.{AsyncFunSpec, BeforeAndAfterAll, Matchers} + +import scala.concurrent.duration._ +import scala.concurrent.{Await, Future} + +abstract class CommonBaaSServerClientSpec[F[_]]( + clientBaker: Baker[F], + serverBaker: ScalaBaker, + host: String, + port: Int, + toFuture: F ~> Future)( + implicit system: ActorSystem, materializer: Materializer + ) + extends AsyncFunSpec + with Matchers + with BeforeAndAfterAll + with LanguageApi { + + var serverShutdown: Http.ServerBinding = _ + + implicit val timer: Timer[IO] = IO.timer(system.dispatcher) + + override def beforeAll(): Unit = { + val makePaymentInstance: InteractionInstance = InteractionInstance.unsafeFrom(new MakePaymentInstance()) + val reserveItemsInstance: InteractionInstance = InteractionInstance.unsafeFrom(new ReserveItemsInstance()) + val shipItemsInstance: InteractionInstance = InteractionInstance.unsafeFrom(new ShipItemsInstance()) + val addInteractions = serverBaker.addInteractionInstances(Seq(makePaymentInstance, reserveItemsInstance, shipItemsInstance)) + Await.result(addInteractions, 10 seconds) + serverShutdown = Await.result(BaaSServer.run(serverBaker, host, port), 10 seconds) + } + + override def afterAll(): Unit = { + Await.result(serverShutdown.unbind(), 10 seconds) + } + + describe("Baker Client-Server comm") { + it("Baker.addRecipe") { + val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) + for { + recipeId <- toFuture(clientBaker.addRecipe(compiledRecipe)) + recipeInformation <- serverBaker.getRecipe(recipeId) + } yield recipeInformation.compiledRecipe shouldBe compiledRecipe + } + } +} diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/MakePaymentInstance.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/common/MakePaymentInstance.scala new file mode 100644 index 000000000..307c1cb19 --- /dev/null +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/common/MakePaymentInstance.scala @@ -0,0 +1,18 @@ +package com.ing.baker.runtime.baas.common + +import cats.effect.{IO, Timer} +import com.ing.baker.runtime.baas.common.CheckoutFlowEvents.MakePaymentOutput +import com.ing.baker.runtime.baas.common.CheckoutFlowIngredients.{PaymentInformation, ReservedItems, ShippingAddress, ShippingOrder} +import com.ing.baker.runtime.baas.common.CheckoutFlowInteractions.MakePayment + +import scala.concurrent.Future +import scala.concurrent.duration._ + +class MakePaymentInstance(implicit timer: Timer[IO]) extends MakePayment { + + override def apply(items: ReservedItems, address: ShippingAddress, payment: PaymentInformation): Future[MakePaymentOutput] = { + IO.sleep(5 second) + .map(_ => CheckoutFlowEvents.PaymentSuccessful(ShippingOrder(items.items, items.data, address))) + .unsafeToFuture() + } +} diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/ReserveItemsInstance.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/common/ReserveItemsInstance.scala new file mode 100644 index 000000000..e8b462fef --- /dev/null +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/common/ReserveItemsInstance.scala @@ -0,0 +1,19 @@ +package com.ing.baker.runtime.baas.common + +import cats.effect.{IO, Timer} +import cats.implicits._ +import com.ing.baker.runtime.baas.common.CheckoutFlowEvents.ReserveItemsOutput +import com.ing.baker.runtime.baas.common.CheckoutFlowIngredients.{Item, OrderId, ReservedItems} +import com.ing.baker.runtime.baas.common.CheckoutFlowInteractions.ReserveItems + +import scala.concurrent.Future +import scala.concurrent.duration._ + +class ReserveItemsInstance(implicit timer: Timer[IO]) extends ReserveItems { + + override def apply(orderId: OrderId, items: List[Item]): Future[ReserveItemsOutput] = { + IO.sleep(1 second) + .as(CheckoutFlowEvents.ItemsReserved(ReservedItems(items, Array.fill(1000)(Byte.MaxValue)))) + .unsafeToFuture() + } +} diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/ShipItemsInstance.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/common/ShipItemsInstance.scala new file mode 100644 index 000000000..7eece69a3 --- /dev/null +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/common/ShipItemsInstance.scala @@ -0,0 +1,20 @@ +package com.ing.baker.runtime.baas.common + +import cats.effect.{IO, Timer} +import cats.implicits._ +import com.ing.baker.runtime.baas.common.CheckoutFlowEvents.ShippingConfirmed +import com.ing.baker.runtime.baas.common.CheckoutFlowIngredients.ShippingOrder +import com.ing.baker.runtime.baas.common.CheckoutFlowInteractions.ShipItems + +import scala.concurrent.Future +import scala.concurrent.duration._ + +class ShipItemsInstance(implicit timer: Timer[IO]) extends ShipItems { + + override def apply(order: ShippingOrder): Future[ShippingConfirmed] = { + IO.sleep(500 millis) + .as(ShippingConfirmed()) + .unsafeToFuture() + } +} + diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala new file mode 100644 index 000000000..8346edde6 --- /dev/null +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala @@ -0,0 +1,33 @@ +package com.ing.baker.runtime.baas.scaladsl + +import akka.actor.ActorSystem +import akka.http.scaladsl.model.Uri +import akka.stream.{ActorMaterializer, Materializer} +import cats.arrow.FunctionK +import cats.~> +import com.ing.baker.runtime.baas.common.CommonBaaSServerClientSpec +import com.ing.baker.runtime.scaladsl.{Baker => ScalaBaker} + +import scala.concurrent.Future +import ScalaDSLBaaSServerClientSpec._ +import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi + +object ScalaDSLBaaSServerClientSpec { + + implicit val system: ActorSystem = ActorSystem("ScalaDSLBaaSServerClientSpec") + + implicit val materializer: Materializer = ActorMaterializer() + + val host: String = "localhost" + + val port: Int = 8181 + + val clientBaker = new Baker(Uri(s"http://$host:$port")) + + val serverBaker = ScalaBaker.akkaLocalDefault(system, materializer) + + val IdentityFuture: Future ~> Future = FunctionK.id +} + +class ScalaDSLBaaSServerClientSpec extends CommonBaaSServerClientSpec(clientBaker, serverBaker, host, port, IdentityFuture) with ScalaApi + diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala index adc432c23..eed684aa6 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala @@ -92,7 +92,7 @@ object ProcessInstanceEventSourcing { readJournal: CurrentEventsByPersistenceIdQuery, eventSourceFn: T ⇒ (S ⇒ E ⇒ S))(implicit actorSystem: ActorSystem): Source[(Instance[P, T, S], Event), NotUsed] = { - val serializer = new ProcessInstanceSerialization[P, T, S, E](SerializersProvider(actorSystem, null, encryption)) + val serializer = new ProcessInstanceSerialization[P, T, S, E](SerializersProvider(actorSystem, encryption)) val persistentId = ProcessInstance.recipeInstanceId2PersistenceId(processTypeName, recipeInstanceId) val src = readJournal.currentEventsByPersistenceId(persistentId, 0, Long.MaxValue) @@ -117,7 +117,7 @@ abstract class ProcessInstanceEventSourcing[P : Identifiable, T : Identifiable, val eventSource = ProcessInstanceEventSourcing.apply[P, T, S, E](eventSourceFn) - private val serializer = new ProcessInstanceSerialization[P, T, S, E](SerializersProvider(system, null, encryption)) + private val serializer = new ProcessInstanceSerialization[P, T, S, E](SerializersProvider(system, encryption)) def onRecoveryCompleted(state: Instance[P, T, S]) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/SerializersProvider.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/SerializersProvider.scala index 766d28c05..94984808a 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/SerializersProvider.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/SerializersProvider.scala @@ -7,7 +7,7 @@ case class SerializersProvider(getSerializerFor: AnyRef => Serializer, serialize object SerializersProvider { - def apply(system: ActorSystem, actorRefProvider: ActorRefProvider, encryption: Encryption = Encryption.NoEncryption): SerializersProvider = { + def apply(system: ActorSystem, actorRefProvider: ActorRefProvider, encryption: Encryption): SerializersProvider = { val serialization: Serialization = SerializationExtension.get(system) SerializersProvider( serialization.findSerializerFor, @@ -16,4 +16,16 @@ object SerializersProvider { actorRefProvider ) } + + def apply(system: ActorSystem, actorRefProvider: ActorRefProvider): SerializersProvider = { + apply(system, actorRefProvider, Encryption.NoEncryption) + } + + def apply(system: ActorSystem, encryption: Encryption): SerializersProvider = { + apply(system, null, encryption) + } + + def apply(system: ActorSystem): SerializersProvider = { + apply(system, null, Encryption.NoEncryption) + } } From 63abc8f6f96c91920e623ce1a421ac46e6160622 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Thu, 26 Sep 2019 21:48:41 +0200 Subject: [PATCH 13/86] Continued work on the server/client for baas --- baas/src/main/protobuf/baas.proto | 91 +++++++++++++++++++ .../ing/baker/runtime/baas/BaaSProto.scala | 31 +++++++ .../ing/baker/runtime/baas/BaaSProtocol.scala | 61 +++++++++++++ .../ing/baker/runtime/baas/BaaSServer.scala | 8 +- .../baker/runtime/baas/scaladsl/Baker.scala | 10 +- runtime/src/main/protobuf/common.proto | 13 +++ .../akka/actor/serialization/ProtoMap.scala | 8 +- .../RecipeInformationMapping.scala | 24 +++++ .../RecipeInstanceMetadataMapping.scala | 24 +++++ .../runtime/scaladsl/RecipeInformation.scala | 2 +- 10 files changed, 267 insertions(+), 5 deletions(-) create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RecipeInformationMapping.scala create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RecipeInstanceMetadataMapping.scala diff --git a/baas/src/main/protobuf/baas.proto b/baas/src/main/protobuf/baas.proto index d25dab6bd..53dad03c8 100644 --- a/baas/src/main/protobuf/baas.proto +++ b/baas/src/main/protobuf/baas.proto @@ -19,3 +19,94 @@ message AddRecipeRequest { message AddRecipeResponse { optional string recipeId = 1; } + +message GetRecipeRequest { + optional string recipeId = 1; +} + +message GetRecipeResponse { + optional RecipeInformation recipeInformation = 1; +} + +message GetAllRecipesResponse { + map mapping = 1; +} + +message BakeRequest { + optional string recipeId = 1; + optional string recipeInstanceId = 2; +} + +message FireEventAndResolveWhenReceivedRequest { + optional string recipeInstanceId = 1; + optional RuntimeEvent event = 2; + optional string correlationId = 3; +} + +message FireEventAndResolveWhenReceivedResponse { + optional SensoryEventStatus sensoryEventStatus = 1; +} + +message FireEventAndResolveWhenCompletedRequest { + optional string recipeInstanceId = 1; + optional RuntimeEvent event = 2; + optional string correlationId = 3; +} + +message FireEventAndResolveWhenCompletedResponse { + optional SensoryEventResult sensoryEventResult = 1; +} + +message FireEventAndResolveOnEventRequest { + optional string recipeInstanceId = 1; + optional RuntimeEvent event = 2; + optional string onEvent = 3; + optional string correlationId = 4; +} + +message FireEventAndResolveOnEventResponse { + optional SensoryEventResult sensoryEventResult = 1; +} + +message FireEventRequest { + optional string recipeInstanceId = 1; + optional RuntimeEvent event = 2; + optional string correlationId = 3; +} + +message GetAllRecipeInstancesMetadataResponse { + optional RecipeInstanceMetadata set = 1; +} + +message GetRecipeInstanceStateRequest { + optional string recipeInstanceId = 1; +} + +message GetRecipeInstanceStateResponse { + optional ProcessState recipeInstanceState = 1; +} + +message GetVisualStateRequest { + optional string recipeInstanceId = 1; +} + +message GetVisualStateResponse { + optional string state = 1; +} + +message RetryInteractionRequest { + optional string recipeInstanceId = 1; + optional string interactionName = 2; +} + +message ResolveInteractionRequest { + optional string recipeInstanceId = 1; + optional string interactionName = 2; + optional RuntimeEvent event = 3; +} + +message StopRetryingInteractionRequest { + optional string recipeInstanceId = 1; + optional string interactionName = 2; +} + diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala index 75c25adb3..0b23efa81 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala @@ -3,6 +3,7 @@ package com.ing.baker.runtime.baas import BaaSProtocol._ import com.ing.baker.runtime.akka.actor.serialization.{ProtoMap, SerializersProvider} import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.runtime.scaladsl.RecipeInformation import scalapb.GeneratedMessageCompanion import scala.util.Try @@ -51,4 +52,34 @@ object BaaSProto { versioned(message.recipeId, "recipeId") .map(AddRecipeResponse) } + + implicit def getRecipeRequestProto: ProtoMap[GetRecipeRequest, protobuf.GetRecipeRequest] = + new ProtoMap[GetRecipeRequest, protobuf.GetRecipeRequest] { + + override def companion: GeneratedMessageCompanion[protobuf.GetRecipeRequest] = + protobuf.GetRecipeRequest + + override def toProto(a: GetRecipeRequest): protobuf.GetRecipeRequest = + protobuf.GetRecipeRequest(Some(a.recipeId)) + + override def fromProto(message: protobuf.GetRecipeRequest): Try[GetRecipeRequest] = + versioned(message.recipeId, "recipeId") + .map(GetRecipeRequest) + } + + implicit def getRecipeResponseProto(implicit ev0: SerializersProvider): ProtoMap[GetRecipeResponse, protobuf.GetRecipeResponse] = + new ProtoMap[GetRecipeResponse, protobuf.GetRecipeResponse] { + + override def companion: GeneratedMessageCompanion[protobuf.GetRecipeResponse] = + protobuf.GetRecipeResponse + + override def toProto(a: GetRecipeResponse): protobuf.GetRecipeResponse = + protobuf.GetRecipeResponse(Some(ctxToProto(a.recipeInformation))) + + override def fromProto(message: protobuf.GetRecipeResponse): Try[GetRecipeResponse] = + for { + recipeInformationProto <- versioned(message.recipeInformation, "recipeInformation") + recipeInformation <- ctxFromProto(recipeInformationProto) + } yield GetRecipeResponse(recipeInformation) + } } diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala index 8e8524d0f..1a22d81d9 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala @@ -1,6 +1,8 @@ package com.ing.baker.runtime.baas import com.ing.baker.il.CompiledRecipe +import com.ing.baker.runtime.common.SensoryEventStatus +import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeInformation, RecipeInstanceMetadata, SensoryEventResult} object BaaSProtocol { @@ -9,4 +11,63 @@ object BaaSProtocol { case class AddRecipeRequest(compiledRecipe: CompiledRecipe) case class AddRecipeResponse(recipeId: String) + + case class GetRecipeRequest(recipeId: String) + + case class GetRecipeResponse(recipeInformation: RecipeInformation) + + //case class GetAllRecipesRequest() + + case class GetAllRecipesResponse(map: Map[String, RecipeInformation]) + + case class BakeRequest(recipeId: String, recipeInstanceId: String) + + //case class BakeResponse() + + case class FireEventAndResolveWhenReceivedRequest(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]) + + case class FireEventAndResolveWhenReceivedResponse(sensoryEventStatus: SensoryEventStatus) + + case class FireEventAndResolveWhenCompletedRequest(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]) + + case class FireEventAndResolveWhenCompletedResponse(sensoryEventResult: SensoryEventResult) + + case class FireEventAndResolveOnEventRequest(recipeInstanceId: String, event: EventInstance, onEvent: String, correlationId: Option[String]) + + case class FireEventAndResolveOnEventResponse(sensoryEventResult: SensoryEventResult) + + case class FireEventRequest(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]) + + // case class FireEventResponse() TODO figure out how to deal with this one + //def fireEvent(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): EventResolutions = ??? + + //case class GetAllRecipeInstancesMetadataRequest() + + case class GetAllRecipeInstancesMetadataResponse(set: RecipeInstanceMetadata) + + case class GetRecipeInstanceStateRequest(recipeInstanceId: String) + + case class GetRecipeInstanceStateResponse(recipeInstanceState) + + //case class GetIngredientsRequest(recipeInstanceId: String) + //case class GetIngredientsResponse(map: Map[String, Value]) + //case class GetEventsRequest(re) + //def getEvents(recipeInstanceId: String): Future[Seq[EventMoment]] = ??? + //def getEventNames(recipeInstanceId: String): Future[Seq[String]] = ??? + + case class GetVisualStateRequest(recipeInstanceId: String) + + case class GetVisualStateResponse(state: String) + + case class RetryInteractionRequest(recipeInstanceId: String, interactionName: String) + + //case class RetryInteractionResponse() + + case class ResolveInteractionRequest(recipeInstanceId: String, interactionName: String, event: EventInstance) + + // case class ResolveInteractionResponse() + + case class StopRetryingInteractionRequest(recipeInstanceId: String, interactionName: String) + + // response } diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala index 836a8b792..88be6a250 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala @@ -28,11 +28,17 @@ class BaaSServer(implicit system: ActorSystem, mat: Materializer, baker: Baker, implicit val serializersProvider: SerializersProvider = SerializersProvider(system, encryption) - def route: Route = pathPrefix("api" / "v3")(concat(addRecipe)) + def route: Route = pathPrefix("api" / "v3")(concat(addRecipe, getRecipe)) def addRecipe: Route = post(path("addRecipe") { entity(as[BaaSProtocol.AddRecipeRequest]) { request => complete(baker.addRecipe(request.compiledRecipe).map(BaaSProtocol.AddRecipeResponse)) } }) + + def getRecipe: Route = post(path("getRecipe") { + entity(as[BaaSProtocol.GetRecipeRequest]) { request => + complete(baker.getRecipe(request.recipeId).map(BaaSProtocol.GetRecipeResponse)) + } + }) } diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala index 3ce94105d..44efe91f5 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala @@ -40,7 +40,7 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp override def addRecipe(compiledRecipe: CompiledRecipe): Future[String] = for { encoded <- Marshal(BaaSProtocol.AddRecipeRequest(compiledRecipe)).to[MessageEntity] - request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("addRecipe")), entity = encoded) //, entity = encoded.withContentType(ContentTypes.`application/octet-stream`)) + request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("addRecipe")), entity = encoded) response <- Http().singleRequest(request) decoded <- Unmarshal(response).to[BaaSProtocol.AddRecipeResponse] } yield decoded.recipeId @@ -51,7 +51,13 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * @param recipeId * @return */ - override def getRecipe(recipeId: String): Future[RecipeInformation] = ??? + override def getRecipe(recipeId: String): Future[RecipeInformation] = + for { + encoded <- Marshal(BaaSProtocol.GetRecipeRequest(recipeId)).to[MessageEntity] + request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("getRecipe")), entity = encoded) + response <- Http().singleRequest(request) + decoded <- Unmarshal(response).to[BaaSProtocol.GetRecipeResponse] + } yield decoded.recipeInformation /** * Returns all recipes added to this baker instance. diff --git a/runtime/src/main/protobuf/common.proto b/runtime/src/main/protobuf/common.proto index 6b86bd0b8..c062b0da3 100644 --- a/runtime/src/main/protobuf/common.proto +++ b/runtime/src/main/protobuf/common.proto @@ -7,6 +7,14 @@ option (scalapb.options) = { flat_package: true }; +// other + +message RecipeInformation { + optional CompiledRecipe compiledRecipe = 1; + optional int64 recipeCreatedTime = 2; + repeated string errors = 3; +} + // wrapper object for 'any' data message SerializedData { optional int32 serializer_id = 1; @@ -144,6 +152,11 @@ message EventMoment { optional int64 occurredOn = 2; } +message RecipeInstanceMetadata { + optional string recipeId = 1; + optional string recipeInstanceId = 2; + optional int64 createdTime = 3; +} message ProcessState { optional string recipeInstanceId = 1; diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala index c51f3b341..64cdd3149 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala @@ -5,7 +5,7 @@ import com.ing.baker.il import com.ing.baker.types import com.ing.baker.runtime.akka.actor.protobuf import com.ing.baker.runtime.akka.actor.serialization.protomappings._ -import com.ing.baker.runtime.scaladsl.{EventInstance, EventMoment, IngredientInstance, RecipeInstanceState, SensoryEventResult} +import com.ing.baker.runtime.scaladsl.{EventInstance, EventMoment, IngredientInstance, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult} import scalapb.GeneratedMessageCompanion import scala.util.{Success, Try} @@ -44,6 +44,9 @@ object ProtoMap { implicit def akkaActorRefMapping(implicit ev0: SerializersProvider): ProtoMap[ActorRef, protobuf.ActorRefId] = new ActorRefMapping(ev0) + implicit def recipeInformationMapping(implicit ev0: SerializersProvider): ProtoMap[RecipeInformation, protobuf.RecipeInformation] = + new RecipeInformationMapping() + implicit val eventDescriptorMapping: ProtoMap[il.EventDescriptor, protobuf.EventDescriptor] = new EventDescriptorMapping @@ -68,6 +71,9 @@ object ProtoMap { implicit val runtimeEventMapping: ProtoMap[EventInstance, protobuf.RuntimeEvent] = new RuntimeEventMapping + implicit val recipeInstanceMetadataMapping: ProtoMap[RecipeInstanceMetadata, protobuf.RecipeInstanceMetadata] = + new RecipeInstanceMetadataMapping + implicit val processStateMapping: ProtoMap[RecipeInstanceState, protobuf.ProcessState] = new ProcessStateMapping diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RecipeInformationMapping.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RecipeInformationMapping.scala new file mode 100644 index 000000000..1cf5b9aec --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RecipeInformationMapping.scala @@ -0,0 +1,24 @@ +package com.ing.baker.runtime.akka.actor.serialization.protomappings + +import com.ing.baker.runtime.akka.actor.serialization.{ProtoMap, SerializersProvider} +import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.runtime.akka.actor.{protobuf => proto} +import com.ing.baker.runtime.scaladsl.RecipeInformation + +import scala.util.Try + +class RecipeInformationMapping(implicit ev0: SerializersProvider) extends ProtoMap[RecipeInformation, proto.RecipeInformation] { + + val companion = proto.RecipeInformation + + def toProto(a: RecipeInformation): proto.RecipeInformation = { + proto.RecipeInformation(Some(ctxToProto(a.compiledRecipe)), Some(a.recipeCreatedTime), a.errors.toSeq) + } + + def fromProto(message: proto.RecipeInformation): Try[RecipeInformation] = + for { + compiledRecipeProto <- versioned(message.compiledRecipe, "compiledRecipe") + compiledRecipe <- ctxFromProto(compiledRecipeProto) + recipeCreatedTime <- versioned(message.recipeCreatedTime, "recipeCreatedTime") + } yield RecipeInformation(compiledRecipe, recipeCreatedTime, message.errors.toSet) +} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RecipeInstanceMetadataMapping.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RecipeInstanceMetadataMapping.scala new file mode 100644 index 000000000..19dd05c8a --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RecipeInstanceMetadataMapping.scala @@ -0,0 +1,24 @@ +package com.ing.baker.runtime.akka.actor.serialization.protomappings + +import com.ing.baker.runtime.akka.actor.serialization.ProtoMap +import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.versioned +import com.ing.baker.runtime.akka.actor.{protobuf => proto} +import com.ing.baker.runtime.scaladsl.RecipeInstanceMetadata + +import scala.util.Try + +class RecipeInstanceMetadataMapping extends ProtoMap[RecipeInstanceMetadata, proto.RecipeInstanceMetadata] { + + val companion = proto.RecipeInstanceMetadata + + def toProto(a: RecipeInstanceMetadata): proto.RecipeInstanceMetadata = { + proto.RecipeInstanceMetadata(Some(a.recipeId), Some(a.recipeInstanceId), Some(a.createdTime)) + } + + def fromProto(message: proto.RecipeInstanceMetadata): Try[RecipeInstanceMetadata] = + for { + recipeId <- versioned(message.recipeId, "recipeId") + recipeInstanceId <- versioned(message.recipeInstanceId, "recipeInstanceId") + createdTime <- versioned(message.createdTime, "createdTime") + } yield RecipeInstanceMetadata(recipeId, recipeInstanceId, createdTime) + } diff --git a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInformation.scala b/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInformation.scala index 6e3306aac..e42766a4f 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInformation.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInformation.scala @@ -13,5 +13,5 @@ case class RecipeInformation( errors: Set[String]) extends common.RecipeInformation with ScalaApi { def asJava: javadsl.RecipeInformation = - new javadsl.RecipeInformation(compiledRecipe, recipeCreatedTime, errors.asJava) + javadsl.RecipeInformation(compiledRecipe, recipeCreatedTime, errors.asJava) } From 5451cd090bdee02385b5521e082ee8d06eb9f827 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Mon, 30 Sep 2019 00:34:43 +0200 Subject: [PATCH 14/86] Finished the proto mappings and as well the server and client --- baas/src/main/protobuf/baas.proto | 2 +- .../ing/baker/runtime/baas/BaaSProto.scala | 279 +++++++++++++++++- .../ing/baker/runtime/baas/BaaSProtocol.scala | 6 +- .../ing/baker/runtime/baas/BaaSServer.scala | 97 +++++- .../baker/runtime/baas/scaladsl/Baker.scala | 121 ++++++-- 5 files changed, 475 insertions(+), 30 deletions(-) diff --git a/baas/src/main/protobuf/baas.proto b/baas/src/main/protobuf/baas.proto index 53dad03c8..2381b3db9 100644 --- a/baas/src/main/protobuf/baas.proto +++ b/baas/src/main/protobuf/baas.proto @@ -75,7 +75,7 @@ message FireEventRequest { } message GetAllRecipeInstancesMetadataResponse { - optional RecipeInstanceMetadata set = 1; + repeated RecipeInstanceMetadata set = 1; } message GetRecipeInstanceStateRequest { diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala index 0b23efa81..bc24c6f09 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala @@ -1,9 +1,10 @@ package com.ing.baker.runtime.baas +import cats.implicits._ import BaaSProtocol._ +import com.ing.baker.runtime.akka.actor.serialization.protomappings.SensoryEventStatusMappingHelper import com.ing.baker.runtime.akka.actor.serialization.{ProtoMap, SerializersProvider} import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} -import com.ing.baker.runtime.scaladsl.RecipeInformation import scalapb.GeneratedMessageCompanion import scala.util.Try @@ -82,4 +83,280 @@ object BaaSProto { recipeInformation <- ctxFromProto(recipeInformationProto) } yield GetRecipeResponse(recipeInformation) } + + implicit def getAllRecipesResponseProto(implicit ev0: SerializersProvider): ProtoMap[GetAllRecipesResponse, protobuf.GetAllRecipesResponse] = + new ProtoMap[GetAllRecipesResponse, protobuf.GetAllRecipesResponse] { + + override def companion: GeneratedMessageCompanion[protobuf.GetAllRecipesResponse] = + protobuf.GetAllRecipesResponse + + override def toProto(a: GetAllRecipesResponse): protobuf.GetAllRecipesResponse = + protobuf.GetAllRecipesResponse(a.map.mapValues(ctxToProto(_))) + + override def fromProto(message: protobuf.GetAllRecipesResponse): Try[GetAllRecipesResponse] = + for { + allRecipes <- message.mapping.toList.traverse { case (id, recipeProto) => + ctxFromProto(recipeProto).map(x => (id, x)) + } + } yield GetAllRecipesResponse(allRecipes.toMap) + } + + implicit def bakeRequestProto: ProtoMap[BakeRequest, protobuf.BakeRequest] = + new ProtoMap[BakeRequest, protobuf.BakeRequest] { + + override def companion: GeneratedMessageCompanion[protobuf.BakeRequest] = + protobuf.BakeRequest + + override def toProto(a: BakeRequest): protobuf.BakeRequest = + protobuf.BakeRequest(Some(a.recipeId), Some(a.recipeInstanceId)) + + override def fromProto(message: protobuf.BakeRequest): Try[BakeRequest] = + for { + recipeId <- versioned(message.recipeId, "recipeId") + recipeInstanceId <- versioned(message.recipeInstanceId, "recipeInstanceId") + } yield BakeRequest(recipeId, recipeInstanceId) + } + + implicit def fireEventAndResolveWhenReceivedRequestProto: ProtoMap[FireEventAndResolveWhenReceivedRequest, protobuf.FireEventAndResolveWhenReceivedRequest] = + new ProtoMap[FireEventAndResolveWhenReceivedRequest, protobuf.FireEventAndResolveWhenReceivedRequest] { + + override def companion: GeneratedMessageCompanion[protobuf.FireEventAndResolveWhenReceivedRequest] = + protobuf.FireEventAndResolveWhenReceivedRequest + + override def toProto(a: FireEventAndResolveWhenReceivedRequest): protobuf.FireEventAndResolveWhenReceivedRequest = + protobuf.FireEventAndResolveWhenReceivedRequest(Some(a.recipeInstanceId), Some(ctxToProto(a.event)), a.correlationId) + + override def fromProto(message: protobuf.FireEventAndResolveWhenReceivedRequest): Try[FireEventAndResolveWhenReceivedRequest] = + for { + recipeInstanceId <- versioned(message.recipeInstanceId, "recipeInstanceId") + event <- versioned(message.event, "event") + decodedEvent <- ctxFromProto(event) + } yield FireEventAndResolveWhenReceivedRequest(recipeInstanceId, decodedEvent, message.correlationId) + } + + implicit def fireEventAndResolveWhenReceivedResponseProto: ProtoMap[FireEventAndResolveWhenReceivedResponse, protobuf.FireEventAndResolveWhenReceivedResponse] = + new ProtoMap[FireEventAndResolveWhenReceivedResponse, protobuf.FireEventAndResolveWhenReceivedResponse] { + + override def companion: GeneratedMessageCompanion[protobuf.FireEventAndResolveWhenReceivedResponse] = + protobuf.FireEventAndResolveWhenReceivedResponse + + override def toProto(a: FireEventAndResolveWhenReceivedResponse): protobuf.FireEventAndResolveWhenReceivedResponse = + protobuf.FireEventAndResolveWhenReceivedResponse(Some(SensoryEventStatusMappingHelper.toProto(a.sensoryEventStatus))) + + override def fromProto(message: protobuf.FireEventAndResolveWhenReceivedResponse): Try[FireEventAndResolveWhenReceivedResponse] = + for { + sensoryEventStatus <- versioned(message.sensoryEventStatus, "sensoryEventStatus") + decodedSensoryEventStatus <- SensoryEventStatusMappingHelper.fromProto(sensoryEventStatus) + } yield FireEventAndResolveWhenReceivedResponse(decodedSensoryEventStatus) + } + + implicit def fireEventAndResolveWhenCompletedRequestProto: ProtoMap[FireEventAndResolveWhenCompletedRequest, protobuf.FireEventAndResolveWhenCompletedRequest] = + new ProtoMap[FireEventAndResolveWhenCompletedRequest, protobuf.FireEventAndResolveWhenCompletedRequest] { + + override def companion: GeneratedMessageCompanion[protobuf.FireEventAndResolveWhenCompletedRequest] = + protobuf.FireEventAndResolveWhenCompletedRequest + + override def toProto(a: FireEventAndResolveWhenCompletedRequest): protobuf.FireEventAndResolveWhenCompletedRequest = + protobuf.FireEventAndResolveWhenCompletedRequest(Some(a.recipeInstanceId), Some(ctxToProto(a.event)), a.correlationId) + + override def fromProto(message: protobuf.FireEventAndResolveWhenCompletedRequest): Try[FireEventAndResolveWhenCompletedRequest] = + for { + recipeInstanceId <- versioned(message.recipeInstanceId, "recipeInstanceId") + event <- versioned(message.event, "event") + decodedEvent <- ctxFromProto(event) + } yield FireEventAndResolveWhenCompletedRequest(recipeInstanceId, decodedEvent, message.correlationId) + } + + implicit def fireEventAndResolveWhenCompletedResponseProto: ProtoMap[FireEventAndResolveWhenCompletedResponse, protobuf.FireEventAndResolveWhenCompletedResponse] = + new ProtoMap[FireEventAndResolveWhenCompletedResponse, protobuf.FireEventAndResolveWhenCompletedResponse] { + + override def companion: GeneratedMessageCompanion[protobuf.FireEventAndResolveWhenCompletedResponse] = + protobuf.FireEventAndResolveWhenCompletedResponse + + override def toProto(a: FireEventAndResolveWhenCompletedResponse): protobuf.FireEventAndResolveWhenCompletedResponse = + protobuf.FireEventAndResolveWhenCompletedResponse(Some(ctxToProto(a.sensoryEventResult))) + + override def fromProto(message: protobuf.FireEventAndResolveWhenCompletedResponse): Try[FireEventAndResolveWhenCompletedResponse] = + for { + sensoryEventResult <- versioned(message.sensoryEventResult, "sensoryEventResult") + decodedSensoryEventResult <- ctxFromProto(sensoryEventResult) + } yield FireEventAndResolveWhenCompletedResponse(decodedSensoryEventResult) + } + + implicit def fireEventAndResolveOnEventRequestProto: ProtoMap[FireEventAndResolveOnEventRequest, protobuf.FireEventAndResolveOnEventRequest] = + new ProtoMap[FireEventAndResolveOnEventRequest, protobuf.FireEventAndResolveOnEventRequest] { + + override def companion: GeneratedMessageCompanion[protobuf.FireEventAndResolveOnEventRequest] = + protobuf.FireEventAndResolveOnEventRequest + + override def toProto(a: FireEventAndResolveOnEventRequest): protobuf.FireEventAndResolveOnEventRequest = + protobuf.FireEventAndResolveOnEventRequest(Some(a.recipeInstanceId), Some(ctxToProto(a.event)), Some(a.onEvent), a.correlationId) + + override def fromProto(message: protobuf.FireEventAndResolveOnEventRequest): Try[FireEventAndResolveOnEventRequest] = + for { + recipeInstanceId <- versioned(message.recipeInstanceId, "recipeInstanceId") + onEvent <- versioned(message.onEvent, "onEvent") + event <- versioned(message.event, "event") + decodedEvent <- ctxFromProto(event) + } yield FireEventAndResolveOnEventRequest(recipeInstanceId, decodedEvent, onEvent, message.correlationId) + } + + implicit def fireEventAndResolveOnEventResponseProto: ProtoMap[FireEventAndResolveOnEventResponse, protobuf.FireEventAndResolveOnEventResponse] = + new ProtoMap[FireEventAndResolveOnEventResponse, protobuf.FireEventAndResolveOnEventResponse] { + + override def companion: GeneratedMessageCompanion[protobuf.FireEventAndResolveOnEventResponse] = + protobuf.FireEventAndResolveOnEventResponse + + override def toProto(a: FireEventAndResolveOnEventResponse): protobuf.FireEventAndResolveOnEventResponse = + protobuf.FireEventAndResolveOnEventResponse(Some(ctxToProto(a.sensoryEventResult))) + + override def fromProto(message: protobuf.FireEventAndResolveOnEventResponse): Try[FireEventAndResolveOnEventResponse] = + for { + sensoryEventResult <- versioned(message.sensoryEventResult, "sensoryEventResult") + decodedSensoryEventResult <- ctxFromProto(sensoryEventResult) + } yield FireEventAndResolveOnEventResponse(decodedSensoryEventResult) + } + + implicit def fireEventRequestProto: ProtoMap[FireEventRequest, protobuf.FireEventRequest] = + new ProtoMap[FireEventRequest, protobuf.FireEventRequest] { + + override def companion: GeneratedMessageCompanion[protobuf.FireEventRequest] = + protobuf.FireEventRequest + + override def toProto(a: FireEventRequest): protobuf.FireEventRequest = + protobuf.FireEventRequest(Some(a.recipeInstanceId), Some(ctxToProto(a.event)), a.correlationId) + + override def fromProto(message: protobuf.FireEventRequest): Try[FireEventRequest] = + for { + recipeInstanceId <- versioned(message.recipeInstanceId, "recipeInstanceId") + event <- versioned(message.event, "event") + decodedEvent <- ctxFromProto(event) + } yield FireEventRequest(recipeInstanceId, decodedEvent, message.correlationId) + } + + implicit def getAllRecipeInstancesMetadataResponseProto: ProtoMap[GetAllRecipeInstancesMetadataResponse, protobuf.GetAllRecipeInstancesMetadataResponse] = + new ProtoMap[GetAllRecipeInstancesMetadataResponse, protobuf.GetAllRecipeInstancesMetadataResponse] { + + override def companion: GeneratedMessageCompanion[protobuf.GetAllRecipeInstancesMetadataResponse] = + protobuf.GetAllRecipeInstancesMetadataResponse + + override def toProto(a: GetAllRecipeInstancesMetadataResponse): protobuf.GetAllRecipeInstancesMetadataResponse = + protobuf.GetAllRecipeInstancesMetadataResponse(a.set.toSeq.map(ctxToProto(_))) + + override def fromProto(message: protobuf.GetAllRecipeInstancesMetadataResponse): Try[GetAllRecipeInstancesMetadataResponse] = + for { + set <- message.set.toList.traverse(ctxFromProto(_)) + } yield GetAllRecipeInstancesMetadataResponse(set.toSet) + } + + implicit def getRecipeInstanceStateRequestProto: ProtoMap[GetRecipeInstanceStateRequest, protobuf.GetRecipeInstanceStateRequest] = + new ProtoMap[GetRecipeInstanceStateRequest, protobuf.GetRecipeInstanceStateRequest] { + + override def companion: GeneratedMessageCompanion[protobuf.GetRecipeInstanceStateRequest] = + protobuf.GetRecipeInstanceStateRequest + + override def toProto(a: GetRecipeInstanceStateRequest): protobuf.GetRecipeInstanceStateRequest = + protobuf.GetRecipeInstanceStateRequest(Some(a.recipeInstanceId)) + + override def fromProto(message: protobuf.GetRecipeInstanceStateRequest): Try[GetRecipeInstanceStateRequest] = + for { + recipeInstanceId <- versioned(message.recipeInstanceId, "recipeInstanceId") + } yield GetRecipeInstanceStateRequest(recipeInstanceId) + } + + implicit def getRecipeInstanceStateResponseProto: ProtoMap[GetRecipeInstanceStateResponse, protobuf.GetRecipeInstanceStateResponse] = + new ProtoMap[GetRecipeInstanceStateResponse, protobuf.GetRecipeInstanceStateResponse] { + + override def companion: GeneratedMessageCompanion[protobuf.GetRecipeInstanceStateResponse] = + protobuf.GetRecipeInstanceStateResponse + + override def toProto(a: GetRecipeInstanceStateResponse): protobuf.GetRecipeInstanceStateResponse = + protobuf.GetRecipeInstanceStateResponse(Some(ctxToProto(a.recipeInstanceState))) + + override def fromProto(message: protobuf.GetRecipeInstanceStateResponse): Try[GetRecipeInstanceStateResponse] = + for { + recipeInstanceState <- versioned(message.recipeInstanceState, "recipeInstanceState") + decodedSensoryEventResult <- ctxFromProto(recipeInstanceState) + } yield GetRecipeInstanceStateResponse(decodedSensoryEventResult) + } + + implicit def getVisualStateRequestProto: ProtoMap[GetVisualStateRequest, protobuf.GetVisualStateRequest] = + new ProtoMap[GetVisualStateRequest, protobuf.GetVisualStateRequest] { + + override def companion: GeneratedMessageCompanion[protobuf.GetVisualStateRequest] = + protobuf.GetVisualStateRequest + + override def toProto(a: GetVisualStateRequest): protobuf.GetVisualStateRequest = + protobuf.GetVisualStateRequest(Some(a.recipeInstanceId)) + + override def fromProto(message: protobuf.GetVisualStateRequest): Try[GetVisualStateRequest] = + for { + recipeInstanceId <- versioned(message.recipeInstanceId, "recipeInstanceId") + } yield GetVisualStateRequest(recipeInstanceId) + } + + implicit def getVisualStateResponseProto: ProtoMap[GetVisualStateResponse, protobuf.GetVisualStateResponse] = + new ProtoMap[GetVisualStateResponse, protobuf.GetVisualStateResponse] { + + override def companion: GeneratedMessageCompanion[protobuf.GetVisualStateResponse] = + protobuf.GetVisualStateResponse + + override def toProto(a: GetVisualStateResponse): protobuf.GetVisualStateResponse = + protobuf.GetVisualStateResponse(Some(a.state)) + + override def fromProto(message: protobuf.GetVisualStateResponse): Try[GetVisualStateResponse] = + for { + state <- versioned(message.state, "state") + } yield GetVisualStateResponse(state) + } + + implicit def retryInteractionRequestProto: ProtoMap[RetryInteractionRequest, protobuf.RetryInteractionRequest] = + new ProtoMap[RetryInteractionRequest, protobuf.RetryInteractionRequest] { + + override def companion: GeneratedMessageCompanion[protobuf.RetryInteractionRequest] = + protobuf.RetryInteractionRequest + + override def toProto(a: RetryInteractionRequest): protobuf.RetryInteractionRequest = + protobuf.RetryInteractionRequest(Some(a.recipeInstanceId), Some(a.interactionName)) + + override def fromProto(message: protobuf.RetryInteractionRequest): Try[RetryInteractionRequest] = + for { + recipeInstanceId <- versioned(message.recipeInstanceId, "recipeInstanceId") + interactionName <- versioned(message.interactionName, "interactionName") + } yield RetryInteractionRequest(recipeInstanceId, interactionName) + } + + implicit def resolveInteractionRequestProto: ProtoMap[ResolveInteractionRequest, protobuf.ResolveInteractionRequest] = + new ProtoMap[ResolveInteractionRequest, protobuf.ResolveInteractionRequest] { + + override def companion: GeneratedMessageCompanion[protobuf.ResolveInteractionRequest] = + protobuf.ResolveInteractionRequest + + override def toProto(a: ResolveInteractionRequest): protobuf.ResolveInteractionRequest = + protobuf.ResolveInteractionRequest(Some(a.recipeInstanceId), Some(a.interactionName), Some(ctxToProto(a.event))) + + override def fromProto(message: protobuf.ResolveInteractionRequest): Try[ResolveInteractionRequest] = + for { + recipeInstanceId <- versioned(message.recipeInstanceId, "recipeInstanceId") + interactionName <- versioned(message.interactionName, "interactionName") + event <- versioned(message.event, "event") + decodedEvent <- ctxFromProto(event) + } yield ResolveInteractionRequest(recipeInstanceId, interactionName, decodedEvent) + } + + implicit def stopRetryingInteractionRequestProto: ProtoMap[StopRetryingInteractionRequest, protobuf.StopRetryingInteractionRequest] = + new ProtoMap[StopRetryingInteractionRequest, protobuf.StopRetryingInteractionRequest] { + + override def companion: GeneratedMessageCompanion[protobuf.StopRetryingInteractionRequest] = + protobuf.StopRetryingInteractionRequest + + override def toProto(a: StopRetryingInteractionRequest): protobuf.StopRetryingInteractionRequest = + protobuf.StopRetryingInteractionRequest(Some(a.recipeInstanceId), Some(a.interactionName)) + + override def fromProto(message: protobuf.StopRetryingInteractionRequest): Try[StopRetryingInteractionRequest] = + for { + recipeInstanceId <- versioned(message.recipeInstanceId, "recipeInstanceId") + interactionName <- versioned(message.interactionName, "interactionName") + } yield StopRetryingInteractionRequest(recipeInstanceId, interactionName) + } } diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala index 1a22d81d9..04f3dd591 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala @@ -2,7 +2,7 @@ package com.ing.baker.runtime.baas import com.ing.baker.il.CompiledRecipe import com.ing.baker.runtime.common.SensoryEventStatus -import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeInformation, RecipeInstanceMetadata, SensoryEventResult} +import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult} object BaaSProtocol { @@ -43,11 +43,11 @@ object BaaSProtocol { //case class GetAllRecipeInstancesMetadataRequest() - case class GetAllRecipeInstancesMetadataResponse(set: RecipeInstanceMetadata) + case class GetAllRecipeInstancesMetadataResponse(set: Set[RecipeInstanceMetadata]) case class GetRecipeInstanceStateRequest(recipeInstanceId: String) - case class GetRecipeInstanceStateResponse(recipeInstanceState) + case class GetRecipeInstanceStateResponse(recipeInstanceState: RecipeInstanceState) //case class GetIngredientsRequest(recipeInstanceId: String) //case class GetIngredientsResponse(map: Map[String, Value]) diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala index 88be6a250..58e97b537 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala @@ -2,6 +2,7 @@ package com.ing.baker.runtime.baas import akka.actor.ActorSystem import akka.http.scaladsl.Http +import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import akka.stream.Materializer @@ -25,20 +26,108 @@ class BaaSServer(implicit system: ActorSystem, mat: Materializer, baker: Baker, import system.dispatcher - implicit val serializersProvider: SerializersProvider = + implicit private val serializersProvider: SerializersProvider = SerializersProvider(system, encryption) - def route: Route = pathPrefix("api" / "v3")(concat(addRecipe, getRecipe)) + def route: Route = pathPrefix("api" / "v3")(concat(addRecipe, getRecipe, getAllRecipes, bake, + fireEventAndResolveWhenReceived, fireEventAndResolveWhenCompleted, fireEventAndResolveOnEvent, fireEvent, + getAllRecipeInstancesMetadata, getRecipeInstanceState, getVisualState, retryInteraction, resolveInteraction, + stopRetryingInteraction + )) - def addRecipe: Route = post(path("addRecipe") { + private def addRecipe: Route = post(path("addRecipe") { entity(as[BaaSProtocol.AddRecipeRequest]) { request => complete(baker.addRecipe(request.compiledRecipe).map(BaaSProtocol.AddRecipeResponse)) } }) - def getRecipe: Route = post(path("getRecipe") { + private def getRecipe: Route = post(path("getRecipe") { entity(as[BaaSProtocol.GetRecipeRequest]) { request => complete(baker.getRecipe(request.recipeId).map(BaaSProtocol.GetRecipeResponse)) } }) + + private def getAllRecipes: Route = post(path("getAllRecipes") { + complete(baker.getAllRecipes.map(BaaSProtocol.GetAllRecipesResponse)) + }) + + private def bake: Route = post(path("bake") { + entity(as[BaaSProtocol.BakeRequest]) { request => + onComplete(baker.bake(request.recipeId, request.recipeInstanceId)) { _ => + complete(StatusCodes.OK) + } + } + }) + + private def fireEventAndResolveWhenReceived: Route = post(path("fireEventAndResolveWhenReceived") { + entity(as[BaaSProtocol.FireEventAndResolveWhenReceivedRequest]) { request => + complete(baker.fireEventAndResolveWhenReceived(request.recipeInstanceId, request.event, request.correlationId) + .map(BaaSProtocol.FireEventAndResolveWhenReceivedResponse)) + } + }) + + private def fireEventAndResolveWhenCompleted: Route = post(path("fireEventAndResolveWhenCompleted") { + entity(as[BaaSProtocol.FireEventAndResolveWhenCompletedRequest]) { request => + complete(baker.fireEventAndResolveWhenCompleted(request.recipeInstanceId, request.event, request.correlationId) + .map(BaaSProtocol.FireEventAndResolveWhenCompletedResponse)) + } + }) + + private def fireEventAndResolveOnEvent: Route = post(path("fireEventAndResolveOnEvent") { + entity(as[BaaSProtocol.FireEventAndResolveOnEventRequest]) { request => + complete(baker.fireEventAndResolveOnEvent(request.recipeInstanceId, request.event, request.onEvent, request.correlationId) + .map(BaaSProtocol.FireEventAndResolveOnEventResponse)) + } + }) + + private def fireEvent: Route = post(path("fireEvent") { + entity(as[BaaSProtocol.FireEventRequest]) { request => + complete(baker.fireEvent(request.recipeInstanceId, request.event, request.correlationId).resolveWhenReceived + .map(_ => "TODO")) // TODO figure out what to do here with the 2 different futures + } + }) + + private def getAllRecipeInstancesMetadata: Route = post(path("getAllRecipeInstancesMetadata") { + complete(baker.getAllRecipeInstancesMetadata + .map(BaaSProtocol.GetAllRecipeInstancesMetadataResponse)) + }) + + private def getRecipeInstanceState: Route = post(path("getRecipeInstanceState") { + entity(as[BaaSProtocol.GetRecipeInstanceStateRequest]) { request => + complete(baker.getRecipeInstanceState(request.recipeInstanceId) + .map(BaaSProtocol.GetRecipeInstanceStateResponse)) + } + }) + + private def getVisualState: Route = post(path("getVisualState") { + entity(as[BaaSProtocol.GetVisualStateRequest]) { request => + complete(baker.getVisualState(request.recipeInstanceId) + .map(BaaSProtocol.GetVisualStateResponse)) + } + }) + + private def retryInteraction: Route = post(path("retryInteraction") { + entity(as[BaaSProtocol.RetryInteractionRequest]) { request => + onComplete(baker.retryInteraction(request.recipeInstanceId, request.interactionName)) { _ => + complete(StatusCodes.OK) + } + } + }) + + private def resolveInteraction: Route = post(path("resolveInteraction") { + entity(as[BaaSProtocol.ResolveInteractionRequest]) { request => + onComplete(baker.resolveInteraction(request.recipeInstanceId, request.interactionName, request.event)) { _ => + complete(StatusCodes.OK) + } + } + }) + + private def stopRetryingInteraction: Route = post(path("stopRetryingInteraction") { + entity(as[BaaSProtocol.StopRetryingInteractionRequest]) { request => + onComplete(baker.stopRetryingInteraction(request.recipeInstanceId, request.interactionName)) { _ => + complete(StatusCodes.OK) + } + } + }) + } diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala index 44efe91f5..c430c0078 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala @@ -64,7 +64,13 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * * @return All recipes in the form of map of recipeId -> CompiledRecipe */ - override def getAllRecipes: Future[Map[String, RecipeInformation]] = ??? + override def getAllRecipes: Future[Map[String, RecipeInformation]] = { + val request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("getAllRecipes"))) + for { + response <- Http().singleRequest(request) + decoded <- Unmarshal(response).to[BaaSProtocol.GetAllRecipesResponse] + } yield decoded.map + } /** * Creates a process instance for the given recipeId with the given RecipeInstanceId as identifier @@ -73,7 +79,12 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * @param recipeInstanceId The identifier for the newly baked process * @return */ - override def bake(recipeId: String, recipeInstanceId: String): Future[Unit] = ??? + override def bake(recipeId: String, recipeInstanceId: String): Future[Unit] = + for { + encoded <- Marshal(BaaSProtocol.BakeRequest(recipeId, recipeInstanceId)).to[MessageEntity] + request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("bake")), entity = encoded) + _ <- Http().singleRequest(request) + } yield () /** * Notifies Baker that an event has happened and waits until the event was accepted but not executed by the process. @@ -86,7 +97,13 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * @param event The event object * @param correlationId Id used to ensure the process instance handles unique events */ - override def fireEventAndResolveWhenReceived(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): Future[SensoryEventStatus] = ??? + override def fireEventAndResolveWhenReceived(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): Future[SensoryEventStatus] = + for { + encoded <- Marshal(BaaSProtocol.FireEventAndResolveWhenReceivedRequest(recipeInstanceId, event, correlationId)).to[MessageEntity] + request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("fireEventAndResolveWhenReceived")), entity = encoded) + response <- Http().singleRequest(request) + decoded <- Unmarshal(response).to[BaaSProtocol.FireEventAndResolveWhenReceivedResponse] + } yield decoded.sensoryEventStatus /** * Notifies Baker that an event has happened and waits until all the actions which depend on this event are executed. @@ -99,7 +116,13 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * @param event The event object * @param correlationId Id used to ensure the process instance handles unique events */ - override def fireEventAndResolveWhenCompleted(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): Future[SensoryEventResult] = ??? + override def fireEventAndResolveWhenCompleted(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): Future[SensoryEventResult] = + for { + encoded <- Marshal(BaaSProtocol.FireEventAndResolveWhenCompletedRequest(recipeInstanceId, event, correlationId)).to[MessageEntity] + request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("fireEventAndResolveWhenCompleted")), entity = encoded) + response <- Http().singleRequest(request) + decoded <- Unmarshal(response).to[BaaSProtocol.FireEventAndResolveWhenCompletedResponse] + } yield decoded.sensoryEventResult /** * Notifies Baker that an event has happened and waits until an specific event has executed. @@ -113,7 +136,13 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * @param onEvent The name of the event to wait for * @param correlationId Id used to ensure the process instance handles unique events */ - override def fireEventAndResolveOnEvent(recipeInstanceId: String, event: EventInstance, onEvent: String, correlationId: Option[String]): Future[SensoryEventResult] = ??? + override def fireEventAndResolveOnEvent(recipeInstanceId: String, event: EventInstance, onEvent: String, correlationId: Option[String]): Future[SensoryEventResult] = + for { + encoded <- Marshal(BaaSProtocol.FireEventAndResolveOnEventRequest(recipeInstanceId, event, onEvent, correlationId)).to[MessageEntity] + request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("fireEventAndResolveOnEvent")), entity = encoded) + response <- Http().singleRequest(request) + decoded <- Unmarshal(response).to[BaaSProtocol.FireEventAndResolveOnEventResponse] + } yield decoded.sensoryEventResult /** * Notifies Baker that an event has happened and provides 2 async handlers, one for when the event was accepted by @@ -127,7 +156,15 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * @param event The event object * @param correlationId Id used to ensure the process instance handles unique events */ - override def fireEvent(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): EventResolutions = ??? + override def fireEvent(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): EventResolutions = { + for { + encoded <- Marshal(BaaSProtocol.FireEventRequest(recipeInstanceId, event, correlationId)).to[MessageEntity] + request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("fireEvent")), entity = encoded) + response <- Http().singleRequest(request) + //decoded <- Unmarshal(response).to[BaaSProtocol.???] TODO figure out what to do on this situation with the two futures + } yield () //decoded.recipeInformation + ??? + } /** * Returns an index of all running processes. @@ -139,7 +176,13 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * * @return An index of all processes */ - override def getAllRecipeInstancesMetadata: Future[Set[RecipeInstanceMetadata]] = ??? + override def getAllRecipeInstancesMetadata: Future[Set[RecipeInstanceMetadata]] = { + val request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("getAllRecipeInstancesMetadata"))) + for { + response <- Http().singleRequest(request) + decoded <- Unmarshal(response).to[BaaSProtocol.GetAllRecipeInstancesMetadataResponse] + } yield decoded.set + } /** * Returns the process state. @@ -147,7 +190,13 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * @param recipeInstanceId The process identifier * @return The process state. */ - override def getRecipeInstanceState(recipeInstanceId: String): Future[RecipeInstanceState] = ??? + override def getRecipeInstanceState(recipeInstanceId: String): Future[RecipeInstanceState] = + for { + encoded <- Marshal(BaaSProtocol.GetRecipeInstanceStateRequest(recipeInstanceId)).to[MessageEntity] + request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("getRecipeInstanceState")), entity = encoded) + response <- Http().singleRequest(request) + decoded <- Unmarshal(response).to[BaaSProtocol.GetRecipeInstanceStateResponse] + } yield decoded.recipeInstanceState /** * Returns all provided ingredients for a given RecipeInstance id. @@ -155,7 +204,8 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * @param recipeInstanceId The process id. * @return The provided ingredients. */ - override def getIngredients(recipeInstanceId: String): Future[Map[String, Value]] = ??? + override def getIngredients(recipeInstanceId: String): Future[Map[String, Value]] = + getRecipeInstanceState(recipeInstanceId).map(_.ingredients) /** * Returns all fired events for a given RecipeInstance id. @@ -163,7 +213,8 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * @param recipeInstanceId The process id. * @return The events */ - override def getEvents(recipeInstanceId: String): Future[Seq[EventMoment]] = ??? + override def getEvents(recipeInstanceId: String): Future[Seq[EventMoment]] = + getRecipeInstanceState(recipeInstanceId).map(_.events) /** * Returns all names of fired events for a given RecipeInstance id. @@ -171,7 +222,8 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * @param recipeInstanceId The process id. * @return The event names */ - override def getEventNames(recipeInstanceId: String): Future[Seq[String]] = ??? + override def getEventNames(recipeInstanceId: String): Future[Seq[String]] = + getRecipeInstanceState(recipeInstanceId).map(_.events.map(_.name)) /** * Returns the visual state (.dot) for a given process. @@ -179,21 +231,29 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * @param recipeInstanceId The process identifier. * @return A visual (.dot) representation of the process state. */ - override def getVisualState(recipeInstanceId: String, style: RecipeVisualStyle): Future[String] = ??? + override def getVisualState(recipeInstanceId: String, style: RecipeVisualStyle): Future[String] = + for { + encoded <- Marshal(BaaSProtocol.GetVisualStateRequest(recipeInstanceId)).to[MessageEntity] + request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("getVisualState")), entity = encoded) + response <- Http().singleRequest(request) + decoded <- Unmarshal(response).to[BaaSProtocol.GetVisualStateResponse] + } yield decoded.state /** * Registers a listener to all runtime events for recipes with the given name run in this baker instance. * * Note that the delivery guarantee is *AT MOST ONCE*. Do not use it for critical functionality */ - override def registerEventListener(recipeName: String, listenerFunction: (String, EventInstance) => Unit): Future[Unit] = ??? + override def registerEventListener(recipeName: String, listenerFunction: (String, EventInstance) => Unit): Future[Unit] = + throw new NotImplementedError("registerEventListener is not implemented for client bakers") /** * Registers a listener to all runtime events for all recipes that run in this Baker instance. * * Note that the delivery guarantee is *AT MOST ONCE*. Do not use it for critical functionality */ - override def registerEventListener(listenerFunction: (String, EventInstance) => Unit): Future[Unit] = ??? + override def registerEventListener(listenerFunction: (String, EventInstance) => Unit): Future[Unit] = + throw new NotImplementedError("registerEventListener is not implemented for client bakers") /** * Registers a listener function that listens to all BakerEvents @@ -203,33 +263,42 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * @param listenerFunction * @return */ - override def registerBakerEventListener(listenerFunction: BakerEvent => Unit): Future[Unit] = ??? + override def registerBakerEventListener(listenerFunction: BakerEvent => Unit): Future[Unit] = + throw new NotImplementedError("registerBakerEventListener is not implemented for client bakers") /** * Adds an interaction implementation to baker. * * @param implementation The implementation object */ - override def addInteractionInstance(implementation: InteractionInstance): Future[Unit] = ??? + override def addInteractionInstance(implementation: InteractionInstance): Future[Unit] = + throw new NotImplementedError("addInteractionInstance is not implemented for client bakers, instances are deployed independently, please view the documentation") /** * Adds a sequence of interaction implementation to baker. * * @param implementations The implementation object */ - override def addInteractionInstances(implementations: Seq[InteractionInstance]): Future[Unit] = ??? + override def addInteractionInstances(implementations: Seq[InteractionInstance]): Future[Unit] = + throw new NotImplementedError("addInteractionInstances is not implemented for client bakers, instances are deployed independently, please view the documentation") /** * Attempts to gracefully shutdown the baker system. */ - override def gracefulShutdown(): Future[Unit] = ??? + override def gracefulShutdown(): Future[Unit] = + throw new NotImplementedError("registerBakerEventListener is not yet implemented for client bakers") /** * Retries a blocked interaction. * * @return */ - override def retryInteraction(recipeInstanceId: String, interactionName: String): Future[Unit] = ??? + override def retryInteraction(recipeInstanceId: String, interactionName: String): Future[Unit] = + for { + encoded <- Marshal(BaaSProtocol.RetryInteractionRequest(recipeInstanceId, interactionName)).to[MessageEntity] + request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("retryInteraction")), entity = encoded) + _ <- Http().singleRequest(request) + } yield () /** * Resolves a blocked interaction by specifying it's output. @@ -238,12 +307,22 @@ class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(imp * * @return */ - override def resolveInteraction(recipeInstanceId: String, interactionName: String, event: EventInstance): Future[Unit] = ??? + override def resolveInteraction(recipeInstanceId: String, interactionName: String, event: EventInstance): Future[Unit] = + for { + encoded <- Marshal(BaaSProtocol.ResolveInteractionRequest(recipeInstanceId, interactionName, event)).to[MessageEntity] + request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("resolveInteraction")), entity = encoded) + _ <- Http().singleRequest(request) + } yield () /** * Stops the retrying of an interaction. * * @return */ - override def stopRetryingInteraction(recipeInstanceId: String, interactionName: String): Future[Unit] = ??? + override def stopRetryingInteraction(recipeInstanceId: String, interactionName: String): Future[Unit] = + for { + encoded <- Marshal(BaaSProtocol.StopRetryingInteractionRequest(recipeInstanceId, interactionName)).to[MessageEntity] + request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("stopRetryingInteraction")), entity = encoded) + _ <- Http().singleRequest(request) + } yield () } From 41ed5e0eb695b8e0b775b486d3d1182b4e185280 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Mon, 30 Sep 2019 16:22:42 +0200 Subject: [PATCH 15/86] Continued work on the testing of the BaaS client-server communication --- baas/src/main/resources/reference.conf | 1 - baas/src/test/resources/application.conf | 42 ----- baas/src/test/resources/cassandra.conf | 15 -- baas/src/test/resources/cluster.conf | 34 ---- .../common/CommonBaaSServerClientSpec.scala | 157 +++++++++++++----- .../ScalaDSLBaaSServerClientSpec.scala | 30 +--- .../common/LanguageDataStructures.scala | 2 - 7 files changed, 124 insertions(+), 157 deletions(-) delete mode 100644 baas/src/main/resources/reference.conf delete mode 100644 baas/src/test/resources/application.conf delete mode 100644 baas/src/test/resources/cassandra.conf delete mode 100644 baas/src/test/resources/cluster.conf diff --git a/baas/src/main/resources/reference.conf b/baas/src/main/resources/reference.conf deleted file mode 100644 index 12d38ea5d..000000000 --- a/baas/src/main/resources/reference.conf +++ /dev/null @@ -1 +0,0 @@ -include "baker.conf" diff --git a/baas/src/test/resources/application.conf b/baas/src/test/resources/application.conf deleted file mode 100644 index 08bf154e7..000000000 --- a/baas/src/test/resources/application.conf +++ /dev/null @@ -1,42 +0,0 @@ -include "baker.conf" -//include "cluster.conf" -// include "cassandra.conf" - -baker { - engine-provider = "com.ing.baker.baas.client.BaasBakerProvider" - engine.baas { - actor-system-name = "ActorSystemName" - client-host = "localhost" - client-port = 8091 - baas-host = "localhost" - baas-port = 8081 - } -} - -akka { - log-config-on-start = off - jvm-exit-on-fatal-error = false - loglevel = "DEBUG" - coordinated-shutdown.run-by-jvm-shutdown-hook = off - - // No need to see the java serialization warnings for the tests in this module - actor.allow-java-serialization = on - actor.warn-about-java-serializer-usage = off - -// actor.serialize-messages = on - actor.serialize-creators = off - - test.timefactor = 4 - - loggers = ["akka.event.slf4j.Slf4jLogger"] - loglevel = "DEBUG" - logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" -} - -inmemory-read-journal { - write-plugin = "inmemory-journal" - offset-mode = "sequence" - ask-timeout = "10s" - refresh-interval = "50ms" - max-buffer-size = "100" -} diff --git a/baas/src/test/resources/cassandra.conf b/baas/src/test/resources/cassandra.conf deleted file mode 100644 index ae18df370..000000000 --- a/baas/src/test/resources/cassandra.conf +++ /dev/null @@ -1,15 +0,0 @@ -akka.persistence.journal.plugin = "cassandra-journal" -akka.persistence.snapshot-store.plugin = "cassandra-snapshot-store" - -baker.actor.read-journal-plugin = "cassandra-query-journal" -baker.journal-initialize-timeout = 30 seconds - -cassandra-config = { - keyspace-autocreate = true - tables-autocreate = true - keyspace = baas - cassandra-2x-compat = on -} - -cassandra-journal = ${cassandra-config} -cassandra-snapshot-store = ${cassandra-config} \ No newline at end of file diff --git a/baas/src/test/resources/cluster.conf b/baas/src/test/resources/cluster.conf deleted file mode 100644 index c69da64b4..000000000 --- a/baas/src/test/resources/cluster.conf +++ /dev/null @@ -1,34 +0,0 @@ -akka { - actor.provider = "akka.cluster.ClusterActorRefProvider" - - remote { - maximum-payload-bytes = 10000000 bytes - netty.tcp { - hostname = "127.0.0.1" - port = 2552 - message-frame-size = 10000000b - send-buffer-size = 10000000b - receive-buffer-size = 10000000b - maximum-frame-size = 10000000b - } - } - - cluster { - - seed-nodes = [ - "akka.tcp://BAASAPIActorSystem@127.0.0.1:2552" - ] - - sharding { - least-shard-allocation-strategy.rebalance-threshold = 5 - remember-entities = on - } - -// http.management { -// hostname = "127.0.0.1" -// port = 19999 -// } - } -} - -baker.actor.provider = "cluster-sharded" diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala index e93fc78cf..510169a1d 100644 --- a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala @@ -1,57 +1,140 @@ package com.ing.baker.runtime.baas.common +import java.util.UUID + import akka.actor.ActorSystem -import akka.http.scaladsl.Http -import akka.stream.Materializer +import akka.stream.{ActorMaterializer, Materializer} import cats.effect.{IO, Timer} -import cats.~> import com.ing.baker.compiler.RecipeCompiler import com.ing.baker.runtime.baas.BaaSServer -import com.ing.baker.runtime.common.Baker +import com.ing.baker.runtime.baas.common.CheckoutFlowIngredients.ShippingAddress +import com.ing.baker.runtime.baas.common.CommonBaaSServerClientSpec.ClientServerTest import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi -import com.ing.baker.runtime.scaladsl.{InteractionInstance, Baker => ScalaBaker} -import org.scalatest.{AsyncFunSpec, BeforeAndAfterAll, Matchers} - -import scala.concurrent.duration._ -import scala.concurrent.{Await, Future} - -abstract class CommonBaaSServerClientSpec[F[_]]( - clientBaker: Baker[F], - serverBaker: ScalaBaker, - host: String, - port: Int, - toFuture: F ~> Future)( - implicit system: ActorSystem, materializer: Materializer - ) +import com.ing.baker.runtime.common.SensoryEventStatus +import com.ing.baker.runtime.scaladsl.{EventInstance, InteractionInstance, Baker => ScalaBaker} +import org.scalatest.compatible.Assertion +import org.scalatest.{AsyncFunSpec, BeforeAndAfterAll, BeforeAndAfterEach, Matchers} + +import scala.concurrent.{ExecutionContext, Future} + +abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Materializer) => ScalaBaker) extends AsyncFunSpec with Matchers with BeforeAndAfterAll + with BeforeAndAfterEach with LanguageApi { - var serverShutdown: Http.ServerBinding = _ + val test: ClientServerTest = CommonBaaSServerClientSpec.testWith(clientBaker) - implicit val timer: Timer[IO] = IO.timer(system.dispatcher) + describe("Baker Client-Server") { + it("Baker.addRecipe") { + test { (client, server) => + val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) + for { + recipeId <- client.addRecipe(compiledRecipe) + recipeInformation <- server.getRecipe(recipeId) + } yield recipeInformation.compiledRecipe shouldBe compiledRecipe + } + } + + it("Baker.getRecipe") { + test { (client, _) => + val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) + for { + recipeId <- client.addRecipe(compiledRecipe) + recipeInformation <- client.getRecipe(recipeId) + } yield recipeInformation.compiledRecipe shouldBe compiledRecipe + } + } + + it("Baker.getAllRecipes") { + test { (client, _) => + val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) + for { + recipeId <- client.addRecipe(compiledRecipe) + recipes <- client.getAllRecipes + } yield recipes.get(recipeId).map(_.compiledRecipe) shouldBe Some(compiledRecipe) + } + } + + it("Baker.bake") { + test { (client, server) => + val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) + val recipeInstanceId: String = UUID.randomUUID().toString + for { + recipeId <- client.addRecipe(compiledRecipe) + _ <- client.bake(recipeId, recipeInstanceId) + state <- server.getRecipeInstanceState(recipeInstanceId) + } yield state.recipeInstanceId shouldBe recipeInstanceId + } + } + + it("Baker.fireEventAndResolveWhenReceived") { + test { (client, server) => + val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) + val recipeInstanceId: String = UUID.randomUUID().toString + val event = EventInstance.unsafeFrom( + CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress("address"))) + for { + recipeId <- client.addRecipe(compiledRecipe) + _ <- client.bake(recipeId, recipeInstanceId) + status <- client.fireEventAndResolveWhenReceived(recipeInstanceId, event) + } yield status shouldBe SensoryEventStatus.Received + } + } - override def beforeAll(): Unit = { + it("Baker.fireEventAndResolveWhenCompleted") { + test { (client, server) => + val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) + val recipeInstanceId: String = UUID.randomUUID().toString + val event = EventInstance.unsafeFrom( + CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress("address"))) + for { + recipeId <- client.addRecipe(compiledRecipe) + _ <- client.bake(recipeId, recipeInstanceId) + result <- client.fireEventAndResolveWhenCompleted(recipeInstanceId, event) + } yield result.eventNames should contain("ShippingAddressReceived") + } + } + } +} + +object CommonBaaSServerClientSpec { + + type ClientServerTest = ((ScalaBaker, ScalaBaker) => Future[Assertion]) => Future[Assertion] + + val allPorts: Stream[Int] = Stream.from(50000, 1) + + def testWith[F[_], Lang <: LanguageApi] + (clientBaker: (String, ActorSystem, Materializer) => ScalaBaker) + (t: (ScalaBaker, ScalaBaker) => Future[Assertion]) + (implicit ec: ExecutionContext): Future[Assertion] = { + val testId: UUID = UUID.randomUUID() + implicit val system: ActorSystem = ActorSystem("ScalaDSLBaaSServerClientSpec-" + testId) + implicit val materializer: Materializer = ActorMaterializer() + implicit val timer: Timer[IO] = IO.timer(system.dispatcher) + val host: String = "localhost" + val serverBaker = ScalaBaker.akkaLocalDefault(system, materializer) val makePaymentInstance: InteractionInstance = InteractionInstance.unsafeFrom(new MakePaymentInstance()) val reserveItemsInstance: InteractionInstance = InteractionInstance.unsafeFrom(new ReserveItemsInstance()) val shipItemsInstance: InteractionInstance = InteractionInstance.unsafeFrom(new ShipItemsInstance()) - val addInteractions = serverBaker.addInteractionInstances(Seq(makePaymentInstance, reserveItemsInstance, shipItemsInstance)) - Await.result(addInteractions, 10 seconds) - serverShutdown = Await.result(BaaSServer.run(serverBaker, host, port), 10 seconds) - } - - override def afterAll(): Unit = { - Await.result(serverShutdown.unbind(), 10 seconds) + for { + _ <- serverBaker.addInteractionInstances(Seq(makePaymentInstance, reserveItemsInstance, shipItemsInstance)) + (client, shutdown) <- createClientServerPair(allPorts, { port => + val client = clientBaker(s"http://$host:$port/", system, materializer) + val shutdown = BaaSServer.run(serverBaker, host, port) + shutdown.map(s => (client, s)) + }) + a <- t(client, serverBaker) + _ <- shutdown.unbind() + _ <- serverBaker.gracefulShutdown() + } yield a } - describe("Baker Client-Server comm") { - it("Baker.addRecipe") { - val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) - for { - recipeId <- toFuture(clientBaker.addRecipe(compiledRecipe)) - recipeInformation <- serverBaker.getRecipe(recipeId) - } yield recipeInformation.compiledRecipe shouldBe compiledRecipe + private def createClientServerPair[T](ports: Stream[Int], buildServer: Int => Future[T])(implicit ec: ExecutionContext): Future[T] = + ports match { + case #::(port, tail) => buildServer(port).recoverWith { + case _: java.net.BindException => createClientServerPair(tail, buildServer) + } } - } -} +} \ No newline at end of file diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala index 8346edde6..7c9eb3a2d 100644 --- a/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala @@ -1,33 +1,11 @@ package com.ing.baker.runtime.baas.scaladsl -import akka.actor.ActorSystem import akka.http.scaladsl.model.Uri -import akka.stream.{ActorMaterializer, Materializer} -import cats.arrow.FunctionK -import cats.~> +import com.ing.baker.runtime.akka.actor.serialization.Encryption import com.ing.baker.runtime.baas.common.CommonBaaSServerClientSpec -import com.ing.baker.runtime.scaladsl.{Baker => ScalaBaker} - -import scala.concurrent.Future -import ScalaDSLBaaSServerClientSpec._ import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi -object ScalaDSLBaaSServerClientSpec { - - implicit val system: ActorSystem = ActorSystem("ScalaDSLBaaSServerClientSpec") - - implicit val materializer: Materializer = ActorMaterializer() - - val host: String = "localhost" - - val port: Int = 8181 - - val clientBaker = new Baker(Uri(s"http://$host:$port")) - - val serverBaker = ScalaBaker.akkaLocalDefault(system, materializer) - - val IdentityFuture: Future ~> Future = FunctionK.id -} - -class ScalaDSLBaaSServerClientSpec extends CommonBaaSServerClientSpec(clientBaker, serverBaker, host, port, IdentityFuture) with ScalaApi +class ScalaDSLBaaSServerClientSpec extends CommonBaaSServerClientSpec( + (host, as, mat) => new Baker(Uri(host), Encryption.NoEncryption)(as, mat) +) with ScalaApi diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/LanguageDataStructures.scala b/runtime/src/main/scala/com/ing/baker/runtime/common/LanguageDataStructures.scala index 355fb766d..03fe3eb53 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/common/LanguageDataStructures.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/common/LanguageDataStructures.scala @@ -1,7 +1,5 @@ package com.ing.baker.runtime.common -import java.util.Optional - sealed trait LanguageDataStructures { type Map[A, B] From adfd2adf7e376ed0caa1c11b5729d69a79926dc7 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Wed, 2 Oct 2019 14:09:11 +0200 Subject: [PATCH 16/86] Finished testing the client server interactions --- .../baas/common/CheckoutFlowRecipe.scala | 12 +- .../common/CommonBaaSServerClientSpec.scala | 182 ++++++++++++++++-- .../baas/common/ReserveItemsInstance.scala | 15 ++ 3 files changed, 190 insertions(+), 19 deletions(-) diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CheckoutFlowRecipe.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CheckoutFlowRecipe.scala index bc0ab7a7b..308007985 100644 --- a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CheckoutFlowRecipe.scala +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CheckoutFlowRecipe.scala @@ -1,6 +1,6 @@ package com.ing.baker.runtime.baas.common -import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff +import com.ing.baker.recipe.common.InteractionFailureStrategy.{BlockInteraction, RetryWithIncrementalBackoff} import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff.UntilDeadline import com.ing.baker.recipe.scaladsl.{Event, Ingredient, Interaction, Recipe} import CheckoutFlowIngredients._ @@ -103,7 +103,7 @@ object CheckoutFlowInteractions { object CheckoutFlowRecipe { - def recipe: Recipe = Recipe("Webshop") + private def recipeBase = Recipe("Webshop") .withSensoryEvents( Event[OrderPlaced], Event[PaymentInformationReceived], @@ -112,11 +112,17 @@ object CheckoutFlowRecipe { ReserveItemsInteraction, MakePaymentInteraction, ShipItemsInteraction) - .withDefaultFailureStrategy( + + def recipe: Recipe = + recipeBase.withDefaultFailureStrategy( RetryWithIncrementalBackoff .builder() .withInitialDelay(100 milliseconds) .withUntil(Some(UntilDeadline(24 hours))) .withMaxTimeBetweenRetries(Some(10 minutes)) .build()) + + def recipeWithBlockingStrategy: Recipe = + recipeBase.withDefaultFailureStrategy( + BlockInteraction()) } diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala index 510169a1d..a2dcc7024 100644 --- a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala @@ -6,9 +6,11 @@ import akka.actor.ActorSystem import akka.stream.{ActorMaterializer, Materializer} import cats.effect.{IO, Timer} import com.ing.baker.compiler.RecipeCompiler +import com.ing.baker.il.CompiledRecipe import com.ing.baker.runtime.baas.BaaSServer -import com.ing.baker.runtime.baas.common.CheckoutFlowIngredients.ShippingAddress -import com.ing.baker.runtime.baas.common.CommonBaaSServerClientSpec.ClientServerTest +import com.ing.baker.runtime.baas.common.CheckoutFlowEvents.ItemsReserved +import com.ing.baker.runtime.baas.common.CheckoutFlowIngredients.{Item, OrderId, ReservedItems, ShippingAddress} +import com.ing.baker.runtime.baas.common.CommonBaaSServerClientSpec.{ClientServerTest, setupFailingOnceReserveItems, setupFailingWithRetryReserveItems, setupHappyPath} import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.scaladsl.{EventInstance, InteractionInstance, Baker => ScalaBaker} @@ -26,11 +28,13 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat val test: ClientServerTest = CommonBaaSServerClientSpec.testWith(clientBaker) + implicit val timer: Timer[IO] = IO.timer(executionContext) + describe("Baker Client-Server") { it("Baker.addRecipe") { test { (client, server) => - val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) for { + compiledRecipe <- setupHappyPath(server) recipeId <- client.addRecipe(compiledRecipe) recipeInformation <- server.getRecipe(recipeId) } yield recipeInformation.compiledRecipe shouldBe compiledRecipe @@ -38,9 +42,9 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.getRecipe") { - test { (client, _) => - val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) + test { (client, server) => for { + compiledRecipe <- setupHappyPath(server) recipeId <- client.addRecipe(compiledRecipe) recipeInformation <- client.getRecipe(recipeId) } yield recipeInformation.compiledRecipe shouldBe compiledRecipe @@ -48,9 +52,9 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.getAllRecipes") { - test { (client, _) => - val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) + test { (client, server) => for { + compiledRecipe <- setupHappyPath(server) recipeId <- client.addRecipe(compiledRecipe) recipes <- client.getAllRecipes } yield recipes.get(recipeId).map(_.compiledRecipe) shouldBe Some(compiledRecipe) @@ -59,9 +63,9 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat it("Baker.bake") { test { (client, server) => - val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) val recipeInstanceId: String = UUID.randomUUID().toString for { + compiledRecipe <- setupHappyPath(server) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) state <- server.getRecipeInstanceState(recipeInstanceId) @@ -71,11 +75,11 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat it("Baker.fireEventAndResolveWhenReceived") { test { (client, server) => - val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress("address"))) for { + compiledRecipe <- setupHappyPath(server) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) status <- client.fireEventAndResolveWhenReceived(recipeInstanceId, event) @@ -85,15 +89,136 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat it("Baker.fireEventAndResolveWhenCompleted") { test { (client, server) => - val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress("address"))) for { + compiledRecipe <- setupHappyPath(server) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) result <- client.fireEventAndResolveWhenCompleted(recipeInstanceId, event) - } yield result.eventNames should contain("ShippingAddressReceived") + serverState <- server.getRecipeInstanceState(recipeInstanceId) + } yield { + result.eventNames should contain("ShippingAddressReceived") + serverState.events.map(_.name) should contain("ShippingAddressReceived") + } + } + } + + it("Baker.fireEventAndResolveOnEvent") { + test { (client, server) => + val recipeInstanceId: String = UUID.randomUUID().toString + val event = EventInstance.unsafeFrom( + CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress("address"))) + for { + compiledRecipe <- setupHappyPath(server) + recipeId <- client.addRecipe(compiledRecipe) + _ <- client.bake(recipeId, recipeInstanceId) + result <- client.fireEventAndResolveOnEvent(recipeInstanceId, event, "ShippingAddressReceived") + serverState <- server.getRecipeInstanceState(recipeInstanceId) + } yield { + result.eventNames should contain("ShippingAddressReceived") + serverState.events.map(_.name) should contain("ShippingAddressReceived") + } + } + } + + it("Baker.getAllRecipeInstancesMetadata") { + test { (client, server) => + val recipeInstanceId: String = UUID.randomUUID().toString + for { + compiledRecipe <- setupHappyPath(server) + recipeId <- client.addRecipe(compiledRecipe) + _ <- client.bake(recipeId, recipeInstanceId) + clientMetadata <- client.getAllRecipeInstancesMetadata + serverMetadata <- server.getAllRecipeInstancesMetadata + } yield clientMetadata shouldBe serverMetadata + } + } + + it("Baker.getVisualState") { + test { (client, server) => + val recipeInstanceId: String = UUID.randomUUID().toString + for { + compiledRecipe <- setupHappyPath(server) + recipeId <- client.addRecipe(compiledRecipe) + _ <- client.bake(recipeId, recipeInstanceId) + clientState <- client.getVisualState(recipeInstanceId) + serverState <- server.getVisualState(recipeInstanceId) + } yield clientState shouldBe serverState + } + } + + it("Baker.retryInteraction") { + test { (client, server) => + val recipeInstanceId: String = UUID.randomUUID().toString + val event = EventInstance.unsafeFrom( + CheckoutFlowEvents.OrderPlaced(orderId = OrderId("order1"), List.empty)) + for { + compiledRecipe <- setupFailingOnceReserveItems(server) + recipeId <- client.addRecipe(compiledRecipe) + _ <- client.bake(recipeId, recipeInstanceId) + _ <- client.fireEventAndResolveWhenCompleted(recipeInstanceId, event) + state1 <- client.getRecipeInstanceState(recipeInstanceId).map(_.events.map(_.name)) + _ <- client.retryInteraction(recipeInstanceId, "ReserveItems") + state2 <- client.getRecipeInstanceState(recipeInstanceId).map(_.events.map(_.name)) + } yield { + state1 should contain("OrderPlaced") + state1 should not contain("ItemsReserved") + state2 should contain("OrderPlaced") + state2 should contain("ItemsReserved") + } + } + } + + it("Baker.resolveInteraction") { + test { (client, server) => + val recipeInstanceId: String = UUID.randomUUID().toString + val event = EventInstance.unsafeFrom( + CheckoutFlowEvents.OrderPlaced(orderId = OrderId("order1"), List.empty)) + val resolutionEvent = EventInstance.unsafeFrom( + ItemsReserved(reservedItems = ReservedItems(items = List(Item("item1")), data = Array.empty)) + ) + for { + compiledRecipe <- setupFailingOnceReserveItems(server) + recipeId <- client.addRecipe(compiledRecipe) + _ <- client.bake(recipeId, recipeInstanceId) + _ <- client.fireEventAndResolveWhenCompleted(recipeInstanceId, event) + state1 <- client.getRecipeInstanceState(recipeInstanceId).map(_.events.map(_.name)) + _ <- client.resolveInteraction(recipeInstanceId, "ReserveItems", resolutionEvent) + state2data <- client.getRecipeInstanceState(recipeInstanceId) + state2 = state2data.events.map(_.name) + eventState = state2data.ingredients.get("reservedItems").map(_.as[ReservedItems].items.head.itemId) + } yield { + state1 should contain("OrderPlaced") + state1 should not contain("ItemsReserved") + state2 should contain("OrderPlaced") + state2 should contain("ItemsReserved") + eventState shouldBe Some("item1") + } + } + } + + it("Baker.stopRetryingInteraction") { + test { (client, server) => + val recipeInstanceId: String = UUID.randomUUID().toString + val event = EventInstance.unsafeFrom( + CheckoutFlowEvents.OrderPlaced(orderId = OrderId("order1"), List.empty)) + for { + compiledRecipe <- setupFailingWithRetryReserveItems(server) + recipeId <- client.addRecipe(compiledRecipe) + _ <- client.bake(recipeId, recipeInstanceId) + _ <- client.fireEventAndResolveWhenReceived(recipeInstanceId, event) + state1 <- client.getRecipeInstanceState(recipeInstanceId).map(_.events.map(_.name)) + _ <- client.stopRetryingInteraction(recipeInstanceId, "ReserveItems") + state2data <- client.getRecipeInstanceState(recipeInstanceId) + state2 = state2data.events.map(_.name) + } yield { + state1 should contain("OrderPlaced") + state1 should not contain("ItemsReserved") + state2 should contain("OrderPlaced") + state2 should not contain("ItemsReserved") + } } } } @@ -101,6 +226,36 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat object CommonBaaSServerClientSpec { + def setupHappyPath(serverBaker: ScalaBaker)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { + val makePaymentInstance = InteractionInstance.unsafeFrom(new MakePaymentInstance()) + val reserveItemsInstance = InteractionInstance.unsafeFrom(new ReserveItemsInstance()) + val shipItemsInstance = InteractionInstance.unsafeFrom(new ShipItemsInstance()) + val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) + for { + _ <- serverBaker.addInteractionInstances(Seq(makePaymentInstance, reserveItemsInstance, shipItemsInstance)) + } yield compiledRecipe + } + + def setupFailingOnceReserveItems(serverBaker: ScalaBaker)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { + val makePaymentInstance = InteractionInstance.unsafeFrom(new MakePaymentInstance()) + val reserveItemsInstance = InteractionInstance.unsafeFrom(new FailingOnceReserveItemsInstance()) + val shipItemsInstance = InteractionInstance.unsafeFrom(new ShipItemsInstance()) + val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipeWithBlockingStrategy) + for { + _ <- serverBaker.addInteractionInstances(Seq(makePaymentInstance, reserveItemsInstance, shipItemsInstance)) + } yield compiledRecipe + } + + def setupFailingWithRetryReserveItems(serverBaker: ScalaBaker)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { + val makePaymentInstance = InteractionInstance.unsafeFrom(new MakePaymentInstance()) + val reserveItemsInstance = InteractionInstance.unsafeFrom(new FailingReserveItemsInstance()) + val shipItemsInstance = InteractionInstance.unsafeFrom(new ShipItemsInstance()) + val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) + for { + _ <- serverBaker.addInteractionInstances(Seq(makePaymentInstance, reserveItemsInstance, shipItemsInstance)) + } yield compiledRecipe + } + type ClientServerTest = ((ScalaBaker, ScalaBaker) => Future[Assertion]) => Future[Assertion] val allPorts: Stream[Int] = Stream.from(50000, 1) @@ -112,14 +267,9 @@ object CommonBaaSServerClientSpec { val testId: UUID = UUID.randomUUID() implicit val system: ActorSystem = ActorSystem("ScalaDSLBaaSServerClientSpec-" + testId) implicit val materializer: Materializer = ActorMaterializer() - implicit val timer: Timer[IO] = IO.timer(system.dispatcher) val host: String = "localhost" val serverBaker = ScalaBaker.akkaLocalDefault(system, materializer) - val makePaymentInstance: InteractionInstance = InteractionInstance.unsafeFrom(new MakePaymentInstance()) - val reserveItemsInstance: InteractionInstance = InteractionInstance.unsafeFrom(new ReserveItemsInstance()) - val shipItemsInstance: InteractionInstance = InteractionInstance.unsafeFrom(new ShipItemsInstance()) for { - _ <- serverBaker.addInteractionInstances(Seq(makePaymentInstance, reserveItemsInstance, shipItemsInstance)) (client, shutdown) <- createClientServerPair(allPorts, { port => val client = clientBaker(s"http://$host:$port/", system, materializer) val shutdown = BaaSServer.run(serverBaker, host, port) diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/ReserveItemsInstance.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/common/ReserveItemsInstance.scala index e8b462fef..80299e308 100644 --- a/baas/src/test/scala/com/ing/baker/runtime/baas/common/ReserveItemsInstance.scala +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/common/ReserveItemsInstance.scala @@ -17,3 +17,18 @@ class ReserveItemsInstance(implicit timer: Timer[IO]) extends ReserveItems { .unsafeToFuture() } } + +class FailingOnceReserveItemsInstance extends ReserveItems { + + var times = 1; + + override def apply(orderId: OrderId, items: List[Item]): Future[ReserveItemsOutput] = + if (times == 1) { times = times + 1; Future.failed(new RuntimeException("oups")) } + else Future.successful(CheckoutFlowEvents.ItemsReserved(ReservedItems(items, Array.fill(1000)(Byte.MaxValue)))) +} + +class FailingReserveItemsInstance extends ReserveItems { + + override def apply(orderId: OrderId, items: List[Item]): Future[ReserveItemsOutput] = + Future.failed(new RuntimeException("oups")) +} From 49bac79e306cbd7ef5969e8e085658c5a95695fc Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Thu, 3 Oct 2019 15:12:31 +0200 Subject: [PATCH 17/86] minor --- .../main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala | 2 +- .../runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala | 2 +- project/plugins.sbt | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala index c430c0078..850db7859 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala @@ -18,7 +18,7 @@ import com.ing.baker.types.Value import scala.concurrent.Future -class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(implicit system: ActorSystem, mat: Materializer) extends ScalaBaker { +case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(implicit system: ActorSystem, mat: Materializer) extends ScalaBaker { import system.dispatcher diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala index 7c9eb3a2d..4df90bc78 100644 --- a/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala @@ -6,6 +6,6 @@ import com.ing.baker.runtime.baas.common.CommonBaaSServerClientSpec import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi class ScalaDSLBaaSServerClientSpec extends CommonBaaSServerClientSpec( - (host, as, mat) => new Baker(Uri(host), Encryption.NoEncryption)(as, mat) + (host, as, mat) => Baker(Uri(host), Encryption.NoEncryption)(as, mat) ) with ScalaApi diff --git a/project/plugins.sbt b/project/plugins.sbt index e17de5f7a..ca64b6491 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -22,4 +22,5 @@ addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.25") libraryDependencies += "org.slf4j" % "slf4j-nop" % "1.7.25" -addSbtPlugin("io.kamon" % "sbt-kanela-runner" % "2.0.3") \ No newline at end of file +// For the example application +//addSbtPlugin("io.kamon" % "sbt-kanela-runner" % "2.0.1") From e81c5cd95ec95f274b5c435b735c123325d5da1e Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Fri, 4 Oct 2019 15:45:53 +0200 Subject: [PATCH 18/86] finished the serialization of BakerExceptions --- baas/src/main/protobuf/baas.proto | 2 +- .../ing/baker/runtime/baas/BaaSProto.scala | 5 +- .../ing/baker/runtime/baas/BaaSProtocol.scala | 4 +- .../ing/baker/runtime/baas/BaaSServer.scala | 38 ++++----- .../baker/runtime/baas/MarshallingUtils.scala | 57 ++++++++++++- .../baker/runtime/baas/scaladsl/Baker.scala | 38 +++++---- .../common/CommonBaaSServerClientSpec.scala | 80 +++++++++++++++++-- runtime/src/main/protobuf/common.proto | 5 ++ .../ing/baker/runtime/akka/AkkaBaker.scala | 38 ++++----- .../akka/actor/serialization/ProtoMap.scala | 4 + .../protomappings/BakerExceptionMapping.scala | 26 ++++++ .../baker/runtime/common/BakerException.scala | 51 ++++++++++-- 12 files changed, 274 insertions(+), 74 deletions(-) create mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/BakerExceptionMapping.scala diff --git a/baas/src/main/protobuf/baas.proto b/baas/src/main/protobuf/baas.proto index 2381b3db9..02e04719f 100644 --- a/baas/src/main/protobuf/baas.proto +++ b/baas/src/main/protobuf/baas.proto @@ -9,7 +9,7 @@ option (scalapb.options) = { }; message BaaSRemoteFailure { - optional string message = 1; + optional BakerException failure = 1; } message AddRecipeRequest { diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala index bc24c6f09..1143e7f94 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala @@ -18,10 +18,11 @@ object BaaSProto { protobuf.BaaSRemoteFailure override def toProto(a: BaaSRemoteFailure): protobuf.BaaSRemoteFailure = - protobuf.BaaSRemoteFailure(Some(a.message)) + protobuf.BaaSRemoteFailure(Some(ctxToProto(a.error))) override def fromProto(message: protobuf.BaaSRemoteFailure): Try[BaaSRemoteFailure] = - versioned(message.message, "message") + versioned(message.failure, "failure") + .flatMap(ctxFromProto(_)) .map(BaaSRemoteFailure) } diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala index 04f3dd591..b6b927ba6 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala @@ -1,12 +1,12 @@ package com.ing.baker.runtime.baas import com.ing.baker.il.CompiledRecipe -import com.ing.baker.runtime.common.SensoryEventStatus +import com.ing.baker.runtime.common.{BakerException, SensoryEventStatus} import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult} object BaaSProtocol { - case class BaaSRemoteFailure(message: String) + case class BaaSRemoteFailure(error: BakerException) case class AddRecipeRequest(compiledRecipe: CompiledRecipe) diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala index 58e97b537..4293ba15f 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala @@ -4,11 +4,13 @@ import akka.actor.ActorSystem import akka.http.scaladsl.Http import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.server.Directives._ -import akka.http.scaladsl.server.Route +import akka.http.scaladsl.server.{RequestContext, Route} import akka.stream.Materializer import com.ing.baker.runtime.akka.actor.serialization.{Encryption, SerializersProvider} import com.ing.baker.runtime.baas.BaaSProto._ +import com.ing.baker.runtime.baas.BaaSProtocol.BaaSRemoteFailure import com.ing.baker.runtime.baas.MarshallingUtils._ +import com.ing.baker.runtime.common.BakerException import com.ing.baker.runtime.scaladsl.Baker import scala.concurrent.Future @@ -37,45 +39,43 @@ class BaaSServer(implicit system: ActorSystem, mat: Materializer, baker: Baker, private def addRecipe: Route = post(path("addRecipe") { entity(as[BaaSProtocol.AddRecipeRequest]) { request => - complete(baker.addRecipe(request.compiledRecipe).map(BaaSProtocol.AddRecipeResponse)) + completeWithBakerFailures(baker.addRecipe(request.compiledRecipe).map(BaaSProtocol.AddRecipeResponse)) } }) private def getRecipe: Route = post(path("getRecipe") { entity(as[BaaSProtocol.GetRecipeRequest]) { request => - complete(baker.getRecipe(request.recipeId).map(BaaSProtocol.GetRecipeResponse)) + completeWithBakerFailures(baker.getRecipe(request.recipeId).map(BaaSProtocol.GetRecipeResponse)) } }) private def getAllRecipes: Route = post(path("getAllRecipes") { - complete(baker.getAllRecipes.map(BaaSProtocol.GetAllRecipesResponse)) + completeWithBakerFailures(baker.getAllRecipes.map(BaaSProtocol.GetAllRecipesResponse)) }) private def bake: Route = post(path("bake") { entity(as[BaaSProtocol.BakeRequest]) { request => - onComplete(baker.bake(request.recipeId, request.recipeInstanceId)) { _ => - complete(StatusCodes.OK) - } + completeWithBakerFailures(baker.bake(request.recipeId, request.recipeInstanceId)) } }) private def fireEventAndResolveWhenReceived: Route = post(path("fireEventAndResolveWhenReceived") { entity(as[BaaSProtocol.FireEventAndResolveWhenReceivedRequest]) { request => - complete(baker.fireEventAndResolveWhenReceived(request.recipeInstanceId, request.event, request.correlationId) + completeWithBakerFailures(baker.fireEventAndResolveWhenReceived(request.recipeInstanceId, request.event, request.correlationId) .map(BaaSProtocol.FireEventAndResolveWhenReceivedResponse)) } }) private def fireEventAndResolveWhenCompleted: Route = post(path("fireEventAndResolveWhenCompleted") { entity(as[BaaSProtocol.FireEventAndResolveWhenCompletedRequest]) { request => - complete(baker.fireEventAndResolveWhenCompleted(request.recipeInstanceId, request.event, request.correlationId) + completeWithBakerFailures(baker.fireEventAndResolveWhenCompleted(request.recipeInstanceId, request.event, request.correlationId) .map(BaaSProtocol.FireEventAndResolveWhenCompletedResponse)) } }) private def fireEventAndResolveOnEvent: Route = post(path("fireEventAndResolveOnEvent") { entity(as[BaaSProtocol.FireEventAndResolveOnEventRequest]) { request => - complete(baker.fireEventAndResolveOnEvent(request.recipeInstanceId, request.event, request.onEvent, request.correlationId) + completeWithBakerFailures(baker.fireEventAndResolveOnEvent(request.recipeInstanceId, request.event, request.onEvent, request.correlationId) .map(BaaSProtocol.FireEventAndResolveOnEventResponse)) } }) @@ -88,45 +88,39 @@ class BaaSServer(implicit system: ActorSystem, mat: Materializer, baker: Baker, }) private def getAllRecipeInstancesMetadata: Route = post(path("getAllRecipeInstancesMetadata") { - complete(baker.getAllRecipeInstancesMetadata + completeWithBakerFailures(baker.getAllRecipeInstancesMetadata .map(BaaSProtocol.GetAllRecipeInstancesMetadataResponse)) }) private def getRecipeInstanceState: Route = post(path("getRecipeInstanceState") { entity(as[BaaSProtocol.GetRecipeInstanceStateRequest]) { request => - complete(baker.getRecipeInstanceState(request.recipeInstanceId) + completeWithBakerFailures(baker.getRecipeInstanceState(request.recipeInstanceId) .map(BaaSProtocol.GetRecipeInstanceStateResponse)) } }) private def getVisualState: Route = post(path("getVisualState") { entity(as[BaaSProtocol.GetVisualStateRequest]) { request => - complete(baker.getVisualState(request.recipeInstanceId) + completeWithBakerFailures(baker.getVisualState(request.recipeInstanceId) .map(BaaSProtocol.GetVisualStateResponse)) } }) private def retryInteraction: Route = post(path("retryInteraction") { entity(as[BaaSProtocol.RetryInteractionRequest]) { request => - onComplete(baker.retryInteraction(request.recipeInstanceId, request.interactionName)) { _ => - complete(StatusCodes.OK) - } + completeWithBakerFailures(baker.retryInteraction(request.recipeInstanceId, request.interactionName)) } }) private def resolveInteraction: Route = post(path("resolveInteraction") { entity(as[BaaSProtocol.ResolveInteractionRequest]) { request => - onComplete(baker.resolveInteraction(request.recipeInstanceId, request.interactionName, request.event)) { _ => - complete(StatusCodes.OK) - } + completeWithBakerFailures(baker.resolveInteraction(request.recipeInstanceId, request.interactionName, request.event)) } }) private def stopRetryingInteraction: Route = post(path("stopRetryingInteraction") { entity(as[BaaSProtocol.StopRetryingInteractionRequest]) { request => - onComplete(baker.stopRetryingInteraction(request.recipeInstanceId, request.interactionName)) { _ => - complete(StatusCodes.OK) - } + completeWithBakerFailures(baker.stopRetryingInteraction(request.recipeInstanceId, request.interactionName)) } }) diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/MarshallingUtils.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/MarshallingUtils.scala index aceabff95..f3b7d840a 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/MarshallingUtils.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/MarshallingUtils.scala @@ -1,17 +1,70 @@ package com.ing.baker.runtime.baas import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller} -import akka.http.scaladsl.model.{ContentTypes, MediaTypes} -import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller} +import akka.http.scaladsl.model.{ContentTypes, HttpResponse, MediaTypes, StatusCodes} +import akka.http.scaladsl.server.{Route, StandardRoute} +import akka.http.scaladsl.server.Directives.{complete, onSuccess} +import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshal, Unmarshaller} import com.ing.baker.runtime.akka.actor.serialization.ProtoMap +import com.ing.baker.runtime.common.BakerException +import BaaSProto._ +import akka.stream.Materializer + +import scala.concurrent.{ExecutionContext, Future} object MarshallingUtils { type ProtoMessage[A] = scalapb.GeneratedMessage with scalapb.Message[A] + def completeWithBakerFailures[A, P <: ProtoMessage[P]](f: Future[A])(implicit ec: ExecutionContext, m1: ProtoMap[A, P]): Route = + complete(f.map(Right(_)).recover { case e: BakerException => Left(BaaSProtocol.BaaSRemoteFailure(e)) }) + + def completeWithBakerFailures(f: Future[Unit])(implicit ec: ExecutionContext): Route = + onSuccess(f.map(_ => None).recover { case e: BakerException => Some(e) }) { + case Some(e) => complete(BaaSProtocol.BaaSRemoteFailure(e)) + case None => complete(StatusCodes.OK) + } + + case class UnmarshalWithBakerExceptions[A](response: HttpResponse) { + + def withBakerExceptions[P <: ProtoMessage[P]](implicit ec: ExecutionContext, mat: Materializer, m1: ProtoMap[A, P]): Future[A] = { + for { + decoded <- Unmarshal(response).to[Either[BaaSProtocol.BaaSRemoteFailure, A]] + response <- decoded match { + case Left(e) => Future.failed(e.error) + case Right(a) => Future.successful(a) + } + } yield response + } + } + + def unmarshal[A](response: HttpResponse): UnmarshalWithBakerExceptions[A] = + UnmarshalWithBakerExceptions[A](response) + + def unmarshalBakerExceptions(response: HttpResponse)(implicit ec: ExecutionContext, mat: Materializer): Future[Unit] = + response.entity.httpEntity.contentType match { + case ContentTypes.`application/octet-stream` => + Unmarshal(response) + .to[BaaSProtocol.BaaSRemoteFailure] + .flatMap(e => Future.failed(e.error)) + case _ => + Future.successful(()) + } + implicit def protoMarshaller[A, P <: ProtoMessage[P]](implicit mapping: ProtoMap[A, P]): ToEntityMarshaller[A] = Marshaller.ByteArrayMarshaller.wrap(MediaTypes.`application/octet-stream`)(mapping.toByteArray) implicit def protoUnmarshaller[A, P <: ProtoMessage[P]](implicit mapping: ProtoMap[A, P]): FromEntityUnmarshaller[A] = Unmarshaller.byteArrayUnmarshaller.map(mapping.fromByteArray(_).get) + + implicit def protoEitherMarshaller[A, P0 <: ProtoMessage[P0], B, P1 <: ProtoMessage[P1]](implicit m1: ProtoMap[A, P0], m2: ProtoMap[B, P1]): ToEntityMarshaller[Either[A, B]] = + Marshaller.ByteArrayMarshaller.wrap(MediaTypes.`application/octet-stream`) { + case Left(a) => m1.toByteArray(a) + case Right(b) => m2.toByteArray(b) + } + + implicit def protoEitherUnmarshaller[A, P0 <: ProtoMessage[P0], B, P1 <: ProtoMessage[P1]](implicit m1: ProtoMap[A, P0], m2: ProtoMap[B, P1]): FromEntityUnmarshaller[Either[A, B]] = + Unmarshaller.byteArrayUnmarshaller.map { byteArray => + m1.fromByteArray(byteArray).map(Left(_)).orElse(m2.fromByteArray(byteArray).map(Right(_))).get + } } diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala index 850db7859..a1222e77a 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala @@ -4,19 +4,21 @@ import akka.actor.ActorSystem import akka.http.scaladsl.Http import akka.http.scaladsl.marshalling.Marshal import akka.http.scaladsl.model.Uri.Path -import akka.http.scaladsl.model.{HttpMethods, HttpRequest, MessageEntity, Uri} +import akka.http.scaladsl.model.{ContentTypes, HttpMethods, HttpRequest, HttpResponse, MessageEntity, Uri} import akka.http.scaladsl.unmarshalling.Unmarshal import akka.stream.Materializer import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} import com.ing.baker.runtime.akka.actor.serialization.{Encryption, SerializersProvider} import com.ing.baker.runtime.baas.BaaSProto._ import com.ing.baker.runtime.baas.BaaSProtocol +import com.ing.baker.runtime.baas.BaaSProtocol.BaaSRemoteFailure import com.ing.baker.runtime.baas.MarshallingUtils._ -import com.ing.baker.runtime.common.SensoryEventStatus +import com.ing.baker.runtime.common.{BakerException, SensoryEventStatus} import com.ing.baker.runtime.scaladsl.{BakerEvent, EventInstance, EventMoment, EventResolutions, InteractionInstance, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult, Baker => ScalaBaker} import com.ing.baker.types.Value import scala.concurrent.Future +import scala.util.control.NonFatal case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(implicit system: ActorSystem, mat: Materializer) extends ScalaBaker { @@ -42,7 +44,7 @@ case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption encoded <- Marshal(BaaSProtocol.AddRecipeRequest(compiledRecipe)).to[MessageEntity] request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("addRecipe")), entity = encoded) response <- Http().singleRequest(request) - decoded <- Unmarshal(response).to[BaaSProtocol.AddRecipeResponse] + decoded <- unmarshal[BaaSProtocol.AddRecipeResponse](response).withBakerExceptions } yield decoded.recipeId /** @@ -56,7 +58,7 @@ case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption encoded <- Marshal(BaaSProtocol.GetRecipeRequest(recipeId)).to[MessageEntity] request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("getRecipe")), entity = encoded) response <- Http().singleRequest(request) - decoded <- Unmarshal(response).to[BaaSProtocol.GetRecipeResponse] + decoded <- unmarshal[BaaSProtocol.GetRecipeResponse](response).withBakerExceptions } yield decoded.recipeInformation /** @@ -68,7 +70,7 @@ case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption val request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("getAllRecipes"))) for { response <- Http().singleRequest(request) - decoded <- Unmarshal(response).to[BaaSProtocol.GetAllRecipesResponse] + decoded <- unmarshal[BaaSProtocol.GetAllRecipesResponse](response).withBakerExceptions } yield decoded.map } @@ -83,7 +85,8 @@ case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption for { encoded <- Marshal(BaaSProtocol.BakeRequest(recipeId, recipeInstanceId)).to[MessageEntity] request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("bake")), entity = encoded) - _ <- Http().singleRequest(request) + response <- Http().singleRequest(request) + _ <- unmarshalBakerExceptions(response) } yield () /** @@ -102,7 +105,7 @@ case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption encoded <- Marshal(BaaSProtocol.FireEventAndResolveWhenReceivedRequest(recipeInstanceId, event, correlationId)).to[MessageEntity] request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("fireEventAndResolveWhenReceived")), entity = encoded) response <- Http().singleRequest(request) - decoded <- Unmarshal(response).to[BaaSProtocol.FireEventAndResolveWhenReceivedResponse] + decoded <- unmarshal[BaaSProtocol.FireEventAndResolveWhenReceivedResponse](response).withBakerExceptions } yield decoded.sensoryEventStatus /** @@ -121,7 +124,7 @@ case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption encoded <- Marshal(BaaSProtocol.FireEventAndResolveWhenCompletedRequest(recipeInstanceId, event, correlationId)).to[MessageEntity] request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("fireEventAndResolveWhenCompleted")), entity = encoded) response <- Http().singleRequest(request) - decoded <- Unmarshal(response).to[BaaSProtocol.FireEventAndResolveWhenCompletedResponse] + decoded <- unmarshal[BaaSProtocol.FireEventAndResolveWhenCompletedResponse](response).withBakerExceptions } yield decoded.sensoryEventResult /** @@ -141,7 +144,7 @@ case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption encoded <- Marshal(BaaSProtocol.FireEventAndResolveOnEventRequest(recipeInstanceId, event, onEvent, correlationId)).to[MessageEntity] request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("fireEventAndResolveOnEvent")), entity = encoded) response <- Http().singleRequest(request) - decoded <- Unmarshal(response).to[BaaSProtocol.FireEventAndResolveOnEventResponse] + decoded <- unmarshal[BaaSProtocol.FireEventAndResolveOnEventResponse](response).withBakerExceptions } yield decoded.sensoryEventResult /** @@ -161,7 +164,7 @@ case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption encoded <- Marshal(BaaSProtocol.FireEventRequest(recipeInstanceId, event, correlationId)).to[MessageEntity] request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("fireEvent")), entity = encoded) response <- Http().singleRequest(request) - //decoded <- Unmarshal(response).to[BaaSProtocol.???] TODO figure out what to do on this situation with the two futures + //decoded <- unmarshal(response)[BaaSProtocol.???] TODO f.withBakerExceptionsigure out what to do on this situation with the two futures } yield () //decoded.recipeInformation ??? } @@ -180,7 +183,7 @@ case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption val request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("getAllRecipeInstancesMetadata"))) for { response <- Http().singleRequest(request) - decoded <- Unmarshal(response).to[BaaSProtocol.GetAllRecipeInstancesMetadataResponse] + decoded <- unmarshal[BaaSProtocol.GetAllRecipeInstancesMetadataResponse](response).withBakerExceptions } yield decoded.set } @@ -195,7 +198,7 @@ case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption encoded <- Marshal(BaaSProtocol.GetRecipeInstanceStateRequest(recipeInstanceId)).to[MessageEntity] request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("getRecipeInstanceState")), entity = encoded) response <- Http().singleRequest(request) - decoded <- Unmarshal(response).to[BaaSProtocol.GetRecipeInstanceStateResponse] + decoded <- unmarshal[BaaSProtocol.GetRecipeInstanceStateResponse](response).withBakerExceptions } yield decoded.recipeInstanceState /** @@ -236,7 +239,7 @@ case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption encoded <- Marshal(BaaSProtocol.GetVisualStateRequest(recipeInstanceId)).to[MessageEntity] request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("getVisualState")), entity = encoded) response <- Http().singleRequest(request) - decoded <- Unmarshal(response).to[BaaSProtocol.GetVisualStateResponse] + decoded <- unmarshal[BaaSProtocol.GetVisualStateResponse](response).withBakerExceptions } yield decoded.state /** @@ -297,7 +300,8 @@ case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption for { encoded <- Marshal(BaaSProtocol.RetryInteractionRequest(recipeInstanceId, interactionName)).to[MessageEntity] request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("retryInteraction")), entity = encoded) - _ <- Http().singleRequest(request) + response <- Http().singleRequest(request) + _ <- unmarshalBakerExceptions(response) } yield () /** @@ -311,7 +315,8 @@ case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption for { encoded <- Marshal(BaaSProtocol.ResolveInteractionRequest(recipeInstanceId, interactionName, event)).to[MessageEntity] request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("resolveInteraction")), entity = encoded) - _ <- Http().singleRequest(request) + response <- Http().singleRequest(request) + _ <- unmarshalBakerExceptions(response) } yield () /** @@ -323,6 +328,7 @@ case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption for { encoded <- Marshal(BaaSProtocol.StopRetryingInteractionRequest(recipeInstanceId, interactionName)).to[MessageEntity] request = HttpRequest(method = HttpMethods.POST, uri = withPath(root./("stopRetryingInteraction")), entity = encoded) - _ <- Http().singleRequest(request) + response <- Http().singleRequest(request) + _ <- unmarshalBakerExceptions(response) } yield () } diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala index a2dcc7024..4653b5311 100644 --- a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala @@ -7,12 +7,13 @@ import akka.stream.{ActorMaterializer, Materializer} import cats.effect.{IO, Timer} import com.ing.baker.compiler.RecipeCompiler import com.ing.baker.il.CompiledRecipe +import com.ing.baker.recipe.scaladsl.Recipe import com.ing.baker.runtime.baas.BaaSServer import com.ing.baker.runtime.baas.common.CheckoutFlowEvents.ItemsReserved import com.ing.baker.runtime.baas.common.CheckoutFlowIngredients.{Item, OrderId, ReservedItems, ShippingAddress} import com.ing.baker.runtime.baas.common.CommonBaaSServerClientSpec.{ClientServerTest, setupFailingOnceReserveItems, setupFailingWithRetryReserveItems, setupHappyPath} import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi -import com.ing.baker.runtime.common.SensoryEventStatus +import com.ing.baker.runtime.common.{BakerException, SensoryEventStatus} import com.ing.baker.runtime.scaladsl.{EventInstance, InteractionInstance, Baker => ScalaBaker} import org.scalatest.compatible.Assertion import org.scalatest.{AsyncFunSpec, BeforeAndAfterAll, BeforeAndAfterEach, Matchers} @@ -41,6 +42,22 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } } + it("Baker.addRecipe (fail with ImplementationsException)") { + test { (client, _) => + val badRecipe = Recipe("BadRecipe") + .withInteraction(CheckoutFlowInteractions.ShipItemsInteraction) + val expectedException = + BakerException.ImplementationsException("No implementation provided for interaction: ShipItems") + val compiledRecipe = RecipeCompiler + .compileRecipe(badRecipe) + for { + e <- client.addRecipe(compiledRecipe) + .map(_ => None) + .recover { case e: BakerException => Some(e) } + } yield e shouldBe Some(expectedException) + } + } + it("Baker.getRecipe") { test { (client, server) => for { @@ -51,6 +68,17 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } } + it("Baker.getRecipe (fail with NoSuchRecipeException)") { + test { (client, _) => + for { + e <- client + .getRecipe("non-existent") + .map(_ => None) + .recover { case e: BakerException => Some(e) } + } yield e shouldBe Some(BakerException.NoSuchRecipeException("non-existent")) + } + } + it("Baker.getAllRecipes") { test { (client, server) => for { @@ -73,6 +101,48 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } } + it("Baker.bake (fail with ProcessAlreadyExistsException)") { + test { (client, server) => + val recipeInstanceId: String = UUID.randomUUID().toString + for { + compiledRecipe <- setupHappyPath(server) + recipeId <- client.addRecipe(compiledRecipe) + _ <- client.bake(recipeId, recipeInstanceId) + e <- client + .bake(recipeId, recipeInstanceId) + .map(_ => None) + .recover { case e: BakerException => Some(e) } + state <- server.getRecipeInstanceState(recipeInstanceId) + } yield { + e shouldBe Some(BakerException.ProcessAlreadyExistsException(recipeInstanceId)) + state.recipeInstanceId shouldBe recipeInstanceId + } + } + } + + it("Baker.bake (fail with NoSuchRecipeException)") { + test { (client, _) => + val recipeInstanceId: String = UUID.randomUUID().toString + for { + e <- client + .bake("non-existent", recipeInstanceId) + .map(_ => None) + .recover { case e: BakerException => Some(e) } + } yield e shouldBe Some(BakerException.NoSuchRecipeException("non-existent")) + } + } + + it("Baker.getRecipeInstanceState (fails with NoSuchProcessException)") { + test { (_, server) => + for { + e <- server + .getRecipeInstanceState("non-existent") + .map(_ => None) + .recover { case e: BakerException => Some(e) } + } yield e shouldBe Some(BakerException.NoSuchProcessException("non-existent")) + } + } + it("Baker.fireEventAndResolveWhenReceived") { test { (client, server) => val recipeInstanceId: String = UUID.randomUUID().toString @@ -270,7 +340,7 @@ object CommonBaaSServerClientSpec { val host: String = "localhost" val serverBaker = ScalaBaker.akkaLocalDefault(system, materializer) for { - (client, shutdown) <- createClientServerPair(allPorts, { port => + (client, shutdown) <- buildFromStream(allPorts, { port: Int => val client = clientBaker(s"http://$host:$port/", system, materializer) val shutdown = BaaSServer.run(serverBaker, host, port) shutdown.map(s => (client, s)) @@ -281,10 +351,10 @@ object CommonBaaSServerClientSpec { } yield a } - private def createClientServerPair[T](ports: Stream[Int], buildServer: Int => Future[T])(implicit ec: ExecutionContext): Future[T] = + private def buildFromStream[S, T](ports: Stream[S], f: S => Future[T])(implicit ec: ExecutionContext): Future[T] = ports match { - case #::(port, tail) => buildServer(port).recoverWith { - case _: java.net.BindException => createClientServerPair(tail, buildServer) + case #::(port, tail) => f(port).recoverWith { + case _: java.net.BindException => buildFromStream(tail, f) } } } \ No newline at end of file diff --git a/runtime/src/main/protobuf/common.proto b/runtime/src/main/protobuf/common.proto index c062b0da3..1d46a938c 100644 --- a/runtime/src/main/protobuf/common.proto +++ b/runtime/src/main/protobuf/common.proto @@ -178,6 +178,11 @@ enum SensoryEventStatus { ALREADY_RECEIVED = 5; PROCESS_DELETED = 6; } + +message BakerException { + optional string message = 1; + optional int32 enum = 2; +} // END DATA // DESCRIPTORS (Intermediate Language messages) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala index 2f1b36c85..c80d6b53b 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala @@ -49,10 +49,10 @@ class AkkaBaker private[runtime](config: AkkaBakerConfig) extends Baker { val implementationErrors = getImplementationErrors(compiledRecipe) if (implementationErrors.nonEmpty) - Future.failed(new ImplementationsException(implementationErrors.mkString(", "))) + Future.failed(ImplementationsException(implementationErrors.mkString(", "))) else if (compiledRecipe.validationErrors.nonEmpty) - Future.failed(new RecipeValidationException(compiledRecipe.validationErrors.mkString(", "))) + Future.failed(RecipeValidationException(compiledRecipe.validationErrors.mkString(", "))) else recipeManager.ask(RecipeManagerProtocol.AddRecipe(compiledRecipe))(config.defaultAddRecipeTimeout) flatMap { case RecipeManagerProtocol.AddRecipeResponse(recipeId) => Future.successful(recipeId) @@ -76,7 +76,7 @@ class AkkaBaker private[runtime](config: AkkaBakerConfig) extends Baker { case RecipeManagerProtocol.RecipeFound(compiledRecipe, timestamp) => Future.successful(RecipeInformation(compiledRecipe, timestamp, getImplementationErrors(compiledRecipe))) case RecipeManagerProtocol.NoRecipeFound(_) => - Future.failed(new IllegalArgumentException(s"No recipe found for recipe with id: $recipeId")) + Future.failed(NoSuchRecipeException(recipeId)) } } @@ -104,9 +104,9 @@ class AkkaBaker private[runtime](config: AkkaBakerConfig) extends Baker { case _: Initialized => Future.successful(()) case ProcessAlreadyExists(_) => - Future.failed(new IllegalArgumentException(s"Process with id '$recipeInstanceId' already exists.")) + Future.failed(ProcessAlreadyExistsException(recipeInstanceId)) case RecipeManagerProtocol.NoRecipeFound(_) => - Future.failed(new IllegalArgumentException(s"Recipe with id '$recipeId' does not exist.")) + Future.failed(NoSuchRecipeException(recipeId)) } } @@ -120,9 +120,9 @@ class AkkaBaker private[runtime](config: AkkaBakerConfig) extends Baker { ))(config.defaultProcessEventTimeout).flatMap { // TODO MOVE THIS TO A FUNCTION case FireSensoryEventRejection.InvalidEvent(_, message) => - Future.failed(new IllegalArgumentException(message)) + Future.failed(IllegalEventException(message)) case FireSensoryEventRejection.NoSuchRecipeInstance(recipeInstanceId0) => - Future.failed(new NoSuchProcessException(s"Process with id $recipeInstanceId0 does not exist in the index")) + Future.failed(NoSuchProcessException(recipeInstanceId0)) case _: FireSensoryEventRejection.FiringLimitMet => Future.successful(SensoryEventStatus.FiringLimitMet) case _: FireSensoryEventRejection.AlreadyReceived => @@ -144,9 +144,9 @@ class AkkaBaker private[runtime](config: AkkaBakerConfig) extends Baker { reaction = FireSensoryEventReaction.NotifyWhenCompleted(waitForRetries = true) ))(config.defaultProcessEventTimeout).flatMap { case FireSensoryEventRejection.InvalidEvent(_, message) => - Future.failed(new IllegalArgumentException(message)) + Future.failed(IllegalEventException(message)) case FireSensoryEventRejection.NoSuchRecipeInstance(recipeInstanceId0) => - Future.failed(new NoSuchProcessException(s"Process with id $recipeInstanceId0 does not exist in the index")) + Future.failed(NoSuchProcessException(recipeInstanceId0)) case _: FireSensoryEventRejection.FiringLimitMet => Future.successful(SensoryEventResult(SensoryEventStatus.FiringLimitMet, Seq.empty, Map.empty)) case _: FireSensoryEventRejection.AlreadyReceived => @@ -168,9 +168,9 @@ class AkkaBaker private[runtime](config: AkkaBakerConfig) extends Baker { reaction = FireSensoryEventReaction.NotifyOnEvent(waitForRetries = true, onEvent) ))(config.defaultProcessEventTimeout).flatMap { case FireSensoryEventRejection.InvalidEvent(_, message) => - Future.failed(new IllegalArgumentException(message)) + Future.failed(IllegalEventException(message)) case FireSensoryEventRejection.NoSuchRecipeInstance(recipeInstanceId0) => - Future.failed(new NoSuchProcessException(s"Process with id $recipeInstanceId0 does not exist in the index")) + Future.failed(NoSuchProcessException(recipeInstanceId0)) case _: FireSensoryEventRejection.FiringLimitMet => Future.successful(SensoryEventResult(SensoryEventStatus.FiringLimitMet, Seq.empty, Map.empty)) case _: FireSensoryEventRejection.AlreadyReceived => @@ -196,9 +196,9 @@ class AkkaBaker private[runtime](config: AkkaBakerConfig) extends Baker { completeReceiver = futureRef.ref) ))(config.defaultProcessEventTimeout).flatMap { case FireSensoryEventRejection.InvalidEvent(_, message) => - Future.failed(new IllegalArgumentException(message)) + Future.failed(IllegalEventException(message)) case FireSensoryEventRejection.NoSuchRecipeInstance(recipeInstanceId0) => - Future.failed(new NoSuchProcessException(s"Process with id $recipeInstanceId0 does not exist in the index")) + Future.failed(NoSuchProcessException(recipeInstanceId0)) case _: FireSensoryEventRejection.FiringLimitMet => Future.successful(SensoryEventStatus.FiringLimitMet) case _: FireSensoryEventRejection.AlreadyReceived => @@ -213,9 +213,9 @@ class AkkaBaker private[runtime](config: AkkaBakerConfig) extends Baker { val futureCompleted = futureRef.future.flatMap { case FireSensoryEventRejection.InvalidEvent(_, message) => - Future.failed(new IllegalArgumentException(message)) + Future.failed(IllegalEventException(message)) case FireSensoryEventRejection.NoSuchRecipeInstance(recipeInstanceId0) => - Future.failed(new NoSuchProcessException(s"Process with id $recipeInstanceId0 does not exist in the index")) + Future.failed(NoSuchProcessException(recipeInstanceId0)) case _: FireSensoryEventRejection.FiringLimitMet => Future.successful(SensoryEventResult(SensoryEventStatus.FiringLimitMet, Seq.empty, Map.empty)) case _: FireSensoryEventRejection.AlreadyReceived => @@ -286,8 +286,8 @@ class AkkaBaker private[runtime](config: AkkaBakerConfig) extends Baker { .ask(GetProcessState(recipeInstanceId))(Timeout.durationToTimeout(config.defaultInquireTimeout)) .flatMap { case instance: InstanceState => Future.successful(instance.state.asInstanceOf[RecipeInstanceState]) - case NoSuchProcess(id) => Future.failed(new NoSuchProcessException(s"No such process with: $id")) - case ProcessDeleted(id) => Future.failed(new ProcessDeletedException(s"Process $id is deleted")) + case NoSuchProcess(id) => Future.failed(NoSuchProcessException(id)) + case ProcessDeleted(id) => Future.failed(ProcessDeletedException(id)) } /** @@ -337,9 +337,9 @@ class AkkaBaker private[runtime](config: AkkaBakerConfig) extends Baker { eventNames = processState.eventNames.toSet, ingredientNames = processState.ingredients.keySet)) case ProcessDeleted(_) => - Future.failed(new ProcessDeletedException(s"Process $recipeInstanceId is deleted")) + Future.failed(ProcessDeletedException(recipeInstanceId)) case Uninitialized(_) => - Future.failed(new NoSuchProcessException(s"Process $recipeInstanceId is not found")) + Future.failed(NoSuchProcessException(recipeInstanceId)) } } yield response } diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala index 64cdd3149..b3bbee7ba 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala @@ -5,6 +5,7 @@ import com.ing.baker.il import com.ing.baker.types import com.ing.baker.runtime.akka.actor.protobuf import com.ing.baker.runtime.akka.actor.serialization.protomappings._ +import com.ing.baker.runtime.common.BakerException import com.ing.baker.runtime.scaladsl.{EventInstance, EventMoment, IngredientInstance, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult} import scalapb.GeneratedMessageCompanion @@ -47,6 +48,9 @@ object ProtoMap { implicit def recipeInformationMapping(implicit ev0: SerializersProvider): ProtoMap[RecipeInformation, protobuf.RecipeInformation] = new RecipeInformationMapping() + implicit val bakerExceptionMapping: ProtoMap[BakerException, protobuf.BakerException] = + new BakerExceptionMapping + implicit val eventDescriptorMapping: ProtoMap[il.EventDescriptor, protobuf.EventDescriptor] = new EventDescriptorMapping diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/BakerExceptionMapping.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/BakerExceptionMapping.scala new file mode 100644 index 000000000..97d4e8f43 --- /dev/null +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/BakerExceptionMapping.scala @@ -0,0 +1,26 @@ +package com.ing.baker.runtime.akka.actor.serialization.protomappings + +import com.ing.baker.runtime.akka.actor.protobuf +import com.ing.baker.runtime.akka.actor.serialization.ProtoMap +import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.versioned +import com.ing.baker.runtime.common.BakerException + +import scala.util.Try + +class BakerExceptionMapping extends ProtoMap[BakerException, protobuf.BakerException] { + + val companion: protobuf.BakerException.type = protobuf.BakerException + + override def toProto(a: BakerException): protobuf.BakerException = + BakerException.encode(a) match { + case (message, enum) => + protobuf.BakerException(Some(message), Some(enum)) + } + + override def fromProto(message: protobuf.BakerException): Try[BakerException] = + for { + msg <- versioned(message.message, "message") + enum <- versioned(message.enum, "enum") + decoded <- BakerException.decode(msg, enum) + } yield decoded + } diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/BakerException.scala b/runtime/src/main/scala/com/ing/baker/runtime/common/BakerException.scala index 9a582d105..957bff926 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/common/BakerException.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/common/BakerException.scala @@ -1,15 +1,56 @@ package com.ing.baker.runtime.common -sealed abstract class BakerException(message: String = "An exception occurred at Baker", cause: Throwable = null) +import scala.util.{Failure, Success, Try} + +sealed abstract class BakerException(val message: String = "An exception occurred at Baker", val enum: Int, val cause: Throwable = null) extends RuntimeException(message, cause) object BakerException { - class NoSuchProcessException(message: String) extends BakerException(message) + // TODO this has to be renamed to NoSuchRecipeInstanceException + case class NoSuchProcessException(recipeInstanceId: String) + extends BakerException(s"Recipe instance $recipeInstanceId does not exist in the index", 1) + + // TODO this has to be renamed to RecipeInstanceDeletedException + case class ProcessDeletedException(recipeInstanceId: String) + extends BakerException(s"Recipe instance $recipeInstanceId is deleted", 2) + + case class RecipeValidationException(validationErrors: String) + extends BakerException(validationErrors, 3) + + case class ImplementationsException(implementationErrors: String) + extends BakerException(implementationErrors, 4) + + case class NoSuchRecipeException(recipeId: String) + extends BakerException(s"No recipe found for recipe with id: $recipeId", 5) + + // TODO this has to be renamed to RecipeInstanceAlreadyExistsException + case class ProcessAlreadyExistsException(recipeInstanceId: String) + extends BakerException(s"Process '$recipeInstanceId' already exists.", 6) - class ProcessDeletedException(message: String) extends BakerException(message) + case class IllegalEventException(reason: String) + extends BakerException(reason, 7) - class RecipeValidationException(message: String) extends BakerException(message) + def encode(bakerException: BakerException): (String, Int) = + bakerException match { + case e @ NoSuchProcessException(recipeInstanceId) => (recipeInstanceId, e.enum) + case e @ ProcessDeletedException(recipeInstanceId) => (recipeInstanceId, e.enum) + case e @ RecipeValidationException(validationErrors) => (validationErrors, e.enum) + case e @ ImplementationsException(implementationErrors) => (implementationErrors, e.enum) + case e @ NoSuchRecipeException(recipeId) => (recipeId, e.enum) + case e @ ProcessAlreadyExistsException(recipeInstanceId) => (recipeInstanceId, e.enum) + case e @ IllegalEventException(reason) => (reason, e.enum) + } - class ImplementationsException(message: String) extends BakerException(message) + def decode(message: String, enum: Int): Try[BakerException] = + enum match { + case 1 => Success(NoSuchProcessException(message)) + case 2 => Success(ProcessDeletedException(message)) + case 3 => Success(RecipeValidationException(message)) + case 4 => Success(ImplementationsException(message)) + case 5 => Success(NoSuchRecipeException(message)) + case 6 => Success(ProcessAlreadyExistsException(message)) + case 7 => Success(IllegalEventException(message)) + case _ => Failure(new IllegalArgumentException(s"No BakerException with enum flag $enum")) + } } From 0df48497ac056d84f13ada053ca9646970ce33ef Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Fri, 4 Oct 2019 17:20:27 +0200 Subject: [PATCH 19/86] Created Java API for the remote baker --- .../baker/runtime/baas/javadsl/Baker.scala | 13 ++ .../baker/runtime/baas/scaladsl/Baker.scala | 13 +- .../common/CommonBaaSServerClientSpec.scala | 24 ++- .../JavaDSLBaaSServerClientSpec.scala | 142 ++++++++++++++++++ .../ScalaDSLBaaSServerClientSpec.scala | 6 +- .../scala/com/ing/baker/HappyPathSpec.scala | 2 +- .../com/ing/baker/runtime/javadsl/Baker.scala | 16 +- .../runtime/javadsl/SensoryEventResult.scala | 5 + .../runtime/akka/BakerExecutionSpec.scala | 8 +- 9 files changed, 202 insertions(+), 27 deletions(-) create mode 100644 baas/src/main/scala/com/ing/baker/runtime/baas/javadsl/Baker.scala create mode 100644 baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/JavaDSLBaaSServerClientSpec.scala diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/javadsl/Baker.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/javadsl/Baker.scala new file mode 100644 index 000000000..35f90692c --- /dev/null +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/javadsl/Baker.scala @@ -0,0 +1,13 @@ +package com.ing.baker.runtime.baas.javadsl + +import akka.actor.ActorSystem +import akka.stream.Materializer +import com.ing.baker.runtime.akka.actor.serialization.Encryption +import com.ing.baker.runtime.baas.scaladsl.{ Baker => ScalaRemoteBaker } +import com.ing.baker.runtime.javadsl.{ Baker => JavaBaker } + +object Baker { + + def remote(hostname: String, actorSystem: ActorSystem, mat: Materializer, encryption: Encryption = Encryption.NoEncryption): JavaBaker = + new JavaBaker(ScalaRemoteBaker.remote(hostname, encryption)(actorSystem, mat)) +} diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala b/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala index a1222e77a..8ea9ee8cb 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala +++ b/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala @@ -4,21 +4,24 @@ import akka.actor.ActorSystem import akka.http.scaladsl.Http import akka.http.scaladsl.marshalling.Marshal import akka.http.scaladsl.model.Uri.Path -import akka.http.scaladsl.model.{ContentTypes, HttpMethods, HttpRequest, HttpResponse, MessageEntity, Uri} -import akka.http.scaladsl.unmarshalling.Unmarshal +import akka.http.scaladsl.model.{HttpMethods, HttpRequest, MessageEntity, Uri} import akka.stream.Materializer import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} import com.ing.baker.runtime.akka.actor.serialization.{Encryption, SerializersProvider} import com.ing.baker.runtime.baas.BaaSProto._ import com.ing.baker.runtime.baas.BaaSProtocol -import com.ing.baker.runtime.baas.BaaSProtocol.BaaSRemoteFailure import com.ing.baker.runtime.baas.MarshallingUtils._ -import com.ing.baker.runtime.common.{BakerException, SensoryEventStatus} +import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.scaladsl.{BakerEvent, EventInstance, EventMoment, EventResolutions, InteractionInstance, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult, Baker => ScalaBaker} import com.ing.baker.types.Value import scala.concurrent.Future -import scala.util.control.NonFatal + +object Baker { + + def remote(hostname: String, encryption: Encryption = Encryption.NoEncryption)(implicit system: ActorSystem, mat: Materializer) = + Baker(Uri(hostname), encryption) +} case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(implicit system: ActorSystem, mat: Materializer) extends ScalaBaker { diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala index 4653b5311..cbadea3e3 100644 --- a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala @@ -24,8 +24,7 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat extends AsyncFunSpec with Matchers with BeforeAndAfterAll - with BeforeAndAfterEach - with LanguageApi { + with BeforeAndAfterEach { val test: ClientServerTest = CommonBaaSServerClientSpec.testWith(clientBaker) @@ -75,6 +74,7 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat .getRecipe("non-existent") .map(_ => None) .recover { case e: BakerException => Some(e) } + _ = println(Console.GREEN + e + Console.RESET) } yield e shouldBe Some(BakerException.NoSuchRecipeException("non-existent")) } } @@ -175,6 +175,26 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } } + it("Baker.fireEventAndResolveWhenCompleted (fails with IllegalEventException)") { + test { (client, server) => + val recipeInstanceId: String = UUID.randomUUID().toString + val event = EventInstance("non-existent", Map.empty) + for { + compiledRecipe <- setupHappyPath(server) + recipeId <- client.addRecipe(compiledRecipe) + _ <- client.bake(recipeId, recipeInstanceId) + result <- client + .fireEventAndResolveWhenCompleted(recipeInstanceId, event) + .map(_ => None) + .recover { case e: BakerException => Some(e) } + serverState <- server.getRecipeInstanceState(recipeInstanceId) + } yield { + result shouldBe Some(BakerException.IllegalEventException("No event with name 'non-existent' found in recipe 'Webshop'")) + serverState.events.map(_.name) should not contain("ShippingAddressReceived") + } + } + } + it("Baker.fireEventAndResolveOnEvent") { test { (client, server) => val recipeInstanceId: String = UUID.randomUUID().toString diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/JavaDSLBaaSServerClientSpec.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/JavaDSLBaaSServerClientSpec.scala new file mode 100644 index 000000000..132ddb92b --- /dev/null +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/JavaDSLBaaSServerClientSpec.scala @@ -0,0 +1,142 @@ +package com.ing.baker.runtime.baas.scaladsl + +import java.util.Optional + +import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} +import com.ing.baker.runtime.baas.common.CommonBaaSServerClientSpec +import com.ing.baker.runtime.baas.javadsl +import com.ing.baker.runtime.baas.scaladsl.JavaDSLBaaSServerClientSpec.optionToJava +import com.ing.baker.runtime.common.SensoryEventStatus +import com.ing.baker.runtime.scaladsl +import com.ing.baker.runtime.scaladsl._ +import com.ing.baker.types.Value + +import scala.collection.JavaConverters._ +import scala.compat.java8.FutureConverters +import scala.concurrent.Future + +class JavaDSLBaaSServerClientSpec extends CommonBaaSServerClientSpec( + (host, as, mat) => { + import as.dispatcher + val javaBaker = javadsl.Baker.remote(host, as, mat) + new scaladsl.Baker { + override def addRecipe(compiledRecipe: CompiledRecipe): Future[String] = + FutureConverters.toScala(javaBaker.addRecipe(compiledRecipe)) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def getRecipe(recipeId: String): Future[RecipeInformation] = + FutureConverters.toScala(javaBaker.getRecipe(recipeId)).map(_.asScala) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def getAllRecipes: Future[Map[String, RecipeInformation]] = + FutureConverters.toScala(javaBaker.getAllRecipes).map(_.asScala.mapValues(_.asScala).toMap) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def bake(recipeId: String, recipeInstanceId: String): Future[Unit] = + FutureConverters.toScala(javaBaker.bake(recipeId, recipeInstanceId)) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def fireEventAndResolveWhenReceived(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): Future[SensoryEventStatus] = + FutureConverters.toScala(javaBaker.fireEventAndResolveWhenReceived(recipeInstanceId, event.asJava, optionToJava(correlationId))) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def fireEventAndResolveWhenCompleted(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): Future[SensoryEventResult] = + FutureConverters.toScala(javaBaker.fireEventAndResolveWhenCompleted(recipeInstanceId, event.asJava, optionToJava(correlationId))).map(_.asScala) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def fireEventAndResolveOnEvent(recipeInstanceId: String, event: EventInstance, onEvent: String, correlationId: Option[String]): Future[SensoryEventResult] = + FutureConverters.toScala(javaBaker.fireEventAndResolveOnEvent(recipeInstanceId, event.asJava, onEvent, optionToJava(correlationId))).map(_.asScala) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def fireEvent(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): EventResolutions = { + val res = javaBaker.fireEvent(recipeInstanceId, event.asJava, optionToJava(correlationId)) + scaladsl.EventResolutions( + FutureConverters.toScala(res.resolveWhenReceived) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + }, + FutureConverters.toScala(res.resolveWhenCompleted).map(_.asScala) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + ) + } + override def getAllRecipeInstancesMetadata: Future[Set[RecipeInstanceMetadata]] = + FutureConverters.toScala(javaBaker.getAllRecipeInstancesMetadata).map(_.asScala.toSet.map((x: com.ing.baker.runtime.javadsl.RecipeInstanceMetadata) => x.asScala)) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def getRecipeInstanceState(recipeInstanceId: String): Future[RecipeInstanceState] = + FutureConverters.toScala(javaBaker.getRecipeInstanceState(recipeInstanceId)).map(_.asScala) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def getIngredients(recipeInstanceId: String): Future[Map[String, Value]] = + FutureConverters.toScala(javaBaker.getIngredients(recipeInstanceId)).map(_.asScala.toMap) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def getEvents(recipeInstanceId: String): Future[Seq[EventMoment]] = + FutureConverters.toScala(javaBaker.getEvents(recipeInstanceId)).map(_.asScala.map(_.asScala)) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def getEventNames(recipeInstanceId: String): Future[Seq[String]] = + FutureConverters.toScala(javaBaker.getEventNames(recipeInstanceId)).map(_.asScala) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def getVisualState(recipeInstanceId: String, style: RecipeVisualStyle): Future[String] = + FutureConverters.toScala(javaBaker.getVisualState(recipeInstanceId, style)) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def registerEventListener(recipeName: String, listenerFunction: (String, EventInstance) => Unit): Future[Unit] = + ??? + override def registerEventListener(listenerFunction: (String, EventInstance) => Unit): Future[Unit] = + ??? + override def registerBakerEventListener(listenerFunction: BakerEvent => Unit): Future[Unit] = + ??? + override def addInteractionInstance(implementation: InteractionInstance): Future[Unit] = + ??? + override def addInteractionInstances(implementations: Seq[InteractionInstance]): Future[Unit] = + ??? + override def gracefulShutdown(): Future[Unit] = + FutureConverters.toScala(javaBaker.gracefulShutdown()) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def retryInteraction(recipeInstanceId: String, interactionName: String): Future[Unit] = + FutureConverters.toScala(javaBaker.retryInteraction(recipeInstanceId, interactionName)) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def resolveInteraction(recipeInstanceId: String, interactionName: String, event: EventInstance): Future[Unit] = + FutureConverters.toScala(javaBaker.resolveInteraction(recipeInstanceId, interactionName, event.asJava)) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + override def stopRetryingInteraction(recipeInstanceId: String, interactionName: String): Future[Unit] = + FutureConverters.toScala(javaBaker.stopRetryingInteraction(recipeInstanceId, interactionName)) + .recoverWith { + case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) + } + } + } +) + +object JavaDSLBaaSServerClientSpec { + + def optionToJava[A](option: Option[A]): Optional[A] = + option match { + case Some(a) => Optional.of(a) + case None => Optional.empty() + } +} \ No newline at end of file diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala index 4df90bc78..02163d8eb 100644 --- a/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala @@ -1,11 +1,9 @@ package com.ing.baker.runtime.baas.scaladsl -import akka.http.scaladsl.model.Uri import com.ing.baker.runtime.akka.actor.serialization.Encryption import com.ing.baker.runtime.baas.common.CommonBaaSServerClientSpec -import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi class ScalaDSLBaaSServerClientSpec extends CommonBaaSServerClientSpec( - (host, as, mat) => Baker(Uri(host), Encryption.NoEncryption)(as, mat) -) with ScalaApi + (host, as, mat) => Baker.remote(host, Encryption.NoEncryption)(as, mat) +) diff --git a/integration/src/multi-jvm/scala/com/ing/baker/HappyPathSpec.scala b/integration/src/multi-jvm/scala/com/ing/baker/HappyPathSpec.scala index 5e0ab024a..e2e7a74a6 100644 --- a/integration/src/multi-jvm/scala/com/ing/baker/HappyPathSpec.scala +++ b/integration/src/multi-jvm/scala/com/ing/baker/HappyPathSpec.scala @@ -123,7 +123,7 @@ object HappyPath extends MockitoSugar { def seedNodeConfig(path: ActorPath): Config = ConfigFactory.parseString(s"""baker.cluster.seed-nodes = ["$path"]""") - def implementations(implicit ec: ExecutionContext): Seq[InteractionInstance] = Seq( + def implementations: Seq[InteractionInstance] = Seq( ValidateOrder, ManufactureGoods, SendInvoice, diff --git a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala b/runtime/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala index e31589c5d..39663168f 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala @@ -40,7 +40,7 @@ object Baker { new Baker(baker) } -class Baker private(private val baker: scaladsl.Baker) extends common.Baker[CompletableFuture] with JavaApi { +class Baker private[runtime](private val baker: scaladsl.Baker) extends common.Baker[CompletableFuture] with JavaApi { override type SensoryEventResultType = SensoryEventResult @@ -131,7 +131,7 @@ class Baker private(private val baker: scaladsl.Baker) extends common.Baker[Comp def fireEventAndResolveWhenCompleted(recipeInstanceId: String, event: EventInstance, correlationId: Optional[String]): CompletableFuture[SensoryEventResult] = toCompletableFuture(baker.fireEventAndResolveWhenCompleted(recipeInstanceId, event.asScala, Option.apply(correlationId.orElse(null)))).thenApply { result => - new SensoryEventResult( + SensoryEventResult( sensoryEventStatus = result.sensoryEventStatus, eventNames = result.eventNames.asJava, ingredients = result.ingredients.asJava @@ -140,7 +140,7 @@ class Baker private(private val baker: scaladsl.Baker) extends common.Baker[Comp def fireEventAndResolveOnEvent(recipeInstanceId: String, event: EventInstance, onEvent: String, correlationId: Optional[String]): CompletableFuture[SensoryEventResult] = toCompletableFuture(baker.fireEventAndResolveOnEvent(recipeInstanceId, event.asScala, onEvent, Option.apply(correlationId.orElse(null)))).thenApply { result => - new SensoryEventResult( + SensoryEventResult( sensoryEventStatus = result.sensoryEventStatus, eventNames = result.eventNames.asJava, ingredients = result.ingredients.asJava @@ -149,10 +149,10 @@ class Baker private(private val baker: scaladsl.Baker) extends common.Baker[Comp def fireEvent(recipeInstanceId: String, event: EventInstance, correlationId: Optional[String]): EventResolutions = { val scalaResult = baker.fireEvent(recipeInstanceId, event.asScala) - new EventResolutions( + EventResolutions( resolveWhenReceived = toCompletableFuture(scalaResult.resolveWhenReceived), resolveWhenCompleted = toCompletableFuture(scalaResult.resolveWhenCompleted).thenApply { result => - new SensoryEventResult( + SensoryEventResult( sensoryEventStatus = result.sensoryEventStatus, eventNames = result.eventNames.asJava, ingredients = result.ingredients.asJava @@ -358,12 +358,6 @@ class Baker private(private val baker: scaladsl.Baker) extends common.Baker[Comp private def toCompletableFuture[T](scalaFuture: Future[T]): CompletableFuture[T] = FutureConverters.toJava(scalaFuture).toCompletableFuture - private def toCompletableFutureSet[T](scalaFuture: Future[Set[T]]): CompletableFuture[java.util.Set[T]] = - FutureConverters.toJava( - scalaFuture) - .toCompletableFuture - .thenApply(_.asJava) - private def toCompletableFutureMap[K, V](scalaFuture: Future[Map[K, V]]): CompletableFuture[java.util.Map[K, V]] = FutureConverters.toJava( scalaFuture) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala b/runtime/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala index b9ea4b617..0ac75f73f 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala @@ -4,6 +4,8 @@ import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi import com.ing.baker.types.Value +import com.ing.baker.runtime.scaladsl +import scala.collection.JavaConverters._ case class SensoryEventResult( sensoryEventStatus: SensoryEventStatus, @@ -16,4 +18,7 @@ case class SensoryEventResult( def getEventNames: java.util.List[String] = eventNames def getIngredients: java.util.Map[String, Value] = ingredients + + def asScala: scaladsl.SensoryEventResult = + scaladsl.SensoryEventResult(sensoryEventStatus, eventNames.asScala, ingredients.asScala.toMap) } diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala index 7da203f5f..5a0ca72d0 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala @@ -130,12 +130,12 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { } yield succeed } - "throw an IllegalArgumentException if baking a process with the same identifier twice" in { + "throw an ProcessAlreadyExistsException if baking a process with the same identifier twice" in { for { (baker, recipeId) <- setupBakerWithRecipe("DuplicateIdentifierRecipe") id = UUID.randomUUID().toString _ <- baker.bake(recipeId, id) - _ <- recoverToSucceededIf[IllegalArgumentException] { + _ <- recoverToSucceededIf[ProcessAlreadyExistsException] { baker.bake(recipeId, id) } } yield succeed @@ -166,12 +166,12 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { } } - "throw a IllegalArgumentException if the event fired is not a valid sensory event" in { + "throw a IllegalEventException if the event fired is not a valid sensory event" in { for { (baker, recipeId) <- setupBakerWithRecipe("NonExistingProcessEventTest") recipeInstanceId = UUID.randomUUID().toString _ <- baker.bake(recipeId, recipeInstanceId) - intercepted <- recoverToExceptionIf[IllegalArgumentException] { + intercepted <- recoverToExceptionIf[IllegalEventException] { baker.fireEventAndResolveWhenCompleted(recipeInstanceId, EventInstance.unsafeFrom(SomeNotDefinedEvent("bla"))) } _ = intercepted.getMessage should startWith("No event with name 'SomeNotDefinedEvent' found in recipe 'NonExistingProcessEventTest") From 8ffa25d643a40fded9916faf22bd6bee5853bdf3 Mon Sep 17 00:00:00 2001 From: Tim Linschoten Date: Mon, 14 Oct 2019 10:30:12 +0200 Subject: [PATCH 20/86] Removed println in test. --- .../baker/runtime/baas/common/CommonBaaSServerClientSpec.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala index cbadea3e3..0399d5689 100644 --- a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala @@ -74,7 +74,6 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat .getRecipe("non-existent") .map(_ => None) .recover { case e: BakerException => Some(e) } - _ = println(Console.GREEN + e + Console.RESET) } yield e shouldBe Some(BakerException.NoSuchRecipeException("non-existent")) } } From 8353dcfb1d6d602e73eb7a08b65f690596106166 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Tue, 22 Oct 2019 14:08:51 +0200 Subject: [PATCH 21/86] typos and minor fixes --- .../baker/runtime/baas/common/CommonBaaSServerClientSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala index 0399d5689..51d09f32c 100644 --- a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala @@ -357,7 +357,7 @@ object CommonBaaSServerClientSpec { implicit val system: ActorSystem = ActorSystem("ScalaDSLBaaSServerClientSpec-" + testId) implicit val materializer: Materializer = ActorMaterializer() val host: String = "localhost" - val serverBaker = ScalaBaker.akkaLocalDefault(system, materializer) + val serverBaker = ScalaBaker.akkaLocalDefault(system) for { (client, shutdown) <- buildFromStream(allPorts, { port: Int => val client = clientBaker(s"http://$host:$port/", system, materializer) From be0f15337eef27d113a801548646de0949a34ba1 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Tue, 22 Oct 2019 14:12:04 +0200 Subject: [PATCH 22/86] minor --- .../main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala index 3f9654de6..f1e56111a 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala @@ -6,7 +6,7 @@ import akka.persistence.query.scaladsl.{CurrentEventsByPersistenceIdQuery, Curre import cats.data.NonEmptyList import com.ing.baker.runtime.akka.AkkaBakerConfig.BakerPersistenceQuery import com.ing.baker.runtime.akka.actor.serialization.Encryption -import com.ing.baker.runtime.akka.actor.{BakerActorProvider, ClusterBakerActorProvider, LocalBakerActorProvider} +import com.ing.baker.runtime.akka.actor.{ BakerActorProvider, ClusterBakerActorProvider, LocalBakerActorProvider } import com.ing.baker.runtime.akka.internal.{InteractionManager, InteractionManagerDis, InteractionManagerLocal} import com.typesafe.config.Config import net.ceedubs.ficus.Ficus._ From 04ea311a30cd3a607ceb17d206dc7bc8f1dd110e Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Wed, 23 Oct 2019 11:16:04 +0200 Subject: [PATCH 23/86] WIP separation of the interface --- .../com/ing/baker/runtime/common/Baker.scala | 0 .../ing/baker/runtime/common/BakerEvent.scala | 3 +- .../baker/runtime/common/BakerException.scala | 0 .../baker/runtime/common/EventInstance.scala | 0 .../baker/runtime/common/EventMoment.scala | 0 .../runtime/common/EventResolutions.scala | 0 .../runtime/common/IngredientInstance.scala | 0 .../runtime/common/InteractionInstance.scala | 0 .../common/LanguageDataStructures.scala | 0 .../runtime/common/RecipeInformation.scala | 0 .../common/RecipeInstanceMetadata.scala | 0 .../runtime/common/RecipeInstanceState.scala | 0 .../baker/runtime/common/RejectReason.java | 0 .../runtime/common/SensoryEventResult.scala | 0 .../runtime/common/SensoryEventStatus.java | 0 .../ing/baker/runtime/common/package.scala | 28 +++++++ .../com/ing/baker/runtime/javadsl/Baker.scala | 77 +++++++------------ .../baker/runtime/javadsl/BakerEvent.scala | 1 - .../baker/runtime/javadsl/EventInstance.scala | 3 +- .../baker/runtime/javadsl/EventListener.scala | 0 .../baker/runtime/javadsl/EventMoment.scala | 3 +- .../runtime/javadsl/EventResolutions.scala | 3 +- .../runtime/javadsl/IngredientInstance.scala | 1 - .../runtime/javadsl/InteractionInstance.scala | 10 +-- .../runtime/javadsl/RecipeInformation.scala | 5 +- .../javadsl/RecipeInstanceMetadata.scala | 3 +- .../runtime/javadsl/RecipeInstanceState.scala | 4 +- .../runtime/javadsl/SensoryEventResult.scala | 5 +- .../ing/baker/runtime/scaladsl/Baker.scala | 23 +----- .../baker/runtime/scaladsl/BakerEvent.scala | 14 ++-- .../runtime/scaladsl/EventInstance.scala | 3 +- .../baker/runtime/scaladsl/EventMoment.scala | 3 +- .../runtime/scaladsl/EventResolutions.scala | 2 +- .../runtime/scaladsl/IngredientInstance.scala | 7 +- .../scaladsl/InteractionInstance.scala | 7 +- .../runtime/scaladsl/RecipeInformation.scala | 5 +- .../scaladsl/RecipeInstanceMetadata.scala | 4 +- .../scaladsl/RecipeInstanceState.scala | 4 +- .../runtime/scaladsl/SensoryEventResult.scala | 0 build.sbt | 12 ++- docs/archive/dictionary.md | 2 +- docs/archive/recipe-visualization.md | 2 +- .../development-life-cycle/design-a-recipe.md | 4 +- docs/sections/reference/dsls.md | 8 +- .../versions/baker-3-release-notes.md | 6 +- docs/sections/versions/baker-3.md | 2 +- .../src/main/resources/reference.conf | 2 +- .../com/ing/baker/il/RecipeVisualStyle.scala | 2 +- .../ing/baker/runtime/akka/AkkaBaker.scala | 50 ++++++++++-- .../ProcessInstanceProtocol.scala | 4 +- .../com/ing/baker/runtime/akka/package.scala | 23 ------ .../test/java/com/ing/baker/BakerTest.java | 9 ++- .../com/ing/baker/BakerRuntimeTestBase.scala | 19 +++-- .../com/ing/baker/runtime/ExamplesSpec.scala | 5 +- .../runtime/akka/BakerExecutionSpec.scala | 6 +- .../baker/runtime/akka/BakerSetupSpec.scala | 20 ++--- 56 files changed, 197 insertions(+), 197 deletions(-) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/Baker.scala (100%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/BakerEvent.scala (94%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/BakerException.scala (100%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/EventInstance.scala (100%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/EventMoment.scala (100%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/EventResolutions.scala (100%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/IngredientInstance.scala (100%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/InteractionInstance.scala (100%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/LanguageDataStructures.scala (100%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/RecipeInformation.scala (100%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/RecipeInstanceMetadata.scala (100%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/RecipeInstanceState.scala (100%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/RejectReason.java (100%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/SensoryEventResult.scala (100%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/common/SensoryEventStatus.java (100%) create mode 100644 baker-interface/src/main/scala/com/ing/baker/runtime/common/package.scala rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala (78%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala (99%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala (93%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/javadsl/EventListener.scala (100%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala (78%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/javadsl/EventResolutions.scala (83%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala (91%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/javadsl/InteractionInstance.scala (95%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala (90%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala (88%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala (92%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala (99%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala (79%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala (94%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/scaladsl/EventInstance.scala (96%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/scaladsl/EventMoment.scala (80%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/scaladsl/EventResolutions.scala (85%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/scaladsl/IngredientInstance.scala (59%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/scaladsl/InteractionInstance.scala (96%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInformation.scala (88%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceMetadata.scala (67%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceState.scala (87%) rename {runtime => baker-interface}/src/main/scala/com/ing/baker/runtime/scaladsl/SensoryEventResult.scala (100%) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/Baker.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/Baker.scala similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/common/Baker.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/Baker.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/BakerEvent.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/BakerEvent.scala similarity index 94% rename from runtime/src/main/scala/com/ing/baker/runtime/common/BakerEvent.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/BakerEvent.scala index 81433b2e0..f98132191 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/common/BakerEvent.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/common/BakerEvent.scala @@ -1,12 +1,11 @@ package com.ing.baker.runtime.common -import akka.actor.NoSerializationVerificationNeeded import com.ing.baker.il.CompiledRecipe import com.ing.baker.il.failurestrategy.ExceptionStrategyOutcome import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi // TODO: rename subtypes of BakerEvent to resamble the new names -trait BakerEvent extends LanguageApi with NoSerializationVerificationNeeded { +trait BakerEvent extends LanguageApi { self => type Event <: EventInstance {type Language <: self.Language} } diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/BakerException.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/BakerException.scala similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/common/BakerException.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/BakerException.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/EventInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/EventInstance.scala similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/common/EventInstance.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/EventInstance.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/EventMoment.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/EventMoment.scala similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/common/EventMoment.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/EventMoment.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/EventResolutions.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/EventResolutions.scala similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/common/EventResolutions.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/EventResolutions.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/IngredientInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/IngredientInstance.scala similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/common/IngredientInstance.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/IngredientInstance.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/InteractionInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/InteractionInstance.scala similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/common/InteractionInstance.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/InteractionInstance.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/LanguageDataStructures.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/LanguageDataStructures.scala similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/common/LanguageDataStructures.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/LanguageDataStructures.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/RecipeInformation.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/RecipeInformation.scala similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/common/RecipeInformation.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/RecipeInformation.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/RecipeInstanceMetadata.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/RecipeInstanceMetadata.scala similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/common/RecipeInstanceMetadata.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/RecipeInstanceMetadata.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/RecipeInstanceState.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/RecipeInstanceState.scala similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/common/RecipeInstanceState.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/RecipeInstanceState.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/RejectReason.java b/baker-interface/src/main/scala/com/ing/baker/runtime/common/RejectReason.java similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/common/RejectReason.java rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/RejectReason.java diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/SensoryEventResult.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/SensoryEventResult.scala similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/common/SensoryEventResult.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/SensoryEventResult.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/common/SensoryEventStatus.java b/baker-interface/src/main/scala/com/ing/baker/runtime/common/SensoryEventStatus.java similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/common/SensoryEventStatus.java rename to baker-interface/src/main/scala/com/ing/baker/runtime/common/SensoryEventStatus.java diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/common/package.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/package.scala new file mode 100644 index 000000000..2532bca51 --- /dev/null +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/common/package.scala @@ -0,0 +1,28 @@ +package com.ing.baker.runtime + +package object common { + + /** + * Mockito breaks reflection when mocking classes, for example: + * + * interface A { } + * class B extends A + * val b = mock[B] + * + * When inspecting b, the fact that it extends from A can no longer be reflected. + * + * Here we obtain the original class that was mocked. + * + * @param clazz The (potentially mocked) class + * @return The original class + */ + private[runtime] def unmock(clazz: Class[_]) = { + + if (clazz.getName.contains("$$EnhancerByMockitoWithCGLIB$$")) { + val originalName: String = clazz.getName.split("\\$\\$EnhancerByMockitoWithCGLIB\\$\\$")(0) + clazz.getClassLoader.loadClass(originalName) + } else + clazz + } + +} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala similarity index 78% rename from runtime/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala index 39663168f..e96add1f6 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala @@ -1,44 +1,19 @@ package com.ing.baker.runtime.javadsl -import akka.actor.{ ActorSystem, Address } -import cats.data.NonEmptyList -import com.ing.baker.il.{ CompiledRecipe, RecipeVisualStyle } -import com.ing.baker.runtime.akka.{ AkkaBaker, _ } -import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi -import com.ing.baker.runtime.common.SensoryEventStatus -import com.ing.baker.runtime.{ common, scaladsl } -import com.ing.baker.types.Value -import com.typesafe.config.Config import java.util import java.util.Optional import java.util.concurrent.CompletableFuture -import java.util.function.{ BiConsumer, Consumer } +import java.util.function.{BiConsumer, Consumer} import javax.annotation.Nonnull -import scala.collection.JavaConverters._ -import scala.compat.java8.FutureConverters -import scala.concurrent.Future - -object Baker { - - def akkaLocalDefault(actorSystem: ActorSystem): Baker = - new Baker(new AkkaBaker(AkkaBakerConfig.localDefault(actorSystem))) - - def akkaClusterDefault(seedNodes: java.util.List[Address], actorSystem: ActorSystem): Baker = { - val nodes = - if (seedNodes.isEmpty) throw new IllegalStateException("Baker cluster configuration without baker.cluster.seed-nodes") - else NonEmptyList.fromListUnsafe(seedNodes.asScala.toList) - new Baker(new AkkaBaker(AkkaBakerConfig.clusterDefault(nodes, actorSystem))) - } - - def akka(config: AkkaBakerConfig): Baker = - new Baker(scaladsl.Baker.akka(config)) - def akka(config: Config, actorSystem: ActorSystem): Baker = - new Baker(scaladsl.Baker.akka(config, actorSystem)) +import com.ing.baker.runtime.common.SensoryEventStatus +import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} +import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi +import com.ing.baker.runtime.{common, scaladsl} +import com.ing.baker.types.Value - def other(baker: scaladsl.Baker) = - new Baker(baker) -} +import scala.collection.JavaConverters._ +import scala.concurrent.Future class Baker private[runtime](private val baker: scaladsl.Baker) extends common.Baker[CompletableFuture] with JavaApi { @@ -102,34 +77,34 @@ class Baker private[runtime](private val baker: scaladsl.Baker) extends common.B def bake(@Nonnull recipeId: String, @Nonnull recipeInstanceId: String): CompletableFuture[Unit] = toCompletableFuture(baker.bake(recipeId, recipeInstanceId)) - def fireEventAndResolveWhenReceived(recipeInstanceId: String, event: EventInstance, correlationId: String): CompletableFuture[SensoryEventStatus] = + def fireEventAndResolveWhenReceived(@Nonnull recipeInstanceId: String, @Nonnull event: EventInstance, @Nonnull correlationId: String): CompletableFuture[SensoryEventStatus] = fireEventAndResolveWhenReceived(recipeInstanceId, event, Optional.of(correlationId)) - def fireEventAndResolveWhenCompleted(recipeInstanceId: String, event: EventInstance, correlationId: String): CompletableFuture[SensoryEventResult] = + def fireEventAndResolveWhenCompleted(@Nonnull recipeInstanceId: String, @Nonnull event: EventInstance, @Nonnull correlationId: String): CompletableFuture[SensoryEventResult] = fireEventAndResolveWhenCompleted(recipeInstanceId, event, Optional.of(correlationId)) - def fireEventAndResolveOnEvent(recipeInstanceId: String, event: EventInstance, onEvent: String, correlationId: String): CompletableFuture[SensoryEventResult] = + def fireEventAndResolveOnEvent(@Nonnull recipeInstanceId: String, @Nonnull event: EventInstance, @Nonnull onEvent: String, @Nonnull correlationId: String): CompletableFuture[SensoryEventResult] = fireEventAndResolveOnEvent(recipeInstanceId, event, onEvent, Optional.of(correlationId)) - def fireEvent(recipeInstanceId: String, event: EventInstance, correlationId: String): EventResolutions = + def fireEvent(@Nonnull recipeInstanceId: String, @Nonnull event: EventInstance, @Nonnull correlationId: String): EventResolutions = fireEvent(recipeInstanceId, event, Optional.of(correlationId)) - def fireEventAndResolveWhenReceived(recipeInstanceId: String, event: EventInstance): CompletableFuture[SensoryEventStatus] = + def fireEventAndResolveWhenReceived(@Nonnull recipeInstanceId: String, @Nonnull event: EventInstance): CompletableFuture[SensoryEventStatus] = fireEventAndResolveWhenReceived(recipeInstanceId, event, Optional.empty[String]()) - def fireEventAndResolveWhenCompleted(recipeInstanceId: String, event: EventInstance): CompletableFuture[SensoryEventResult] = + def fireEventAndResolveWhenCompleted(@Nonnull recipeInstanceId: String, @Nonnull event: EventInstance): CompletableFuture[SensoryEventResult] = fireEventAndResolveWhenCompleted(recipeInstanceId, event, Optional.empty[String]()) - def fireEventAndResolveOnEvent(recipeInstanceId: String, event: EventInstance, onEvent: String): CompletableFuture[SensoryEventResult] = + def fireEventAndResolveOnEvent(@Nonnull recipeInstanceId: String, @Nonnull event: EventInstance, @Nonnull onEvent: String): CompletableFuture[SensoryEventResult] = fireEventAndResolveOnEvent(recipeInstanceId, event, onEvent, Optional.empty[String]()) - def fireEvent(recipeInstanceId: String, event: EventInstance): EventResolutions = + def fireEvent(@Nonnull recipeInstanceId: String, @Nonnull event: EventInstance): EventResolutions = fireEvent(recipeInstanceId, event, Optional.empty[String]()) - def fireEventAndResolveWhenReceived(recipeInstanceId: String, event: EventInstance, correlationId: Optional[String]): CompletableFuture[SensoryEventStatus] = + def fireEventAndResolveWhenReceived(@Nonnull recipeInstanceId: String, @Nonnull event: EventInstance, @Nonnull correlationId: Optional[String]): CompletableFuture[SensoryEventStatus] = toCompletableFuture(baker.fireEventAndResolveWhenReceived(recipeInstanceId, event.asScala, Option.apply(correlationId.orElse(null)))) - def fireEventAndResolveWhenCompleted(recipeInstanceId: String, event: EventInstance, correlationId: Optional[String]): CompletableFuture[SensoryEventResult] = + def fireEventAndResolveWhenCompleted(@Nonnull recipeInstanceId: String, @Nonnull event: EventInstance, @Nonnull correlationId: Optional[String]): CompletableFuture[SensoryEventResult] = toCompletableFuture(baker.fireEventAndResolveWhenCompleted(recipeInstanceId, event.asScala, Option.apply(correlationId.orElse(null)))).thenApply { result => SensoryEventResult( sensoryEventStatus = result.sensoryEventStatus, @@ -138,7 +113,7 @@ class Baker private[runtime](private val baker: scaladsl.Baker) extends common.B ) } - def fireEventAndResolveOnEvent(recipeInstanceId: String, event: EventInstance, onEvent: String, correlationId: Optional[String]): CompletableFuture[SensoryEventResult] = + def fireEventAndResolveOnEvent(@Nonnull recipeInstanceId: String, @Nonnull event: EventInstance, @Nonnull onEvent: String, @Nonnull correlationId: Optional[String]): CompletableFuture[SensoryEventResult] = toCompletableFuture(baker.fireEventAndResolveOnEvent(recipeInstanceId, event.asScala, onEvent, Option.apply(correlationId.orElse(null)))).thenApply { result => SensoryEventResult( sensoryEventStatus = result.sensoryEventStatus, @@ -147,7 +122,7 @@ class Baker private[runtime](private val baker: scaladsl.Baker) extends common.B ) } - def fireEvent(recipeInstanceId: String, event: EventInstance, correlationId: Optional[String]): EventResolutions = { + def fireEvent(@Nonnull recipeInstanceId: String, @Nonnull event: EventInstance, @Nonnull correlationId: Optional[String]): EventResolutions = { val scalaResult = baker.fireEvent(recipeInstanceId, event.asScala) EventResolutions( resolveWhenReceived = toCompletableFuture(scalaResult.resolveWhenReceived), @@ -300,7 +275,7 @@ class Baker private[runtime](private val baker: scaladsl.Baker) extends common.B * * @param listenerFunction The listener function that is called once these events occur */ - override def registerEventListener(listenerFunction: BiConsumer[String, EventInstance]): CompletableFuture[Unit] = + override def registerEventListener(@Nonnull listenerFunction: BiConsumer[String, EventInstance]): CompletableFuture[Unit] = toCompletableFuture(baker.registerEventListener( (recipeInstanceId: String, event: scaladsl.EventInstance) => listenerFunction.accept(recipeInstanceId, event.asJava))) @@ -323,7 +298,7 @@ class Baker private[runtime](private val baker: scaladsl.Baker) extends common.B * @param eventListener The EventListener class the processEvent will be called once these events occur */ @deprecated(message = "Replaced with the consumer function variant", since = "3.0.0") - def registerEventListener(eventListener: EventListener): Future[Unit] = + def registerEventListener(@Nonnull eventListener: EventListener): Future[Unit] = baker.registerEventListener((recipeInstanceId: String, runtimeEvent: scaladsl.EventInstance) => eventListener.processEvent(recipeInstanceId, runtimeEvent.asJava)) @@ -333,7 +308,7 @@ class Baker private[runtime](private val baker: scaladsl.Baker) extends common.B * @param listenerFunction * @return */ - override def registerBakerEventListener(listenerFunction: Consumer[BakerEvent]): CompletableFuture[Unit] = + override def registerBakerEventListener(@Nonnull listenerFunction: Consumer[BakerEvent]): CompletableFuture[Unit] = toCompletableFuture(baker.registerBakerEventListener((event: scaladsl.BakerEvent) => listenerFunction.accept(event.asJava()))) @@ -352,13 +327,13 @@ class Baker private[runtime](private val baker: scaladsl.Baker) extends common.B * @param recipeInstanceId The process identifier * @return */ - def getVisualState(@Nonnull recipeInstanceId: String, style: RecipeVisualStyle): CompletableFuture[String] = + def getVisualState(@Nonnull recipeInstanceId: String, @Nonnull style: RecipeVisualStyle): CompletableFuture[String] = toCompletableFuture(baker.getVisualState(recipeInstanceId, style)) - private def toCompletableFuture[T](scalaFuture: Future[T]): CompletableFuture[T] = + private def toCompletableFuture[T](@Nonnull scalaFuture: Future[T]): CompletableFuture[T] = FutureConverters.toJava(scalaFuture).toCompletableFuture - private def toCompletableFutureMap[K, V](scalaFuture: Future[Map[K, V]]): CompletableFuture[java.util.Map[K, V]] = + private def toCompletableFutureMap[K, V](@Nonnull scalaFuture: Future[Map[K, V]]): CompletableFuture[java.util.Map[K, V]] = FutureConverters.toJava( scalaFuture) .toCompletableFuture diff --git a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala similarity index 99% rename from runtime/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala index f24d352a7..607f74250 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala @@ -6,7 +6,6 @@ import com.ing.baker.il.CompiledRecipe import com.ing.baker.il.failurestrategy.ExceptionStrategyOutcome import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi -import com.ing.baker.runtime.common.RejectReason sealed trait BakerEvent extends common.BakerEvent with JavaApi { type Event = EventInstance diff --git a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala similarity index 93% rename from runtime/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala index 850a5e1cc..699fa13c7 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala @@ -4,14 +4,13 @@ import java.util import com.ing.baker.il.EventDescriptor import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi -import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.types.Value import scala.collection.JavaConverters._ case class EventInstance(name: String, providedIngredients: util.Map[String, Value]) - extends common.EventInstance with JavaApi { + extends com.ing.baker.runtime.common.EventInstance with JavaApi { def getProvidedIngredients: util.Map[String, Value] = providedIngredients diff --git a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/EventListener.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventListener.scala similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/javadsl/EventListener.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventListener.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala similarity index 78% rename from runtime/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala index de95acf7f..03462a9c4 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala @@ -1,11 +1,10 @@ package com.ing.baker.runtime.javadsl import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi -import com.ing.baker.runtime.{common, scaladsl} case class EventMoment(name: String, occurredOn: Long) - extends common.EventMoment with JavaApi { + extends com.ing.baker.runtime.common.EventMoment with JavaApi { def getName: String = name diff --git a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/EventResolutions.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventResolutions.scala similarity index 83% rename from runtime/src/main/scala/com/ing/baker/runtime/javadsl/EventResolutions.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventResolutions.scala index 9275cce24..05e0009b4 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/EventResolutions.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventResolutions.scala @@ -2,13 +2,12 @@ package com.ing.baker.runtime.javadsl import java.util.concurrent.CompletableFuture -import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi case class EventResolutions(resolveWhenReceived: CompletableFuture[SensoryEventStatus], resolveWhenCompleted: CompletableFuture[SensoryEventResult] -) extends common.EventResolutions[CompletableFuture] with JavaApi { +) extends com.ing.baker.runtime.common.EventResolutions[CompletableFuture] with JavaApi { type SensoryEventResultType = SensoryEventResult diff --git a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala similarity index 91% rename from runtime/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala index 675694c73..7f00ec79e 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala @@ -1,6 +1,5 @@ package com.ing.baker.runtime.javadsl -import com.ing.baker.runtime.scaladsl import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi import com.ing.baker.types.Value diff --git a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/InteractionInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/InteractionInstance.scala similarity index 95% rename from runtime/src/main/scala/com/ing/baker/runtime/javadsl/InteractionInstance.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/InteractionInstance.scala index 7a76866e5..6a5a064b5 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/InteractionInstance.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/InteractionInstance.scala @@ -5,14 +5,12 @@ import java.util import java.util.Optional import java.util.concurrent.CompletableFuture -import com.ing.baker.runtime.akka -import com.ing.baker.runtime.scaladsl -import com.ing.baker.runtime.common +import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi -import com.ing.baker.types.{Converters, Type, Value} +import com.ing.baker.types.{Converters, Type} -import scala.collection.JavaConverters._ import scala.compat.java8.FutureConverters +import scala.collection.JavaConverters._ import scala.reflect.ClassTag import scala.util.Try @@ -54,7 +52,7 @@ object InteractionInstance { new InteractionInstance { val method: Method = { - val unmockedClass = akka.unmock(implementation.getClass) + val unmockedClass = common.unmock(implementation.getClass) unmockedClass.getMethods.count(_.getName == "apply") match { case 0 => throw new IllegalArgumentException("Implementation does not have a apply function") case n if n > 1 => throw new IllegalArgumentException("Implementation has multiple apply functions") diff --git a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala similarity index 90% rename from runtime/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala index 3116a13a7..e9929c896 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala @@ -1,15 +1,14 @@ package com.ing.baker.runtime.javadsl +import com.ing.baker.runtime.scaladsl import com.ing.baker.il.CompiledRecipe import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi -import com.ing.baker.runtime.common -import com.ing.baker.runtime.scaladsl import scala.collection.JavaConverters._ case class RecipeInformation(compiledRecipe: CompiledRecipe, recipeCreatedTime: Long, - errors: java.util.Set[String]) extends common.RecipeInformation with JavaApi { + errors: java.util.Set[String]) extends com.ing.baker.runtime.common.RecipeInformation with JavaApi { def getRecipeId: String = compiledRecipe.recipeId diff --git a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala similarity index 88% rename from runtime/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala index 626168bbf..7e8854926 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala @@ -1,10 +1,9 @@ package com.ing.baker.runtime.javadsl import com.ing.baker.runtime.scaladsl -import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi -case class RecipeInstanceMetadata(recipeId: String, recipeInstanceId: String, createdTime: Long) extends common.RecipeInstanceMetadata with JavaApi { +case class RecipeInstanceMetadata(recipeId: String, recipeInstanceId: String, createdTime: Long) extends com.ing.baker.runtime.common.RecipeInstanceMetadata with JavaApi { /** * Returns the recipe id of the process. diff --git a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala similarity index 92% rename from runtime/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala index a0627f161..9c233767c 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala @@ -2,8 +2,8 @@ package com.ing.baker.runtime.javadsl import java.util.stream.Collectors +import com.ing.baker.runtime.scaladsl import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi -import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.types.Value import scala.collection.JavaConverters._ @@ -19,7 +19,7 @@ case class RecipeInstanceState( recipeInstanceId: String, ingredients: java.util.Map[String, Value], events: java.util.List[EventMoment] - ) extends common.RecipeInstanceState with JavaApi { + ) extends com.ing.baker.runtime.common.RecipeInstanceState with JavaApi { type EventType = EventMoment diff --git a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala similarity index 99% rename from runtime/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala index 0ac75f73f..36d9473ac 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala @@ -1,10 +1,11 @@ package com.ing.baker.runtime.javadsl -import com.ing.baker.runtime.common.SensoryEventStatus +import com.ing.baker.runtime.scaladsl import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi +import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.types.Value -import com.ing.baker.runtime.scaladsl + import scala.collection.JavaConverters._ case class SensoryEventResult( diff --git a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala similarity index 79% rename from runtime/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala index 7216e89f2..dff89dddb 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala @@ -1,29 +1,10 @@ package com.ing.baker.runtime.scaladsl -import akka.actor.{ ActorSystem, Address } -import cats.data.NonEmptyList -import com.ing.baker.runtime.akka.{ AkkaBaker, AkkaBakerConfig } import com.ing.baker.runtime.common -import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi import com.ing.baker.runtime.common.SensoryEventStatus -import com.typesafe.config.Config -import scala.concurrent.Future - -object Baker { - - def akkaLocalDefault(actorSystem: ActorSystem): AkkaBaker = - new AkkaBaker(AkkaBakerConfig.localDefault(actorSystem)) - - def akkaClusterDefault(seedNodes: NonEmptyList[Address], actorSystem: ActorSystem): AkkaBaker = - new AkkaBaker(AkkaBakerConfig.clusterDefault(seedNodes, actorSystem)) - - def akka(config: AkkaBakerConfig): AkkaBaker = - new AkkaBaker(config) - - def akka(config: Config, actorSystem: ActorSystem): AkkaBaker = - new AkkaBaker(AkkaBakerConfig.from(config, actorSystem)) +import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi -} +import scala.concurrent.Future /** * The Baker is the component of the Baker library that runs one or multiples recipes. diff --git a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala similarity index 94% rename from runtime/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala index 07b00ac5e..15240f9fe 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala @@ -5,12 +5,10 @@ import java.util.Optional import com.ing.baker.il.CompiledRecipe import com.ing.baker.il.failurestrategy.ExceptionStrategyOutcome -import com.ing.baker.runtime.common -import com.ing.baker.runtime.javadsl import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi -import com.ing.baker.runtime.common.RejectReason +import com.ing.baker.runtime.{common, javadsl} -sealed trait BakerEvent extends common.BakerEvent with ScalaApi { +sealed trait BakerEvent extends com.ing.baker.runtime.common.BakerEvent with ScalaApi { type Event = EventInstance def asJava(): javadsl.BakerEvent = this match { @@ -46,7 +44,7 @@ case class EventReceived(timeStamp: Long, recipeId: String, recipeInstanceId: String, correlationId: Option[String], - event: EventInstance) extends BakerEvent with common.EventReceived + event: EventInstance) extends BakerEvent with com.ing.baker.runtime.common.EventReceived /** * Event describing the fact that an event was received but rejected for a process @@ -83,7 +81,7 @@ case class InteractionFailed(timeStamp: Long, interactionName: String, failureCount: Int, throwable: Throwable, - exceptionStrategyOutcome: ExceptionStrategyOutcome) extends BakerEvent with common.InteractionFailed + exceptionStrategyOutcome: ExceptionStrategyOutcome) extends BakerEvent with com.ing.baker.runtime.common.InteractionFailed /** * Event describing the fact that an interaction has started executing @@ -118,7 +116,7 @@ case class InteractionCompleted(timeStamp: Long, recipeId: String, recipeInstanceId: String, interactionName: String, - event: Option[EventInstance]) extends BakerEvent with common.InteractionCompleted + event: Option[EventInstance]) extends BakerEvent with com.ing.baker.runtime.common.InteractionCompleted /** * Event describing the fact that a baker process was created @@ -131,7 +129,7 @@ case class InteractionCompleted(timeStamp: Long, case class RecipeInstanceCreated(timeStamp: Long, recipeId: String, recipeName: String, - recipeInstanceId: String) extends BakerEvent with common.RecipeInstanceCreated + recipeInstanceId: String) extends BakerEvent with com.ing.baker.runtime.common.RecipeInstanceCreated /** * An event describing the fact that a recipe was added to baker. diff --git a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/EventInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/EventInstance.scala similarity index 96% rename from runtime/src/main/scala/com/ing/baker/runtime/scaladsl/EventInstance.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/EventInstance.scala index 213a57941..d1365be2c 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/EventInstance.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/EventInstance.scala @@ -1,9 +1,8 @@ package com.ing.baker.runtime.scaladsl import com.ing.baker.il.EventDescriptor -import com.ing.baker.runtime.javadsl -import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi +import com.ing.baker.runtime.{common, javadsl} import com.ing.baker.types.{Converters, NullValue, RecordValue, Value} import scala.collection.JavaConverters._ diff --git a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/EventMoment.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/EventMoment.scala similarity index 80% rename from runtime/src/main/scala/com/ing/baker/runtime/scaladsl/EventMoment.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/EventMoment.scala index fb90dfe88..3319ab5a8 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/EventMoment.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/EventMoment.scala @@ -1,8 +1,7 @@ package com.ing.baker.runtime.scaladsl -import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi -import com.ing.baker.runtime.javadsl +import com.ing.baker.runtime.{common, javadsl} case class EventMoment(name: String, occurredOn: Long) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/EventResolutions.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/EventResolutions.scala similarity index 85% rename from runtime/src/main/scala/com/ing/baker/runtime/scaladsl/EventResolutions.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/EventResolutions.scala index b54a9a6f7..94bde2ccb 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/EventResolutions.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/EventResolutions.scala @@ -9,7 +9,7 @@ import scala.concurrent.Future case class EventResolutions( resolveWhenReceived: Future[SensoryEventStatus], resolveWhenCompleted: Future[SensoryEventResult] -) extends common.EventResolutions[Future] with ScalaApi { +) extends com.ing.baker.runtime.common.EventResolutions[Future] with ScalaApi { type SensoryEventResultType = SensoryEventResult } diff --git a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/IngredientInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/IngredientInstance.scala similarity index 59% rename from runtime/src/main/scala/com/ing/baker/runtime/scaladsl/IngredientInstance.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/IngredientInstance.scala index 49e3506bc..25b2c7007 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/IngredientInstance.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/IngredientInstance.scala @@ -1,12 +1,11 @@ package com.ing.baker.runtime.scaladsl -import com.ing.baker.runtime.javadsl -import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi +import com.ing.baker.runtime.javadsl import com.ing.baker.types.Value -case class IngredientInstance(name: String, value: Value) extends common.IngredientInstance with ScalaApi { +case class IngredientInstance(name: String, value: Value) extends com.ing.baker.runtime.common.IngredientInstance with ScalaApi { - def asJava: javadsl.IngredientInstance = new javadsl.IngredientInstance(name, value) + def asJava: javadsl.IngredientInstance = javadsl.IngredientInstance(name, value) } diff --git a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/InteractionInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/InteractionInstance.scala similarity index 96% rename from runtime/src/main/scala/com/ing/baker/runtime/scaladsl/InteractionInstance.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/InteractionInstance.scala index 622ea9c3e..ea6ec0ac9 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/InteractionInstance.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/InteractionInstance.scala @@ -5,15 +5,12 @@ import java.util import java.util.Optional import java.util.concurrent.CompletableFuture -import com.ing.baker.runtime.akka -import com.ing.baker.runtime.javadsl -import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi +import com.ing.baker.runtime.{common, javadsl} import com.ing.baker.types.{Converters, Type} -import scala.concurrent.{ExecutionContext, Future} import scala.collection.JavaConverters._ -import scala.compat.java8.FutureConverters +import scala.concurrent.{ExecutionContext, Future} import scala.reflect.ClassTag import scala.util.Try diff --git a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInformation.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInformation.scala similarity index 88% rename from runtime/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInformation.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInformation.scala index e42766a4f..d6e8853be 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInformation.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInformation.scala @@ -1,10 +1,9 @@ package com.ing.baker.runtime.scaladsl import com.ing.baker.il.CompiledRecipe - import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi -import com.ing.baker.runtime.common -import com.ing.baker.runtime.javadsl +import com.ing.baker.runtime.{common, javadsl} + import scala.collection.JavaConverters._ case class RecipeInformation( diff --git a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceMetadata.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceMetadata.scala similarity index 67% rename from runtime/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceMetadata.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceMetadata.scala index 8a56a9d59..ae8d42efe 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceMetadata.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceMetadata.scala @@ -1,9 +1,9 @@ package com.ing.baker.runtime.scaladsl import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi -import com.ing.baker.runtime.{common, javadsl} +import com.ing.baker.runtime.javadsl -case class RecipeInstanceMetadata(recipeId: String, recipeInstanceId: String, createdTime: Long) extends common.RecipeInstanceMetadata with ScalaApi { +case class RecipeInstanceMetadata(recipeId: String, recipeInstanceId: String, createdTime: Long) extends com.ing.baker.runtime.common.RecipeInstanceMetadata with ScalaApi { def asJava: javadsl.RecipeInstanceMetadata = new javadsl.RecipeInstanceMetadata(recipeId, recipeInstanceId, createdTime) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceState.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceState.scala similarity index 87% rename from runtime/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceState.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceState.scala index 04e8d9753..f22f88d1a 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceState.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceState.scala @@ -1,7 +1,7 @@ package com.ing.baker.runtime.scaladsl import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi -import com.ing.baker.runtime.{common, javadsl} +import com.ing.baker.runtime.javadsl import com.ing.baker.types.Value import scala.collection.JavaConverters._ @@ -17,7 +17,7 @@ case class RecipeInstanceState( recipeInstanceId: String, ingredients: Map[String, Value], events: Seq[EventMoment]) - extends common.RecipeInstanceState with ScalaApi { + extends com.ing.baker.runtime.common.RecipeInstanceState with ScalaApi { type EventType = EventMoment diff --git a/runtime/src/main/scala/com/ing/baker/runtime/scaladsl/SensoryEventResult.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/SensoryEventResult.scala similarity index 100% rename from runtime/src/main/scala/com/ing/baker/runtime/scaladsl/SensoryEventResult.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/SensoryEventResult.scala diff --git a/build.sbt b/build.sbt index d0fa53724..4b0833824 100644 --- a/build.sbt +++ b/build.sbt @@ -76,6 +76,16 @@ lazy val intermediateLanguage = project.in(file("intermediate-language")) ) ++ testDeps(scalaTest, scalaCheck, logback) ).dependsOn(bakertypes) +lazy val interface = project.in(file("baker-interface")) + .settings(defaultModuleSettings) + .settings(noPublishSettings) + .settings( + moduleName := "baker-interface", + libraryDependencies ++= Seq( + objenisis + ) ++ providedDeps(findbugs) + ) + .dependsOn(intermediateLanguage) lazy val runtime = project.in(file("runtime")) .settings(defaultModuleSettings) @@ -125,7 +135,7 @@ lazy val runtime = project.in(file("runtime")) logback) ++ providedDeps(findbugs) ) - .dependsOn(intermediateLanguage, testScope(recipeDsl), testScope(recipeCompiler), testScope(bakertypes)) + .dependsOn(intermediateLanguage, interface, testScope(recipeDsl), testScope(recipeCompiler), testScope(bakertypes)) .enablePlugins(MultiJvmPlugin) .configs(MultiJvm) diff --git a/docs/archive/dictionary.md b/docs/archive/dictionary.md index 1cbedd350..cba37c2e9 100644 --- a/docs/archive/dictionary.md +++ b/docs/archive/dictionary.md @@ -1,6 +1,6 @@ # Dictionary -Here we define some common used lanuage that is used in this documentation. +Here we define some com.ing.baker.runtime.common used lanuage that is used in this documentation. | Name | Description | | --- | --- | diff --git a/docs/archive/recipe-visualization.md b/docs/archive/recipe-visualization.md index 6fad45cc8..fa6f76e9d 100644 --- a/docs/archive/recipe-visualization.md +++ b/docs/archive/recipe-visualization.md @@ -96,4 +96,4 @@ For an overview on what is possible to configure check out the [graphviz](https: It is not possible to alter the `shape` attribute, it is hard coded (fixed) for all elements in the graph. -This is done to garuantee a common visual language for all recipes. \ No newline at end of file +This is done to garuantee a com.ing.baker.runtime.common visual language for all recipes. \ No newline at end of file diff --git a/docs/sections/development-life-cycle/design-a-recipe.md b/docs/sections/development-life-cycle/design-a-recipe.md index 50ef93938..d9195726c 100644 --- a/docs/sections/development-life-cycle/design-a-recipe.md +++ b/docs/sections/development-life-cycle/design-a-recipe.md @@ -230,11 +230,11 @@ public class JWebshopRecipe { ``` Let us remember that this is just a _description_ of what our program across multiple services should do, on the next -sections we will see how to visualize it, create runtime `instances` of our recipes and their parts, what common practices +sections we will see how to visualize it, create runtime `instances` of our recipes and their parts, what com.ing.baker.runtime.common practices are there for testing, everything you need to know to deploy and monitor a baker cluster, and how Baker helps you handle and resolve failure which is not modeled in the domain (in the recipe). -As you might have realised `Ingredients`, `Events` and `Interactions` could be reused on different Recipes, giving common +As you might have realised `Ingredients`, `Events` and `Interactions` could be reused on different Recipes, giving com.ing.baker.runtime.common business verbs that your programs and organisation can use across teams, the same way different cooking recipes share same processes (simmering, boiling, cutting) you should reuse interactions across your different business recipes. diff --git a/docs/sections/reference/dsls.md b/docs/sections/reference/dsls.md index 45dfd7c1b..541e8d5bc 100644 --- a/docs/sections/reference/dsls.md +++ b/docs/sections/reference/dsls.md @@ -12,8 +12,8 @@ we provide an API that uses Java and Scala reflection to generate most of the da classes or interfaces. ```scala tab="Scala" -import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff -import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff.UntilDeadline +import com.ing.baker.recipe.com.ing.baker.runtime.common.InteractionFailureStrategy.RetryWithIncrementalBackoff +import com.ing.baker.recipe.com.ing.baker.runtime.common.InteractionFailureStrategy.RetryWithIncrementalBackoff.UntilDeadline import com.ing.baker.recipe.scaladsl.{Event, Ingredient, Interaction, Recipe} import scala.concurrent.duration._ @@ -103,8 +103,8 @@ object WebshopRecipe { ```scala tab="Scala (Reflection API)" -import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff -import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff.UntilDeadline +import com.ing.baker.recipe.com.ing.baker.runtime.common.InteractionFailureStrategy.RetryWithIncrementalBackoff +import com.ing.baker.recipe.com.ing.baker.runtime.common.InteractionFailureStrategy.RetryWithIncrementalBackoff.UntilDeadline import com.ing.baker.recipe.scaladsl.{Event, Ingredient, Interaction, Recipe} import scala.concurrent.duration._ diff --git a/docs/sections/versions/baker-3-release-notes.md b/docs/sections/versions/baker-3-release-notes.md index 7c597bac6..409a7781f 100644 --- a/docs/sections/versions/baker-3-release-notes.md +++ b/docs/sections/versions/baker-3-release-notes.md @@ -21,7 +21,7 @@ The problem with this approach was that the interfaces for Java and Scala develo In this release we have created two separate packages for Java and Scala interfaces. The javadsl and scaladsl packages contain the same objects but created for those users in mind. -These objects share a common parent to ensure the Java and Scala runtime DSLs are in sync. +These objects share a com.ing.baker.runtime.common parent to ensure the Java and Scala runtime DSLs are in sync. As user you just chooses the correct objects by having either the javadsl or scaladsl imported. ### No more blocking! Future and CompletableFuture @@ -139,7 +139,7 @@ case class SensoryEventResult( sensoryEventStatus: SensoryEventStatus, eventNames: Seq[String], ingredients: Map[String, Value] -) extends common.SensoryEventResult with ScalaApi +) extends com.ing.baker.runtime.common.SensoryEventResult with ScalaApi ``` ```java tab="Java" @@ -147,7 +147,7 @@ case class SensoryEventResult( sensoryEventStatus: SensoryEventStatus, eventNames: java.util.List[String], ingredients: java.util.Map[String, Value] -) extends common.SensoryEventResult with JavaApi { +) extends com.ing.baker.runtime.common.SensoryEventResult with JavaApi { def getSensoryEventStatus: SensoryEventStatus = sensoryEventStatus diff --git a/docs/sections/versions/baker-3.md b/docs/sections/versions/baker-3.md index a47a640ca..11bd7bd90 100644 --- a/docs/sections/versions/baker-3.md +++ b/docs/sections/versions/baker-3.md @@ -24,7 +24,7 @@ It is safer to bring the complete cluster down. ### Renames/package changes -* com.ing.baker.runtime.core -> com.ing.baker.runtime.javadsl/scaladsl/common (depends per object) +* com.ing.baker.runtime.core -> com.ing.baker.runtime.javadsl/scaladsl/com.ing.baker.runtime.common (depends per object) * com.ing.baker.runtime.java_api -> com.ing.baker.runtime.javadsl * processId -> recipeInstanceId * getProcessId -> GetRecipeInstanceId diff --git a/intermediate-language/src/main/resources/reference.conf b/intermediate-language/src/main/resources/reference.conf index 543037a31..4cdf3c75b 100644 --- a/intermediate-language/src/main/resources/reference.conf +++ b/intermediate-language/src/main/resources/reference.conf @@ -16,7 +16,7 @@ baker { } // these attributes are shared for all nodes (ingredients, interactions & events) - common { + com.ing.baker.runtime.common { "fontname" = "ING Me" "fontsize" = 22 "fontcolor" = "white" diff --git a/intermediate-language/src/main/scala/com/ing/baker/il/RecipeVisualStyle.scala b/intermediate-language/src/main/scala/com/ing/baker/il/RecipeVisualStyle.scala index 754501dcf..277597396 100644 --- a/intermediate-language/src/main/scala/com/ing/baker/il/RecipeVisualStyle.scala +++ b/intermediate-language/src/main/scala/com/ing/baker/il/RecipeVisualStyle.scala @@ -49,7 +49,7 @@ object RecipeVisualStyle { commonNodeAttributes = List( DotAttrStmt( Elem.node, - readAttributes("common") + readAttributes("com.ing.baker.runtime.common") )), ingredientAttributes = DotAttr("shape", "circle") +: readAttributes("ingredient"), diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala index c80d6b53b..80ee8ae03 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala @@ -1,29 +1,69 @@ package com.ing.baker.runtime.akka -import akka.actor.{ Actor, ActorRef, Props } -import akka.pattern.{ FutureRef, ask } +import akka.actor.{Actor, ActorRef, ActorSystem, Address, Props} +import akka.pattern.{FutureRef, ask} import akka.util.Timeout +import cats.data.NonEmptyList import com.ing.baker.il._ import com.ing.baker.il.failurestrategy.ExceptionStrategyOutcome import com.ing.baker.runtime.akka.actor._ import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProtocol._ -import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol.{ Initialized, InstanceState, Uninitialized } +import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol.{Initialized, InstanceState, Uninitialized} import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProtocol import com.ing.baker.runtime.common.BakerException._ import com.ing.baker.runtime.common.SensoryEventStatus +import com.ing.baker.runtime.javadsl.Baker +import com.ing.baker.runtime.scaladsl import com.ing.baker.runtime.scaladsl._ import com.ing.baker.types.Value -import org.slf4j.{ Logger, LoggerFactory } +import com.typesafe.config.Config +import org.slf4j.{Logger, LoggerFactory} + +import scala.collection.JavaConverters._ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.language.postfixOps import scala.util.Try +object AkkaBaker { + + def apply(config: AkkaBakerConfig): AkkaBaker = + new AkkaBaker(config) + + def apply(config: Config, actorSystem: ActorSystem): AkkaBaker = + new AkkaBaker(AkkaBakerConfig.from(config, actorSystem)) + + def localDefault(actorSystem: ActorSystem): AkkaBaker = + new AkkaBaker(AkkaBakerConfig.localDefault(actorSystem)) + + def clusterDefault(seedNodes: NonEmptyList[Address], actorSystem: ActorSystem): AkkaBaker = + new AkkaBaker(AkkaBakerConfig.clusterDefault(seedNodes, actorSystem)) + + def java(config: AkkaBakerConfig): Baker = + new Baker(apply(config)) + + def java(config: Config, actorSystem: ActorSystem): Baker = + new Baker(apply(config, actorSystem)) + + def javaLocalDefault(actorSystem: ActorSystem): Baker = + new Baker(new AkkaBaker(AkkaBakerConfig.localDefault(actorSystem))) + + def javaClusterDefault(seedNodes: java.util.List[Address], actorSystem: ActorSystem): Baker = { + val nodes = + if (seedNodes.isEmpty) throw new IllegalStateException("Baker cluster configuration without baker.cluster.seed-nodes") + else NonEmptyList.fromListUnsafe(seedNodes.asScala.toList) + new Baker(new AkkaBaker(AkkaBakerConfig.clusterDefault(nodes, actorSystem))) + } + + def javaOther(baker: scaladsl.Baker) = + new Baker(baker) +} + /** * The Baker is the component of the Baker library that runs one or multiples recipes. * For each recipe a new instance can be baked, sensory events can be send and state can be inquired upon */ -class AkkaBaker private[runtime](config: AkkaBakerConfig) extends Baker { +class AkkaBaker private[runtime](config: AkkaBakerConfig) extends scaladsl.Baker { import config.system diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala index 8d0376c38..509c65b6b 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala @@ -9,7 +9,7 @@ import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable object ProcessInstanceProtocol { /** - * A common trait for all commands to a petri net instance. + * A com.ing.baker.runtime.common trait for all commands to a petri net instance. */ sealed trait Command extends BakerSerializable @@ -52,7 +52,7 @@ object ProcessInstanceProtocol { case class OverrideExceptionStrategy(jobId: Long, failureStrategy: ExceptionStrategy) extends Command /** - * A common trait for all responses coming from a petri net instance. + * A com.ing.baker.runtime.common trait for all responses coming from a petri net instance. */ sealed trait Response extends BakerSerializable diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/package.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/package.scala index b0aa8889e..0a34163b6 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/package.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/package.scala @@ -31,29 +31,6 @@ package object akka { def toScala: FiniteDuration = FiniteDuration(duration.toMillis, TimeUnit.MILLISECONDS) } - /** - * Mockito breaks reflection when mocking classes, for example: - * - * interface A { } - * class B extends A - * val b = mock[B] - * - * When inspecting b, the fact that it extends from A can no longer be reflected. - * - * Here we obtain the original class that was mocked. - * - * @param clazz The (potentially mocked) class - * @return The original class - */ - def unmock(clazz: Class[_]) = { - - if (clazz.getName.contains("$$EnhancerByMockitoWithCGLIB$$")) { - val originalName: String = clazz.getName.split("\\$\\$EnhancerByMockitoWithCGLIB\\$\\$")(0) - clazz.getClassLoader.loadClass(originalName) - } else - clazz - } - def namedCachedThreadPool(threadNamePrefix: String): ExecutionContext = ExecutionContext.fromExecutorService(Executors.newCachedThreadPool(daemonThreadFactory(threadNamePrefix))) diff --git a/runtime/src/test/java/com/ing/baker/BakerTest.java b/runtime/src/test/java/com/ing/baker/BakerTest.java index eb69bafeb..d6eea421d 100644 --- a/runtime/src/test/java/com/ing/baker/BakerTest.java +++ b/runtime/src/test/java/com/ing/baker/BakerTest.java @@ -5,6 +5,7 @@ import com.ing.baker.compiler.JavaCompiledRecipeTest; import com.ing.baker.compiler.RecipeCompiler; import com.ing.baker.il.CompiledRecipe; +import com.ing.baker.runtime.akka.AkkaBaker; import com.ing.baker.runtime.common.BakerException; import com.ing.baker.runtime.common.SensoryEventStatus; import com.ing.baker.runtime.javadsl.*; @@ -56,7 +57,7 @@ public void shouldSetupJBakerWithDefaultActorFramework() throws BakerException, CompiledRecipe compiledRecipe = RecipeCompiler.compileRecipe(JavaCompiledRecipeTest.setupSimpleRecipe()); String recipeInstanceId = UUID.randomUUID().toString(); - Baker jBaker = Baker.akka(config, actorSystem); + Baker jBaker = AkkaBaker.java(config, actorSystem); java.util.Map ingredients = jBaker.addInteractionInstances(implementationsList) .thenCompose(x -> jBaker.addRecipe(compiledRecipe)) .thenCompose(recipeId -> { @@ -80,7 +81,7 @@ public void shouldSetupJBakerWithGivenActorFramework() throws BakerException, Ex assertEquals(compiledRecipe.getValidationErrors().size(), 0); - Baker jBaker = Baker.akka(config, actorSystem); + Baker jBaker = AkkaBaker.java(config, actorSystem); jBaker.addInteractionInstances(implementationsList); String recipeId = jBaker.addRecipe(compiledRecipe).get(); @@ -100,7 +101,7 @@ public void shouldFailWhenMissingImplementations() throws BakerException, Execut exception.expect(ExecutionException.class); CompiledRecipe compiledRecipe = RecipeCompiler.compileRecipe(JavaCompiledRecipeTest.setupComplexRecipe()); - Baker jBaker = Baker.akka(config, actorSystem); + Baker jBaker = AkkaBaker.java(config, actorSystem); jBaker.addRecipe(compiledRecipe).get(); } @@ -108,7 +109,7 @@ public void shouldFailWhenMissingImplementations() throws BakerException, Execut @Test public void shouldExecuteCompleteFlow() throws BakerException, ExecutionException, InterruptedException { - Baker jBaker = Baker.akka(config, actorSystem); + Baker jBaker = AkkaBaker.java(config, actorSystem); List bakerEvents = new LinkedList<>(); jBaker.registerBakerEventListener(bakerEvents::add); diff --git a/runtime/src/test/scala/com/ing/baker/BakerRuntimeTestBase.scala b/runtime/src/test/scala/com/ing/baker/BakerRuntimeTestBase.scala index 5d3835e82..35066d6de 100644 --- a/runtime/src/test/scala/com/ing/baker/BakerRuntimeTestBase.scala +++ b/runtime/src/test/scala/com/ing/baker/BakerRuntimeTestBase.scala @@ -4,17 +4,20 @@ import akka.actor.ActorSystem import akka.testkit.TestKit import com.ing.baker.compiler.RecipeCompiler import com.ing.baker.il.CompiledRecipe -import com.ing.baker.recipe.TestRecipe.{ fireTwoEventsInteraction, _ } -import com.ing.baker.recipe.{ CaseClassIngredient, common } -import com.ing.baker.runtime.scaladsl.{ Baker, EventInstance, InteractionInstance } -import com.ing.baker.types.{ Converters, Value } -import com.typesafe.config.{ Config, ConfigFactory } +import com.ing.baker.recipe.TestRecipe.{fireTwoEventsInteraction, _} +import com.ing.baker.recipe.{CaseClassIngredient, common} +import com.ing.baker.runtime.scaladsl.{Baker, EventInstance, InteractionInstance} +import com.ing.baker.types.{Converters, Value} +import com.typesafe.config.{Config, ConfigFactory} import java.nio.file.Paths import java.util.UUID + +import com.ing.baker.runtime.akka.AkkaBaker import org.mockito.Matchers._ import org.mockito.Mockito._ import org.scalatest._ import org.scalatest.mockito.MockitoSugar + import scala.concurrent.Future import scala.concurrent.duration._ import scala.language.postfixOps @@ -202,9 +205,9 @@ trait BakerRuntimeTestBase setupBakerWithRecipe(recipe, mockImplementations)(actorSystem) } - protected def setupBakerWithRecipe(recipe: common.Recipe, implementations: Seq[InteractionInstance]) + protected def setupBakerWithRecipe(recipe: com.ing.baker.runtime.common.Recipe, implementations: Seq[InteractionInstance]) (implicit actorSystem: ActorSystem): Future[(Baker, String)] = { - val baker = Baker.akka(ConfigFactory.load(), actorSystem) + val baker = AkkaBaker(ConfigFactory.load(), actorSystem) baker.addInteractionInstances(implementations).flatMap { _ => baker.addRecipe(RecipeCompiler.compileRecipe(recipe)).map(baker -> _)(actorSystem.dispatcher) } @@ -212,7 +215,7 @@ trait BakerRuntimeTestBase protected def setupBakerWithNoRecipe()(implicit actorSystem: ActorSystem): Future[Baker] = { setupMockResponse() - val baker = Baker.akka(ConfigFactory.load(), actorSystem) + val baker = AkkaBaker(ConfigFactory.load(), actorSystem) baker.addInteractionInstances(mockImplementations).map { _ => baker } } diff --git a/runtime/src/test/scala/com/ing/baker/runtime/ExamplesSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/ExamplesSpec.scala index 060d995c3..8b3e90e51 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/ExamplesSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/ExamplesSpec.scala @@ -7,6 +7,9 @@ import com.ing.baker.runtime.ScalaDSLRuntime._ import com.ing.baker.runtime.scaladsl.Baker import com.typesafe.config.ConfigFactory import java.util.UUID + +import com.ing.baker.runtime.akka.AkkaBaker + import scala.concurrent.Future class ExamplesSpec extends BakerRuntimeTestBase { @@ -63,7 +66,7 @@ class ExamplesSpec extends BakerRuntimeTestBase { val implementations = Seq(validateOrderImpl, manufactureGoodsImpl, sendInvoiceImpl, shipGoodsImpl) - val baker = Baker.akka(ConfigFactory.load(), defaultActorSystem) + val baker = AkkaBaker(ConfigFactory.load(), defaultActorSystem) for { _ <- Future.traverse(implementations)(baker.addInteractionInstance) diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala index 5a0ca72d0..757372d51 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala @@ -230,7 +230,7 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { |baker.interaction-manager = remote """.stripMargin).withFallback(ConfigFactory.load()) - val baker = Baker.akka(config, ActorSystem.apply("remoteTest", config)) + val baker = AkkaBaker(config, ActorSystem.apply("remoteTest", config)) for { _ <- baker.addInteractionInstances(mockImplementations) @@ -562,7 +562,7 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { .withPredefinedIngredients(("missingJavaOptional", ingredientValue))) .withSensoryEvent(initialEvent) - val baker = Baker.akka(ConfigFactory.load(), defaultActorSystem) + val baker = AkkaBaker(ConfigFactory.load(), defaultActorSystem) for { _ <- baker.addInteractionInstances(mockImplementations) @@ -1164,7 +1164,7 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { def second(recipeId: String) = { val system2 = ActorSystem("persistenceTest2", localLevelDBConfig("persistenceTest2")) - val baker2 = Baker.akka(ConfigFactory.load(), system2) + val baker2 = AkkaBaker(ConfigFactory.load(), system2) (for { _ <- baker2.addInteractionInstances(mockImplementations) state <- baker2.getRecipeInstanceState(recipeInstanceId) diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerSetupSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerSetupSpec.scala index 83edec81d..9c26b1dd3 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerSetupSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerSetupSpec.scala @@ -33,7 +33,7 @@ class BakerSetupSpec extends BakerRuntimeTestBase { .withInteraction(interactionOne) .withSensoryEvent(initialEvent)) - val baker = Baker.akka(ConfigFactory.load(), defaultActorSystem) + val baker = AkkaBaker(ConfigFactory.load(), defaultActorSystem) for { _ <- baker.addInteractionInstances(mockImplementations) @@ -46,12 +46,12 @@ class BakerSetupSpec extends BakerRuntimeTestBase { } "providing implementations in a sequence" in { - val baker = Baker.akka(ConfigFactory.load(), defaultActorSystem) + val baker = AkkaBaker(ConfigFactory.load(), defaultActorSystem) baker.addInteractionInstances(mockImplementations).map(_ => succeed) } "providing an implementation with the class simplename same as the interaction" in { - val baker = Baker.akka(ConfigFactory.load(), defaultActorSystem) + val baker = AkkaBaker(ConfigFactory.load(), defaultActorSystem) baker.addInteractionInstance(InteractionInstance.unsafeFrom(new implementations.InteractionOne())).map(_ => succeed) } @@ -61,7 +61,7 @@ class BakerSetupSpec extends BakerRuntimeTestBase { .withInteraction(interactionOne.withName("interactionOneRenamed")) .withSensoryEvent(initialEvent) - val baker = Baker.akka(ConfigFactory.load(), defaultActorSystem) + val baker = AkkaBaker(ConfigFactory.load(), defaultActorSystem) for { _ <- baker.addInteractionInstance(InteractionInstance.unsafeFrom(new implementations.InteractionOne())) @@ -75,7 +75,7 @@ class BakerSetupSpec extends BakerRuntimeTestBase { .withInteraction(interactionOne) .withSensoryEvent(initialEvent) - val baker = Baker.akka(ConfigFactory.load(), defaultActorSystem) + val baker = AkkaBaker(ConfigFactory.load(), defaultActorSystem) for { _ <- baker.addInteractionInstance(InteractionInstance.unsafeFrom(new InteractionOneFieldName())) @@ -89,7 +89,7 @@ class BakerSetupSpec extends BakerRuntimeTestBase { .withInteraction(interactionOne) .withSensoryEvent(initialEvent) - val baker = Baker.akka(ConfigFactory.load(), defaultActorSystem) + val baker = AkkaBaker(ConfigFactory.load(), defaultActorSystem) for { _ <- baker.addInteractionInstance(InteractionInstance.unsafeFrom(new InteractionOneInterfaceImplementation())) @@ -102,7 +102,7 @@ class BakerSetupSpec extends BakerRuntimeTestBase { .withInteraction(interactionWithAComplexIngredient) .withSensoryEvent(initialEvent) - val baker = Baker.akka(ConfigFactory.load(), defaultActorSystem) + val baker = AkkaBaker(ConfigFactory.load(), defaultActorSystem) for { _ <- baker.addInteractionInstance(InteractionInstance.unsafeFrom(mock[ComplexIngredientInteraction])) @@ -118,7 +118,7 @@ class BakerSetupSpec extends BakerRuntimeTestBase { .withInteraction(interactionOne) .withSensoryEvent(secondEvent) - val baker = Baker.akka(ConfigFactory.load(), defaultActorSystem) + val baker = AkkaBaker(ConfigFactory.load(), defaultActorSystem) baker.addInteractionInstances(mockImplementations) @@ -133,7 +133,7 @@ class BakerSetupSpec extends BakerRuntimeTestBase { .withInteraction(interactionOne) .withSensoryEvent(initialEvent) - val baker = Baker.akka(ConfigFactory.load(), defaultActorSystem) + val baker = AkkaBaker(ConfigFactory.load(), defaultActorSystem) recoverToExceptionIf[ImplementationsException] { baker.addRecipe(RecipeCompiler.compileRecipe(recipe)) @@ -146,7 +146,7 @@ class BakerSetupSpec extends BakerRuntimeTestBase { .withInteraction(interactionOne) .withSensoryEvent(initialEvent) - val baker = Baker.akka(ConfigFactory.load(), defaultActorSystem) + val baker = AkkaBaker(ConfigFactory.load(), defaultActorSystem) baker.addInteractionInstance(InteractionInstance.unsafeFrom(new InteractionOneWrongApply())) From ec393958bc8d591912bc1cf9f07fb89e8816d1c6 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Wed, 23 Oct 2019 14:18:10 +0200 Subject: [PATCH 24/86] Finished moving the interface into its own project --- .../common/CommonBaaSServerClientSpec.scala | 3 ++- .../com/ing/baker/runtime/javadsl/Baker.scala | 1 + .../ing/baker/runtime/javadsl/BakerEvent.scala | 1 + .../baker/runtime/javadsl/EventInstance.scala | 1 + .../ing/baker/runtime/javadsl/EventMoment.scala | 4 +++- .../runtime/javadsl/EventResolutions.scala | 3 ++- .../runtime/javadsl/IngredientInstance.scala | 1 + .../runtime/javadsl/RecipeInformation.scala | 4 ++-- .../javadsl/RecipeInstanceMetadata.scala | 4 ++-- .../runtime/javadsl/RecipeInstanceState.scala | 4 ++-- .../ing/baker/runtime/scaladsl/BakerEvent.scala | 1 + .../runtime/scaladsl/InteractionInstance.scala | 3 ++- build.sbt | 2 +- project/Dependencies.scala | 1 + .../com/ing/baker/runtime/akka/AkkaBaker.scala | 17 +++++------------ .../src/test/java/com/ing/baker/Webshop.java | 3 ++- .../com/ing/baker/BakerRuntimeTestBase.scala | 3 ++- 17 files changed, 31 insertions(+), 25 deletions(-) diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala index 51d09f32c..3218d45c6 100644 --- a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala +++ b/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala @@ -8,6 +8,7 @@ import cats.effect.{IO, Timer} import com.ing.baker.compiler.RecipeCompiler import com.ing.baker.il.CompiledRecipe import com.ing.baker.recipe.scaladsl.Recipe +import com.ing.baker.runtime.akka.AkkaBaker import com.ing.baker.runtime.baas.BaaSServer import com.ing.baker.runtime.baas.common.CheckoutFlowEvents.ItemsReserved import com.ing.baker.runtime.baas.common.CheckoutFlowIngredients.{Item, OrderId, ReservedItems, ShippingAddress} @@ -357,7 +358,7 @@ object CommonBaaSServerClientSpec { implicit val system: ActorSystem = ActorSystem("ScalaDSLBaaSServerClientSpec-" + testId) implicit val materializer: Materializer = ActorMaterializer() val host: String = "localhost" - val serverBaker = ScalaBaker.akkaLocalDefault(system) + val serverBaker = AkkaBaker.localDefault(system) for { (client, shutdown) <- buildFromStream(allPorts, { port: Int => val client = clientBaker(s"http://$host:$port/", system, materializer) diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala index e96add1f6..f6e2e0afc 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala @@ -12,6 +12,7 @@ import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.types.Value +import scala.compat.java8.FutureConverters import scala.collection.JavaConverters._ import scala.concurrent.Future diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala index 607f74250..19c691388 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala @@ -5,6 +5,7 @@ import java.util.Optional import com.ing.baker.il.CompiledRecipe import com.ing.baker.il.failurestrategy.ExceptionStrategyOutcome import com.ing.baker.runtime.common +import com.ing.baker.runtime.common.RejectReason import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi sealed trait BakerEvent extends common.BakerEvent with JavaApi { diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala index 699fa13c7..f026f152d 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala @@ -2,6 +2,7 @@ package com.ing.baker.runtime.javadsl import java.util +import com.ing.baker.runtime.scaladsl import com.ing.baker.il.EventDescriptor import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi import com.ing.baker.types.Value diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala index 03462a9c4..661f08e8f 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala @@ -1,10 +1,12 @@ package com.ing.baker.runtime.javadsl +import com.ing.baker.runtime.scaladsl +import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi case class EventMoment(name: String, occurredOn: Long) - extends com.ing.baker.runtime.common.EventMoment with JavaApi { + extends common.EventMoment with JavaApi { def getName: String = name diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventResolutions.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventResolutions.scala index 05e0009b4..456e8ab8b 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventResolutions.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventResolutions.scala @@ -4,10 +4,11 @@ import java.util.concurrent.CompletableFuture import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi +import com.ing.baker.runtime.common.SensoryEventStatus case class EventResolutions(resolveWhenReceived: CompletableFuture[SensoryEventStatus], resolveWhenCompleted: CompletableFuture[SensoryEventResult] -) extends com.ing.baker.runtime.common.EventResolutions[CompletableFuture] with JavaApi { +) extends common.EventResolutions[CompletableFuture] with JavaApi { type SensoryEventResultType = SensoryEventResult diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala index 7f00ec79e..bc6443f96 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala @@ -2,6 +2,7 @@ package com.ing.baker.runtime.javadsl import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi +import com.ing.baker.runtime.scaladsl import com.ing.baker.types.Value case class IngredientInstance(name: String, value: Value) extends common.IngredientInstance with JavaApi { diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala index e9929c896..185458e30 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala @@ -1,6 +1,6 @@ package com.ing.baker.runtime.javadsl -import com.ing.baker.runtime.scaladsl +import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.il.CompiledRecipe import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi @@ -8,7 +8,7 @@ import scala.collection.JavaConverters._ case class RecipeInformation(compiledRecipe: CompiledRecipe, recipeCreatedTime: Long, - errors: java.util.Set[String]) extends com.ing.baker.runtime.common.RecipeInformation with JavaApi { + errors: java.util.Set[String]) extends common.RecipeInformation with JavaApi { def getRecipeId: String = compiledRecipe.recipeId diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala index 7e8854926..56208130c 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala @@ -1,9 +1,9 @@ package com.ing.baker.runtime.javadsl -import com.ing.baker.runtime.scaladsl +import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi -case class RecipeInstanceMetadata(recipeId: String, recipeInstanceId: String, createdTime: Long) extends com.ing.baker.runtime.common.RecipeInstanceMetadata with JavaApi { +case class RecipeInstanceMetadata(recipeId: String, recipeInstanceId: String, createdTime: Long) extends common.RecipeInstanceMetadata with JavaApi { /** * Returns the recipe id of the process. diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala index 9c233767c..cf31c1253 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala @@ -2,7 +2,7 @@ package com.ing.baker.runtime.javadsl import java.util.stream.Collectors -import com.ing.baker.runtime.scaladsl +import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi import com.ing.baker.types.Value @@ -19,7 +19,7 @@ case class RecipeInstanceState( recipeInstanceId: String, ingredients: java.util.Map[String, Value], events: java.util.List[EventMoment] - ) extends com.ing.baker.runtime.common.RecipeInstanceState with JavaApi { + ) extends common.RecipeInstanceState with JavaApi { type EventType = EventMoment diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala index 15240f9fe..519ca3d47 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala @@ -7,6 +7,7 @@ import com.ing.baker.il.CompiledRecipe import com.ing.baker.il.failurestrategy.ExceptionStrategyOutcome import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi import com.ing.baker.runtime.{common, javadsl} +import com.ing.baker.runtime.common.RejectReason sealed trait BakerEvent extends com.ing.baker.runtime.common.BakerEvent with ScalaApi { type Event = EventInstance diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/InteractionInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/InteractionInstance.scala index ea6ec0ac9..c0bacb34f 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/InteractionInstance.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/InteractionInstance.scala @@ -10,6 +10,7 @@ import com.ing.baker.runtime.{common, javadsl} import com.ing.baker.types.{Converters, Type} import scala.collection.JavaConverters._ +import scala.compat.java8.FutureConverters import scala.concurrent.{ExecutionContext, Future} import scala.reflect.ClassTag import scala.util.Try @@ -55,7 +56,7 @@ object InteractionInstance { def unsafeFrom(implementation: AnyRef)(implicit ec: ExecutionContext): InteractionInstance = { val method: Method = { - val unmockedClass = akka.unmock(implementation.getClass) + val unmockedClass = common.unmock(implementation.getClass) unmockedClass.getMethods.count(_.getName == "apply") match { case 0 => throw new IllegalArgumentException("Implementation does not have a apply function") case n if n > 1 => throw new IllegalArgumentException("Implementation has multiple apply functions") diff --git a/build.sbt b/build.sbt index 4b0833824..665c07111 100644 --- a/build.sbt +++ b/build.sbt @@ -82,7 +82,7 @@ lazy val interface = project.in(file("baker-interface")) .settings( moduleName := "baker-interface", libraryDependencies ++= Seq( - objenisis + scalaJava8Compat ) ++ providedDeps(findbugs) ) .dependsOn(intermediateLanguage) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index ab3db1470..13060b0d7 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -18,6 +18,7 @@ object Dependencies { .exclude("com.typesafe.akka", "akka-persistence-query") .exclude("com.typesafe.akka", "akka-stream") + val scalaJava8Compat = "org.scala-lang.modules" %% "scala-java8-compat" % "0.8.0" val scalaTest = "org.scalatest" %% "scalatest" % "3.0.5" val mockito = "org.mockito" % "mockito-all" % "1.10.19" val junitInterface = "com.novocode" % "junit-interface" % "0.11" diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala index 80ee8ae03..b7609573a 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala @@ -27,20 +27,20 @@ import scala.util.Try object AkkaBaker { - def apply(config: AkkaBakerConfig): AkkaBaker = - new AkkaBaker(config) - def apply(config: Config, actorSystem: ActorSystem): AkkaBaker = new AkkaBaker(AkkaBakerConfig.from(config, actorSystem)) + def withConfig(config: AkkaBakerConfig): AkkaBaker = + new AkkaBaker(config) + def localDefault(actorSystem: ActorSystem): AkkaBaker = new AkkaBaker(AkkaBakerConfig.localDefault(actorSystem)) def clusterDefault(seedNodes: NonEmptyList[Address], actorSystem: ActorSystem): AkkaBaker = new AkkaBaker(AkkaBakerConfig.clusterDefault(seedNodes, actorSystem)) - def java(config: AkkaBakerConfig): Baker = - new Baker(apply(config)) + def javaWithConfig(config: AkkaBakerConfig): Baker = + new Baker(withConfig(config)) def java(config: Config, actorSystem: ActorSystem): Baker = new Baker(apply(config, actorSystem)) @@ -48,13 +48,6 @@ object AkkaBaker { def javaLocalDefault(actorSystem: ActorSystem): Baker = new Baker(new AkkaBaker(AkkaBakerConfig.localDefault(actorSystem))) - def javaClusterDefault(seedNodes: java.util.List[Address], actorSystem: ActorSystem): Baker = { - val nodes = - if (seedNodes.isEmpty) throw new IllegalStateException("Baker cluster configuration without baker.cluster.seed-nodes") - else NonEmptyList.fromListUnsafe(seedNodes.asScala.toList) - new Baker(new AkkaBaker(AkkaBakerConfig.clusterDefault(nodes, actorSystem))) - } - def javaOther(baker: scaladsl.Baker) = new Baker(baker) } diff --git a/runtime/src/test/java/com/ing/baker/Webshop.java b/runtime/src/test/java/com/ing/baker/Webshop.java index f67198caa..9ac3b2e70 100644 --- a/runtime/src/test/java/com/ing/baker/Webshop.java +++ b/runtime/src/test/java/com/ing/baker/Webshop.java @@ -10,6 +10,7 @@ import com.ing.baker.recipe.javadsl.Interaction; import com.ing.baker.recipe.javadsl.InteractionFailureStrategy; import com.ing.baker.recipe.javadsl.Recipe; +import com.ing.baker.runtime.akka.AkkaBaker; import com.ing.baker.runtime.javadsl.Baker; import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; @@ -151,7 +152,7 @@ public void testWebshop() throws ExecutionException, InterruptedException { when(validateOrderMock.apply(any(), any())).thenReturn(new ValidateOrder.Valid()); ActorSystem system = ActorSystem.create("webshop"); - Baker baker = Baker.akka(config, system); + Baker baker = AkkaBaker.java(config, system); baker.addInteractionInstances(ImmutableList.of(shipGoodsMock, sendInvoiceMock, manufactureGoodsMock, validateOrderMock)); diff --git a/runtime/src/test/scala/com/ing/baker/BakerRuntimeTestBase.scala b/runtime/src/test/scala/com/ing/baker/BakerRuntimeTestBase.scala index 35066d6de..c3e077835 100644 --- a/runtime/src/test/scala/com/ing/baker/BakerRuntimeTestBase.scala +++ b/runtime/src/test/scala/com/ing/baker/BakerRuntimeTestBase.scala @@ -12,6 +12,7 @@ import com.typesafe.config.{Config, ConfigFactory} import java.nio.file.Paths import java.util.UUID +import com.ing.baker.recipe.common.Recipe import com.ing.baker.runtime.akka.AkkaBaker import org.mockito.Matchers._ import org.mockito.Mockito._ @@ -205,7 +206,7 @@ trait BakerRuntimeTestBase setupBakerWithRecipe(recipe, mockImplementations)(actorSystem) } - protected def setupBakerWithRecipe(recipe: com.ing.baker.runtime.common.Recipe, implementations: Seq[InteractionInstance]) + protected def setupBakerWithRecipe(recipe: Recipe, implementations: Seq[InteractionInstance]) (implicit actorSystem: ActorSystem): Future[(Baker, String)] = { val baker = AkkaBaker(ConfigFactory.load(), actorSystem) baker.addInteractionInstances(implementations).flatMap { _ => From 2157818908629d3d1b8250d0815f68d4fdc1b463 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Wed, 23 Oct 2019 14:32:51 +0200 Subject: [PATCH 25/86] Fixes typos created by Intellij refactoring tool D: --- docs/archive/dictionary.md | 2 +- docs/archive/recipe-visualization.md | 2 +- docs/sections/development-life-cycle/design-a-recipe.md | 4 ++-- docs/sections/reference/dsls.md | 8 ++++---- docs/sections/versions/baker-3-release-notes.md | 2 +- docs/sections/versions/baker-3.md | 2 +- intermediate-language/src/main/resources/reference.conf | 2 +- .../main/scala/com/ing/baker/il/RecipeVisualStyle.scala | 2 +- .../actor/process_instance/ProcessInstanceProtocol.scala | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/archive/dictionary.md b/docs/archive/dictionary.md index cba37c2e9..1cbedd350 100644 --- a/docs/archive/dictionary.md +++ b/docs/archive/dictionary.md @@ -1,6 +1,6 @@ # Dictionary -Here we define some com.ing.baker.runtime.common used lanuage that is used in this documentation. +Here we define some common used lanuage that is used in this documentation. | Name | Description | | --- | --- | diff --git a/docs/archive/recipe-visualization.md b/docs/archive/recipe-visualization.md index fa6f76e9d..6fad45cc8 100644 --- a/docs/archive/recipe-visualization.md +++ b/docs/archive/recipe-visualization.md @@ -96,4 +96,4 @@ For an overview on what is possible to configure check out the [graphviz](https: It is not possible to alter the `shape` attribute, it is hard coded (fixed) for all elements in the graph. -This is done to garuantee a com.ing.baker.runtime.common visual language for all recipes. \ No newline at end of file +This is done to garuantee a common visual language for all recipes. \ No newline at end of file diff --git a/docs/sections/development-life-cycle/design-a-recipe.md b/docs/sections/development-life-cycle/design-a-recipe.md index d9195726c..50ef93938 100644 --- a/docs/sections/development-life-cycle/design-a-recipe.md +++ b/docs/sections/development-life-cycle/design-a-recipe.md @@ -230,11 +230,11 @@ public class JWebshopRecipe { ``` Let us remember that this is just a _description_ of what our program across multiple services should do, on the next -sections we will see how to visualize it, create runtime `instances` of our recipes and their parts, what com.ing.baker.runtime.common practices +sections we will see how to visualize it, create runtime `instances` of our recipes and their parts, what common practices are there for testing, everything you need to know to deploy and monitor a baker cluster, and how Baker helps you handle and resolve failure which is not modeled in the domain (in the recipe). -As you might have realised `Ingredients`, `Events` and `Interactions` could be reused on different Recipes, giving com.ing.baker.runtime.common +As you might have realised `Ingredients`, `Events` and `Interactions` could be reused on different Recipes, giving common business verbs that your programs and organisation can use across teams, the same way different cooking recipes share same processes (simmering, boiling, cutting) you should reuse interactions across your different business recipes. diff --git a/docs/sections/reference/dsls.md b/docs/sections/reference/dsls.md index 541e8d5bc..45dfd7c1b 100644 --- a/docs/sections/reference/dsls.md +++ b/docs/sections/reference/dsls.md @@ -12,8 +12,8 @@ we provide an API that uses Java and Scala reflection to generate most of the da classes or interfaces. ```scala tab="Scala" -import com.ing.baker.recipe.com.ing.baker.runtime.common.InteractionFailureStrategy.RetryWithIncrementalBackoff -import com.ing.baker.recipe.com.ing.baker.runtime.common.InteractionFailureStrategy.RetryWithIncrementalBackoff.UntilDeadline +import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff +import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff.UntilDeadline import com.ing.baker.recipe.scaladsl.{Event, Ingredient, Interaction, Recipe} import scala.concurrent.duration._ @@ -103,8 +103,8 @@ object WebshopRecipe { ```scala tab="Scala (Reflection API)" -import com.ing.baker.recipe.com.ing.baker.runtime.common.InteractionFailureStrategy.RetryWithIncrementalBackoff -import com.ing.baker.recipe.com.ing.baker.runtime.common.InteractionFailureStrategy.RetryWithIncrementalBackoff.UntilDeadline +import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff +import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff.UntilDeadline import com.ing.baker.recipe.scaladsl.{Event, Ingredient, Interaction, Recipe} import scala.concurrent.duration._ diff --git a/docs/sections/versions/baker-3-release-notes.md b/docs/sections/versions/baker-3-release-notes.md index 409a7781f..947a6f9ed 100644 --- a/docs/sections/versions/baker-3-release-notes.md +++ b/docs/sections/versions/baker-3-release-notes.md @@ -21,7 +21,7 @@ The problem with this approach was that the interfaces for Java and Scala develo In this release we have created two separate packages for Java and Scala interfaces. The javadsl and scaladsl packages contain the same objects but created for those users in mind. -These objects share a com.ing.baker.runtime.common parent to ensure the Java and Scala runtime DSLs are in sync. +These objects share a common parent to ensure the Java and Scala runtime DSLs are in sync. As user you just chooses the correct objects by having either the javadsl or scaladsl imported. ### No more blocking! Future and CompletableFuture diff --git a/docs/sections/versions/baker-3.md b/docs/sections/versions/baker-3.md index 11bd7bd90..a47a640ca 100644 --- a/docs/sections/versions/baker-3.md +++ b/docs/sections/versions/baker-3.md @@ -24,7 +24,7 @@ It is safer to bring the complete cluster down. ### Renames/package changes -* com.ing.baker.runtime.core -> com.ing.baker.runtime.javadsl/scaladsl/com.ing.baker.runtime.common (depends per object) +* com.ing.baker.runtime.core -> com.ing.baker.runtime.javadsl/scaladsl/common (depends per object) * com.ing.baker.runtime.java_api -> com.ing.baker.runtime.javadsl * processId -> recipeInstanceId * getProcessId -> GetRecipeInstanceId diff --git a/intermediate-language/src/main/resources/reference.conf b/intermediate-language/src/main/resources/reference.conf index 4cdf3c75b..543037a31 100644 --- a/intermediate-language/src/main/resources/reference.conf +++ b/intermediate-language/src/main/resources/reference.conf @@ -16,7 +16,7 @@ baker { } // these attributes are shared for all nodes (ingredients, interactions & events) - com.ing.baker.runtime.common { + common { "fontname" = "ING Me" "fontsize" = 22 "fontcolor" = "white" diff --git a/intermediate-language/src/main/scala/com/ing/baker/il/RecipeVisualStyle.scala b/intermediate-language/src/main/scala/com/ing/baker/il/RecipeVisualStyle.scala index 277597396..754501dcf 100644 --- a/intermediate-language/src/main/scala/com/ing/baker/il/RecipeVisualStyle.scala +++ b/intermediate-language/src/main/scala/com/ing/baker/il/RecipeVisualStyle.scala @@ -49,7 +49,7 @@ object RecipeVisualStyle { commonNodeAttributes = List( DotAttrStmt( Elem.node, - readAttributes("com.ing.baker.runtime.common") + readAttributes("common") )), ingredientAttributes = DotAttr("shape", "circle") +: readAttributes("ingredient"), diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala index 509c65b6b..b10cdc20f 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala @@ -9,7 +9,7 @@ import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable object ProcessInstanceProtocol { /** - * A com.ing.baker.runtime.common trait for all commands to a petri net instance. + * A common trait for all commands to a petri net instance. */ sealed trait Command extends BakerSerializable From 2d6498cd27c417d3e1752c774c769e3a5ce7dfda Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Wed, 23 Oct 2019 14:59:09 +0200 Subject: [PATCH 26/86] Fixes typos created by Intellij refactoring tool D: --- .../akka/actor/process_instance/ProcessInstanceProtocol.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala index b10cdc20f..8d0376c38 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala @@ -52,7 +52,7 @@ object ProcessInstanceProtocol { case class OverrideExceptionStrategy(jobId: Long, failureStrategy: ExceptionStrategy) extends Command /** - * A com.ing.baker.runtime.common trait for all responses coming from a petri net instance. + * A common trait for all responses coming from a petri net instance. */ sealed trait Response extends BakerSerializable From bdf4eb654d9665cf1379befe07d1b58b49380be2 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Wed, 23 Oct 2019 15:15:34 +0200 Subject: [PATCH 27/86] Fixes typos created by Intellij refactoring tool D: --- .../com/ing/baker/runtime/javadsl/Baker.scala | 6 ++-- .../baker/runtime/javadsl/BakerEvent.scala | 2 +- .../baker/runtime/javadsl/EventInstance.scala | 4 +-- .../baker/runtime/javadsl/EventMoment.scala | 3 +- .../runtime/javadsl/IngredientInstance.scala | 3 +- .../runtime/javadsl/InteractionInstance.scala | 4 +-- .../runtime/javadsl/RecipeInformation.scala | 2 +- .../javadsl/RecipeInstanceMetadata.scala | 2 +- .../runtime/javadsl/RecipeInstanceState.scala | 2 +- .../runtime/javadsl/SensoryEventResult.scala | 3 +- .../ing/baker/runtime/scaladsl/Baker.scala | 2 +- .../baker/runtime/scaladsl/BakerEvent.scala | 4 +-- .../runtime/scaladsl/EventResolutions.scala | 2 +- .../runtime/scaladsl/IngredientInstance.scala | 4 +-- .../scaladsl/RecipeInstanceMetadata.scala | 4 +-- .../scaladsl/RecipeInstanceState.scala | 4 +-- .../ing/baker/runtime/akka/AkkaBaker.scala | 28 +++++++++---------- 17 files changed, 37 insertions(+), 42 deletions(-) diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala index f6e2e0afc..8bcc0a5a8 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala @@ -4,16 +4,16 @@ import java.util import java.util.Optional import java.util.concurrent.CompletableFuture import java.util.function.{BiConsumer, Consumer} -import javax.annotation.Nonnull -import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi +import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.types.Value +import javax.annotation.Nonnull -import scala.compat.java8.FutureConverters import scala.collection.JavaConverters._ +import scala.compat.java8.FutureConverters import scala.concurrent.Future class Baker private[runtime](private val baker: scaladsl.Baker) extends common.Baker[CompletableFuture] with JavaApi { diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala index 19c691388..f24d352a7 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/BakerEvent.scala @@ -5,8 +5,8 @@ import java.util.Optional import com.ing.baker.il.CompiledRecipe import com.ing.baker.il.failurestrategy.ExceptionStrategyOutcome import com.ing.baker.runtime.common -import com.ing.baker.runtime.common.RejectReason import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi +import com.ing.baker.runtime.common.RejectReason sealed trait BakerEvent extends common.BakerEvent with JavaApi { type Event = EventInstance diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala index f026f152d..d6f4f3840 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventInstance.scala @@ -2,7 +2,7 @@ package com.ing.baker.runtime.javadsl import java.util -import com.ing.baker.runtime.scaladsl +import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.il.EventDescriptor import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi import com.ing.baker.types.Value @@ -11,7 +11,7 @@ import scala.collection.JavaConverters._ case class EventInstance(name: String, providedIngredients: util.Map[String, Value]) - extends com.ing.baker.runtime.common.EventInstance with JavaApi { + extends common.EventInstance with JavaApi { def getProvidedIngredients: util.Map[String, Value] = providedIngredients diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala index 661f08e8f..de95acf7f 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/EventMoment.scala @@ -1,8 +1,7 @@ package com.ing.baker.runtime.javadsl -import com.ing.baker.runtime.scaladsl -import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi +import com.ing.baker.runtime.{common, scaladsl} case class EventMoment(name: String, occurredOn: Long) diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala index bc6443f96..b94fee297 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/IngredientInstance.scala @@ -1,8 +1,7 @@ package com.ing.baker.runtime.javadsl -import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi -import com.ing.baker.runtime.scaladsl +import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.types.Value case class IngredientInstance(name: String, value: Value) extends common.IngredientInstance with JavaApi { diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/InteractionInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/InteractionInstance.scala index 6a5a064b5..3add46f5e 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/InteractionInstance.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/InteractionInstance.scala @@ -5,12 +5,12 @@ import java.util import java.util.Optional import java.util.concurrent.CompletableFuture -import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi +import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.types.{Converters, Type} -import scala.compat.java8.FutureConverters import scala.collection.JavaConverters._ +import scala.compat.java8.FutureConverters import scala.reflect.ClassTag import scala.util.Try diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala index 185458e30..3e11bf57a 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInformation.scala @@ -1,8 +1,8 @@ package com.ing.baker.runtime.javadsl -import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.il.CompiledRecipe import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi +import com.ing.baker.runtime.{common, scaladsl} import scala.collection.JavaConverters._ diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala index 56208130c..fbf28db72 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceMetadata.scala @@ -1,7 +1,7 @@ package com.ing.baker.runtime.javadsl -import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi +import com.ing.baker.runtime.{common, scaladsl} case class RecipeInstanceMetadata(recipeId: String, recipeInstanceId: String, createdTime: Long) extends common.RecipeInstanceMetadata with JavaApi { diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala index cf31c1253..a0627f161 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeInstanceState.scala @@ -2,8 +2,8 @@ package com.ing.baker.runtime.javadsl import java.util.stream.Collectors -import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi +import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.types.Value import scala.collection.JavaConverters._ diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala index 36d9473ac..b761c0f20 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/SensoryEventResult.scala @@ -1,9 +1,8 @@ package com.ing.baker.runtime.javadsl -import com.ing.baker.runtime.scaladsl -import com.ing.baker.runtime.common import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi import com.ing.baker.runtime.common.SensoryEventStatus +import com.ing.baker.runtime.{common, scaladsl} import com.ing.baker.types.Value import scala.collection.JavaConverters._ diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala index dff89dddb..9770cd60d 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala @@ -1,8 +1,8 @@ package com.ing.baker.runtime.scaladsl import com.ing.baker.runtime.common -import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi +import com.ing.baker.runtime.common.SensoryEventStatus import scala.concurrent.Future diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala index 519ca3d47..24c368e72 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala @@ -6,10 +6,10 @@ import java.util.Optional import com.ing.baker.il.CompiledRecipe import com.ing.baker.il.failurestrategy.ExceptionStrategyOutcome import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi -import com.ing.baker.runtime.{common, javadsl} import com.ing.baker.runtime.common.RejectReason +import com.ing.baker.runtime.{common, javadsl} -sealed trait BakerEvent extends com.ing.baker.runtime.common.BakerEvent with ScalaApi { +sealed trait BakerEvent extends common.BakerEvent with ScalaApi { type Event = EventInstance def asJava(): javadsl.BakerEvent = this match { diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/EventResolutions.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/EventResolutions.scala index 94bde2ccb..b54a9a6f7 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/EventResolutions.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/EventResolutions.scala @@ -9,7 +9,7 @@ import scala.concurrent.Future case class EventResolutions( resolveWhenReceived: Future[SensoryEventStatus], resolveWhenCompleted: Future[SensoryEventResult] -) extends com.ing.baker.runtime.common.EventResolutions[Future] with ScalaApi { +) extends common.EventResolutions[Future] with ScalaApi { type SensoryEventResultType = SensoryEventResult } diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/IngredientInstance.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/IngredientInstance.scala index 25b2c7007..ffbfa778b 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/IngredientInstance.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/IngredientInstance.scala @@ -1,10 +1,10 @@ package com.ing.baker.runtime.scaladsl import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi -import com.ing.baker.runtime.javadsl +import com.ing.baker.runtime.{common, javadsl} import com.ing.baker.types.Value -case class IngredientInstance(name: String, value: Value) extends com.ing.baker.runtime.common.IngredientInstance with ScalaApi { +case class IngredientInstance(name: String, value: Value) extends common.IngredientInstance with ScalaApi { def asJava: javadsl.IngredientInstance = javadsl.IngredientInstance(name, value) } diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceMetadata.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceMetadata.scala index ae8d42efe..8a56a9d59 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceMetadata.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceMetadata.scala @@ -1,9 +1,9 @@ package com.ing.baker.runtime.scaladsl import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi -import com.ing.baker.runtime.javadsl +import com.ing.baker.runtime.{common, javadsl} -case class RecipeInstanceMetadata(recipeId: String, recipeInstanceId: String, createdTime: Long) extends com.ing.baker.runtime.common.RecipeInstanceMetadata with ScalaApi { +case class RecipeInstanceMetadata(recipeId: String, recipeInstanceId: String, createdTime: Long) extends common.RecipeInstanceMetadata with ScalaApi { def asJava: javadsl.RecipeInstanceMetadata = new javadsl.RecipeInstanceMetadata(recipeId, recipeInstanceId, createdTime) diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceState.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceState.scala index f22f88d1a..04e8d9753 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceState.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeInstanceState.scala @@ -1,7 +1,7 @@ package com.ing.baker.runtime.scaladsl import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi -import com.ing.baker.runtime.javadsl +import com.ing.baker.runtime.{common, javadsl} import com.ing.baker.types.Value import scala.collection.JavaConverters._ @@ -17,7 +17,7 @@ case class RecipeInstanceState( recipeInstanceId: String, ingredients: Map[String, Value], events: Seq[EventMoment]) - extends com.ing.baker.runtime.common.RecipeInstanceState with ScalaApi { + extends common.RecipeInstanceState with ScalaApi { type EventType = EventMoment diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala index b7609573a..60b449f58 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala @@ -12,14 +12,12 @@ import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProtocol import com.ing.baker.runtime.common.BakerException._ import com.ing.baker.runtime.common.SensoryEventStatus -import com.ing.baker.runtime.javadsl.Baker -import com.ing.baker.runtime.scaladsl +import com.ing.baker.runtime.{javadsl, scaladsl} import com.ing.baker.runtime.scaladsl._ import com.ing.baker.types.Value import com.typesafe.config.Config import org.slf4j.{Logger, LoggerFactory} -import scala.collection.JavaConverters._ import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.language.postfixOps @@ -27,29 +25,29 @@ import scala.util.Try object AkkaBaker { - def apply(config: Config, actorSystem: ActorSystem): AkkaBaker = + def apply(config: Config, actorSystem: ActorSystem): scaladsl.Baker = new AkkaBaker(AkkaBakerConfig.from(config, actorSystem)) - def withConfig(config: AkkaBakerConfig): AkkaBaker = + def withConfig(config: AkkaBakerConfig): scaladsl.Baker = new AkkaBaker(config) - def localDefault(actorSystem: ActorSystem): AkkaBaker = + def localDefault(actorSystem: ActorSystem): scaladsl.Baker = new AkkaBaker(AkkaBakerConfig.localDefault(actorSystem)) - def clusterDefault(seedNodes: NonEmptyList[Address], actorSystem: ActorSystem): AkkaBaker = + def clusterDefault(seedNodes: NonEmptyList[Address], actorSystem: ActorSystem): scaladsl.Baker = new AkkaBaker(AkkaBakerConfig.clusterDefault(seedNodes, actorSystem)) - def javaWithConfig(config: AkkaBakerConfig): Baker = - new Baker(withConfig(config)) + def javaWithConfig(config: AkkaBakerConfig): javadsl.Baker = + new javadsl.Baker(withConfig(config)) - def java(config: Config, actorSystem: ActorSystem): Baker = - new Baker(apply(config, actorSystem)) + def java(config: Config, actorSystem: ActorSystem): javadsl.Baker = + new javadsl.Baker(apply(config, actorSystem)) - def javaLocalDefault(actorSystem: ActorSystem): Baker = - new Baker(new AkkaBaker(AkkaBakerConfig.localDefault(actorSystem))) + def javaLocalDefault(actorSystem: ActorSystem): javadsl.Baker = + new javadsl.Baker(new AkkaBaker(AkkaBakerConfig.localDefault(actorSystem))) - def javaOther(baker: scaladsl.Baker) = - new Baker(baker) + def javaOther(baker: scaladsl.Baker): javadsl.Baker = + new javadsl.Baker(baker) } /** From fdbf23d34e18bdb315757ebbed777e2393c028ba Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Wed, 23 Oct 2019 15:16:44 +0200 Subject: [PATCH 28/86] Fixes typos created by Intellij refactoring tool D: --- .../scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala index 24c368e72..f488c212a 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/BakerEvent.scala @@ -45,7 +45,7 @@ case class EventReceived(timeStamp: Long, recipeId: String, recipeInstanceId: String, correlationId: Option[String], - event: EventInstance) extends BakerEvent with com.ing.baker.runtime.common.EventReceived + event: EventInstance) extends BakerEvent with common.EventReceived /** * Event describing the fact that an event was received but rejected for a process @@ -82,7 +82,7 @@ case class InteractionFailed(timeStamp: Long, interactionName: String, failureCount: Int, throwable: Throwable, - exceptionStrategyOutcome: ExceptionStrategyOutcome) extends BakerEvent with com.ing.baker.runtime.common.InteractionFailed + exceptionStrategyOutcome: ExceptionStrategyOutcome) extends BakerEvent with common.InteractionFailed /** * Event describing the fact that an interaction has started executing @@ -117,7 +117,7 @@ case class InteractionCompleted(timeStamp: Long, recipeId: String, recipeInstanceId: String, interactionName: String, - event: Option[EventInstance]) extends BakerEvent with com.ing.baker.runtime.common.InteractionCompleted + event: Option[EventInstance]) extends BakerEvent with common.InteractionCompleted /** * Event describing the fact that a baker process was created @@ -130,7 +130,7 @@ case class InteractionCompleted(timeStamp: Long, case class RecipeInstanceCreated(timeStamp: Long, recipeId: String, recipeName: String, - recipeInstanceId: String) extends BakerEvent with com.ing.baker.runtime.common.RecipeInstanceCreated + recipeInstanceId: String) extends BakerEvent with common.RecipeInstanceCreated /** * An event describing the fact that a recipe was added to baker. From 7b04648869b706b8c9dc8241a23eba204e52eb23 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Wed, 23 Oct 2019 16:36:47 +0200 Subject: [PATCH 29/86] WIP baas project separation --- .../ing/baker/baas/javadsl/BakerClient.scala | 4 ++-- .../ing/baker/baas/scaladsl/BakerClient.scala | 2 +- .../src/main/protobuf/baas.proto | 0 .../com/ing/baker/baas/common}/BaaSProto.scala | 0 .../ing/baker/baas/common}/BaaSProtocol.scala | 0 .../baker/baas/common}/MarshallingUtils.scala | 0 .../com/ing/baker/baas/state}/BaaSServer.scala | 0 .../baas}/CommonBaaSServerClientSpec.scala | 0 .../baas}/JavaDSLBaaSServerClientSpec.scala | 6 +++--- .../baas}/ScalaDSLBaaSServerClientSpec.scala | 2 +- .../baas/recipe}/CheckoutFlowRecipe.scala | 0 .../baas/recipe}/MakePaymentInstance.scala | 0 .../baas/recipe}/ReserveItemsInstance.scala | 0 .../baker/baas/recipe}/ShipItemsInstance.scala | 0 baas/src/test/resources/logback.xml | 18 ------------------ .../src/main/protobuf/common.proto | 0 .../runtime}/serialization/Encryption.scala | 2 +- .../runtime}/serialization/ProtoMap.scala | 11 +++++------ .../serialization/SerializersProvider.scala | 2 +- .../protomappings/ActorRefMapping.scala | 8 ++++---- .../protomappings/AnyRefMapping.scala | 8 ++++---- .../protomappings/BakerExceptionMapping.scala | 6 +++--- .../protomappings/BakerTypesMapping.scala | 12 ++++++------ .../protomappings/BakerValuesMapping.scala | 14 ++++++-------- .../protomappings/CompiledRecipeMapping.scala | 12 ++++-------- .../protomappings/EventDescriptorMapping.scala | 6 +++--- .../protomappings/EventMomentMapping.scala | 6 +++--- .../EventOutputTransformerMapping.scala | 6 +++--- .../IngredientDescriptorMapping.scala | 6 +++--- .../IngredientInstanceMapping.scala | 6 +++--- .../InteractionFailureStrategyMapping.scala | 6 +++--- .../protomappings/ProcessStateMapping.scala | 10 ++++------ .../RecipeInformationMapping.scala | 6 +++--- .../RecipeInstanceMetadataMapping.scala | 6 +++--- .../protomappings/RuntimeEventMapping.scala | 10 ++++------ .../SensoryEventResultMapping.scala | 10 ++++------ .../SensoryEventStatusMappingHelper.scala | 2 +- 37 files changed, 78 insertions(+), 109 deletions(-) rename baas/src/main/scala/com/ing/baker/runtime/baas/javadsl/Baker.scala => baas-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala (78%) rename baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala => baas-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala (99%) rename {baas => baas-common}/src/main/protobuf/baas.proto (100%) rename {baas/src/main/scala/com/ing/baker/runtime/baas => baas-common/src/main/scala/com/ing/baker/baas/common}/BaaSProto.scala (100%) rename {baas/src/main/scala/com/ing/baker/runtime/baas => baas-common/src/main/scala/com/ing/baker/baas/common}/BaaSProtocol.scala (100%) rename {baas/src/main/scala/com/ing/baker/runtime/baas => baas-common/src/main/scala/com/ing/baker/baas/common}/MarshallingUtils.scala (100%) rename {baas/src/main/scala/com/ing/baker/runtime/baas => baas-state/src/main/scala/com/ing/baker/baas/state}/BaaSServer.scala (100%) rename {baas/src/test/scala/com/ing/baker/runtime/baas/common => baas-tests/src/test/scala/com/ing/baker/baas}/CommonBaaSServerClientSpec.scala (100%) rename {baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl => baas-tests/src/test/scala/com/ing/baker/baas}/JavaDSLBaaSServerClientSpec.scala (97%) rename {baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl => baas-tests/src/test/scala/com/ing/baker/baas}/ScalaDSLBaaSServerClientSpec.scala (86%) rename {baas/src/test/scala/com/ing/baker/runtime/baas/common => baas-tests/src/test/scala/com/ing/baker/baas/recipe}/CheckoutFlowRecipe.scala (100%) rename {baas/src/test/scala/com/ing/baker/runtime/baas/common => baas-tests/src/test/scala/com/ing/baker/baas/recipe}/MakePaymentInstance.scala (100%) rename {baas/src/test/scala/com/ing/baker/runtime/baas/common => baas-tests/src/test/scala/com/ing/baker/baas/recipe}/ReserveItemsInstance.scala (100%) rename {baas/src/test/scala/com/ing/baker/runtime/baas/common => baas-tests/src/test/scala/com/ing/baker/baas/recipe}/ShipItemsInstance.scala (100%) delete mode 100644 baas/src/test/resources/logback.xml rename {runtime => baker-interface}/src/main/protobuf/common.proto (100%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/Encryption.scala (95%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/ProtoMap.scala (91%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/SerializersProvider.scala (95%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/ActorRefMapping.scala (69%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/AnyRefMapping.scala (88%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/BakerExceptionMapping.scala (79%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/BakerTypesMapping.scala (95%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/BakerValuesMapping.scala (94%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/CompiledRecipeMapping.scala (96%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/EventDescriptorMapping.scala (77%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/EventMomentMapping.scala (73%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/EventOutputTransformerMapping.scala (78%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/IngredientDescriptorMapping.scala (76%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/IngredientInstanceMapping.scala (74%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/InteractionFailureStrategyMapping.scala (93%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/ProcessStateMapping.scala (79%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/RecipeInformationMapping.scala (77%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/RecipeInstanceMetadataMapping.scala (81%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/RuntimeEventMapping.scala (76%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/SensoryEventResultMapping.scala (78%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor => baker-interface/src/main/scala/com/ing/baker/runtime}/serialization/protomappings/SensoryEventStatusMappingHelper.scala (96%) diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/javadsl/Baker.scala b/baas-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala similarity index 78% rename from baas/src/main/scala/com/ing/baker/runtime/baas/javadsl/Baker.scala rename to baas-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala index 35f90692c..6435bdb1c 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/javadsl/Baker.scala +++ b/baas-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala @@ -1,9 +1,9 @@ -package com.ing.baker.runtime.baas.javadsl +package com.ing.baker.baas.javadsl import akka.actor.ActorSystem import akka.stream.Materializer import com.ing.baker.runtime.akka.actor.serialization.Encryption -import com.ing.baker.runtime.baas.scaladsl.{ Baker => ScalaRemoteBaker } +import com.ing.baker.baas.scaladsl.{ Baker => ScalaRemoteBaker } import com.ing.baker.runtime.javadsl.{ Baker => JavaBaker } object Baker { diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala b/baas-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala similarity index 99% rename from baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala rename to baas-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala index 8ea9ee8cb..f931a267b 100644 --- a/baas/src/main/scala/com/ing/baker/runtime/baas/scaladsl/Baker.scala +++ b/baas-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala @@ -1,4 +1,4 @@ -package com.ing.baker.runtime.baas.scaladsl +package com.ing.baker.baas.scaladsl import akka.actor.ActorSystem import akka.http.scaladsl.Http diff --git a/baas/src/main/protobuf/baas.proto b/baas-common/src/main/protobuf/baas.proto similarity index 100% rename from baas/src/main/protobuf/baas.proto rename to baas-common/src/main/protobuf/baas.proto diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala b/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala similarity index 100% rename from baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProto.scala rename to baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala b/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProtocol.scala similarity index 100% rename from baas/src/main/scala/com/ing/baker/runtime/baas/BaaSProtocol.scala rename to baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProtocol.scala diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/MarshallingUtils.scala b/baas-common/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala similarity index 100% rename from baas/src/main/scala/com/ing/baker/runtime/baas/MarshallingUtils.scala rename to baas-common/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala diff --git a/baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala b/baas-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala similarity index 100% rename from baas/src/main/scala/com/ing/baker/runtime/baas/BaaSServer.scala rename to baas-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/CommonBaaSServerClientSpec.scala similarity index 100% rename from baas/src/test/scala/com/ing/baker/runtime/baas/common/CommonBaaSServerClientSpec.scala rename to baas-tests/src/test/scala/com/ing/baker/baas/CommonBaaSServerClientSpec.scala diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/JavaDSLBaaSServerClientSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/JavaDSLBaaSServerClientSpec.scala similarity index 97% rename from baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/JavaDSLBaaSServerClientSpec.scala rename to baas-tests/src/test/scala/com/ing/baker/baas/JavaDSLBaaSServerClientSpec.scala index 132ddb92b..376500ae4 100644 --- a/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/JavaDSLBaaSServerClientSpec.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/JavaDSLBaaSServerClientSpec.scala @@ -1,11 +1,11 @@ -package com.ing.baker.runtime.baas.scaladsl +package com.ing.baker.baas.scaladsl import java.util.Optional import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} import com.ing.baker.runtime.baas.common.CommonBaaSServerClientSpec -import com.ing.baker.runtime.baas.javadsl -import com.ing.baker.runtime.baas.scaladsl.JavaDSLBaaSServerClientSpec.optionToJava +import com.ing.baker.baas.javadsl +import com.ing.baker.baas.scaladsl.JavaDSLBaaSServerClientSpec.optionToJava import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.scaladsl import com.ing.baker.runtime.scaladsl._ diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/ScalaDSLBaaSServerClientSpec.scala similarity index 86% rename from baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala rename to baas-tests/src/test/scala/com/ing/baker/baas/ScalaDSLBaaSServerClientSpec.scala index 02163d8eb..455fe8bae 100644 --- a/baas/src/test/scala/com/ing/baker/runtime/baas/scaladsl/ScalaDSLBaaSServerClientSpec.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/ScalaDSLBaaSServerClientSpec.scala @@ -1,4 +1,4 @@ -package com.ing.baker.runtime.baas.scaladsl +package com.ing.baker.baas.scaladsl import com.ing.baker.runtime.akka.actor.serialization.Encryption import com.ing.baker.runtime.baas.common.CommonBaaSServerClientSpec diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/CheckoutFlowRecipe.scala b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/CheckoutFlowRecipe.scala similarity index 100% rename from baas/src/test/scala/com/ing/baker/runtime/baas/common/CheckoutFlowRecipe.scala rename to baas-tests/src/test/scala/com/ing/baker/baas/recipe/CheckoutFlowRecipe.scala diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/MakePaymentInstance.scala b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/MakePaymentInstance.scala similarity index 100% rename from baas/src/test/scala/com/ing/baker/runtime/baas/common/MakePaymentInstance.scala rename to baas-tests/src/test/scala/com/ing/baker/baas/recipe/MakePaymentInstance.scala diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/ReserveItemsInstance.scala b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ReserveItemsInstance.scala similarity index 100% rename from baas/src/test/scala/com/ing/baker/runtime/baas/common/ReserveItemsInstance.scala rename to baas-tests/src/test/scala/com/ing/baker/baas/recipe/ReserveItemsInstance.scala diff --git a/baas/src/test/scala/com/ing/baker/runtime/baas/common/ShipItemsInstance.scala b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ShipItemsInstance.scala similarity index 100% rename from baas/src/test/scala/com/ing/baker/runtime/baas/common/ShipItemsInstance.scala rename to baas-tests/src/test/scala/com/ing/baker/baas/recipe/ShipItemsInstance.scala diff --git a/baas/src/test/resources/logback.xml b/baas/src/test/resources/logback.xml deleted file mode 100644 index 03c45b50f..000000000 --- a/baas/src/test/resources/logback.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - %d{ISO8601} [%thread] [%X{recipeInstanceId}] %-5level %logger{36} - %msg%n - - - - - - - - - - - - - \ No newline at end of file diff --git a/runtime/src/main/protobuf/common.proto b/baker-interface/src/main/protobuf/common.proto similarity index 100% rename from runtime/src/main/protobuf/common.proto rename to baker-interface/src/main/protobuf/common.proto diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/Encryption.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/Encryption.scala similarity index 95% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/Encryption.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/Encryption.scala index 585bb48df..295d6d359 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/Encryption.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/Encryption.scala @@ -1,4 +1,4 @@ -package com.ing.baker.runtime.akka.actor.serialization +package com.ing.baker.runtime.serialization import javax.crypto.Cipher import javax.crypto.spec.SecretKeySpec diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/ProtoMap.scala similarity index 91% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/ProtoMap.scala index b3bbee7ba..b3379656d 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/ProtoMap.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/ProtoMap.scala @@ -1,13 +1,12 @@ -package com.ing.baker.runtime.akka.actor.serialization +package com.ing.baker.runtime.serialization import akka.actor.ActorRef -import com.ing.baker.il -import com.ing.baker.types -import com.ing.baker.runtime.akka.actor.protobuf -import com.ing.baker.runtime.akka.actor.serialization.protomappings._ import com.ing.baker.runtime.common.BakerException -import com.ing.baker.runtime.scaladsl.{EventInstance, EventMoment, IngredientInstance, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult} +import com.ing.baker.runtime.scaladsl._ +import com.ing.baker.runtime.serialization.protomappings._ +import com.ing.baker.{il, types} import scalapb.GeneratedMessageCompanion +import com.ing.baker.runtime.akka.actor.protobuf import scala.util.{Success, Try} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/SerializersProvider.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/SerializersProvider.scala similarity index 95% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/SerializersProvider.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/SerializersProvider.scala index 94984808a..7efdfe6ad 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/SerializersProvider.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/SerializersProvider.scala @@ -1,4 +1,4 @@ -package com.ing.baker.runtime.akka.actor.serialization +package com.ing.baker.runtime.serialization import akka.actor.{ActorRefProvider, ActorSystem} import akka.serialization.{Serialization, SerializationExtension, Serializer} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/ActorRefMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/ActorRefMapping.scala similarity index 69% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/ActorRefMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/ActorRefMapping.scala index 1b647a0f9..361d8c4ef 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/ActorRefMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/ActorRefMapping.scala @@ -1,10 +1,10 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings import akka.actor.ActorRef -import com.ing.baker.runtime.akka.actor.serialization.{ProtoMap, SerializersProvider} -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.versioned +import com.ing.baker.runtime.serialization.ProtoMap.versioned import com.ing.baker.runtime.akka.actor.protobuf import com.ing.baker.runtime.akka.actor.protobuf.ActorRefId +import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} import scala.util.Try @@ -12,7 +12,7 @@ class ActorRefMapping(provider: SerializersProvider) extends ProtoMap[ActorRef, val companion = protobuf.ActorRefId - override def toProto(a: ActorRef): ActorRefId = + override def toProto(a: ActorRef): protobuf.ActorRefId = protobuf.ActorRefId(Some(akka.serialization.Serialization.serializedActorPath(a))) override def fromProto(message: ActorRefId): Try[ActorRef] = diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/AnyRefMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/AnyRefMapping.scala similarity index 88% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/AnyRefMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/AnyRefMapping.scala index 39adbafdb..bee47e4f5 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/AnyRefMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/AnyRefMapping.scala @@ -1,10 +1,10 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings -import com.google.protobuf.ByteString import akka.serialization.{Serializer, SerializerWithStringManifest} -import com.ing.baker.runtime.akka.actor.serialization.{ProtoMap, SerializersProvider} -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.versioned +import com.google.protobuf.ByteString +import com.ing.baker.runtime.serialization.ProtoMap.versioned import com.ing.baker.runtime.akka.actor.protobuf +import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} import scala.util.{Failure, Success, Try} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/BakerExceptionMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/BakerExceptionMapping.scala similarity index 79% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/BakerExceptionMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/BakerExceptionMapping.scala index 97d4e8f43..a055b4aed 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/BakerExceptionMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/BakerExceptionMapping.scala @@ -1,9 +1,9 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings import com.ing.baker.runtime.akka.actor.protobuf -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.versioned +import com.ing.baker.runtime.serialization.ProtoMap.versioned import com.ing.baker.runtime.common.BakerException +import com.ing.baker.runtime.serialization.ProtoMap import scala.util.Try diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/BakerTypesMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/BakerTypesMapping.scala similarity index 95% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/BakerTypesMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/BakerTypesMapping.scala index 833dab6f2..5f5359bb2 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/BakerTypesMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/BakerTypesMapping.scala @@ -1,13 +1,13 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings import cats.implicits._ -import com.ing.baker.types -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap import com.ing.baker.runtime.akka.actor.protobuf -import com.ing.baker.runtime.akka.actor.protobuf._ -import Type.OneofType._ -import PrimitiveType._ +import com.ing.baker.runtime.akka.actor.protobuf.PrimitiveType._ import com.ing.baker.runtime.akka.actor.protobuf.Type.OneofType +import com.ing.baker.runtime.akka.actor.protobuf.Type.OneofType.Primitive +import com.ing.baker.runtime.akka.actor.protobuf._ +import com.ing.baker.runtime.serialization.ProtoMap +import com.ing.baker.types import scala.util.{Failure, Success, Try} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/BakerValuesMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/BakerValuesMapping.scala similarity index 94% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/BakerValuesMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/BakerValuesMapping.scala index d2ef70c92..2479a2911 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/BakerValuesMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/BakerValuesMapping.scala @@ -1,15 +1,13 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings -import cats.instances.list._ -import cats.instances.try_._ -import cats.syntax.traverse._ +import cats.implicits._ import com.google.protobuf.ByteString -import com.ing.baker.types -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap import com.ing.baker.runtime.akka.actor.protobuf -import protobuf.Value.OneofValue._ -import org.joda.time.{LocalDate, LocalDateTime, LocalTime} +import com.ing.baker.runtime.akka.actor.protobuf.Value.OneofValue._ +import com.ing.baker.runtime.serialization.ProtoMap +import com.ing.baker.types import org.joda.time.format.ISODateTimeFormat +import org.joda.time.{LocalDate, LocalDateTime, LocalTime} import scala.util.{Failure, Success, Try} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/CompiledRecipeMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/CompiledRecipeMapping.scala similarity index 96% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/CompiledRecipeMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/CompiledRecipeMapping.scala index 7f535fa25..b37b72b3a 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/CompiledRecipeMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/CompiledRecipeMapping.scala @@ -1,19 +1,15 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings import java.util.concurrent.TimeUnit -import cats.syntax.traverse._ -import cats.instances.list._ -import cats.instances.option._ -import cats.instances.try_._ +import cats.implicits._ import com.ing.baker.il import com.ing.baker.petrinet.api._ -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap -import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceSerialization.tokenIdentifier import com.ing.baker.runtime.akka.actor.protobuf -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{versioned, ctxFromProto, ctxToProto} +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} import com.ing.baker.il.petrinet.{Node, Place, RecipePetriNet, Transition} import com.ing.baker.petrinet.api.Marking +import com.ing.baker.runtime.serialization.ProtoMap import com.ing.baker.types.Value import scalax.collection.GraphEdge import scalax.collection.edge.WLDiEdge diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/EventDescriptorMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/EventDescriptorMapping.scala similarity index 77% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/EventDescriptorMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/EventDescriptorMapping.scala index 0a531a3a3..1385dcce3 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/EventDescriptorMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/EventDescriptorMapping.scala @@ -1,10 +1,10 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings import cats.implicits._ import com.ing.baker.il -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ ctxToProto, ctxFromProto, versioned } +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} import com.ing.baker.runtime.akka.actor.protobuf +import com.ing.baker.runtime.serialization.ProtoMap import scala.util.Try diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/EventMomentMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/EventMomentMapping.scala similarity index 73% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/EventMomentMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/EventMomentMapping.scala index 3fb0f51a7..54439f4c9 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/EventMomentMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/EventMomentMapping.scala @@ -1,9 +1,9 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings import com.ing.baker.runtime.akka.actor.protobuf -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.versioned +import com.ing.baker.runtime.serialization.ProtoMap.versioned import com.ing.baker.runtime.scaladsl.EventMoment +import com.ing.baker.runtime.serialization.ProtoMap import scala.util.Try diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/EventOutputTransformerMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/EventOutputTransformerMapping.scala similarity index 78% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/EventOutputTransformerMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/EventOutputTransformerMapping.scala index f50949288..2f7785079 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/EventOutputTransformerMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/EventOutputTransformerMapping.scala @@ -1,10 +1,10 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings import com.ing.baker.il import com.ing.baker.il.EventOutputTransformer -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap import com.ing.baker.runtime.akka.actor.protobuf -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.versioned +import com.ing.baker.runtime.serialization.ProtoMap.versioned +import com.ing.baker.runtime.serialization.ProtoMap import scala.util.Try diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/IngredientDescriptorMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/IngredientDescriptorMapping.scala similarity index 76% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/IngredientDescriptorMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/IngredientDescriptorMapping.scala index 4d9d98276..ff7c84163 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/IngredientDescriptorMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/IngredientDescriptorMapping.scala @@ -1,9 +1,9 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings import com.ing.baker.il -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ ctxToProto, ctxFromProto, versioned } +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} import com.ing.baker.runtime.akka.actor.protobuf +import com.ing.baker.runtime.serialization.ProtoMap import scala.util.Try diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/IngredientInstanceMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/IngredientInstanceMapping.scala similarity index 74% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/IngredientInstanceMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/IngredientInstanceMapping.scala index a2b40b417..bed54700a 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/IngredientInstanceMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/IngredientInstanceMapping.scala @@ -1,9 +1,9 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap import com.ing.baker.runtime.akka.actor.protobuf import com.ing.baker.runtime.scaladsl.IngredientInstance -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.runtime.serialization.ProtoMap import scala.util.Try diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/InteractionFailureStrategyMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/InteractionFailureStrategyMapping.scala similarity index 93% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/InteractionFailureStrategyMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/InteractionFailureStrategyMapping.scala index dff5c3eb1..293dd4327 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/InteractionFailureStrategyMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/InteractionFailureStrategyMapping.scala @@ -1,13 +1,13 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings import java.util.concurrent.TimeUnit import cats.implicits._ -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap import com.ing.baker.il import com.ing.baker.il.failurestrategy.InteractionFailureStrategy import com.ing.baker.runtime.akka.actor.protobuf -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{versioned, ctxFromProto, ctxToProto} +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.runtime.serialization.ProtoMap import scala.util.{Failure, Success, Try} import scala.concurrent.duration._ diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/ProcessStateMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/ProcessStateMapping.scala similarity index 79% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/ProcessStateMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/ProcessStateMapping.scala index 3e18a8d8f..6b48224c7 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/ProcessStateMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/ProcessStateMapping.scala @@ -1,13 +1,11 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings -import cats.instances.list._ -import cats.instances.try_._ -import cats.syntax.traverse._ +import cats.implicits._ import com.ing.baker.types.Value import com.ing.baker.runtime.akka.actor.{protobuf => proto} -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} import com.ing.baker.runtime.scaladsl.{EventMoment, RecipeInstanceState} +import com.ing.baker.runtime.serialization.ProtoMap import scala.util.Try diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RecipeInformationMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/RecipeInformationMapping.scala similarity index 77% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RecipeInformationMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/RecipeInformationMapping.scala index 1cf5b9aec..f295d2a90 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RecipeInformationMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/RecipeInformationMapping.scala @@ -1,9 +1,9 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings -import com.ing.baker.runtime.akka.actor.serialization.{ProtoMap, SerializersProvider} -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} import com.ing.baker.runtime.akka.actor.{protobuf => proto} import com.ing.baker.runtime.scaladsl.RecipeInformation +import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} import scala.util.Try diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RecipeInstanceMetadataMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/RecipeInstanceMetadataMapping.scala similarity index 81% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RecipeInstanceMetadataMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/RecipeInstanceMetadataMapping.scala index 19dd05c8a..da3614a5b 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RecipeInstanceMetadataMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/RecipeInstanceMetadataMapping.scala @@ -1,9 +1,9 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.versioned +import com.ing.baker.runtime.serialization.ProtoMap.versioned import com.ing.baker.runtime.akka.actor.{protobuf => proto} import com.ing.baker.runtime.scaladsl.RecipeInstanceMetadata +import com.ing.baker.runtime.serialization.ProtoMap import scala.util.Try diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RuntimeEventMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/RuntimeEventMapping.scala similarity index 76% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RuntimeEventMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/RuntimeEventMapping.scala index 810e4a9e6..f71e6a0b1 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/RuntimeEventMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/RuntimeEventMapping.scala @@ -1,12 +1,10 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings -import cats.instances.list._ -import cats.instances.try_._ -import cats.syntax.traverse._ +import cats.implicits._ import com.ing.baker.runtime.akka.actor.protobuf -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} import com.ing.baker.runtime.scaladsl.EventInstance +import com.ing.baker.runtime.serialization.ProtoMap import com.ing.baker.types.Value import scala.util.Try diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/SensoryEventResultMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/SensoryEventResultMapping.scala similarity index 78% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/SensoryEventResultMapping.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/SensoryEventResultMapping.scala index db2764b77..f5a400799 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/SensoryEventResultMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/SensoryEventResultMapping.scala @@ -1,12 +1,10 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings -import cats.instances.list._ -import cats.instances.try_._ -import cats.syntax.traverse._ +import cats.implicits._ import com.ing.baker.runtime.akka.actor.protobuf -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} import com.ing.baker.runtime.scaladsl.SensoryEventResult +import com.ing.baker.runtime.serialization.ProtoMap import com.ing.baker.types.Value import scalapb.GeneratedMessageCompanion diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/SensoryEventStatusMappingHelper.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/SensoryEventStatusMappingHelper.scala similarity index 96% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/SensoryEventStatusMappingHelper.scala rename to baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/SensoryEventStatusMappingHelper.scala index 3186e24d2..8d145df13 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/protomappings/SensoryEventStatusMappingHelper.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/SensoryEventStatusMappingHelper.scala @@ -1,4 +1,4 @@ -package com.ing.baker.runtime.akka.actor.serialization.protomappings +package com.ing.baker.runtime.serialization.protomappings import com.ing.baker.runtime.akka.actor.protobuf import com.ing.baker.runtime.common.SensoryEventStatus From e26bab2f2441640cbbe5c83012c3b0071ac51485 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Wed, 23 Oct 2019 16:38:11 +0200 Subject: [PATCH 30/86] WIP baas project separation --- .../ing/baker/baas/javadsl/BakerClient.scala | 11 +-- .../ing/baker/baas/scaladsl/BakerClient.scala | 12 ++-- .../com/ing/baker/baas/common/BaaSProto.scala | 11 +-- .../ing/baker/baas/common/BaaSProtocol.scala | 4 +- .../baker/baas/common/MarshallingUtils.scala | 8 +-- .../com/ing/baker/baas/state/BaaSServer.scala | 14 ++-- .../baas/CommonBaaSServerClientSpec.scala | 14 ++-- .../baas/JavaDSLBaaSServerClientSpec.scala | 13 ++-- .../baas/ScalaDSLBaaSServerClientSpec.scala | 8 +-- .../baas/recipe/CheckoutFlowRecipe.scala | 10 +-- .../baas/recipe/MakePaymentInstance.scala | 8 +-- .../baas/recipe/ReserveItemsInstance.scala | 8 +-- .../baker/baas/recipe/ShipItemsInstance.scala | 8 +-- build.sbt | 71 ++++++++++++++++--- .../baker/runtime/akka/AkkaBakerConfig.scala | 4 +- .../actor/ClusterBakerActorProvider.scala | 3 +- .../akka/actor/LocalBakerActorProvider.scala | 7 +- .../InteractionSchedulingProto.scala | 5 +- .../actor/process_index/ProcessIndex.scala | 30 ++++---- .../process_index/ProcessIndexProto.scala | 7 +- .../process_instance/ProcessInstance.scala | 2 +- .../ProcessInstanceEventSourcing.scala | 2 +- .../ProcessInstanceProto.scala | 4 +- .../ProcessInstanceSerialization.scala | 4 +- .../recipe_manager/RecipeManagerProto.scala | 4 +- .../BakerTypedProtobufSerializer.scala | 1 + .../process_index/ProcessIndexSpec.scala | 2 +- .../serialization/SerializationSpec.scala | 3 +- 28 files changed, 164 insertions(+), 114 deletions(-) diff --git a/baas-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala b/baas-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala index 6435bdb1c..213a3ebef 100644 --- a/baas-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala +++ b/baas-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala @@ -3,11 +3,12 @@ package com.ing.baker.baas.javadsl import akka.actor.ActorSystem import akka.stream.Materializer import com.ing.baker.runtime.akka.actor.serialization.Encryption -import com.ing.baker.baas.scaladsl.{ Baker => ScalaRemoteBaker } -import com.ing.baker.runtime.javadsl.{ Baker => JavaBaker } +import com.ing.baker.baas.scaladsl.{BakerClient => ScalaRemoteBaker} +import com.ing.baker.runtime.akka.AkkaBaker +import com.ing.baker.runtime.javadsl.{Baker => JavaBaker} -object Baker { +object BakerClient { - def remote(hostname: String, actorSystem: ActorSystem, mat: Materializer, encryption: Encryption = Encryption.NoEncryption): JavaBaker = - new JavaBaker(ScalaRemoteBaker.remote(hostname, encryption)(actorSystem, mat)) + def build(hostname: String, actorSystem: ActorSystem, mat: Materializer, encryption: Encryption = Encryption.NoEncryption): JavaBaker = + AkkaBaker.javaOther(ScalaRemoteBaker.build(hostname, encryption)(actorSystem, mat)) } diff --git a/baas-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala b/baas-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala index f931a267b..b44917f14 100644 --- a/baas-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala +++ b/baas-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala @@ -8,8 +8,8 @@ import akka.http.scaladsl.model.{HttpMethods, HttpRequest, MessageEntity, Uri} import akka.stream.Materializer import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} import com.ing.baker.runtime.akka.actor.serialization.{Encryption, SerializersProvider} -import com.ing.baker.runtime.baas.BaaSProto._ -import com.ing.baker.runtime.baas.BaaSProtocol +import com.ing.baker.baas.common.BaaSProto._ +import com.ing.baker.baas.common.BaaSProtocol import com.ing.baker.runtime.baas.MarshallingUtils._ import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.scaladsl.{BakerEvent, EventInstance, EventMoment, EventResolutions, InteractionInstance, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult, Baker => ScalaBaker} @@ -17,13 +17,13 @@ import com.ing.baker.types.Value import scala.concurrent.Future -object Baker { +object BakerClient { - def remote(hostname: String, encryption: Encryption = Encryption.NoEncryption)(implicit system: ActorSystem, mat: Materializer) = - Baker(Uri(hostname), encryption) + def build(hostname: String, encryption: Encryption = Encryption.NoEncryption)(implicit system: ActorSystem, mat: Materializer) = + BakerClient(Uri(hostname), encryption) } -case class Baker(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(implicit system: ActorSystem, mat: Materializer) extends ScalaBaker { +case class BakerClient(hostname: Uri, encryption: Encryption = Encryption.NoEncryption)(implicit system: ActorSystem, mat: Materializer) extends ScalaBaker { import system.dispatcher diff --git a/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala b/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala index 1143e7f94..8c3a2d142 100644 --- a/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala +++ b/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala @@ -1,11 +1,6 @@ -package com.ing.baker.runtime.baas - -import cats.implicits._ -import BaaSProtocol._ -import com.ing.baker.runtime.akka.actor.serialization.protomappings.SensoryEventStatusMappingHelper -import com.ing.baker.runtime.akka.actor.serialization.{ProtoMap, SerializersProvider} -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} -import scalapb.GeneratedMessageCompanion +package com.ing.baker.baas.common + +import com.ing.baker.baas.common.BaaSProtocol._ import scala.util.Try diff --git a/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProtocol.scala b/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProtocol.scala index b6b927ba6..a2a70d4a2 100644 --- a/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProtocol.scala +++ b/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProtocol.scala @@ -1,8 +1,8 @@ -package com.ing.baker.runtime.baas +package com.ing.baker.baas.common import com.ing.baker.il.CompiledRecipe import com.ing.baker.runtime.common.{BakerException, SensoryEventStatus} -import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult} +import com.ing.baker.runtime.scaladsl._ object BaaSProtocol { diff --git a/baas-common/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala b/baas-common/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala index f3b7d840a..423288de7 100644 --- a/baas-common/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala +++ b/baas-common/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala @@ -1,14 +1,12 @@ -package com.ing.baker.runtime.baas +package com.ing.baker.baas.common import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller} import akka.http.scaladsl.model.{ContentTypes, HttpResponse, MediaTypes, StatusCodes} -import akka.http.scaladsl.server.{Route, StandardRoute} import akka.http.scaladsl.server.Directives.{complete, onSuccess} +import akka.http.scaladsl.server.Route import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshal, Unmarshaller} -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap -import com.ing.baker.runtime.common.BakerException -import BaaSProto._ import akka.stream.Materializer +import com.ing.baker.runtime.common.BakerException import scala.concurrent.{ExecutionContext, Future} diff --git a/baas-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala b/baas-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala index 4293ba15f..870f1bfa7 100644 --- a/baas-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala +++ b/baas-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala @@ -1,17 +1,15 @@ -package com.ing.baker.runtime.baas +package com.ing.baker.baas.state import akka.actor.ActorSystem import akka.http.scaladsl.Http -import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.server.Directives._ -import akka.http.scaladsl.server.{RequestContext, Route} +import akka.http.scaladsl.server.Route import akka.stream.Materializer -import com.ing.baker.runtime.akka.actor.serialization.{Encryption, SerializersProvider} -import com.ing.baker.runtime.baas.BaaSProto._ -import com.ing.baker.runtime.baas.BaaSProtocol.BaaSRemoteFailure -import com.ing.baker.runtime.baas.MarshallingUtils._ -import com.ing.baker.runtime.common.BakerException +import com.ing.baker.baas.common.BaaSProtocol +import com.ing.baker.baas.common.MarshallingUtils._ +import com.ing.baker.runtime.akka.actor.serialization.SerializersProvider import com.ing.baker.runtime.scaladsl.Baker +import com.ing.baker.runtime.serialization.{Encryption, SerializersProvider} import scala.concurrent.Future diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/CommonBaaSServerClientSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/CommonBaaSServerClientSpec.scala index 3218d45c6..5b4a88251 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/CommonBaaSServerClientSpec.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/CommonBaaSServerClientSpec.scala @@ -1,23 +1,23 @@ -package com.ing.baker.runtime.baas.common +package com.ing.baker.baas import java.util.UUID import akka.actor.ActorSystem import akka.stream.{ActorMaterializer, Materializer} import cats.effect.{IO, Timer} +import com.ing.baker.baas.CommonBaaSServerClientSpec._ +import com.ing.baker.baas.recipe.CheckoutFlowEvents.ItemsReserved +import com.ing.baker.baas.recipe.CheckoutFlowIngredients.{Item, OrderId, ReservedItems, ShippingAddress} +import com.ing.baker.baas.recipe._ +import com.ing.baker.baas.state.BaaSServer import com.ing.baker.compiler.RecipeCompiler import com.ing.baker.il.CompiledRecipe import com.ing.baker.recipe.scaladsl.Recipe import com.ing.baker.runtime.akka.AkkaBaker -import com.ing.baker.runtime.baas.BaaSServer -import com.ing.baker.runtime.baas.common.CheckoutFlowEvents.ItemsReserved -import com.ing.baker.runtime.baas.common.CheckoutFlowIngredients.{Item, OrderId, ReservedItems, ShippingAddress} -import com.ing.baker.runtime.baas.common.CommonBaaSServerClientSpec.{ClientServerTest, setupFailingOnceReserveItems, setupFailingWithRetryReserveItems, setupHappyPath} import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi import com.ing.baker.runtime.common.{BakerException, SensoryEventStatus} import com.ing.baker.runtime.scaladsl.{EventInstance, InteractionInstance, Baker => ScalaBaker} -import org.scalatest.compatible.Assertion -import org.scalatest.{AsyncFunSpec, BeforeAndAfterAll, BeforeAndAfterEach, Matchers} +import org.scalatest._ import scala.concurrent.{ExecutionContext, Future} diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/JavaDSLBaaSServerClientSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/JavaDSLBaaSServerClientSpec.scala index 376500ae4..d31651ec3 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/JavaDSLBaaSServerClientSpec.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/JavaDSLBaaSServerClientSpec.scala @@ -1,13 +1,10 @@ -package com.ing.baker.baas.scaladsl +package com.ing.baker.baas import java.util.Optional +import com.ing.baker.baas.JavaDSLBaaSServerClientSpec.optionToJava import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} -import com.ing.baker.runtime.baas.common.CommonBaaSServerClientSpec -import com.ing.baker.baas.javadsl -import com.ing.baker.baas.scaladsl.JavaDSLBaaSServerClientSpec.optionToJava import com.ing.baker.runtime.common.SensoryEventStatus -import com.ing.baker.runtime.scaladsl import com.ing.baker.runtime.scaladsl._ import com.ing.baker.types.Value @@ -18,8 +15,8 @@ import scala.concurrent.Future class JavaDSLBaaSServerClientSpec extends CommonBaaSServerClientSpec( (host, as, mat) => { import as.dispatcher - val javaBaker = javadsl.Baker.remote(host, as, mat) - new scaladsl.Baker { + val javaBaker = javadsl.BakerClient.build(host, as, mat) + new com.ing.baker.runtime.scaladsl.Baker { override def addRecipe(compiledRecipe: CompiledRecipe): Future[String] = FutureConverters.toScala(javaBaker.addRecipe(compiledRecipe)) .recoverWith { @@ -57,7 +54,7 @@ class JavaDSLBaaSServerClientSpec extends CommonBaaSServerClientSpec( } override def fireEvent(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): EventResolutions = { val res = javaBaker.fireEvent(recipeInstanceId, event.asJava, optionToJava(correlationId)) - scaladsl.EventResolutions( + com.ing.baker.runtime.scaladsl.EventResolutions( FutureConverters.toScala(res.resolveWhenReceived) .recoverWith { case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/ScalaDSLBaaSServerClientSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/ScalaDSLBaaSServerClientSpec.scala index 455fe8bae..6c99a7d3c 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/ScalaDSLBaaSServerClientSpec.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/ScalaDSLBaaSServerClientSpec.scala @@ -1,9 +1,9 @@ -package com.ing.baker.baas.scaladsl +package com.ing.baker.baas -import com.ing.baker.runtime.akka.actor.serialization.Encryption -import com.ing.baker.runtime.baas.common.CommonBaaSServerClientSpec +import com.ing.baker.baas.scaladsl.BakerClient +import com.ing.baker.runtime.serialization.Encryption class ScalaDSLBaaSServerClientSpec extends CommonBaaSServerClientSpec( - (host, as, mat) => Baker.remote(host, Encryption.NoEncryption)(as, mat) + (host, as, mat) => BakerClient.build(host, Encryption.NoEncryption)(as, mat) ) diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/CheckoutFlowRecipe.scala b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/CheckoutFlowRecipe.scala index 308007985..e3fe5e117 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/CheckoutFlowRecipe.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/CheckoutFlowRecipe.scala @@ -1,11 +1,11 @@ -package com.ing.baker.runtime.baas.common +package com.ing.baker.baas.recipe -import com.ing.baker.recipe.common.InteractionFailureStrategy.{BlockInteraction, RetryWithIncrementalBackoff} +import com.ing.baker.baas.recipe.CheckoutFlowEvents._ +import com.ing.baker.baas.recipe.CheckoutFlowIngredients._ +import com.ing.baker.baas.recipe.CheckoutFlowInteractions._ import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff.UntilDeadline +import com.ing.baker.recipe.common.InteractionFailureStrategy.{BlockInteraction, RetryWithIncrementalBackoff} import com.ing.baker.recipe.scaladsl.{Event, Ingredient, Interaction, Recipe} -import CheckoutFlowIngredients._ -import CheckoutFlowEvents._ -import CheckoutFlowInteractions._ import scala.concurrent.Future import scala.concurrent.duration._ diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/MakePaymentInstance.scala b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/MakePaymentInstance.scala index 307c1cb19..805174db1 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/MakePaymentInstance.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/MakePaymentInstance.scala @@ -1,9 +1,9 @@ -package com.ing.baker.runtime.baas.common +package com.ing.baker.baas.recipe import cats.effect.{IO, Timer} -import com.ing.baker.runtime.baas.common.CheckoutFlowEvents.MakePaymentOutput -import com.ing.baker.runtime.baas.common.CheckoutFlowIngredients.{PaymentInformation, ReservedItems, ShippingAddress, ShippingOrder} -import com.ing.baker.runtime.baas.common.CheckoutFlowInteractions.MakePayment +import com.ing.baker.baas.recipe.CheckoutFlowEvents.MakePaymentOutput +import com.ing.baker.baas.recipe.CheckoutFlowIngredients.{PaymentInformation, ReservedItems, ShippingAddress, ShippingOrder} +import com.ing.baker.baas.recipe.CheckoutFlowInteractions.MakePayment import scala.concurrent.Future import scala.concurrent.duration._ diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ReserveItemsInstance.scala b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ReserveItemsInstance.scala index 80299e308..1bc2d123e 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ReserveItemsInstance.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ReserveItemsInstance.scala @@ -1,10 +1,10 @@ -package com.ing.baker.runtime.baas.common +package com.ing.baker.baas.recipe import cats.effect.{IO, Timer} import cats.implicits._ -import com.ing.baker.runtime.baas.common.CheckoutFlowEvents.ReserveItemsOutput -import com.ing.baker.runtime.baas.common.CheckoutFlowIngredients.{Item, OrderId, ReservedItems} -import com.ing.baker.runtime.baas.common.CheckoutFlowInteractions.ReserveItems +import com.ing.baker.baas.recipe.CheckoutFlowEvents.ReserveItemsOutput +import com.ing.baker.baas.recipe.CheckoutFlowIngredients.{Item, OrderId, ReservedItems} +import com.ing.baker.baas.recipe.CheckoutFlowInteractions.ReserveItems import scala.concurrent.Future import scala.concurrent.duration._ diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ShipItemsInstance.scala b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ShipItemsInstance.scala index 7eece69a3..afa5a5e47 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ShipItemsInstance.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ShipItemsInstance.scala @@ -1,10 +1,10 @@ -package com.ing.baker.runtime.baas.common +package com.ing.baker.baas.recipe import cats.effect.{IO, Timer} import cats.implicits._ -import com.ing.baker.runtime.baas.common.CheckoutFlowEvents.ShippingConfirmed -import com.ing.baker.runtime.baas.common.CheckoutFlowIngredients.ShippingOrder -import com.ing.baker.runtime.baas.common.CheckoutFlowInteractions.ShipItems +import com.ing.baker.baas.recipe.CheckoutFlowEvents.ShippingConfirmed +import com.ing.baker.baas.recipe.CheckoutFlowIngredients.ShippingOrder +import com.ing.baker.baas.recipe.CheckoutFlowInteractions.ShipItems import scala.concurrent.Future import scala.concurrent.duration._ diff --git a/build.sbt b/build.sbt index 665c07111..2e834df56 100644 --- a/build.sbt +++ b/build.sbt @@ -79,9 +79,12 @@ lazy val intermediateLanguage = project.in(file("intermediate-language")) lazy val interface = project.in(file("baker-interface")) .settings(defaultModuleSettings) .settings(noPublishSettings) + .settings(scalaPBSettings) .settings( moduleName := "baker-interface", libraryDependencies ++= Seq( + akkaActor, + catsCore, scalaJava8Compat ) ++ providedDeps(findbugs) ) @@ -193,20 +196,67 @@ lazy val recipeCompiler = project.in(file("compiler")) ) .dependsOn(recipeDsl, intermediateLanguage, testScope(recipeDsl)) -lazy val baas = project.in(file("baas")) +lazy val `baas-common` = project.in(file("baas-common")) .settings(defaultModuleSettings) + .settings(noPublishSettings) .settings(scalaPBSettings) .settings( - moduleName := "baker-baas", - libraryDependencies ++= - compileDeps( - akkaHttp, - akkaPersistenceCassandra) ++ + moduleName := "baas-common", + libraryDependencies ++= Seq( + akkaHttp + ) + ) + .dependsOn(interface) + +lazy val `baas-client` = project.in(file("baas-client")) + .settings(defaultModuleSettings) + .settings( + moduleName := "baas-client", + libraryDependencies ++= Seq( + akkaHttp + ) + ) + .dependsOn(interface, `baas-common`) + +lazy val `baas-state` = project.in(file("baas-state")) + .settings(defaultModuleSettings) + .settings( + moduleName := "baas-state", + libraryDependencies ++= Seq( + akkaHttp, + akkaPersistenceCassandra + ) + ) + .dependsOn(runtime, `baas-common`, `baas-remote-interaction`) + +lazy val `baas-remote-interaction` = project.in(file("baas-remote-interaction")) + .settings(defaultModuleSettings) + .settings( + moduleName := "baas-remote-interaction", + libraryDependencies ++= Seq( + akkaCluster + ) + ) + +lazy val `baas-remote-event-listener` = project.in(file("baas-remote-event-listener")) + .settings(defaultModuleSettings) + .settings( + moduleName := "baas-remote-event-listener", + libraryDependencies ++= Seq( + akkaCluster + ) + ) + +lazy val `baas-tests` = project.in(file("baas-tests")) + .settings(defaultModuleSettings) + .settings(noPublishSettings) + .settings( + moduleName := "baas-tests", + libraryDependencies ++= Seq() ++ testDeps( akkaSlf4j, akkaTestKit, logback, - mockito, scalaTest, junitInterface, levelDB, @@ -214,13 +264,16 @@ lazy val baas = project.in(file("baas")) scalaCheck ) ) - .dependsOn(recipeDsl, recipeCompiler, intermediateLanguage, runtime, testScope(runtime)) + .dependsOn(`baas-client`, `baas-state`, `baas-remote-interaction`) + +//lazy val baas = project + lazy val baker = project .in(file(".")) .settings(defaultModuleSettings) .settings(noPublishSettings) - .aggregate(bakertypes, runtime, recipeCompiler, recipeDsl, intermediateLanguage, splitBrainResolver, baas) + .aggregate(bakertypes, runtime, recipeCompiler, recipeDsl, intermediateLanguage, splitBrainResolver) lazy val integration = project.in(file("integration")) .dependsOn(testScope(runtime)) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala index f1e56111a..a9721b106 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala @@ -5,9 +5,9 @@ import akka.persistence.query.PersistenceQuery import akka.persistence.query.scaladsl.{CurrentEventsByPersistenceIdQuery, CurrentPersistenceIdsQuery, PersistenceIdsQuery} import cats.data.NonEmptyList import com.ing.baker.runtime.akka.AkkaBakerConfig.BakerPersistenceQuery -import com.ing.baker.runtime.akka.actor.serialization.Encryption -import com.ing.baker.runtime.akka.actor.{ BakerActorProvider, ClusterBakerActorProvider, LocalBakerActorProvider } +import com.ing.baker.runtime.akka.actor.{BakerActorProvider, ClusterBakerActorProvider, LocalBakerActorProvider} import com.ing.baker.runtime.akka.internal.{InteractionManager, InteractionManagerDis, InteractionManagerLocal} +import com.ing.baker.runtime.serialization.Encryption import com.typesafe.config.Config import net.ceedubs.ficus.Ficus._ diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/ClusterBakerActorProvider.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/ClusterBakerActorProvider.scala index 84dad5fcb..1ed002e7e 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/ClusterBakerActorProvider.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/ClusterBakerActorProvider.scala @@ -15,8 +15,9 @@ import com.ing.baker.runtime.akka.actor.process_index.ProcessIndex.ActorMetadata import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProtocol._ import com.ing.baker.runtime.akka.actor.process_index._ import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManager -import com.ing.baker.runtime.akka.actor.serialization.{BakerSerializable, Encryption} +import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable import com.ing.baker.runtime.akka.internal.InteractionManager +import com.ing.baker.runtime.serialization.Encryption import org.slf4j.LoggerFactory import scala.concurrent.duration._ diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/LocalBakerActorProvider.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/LocalBakerActorProvider.scala index 9e6967fcd..04c446f52 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/LocalBakerActorProvider.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/LocalBakerActorProvider.scala @@ -1,12 +1,13 @@ package com.ing.baker.runtime.akka.actor -import akka.actor.{ ActorRef, ActorSystem } +import akka.actor.{ActorRef, ActorSystem} import com.ing.baker.runtime.akka.actor.process_index.ProcessIndex import com.ing.baker.runtime.akka.actor.process_index.ProcessIndex.ActorMetadata -import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProtocol.{ GetIndex, Index } +import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProtocol.{GetIndex, Index} import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManager -import com.ing.baker.runtime.akka.actor.serialization.Encryption import com.ing.baker.runtime.akka.internal.InteractionManager +import com.ing.baker.runtime.serialization.Encryption + import scala.concurrent.Await import scala.concurrent.duration._ diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala index 816316b80..d18ae6cfd 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala @@ -6,8 +6,9 @@ import cats.implicits._ import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolInteractionExecution.{ExecuteInstance, InstanceExecutedSuccessfully, InstanceExecutionFailed, InstanceExecutionTimedOut, InvalidExecution, NoInstanceFound} import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolPushPullMatching.{AvailableQuest, Pull, Push} import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolQuestCommit.{Commit, Considering, QuestTaken} -import com.ing.baker.runtime.akka.actor.serialization.{ProtoMap, SerializersProvider} -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.runtime.akka.actor.serialization.SerializersProvider +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} import scala.util.{Success, Try} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndex.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndex.scala index 2f47a9b15..629b0da64 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndex.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndex.scala @@ -1,31 +1,33 @@ package com.ing.baker.runtime.akka.actor.process_index -import akka.actor.{ ActorRef, NoSerializationVerificationNeeded, Props, Terminated } -import akka.event.{ DiagnosticLoggingAdapter, Logging } +import akka.actor.{ActorRef, NoSerializationVerificationNeeded, Props, Terminated} +import akka.event.{DiagnosticLoggingAdapter, Logging} import akka.pattern.ask -import akka.persistence.{ PersistentActor, RecoveryCompleted } -import cats.data.{ EitherT, OptionT } +import akka.persistence.{PersistentActor, RecoveryCompleted} +import cats.data.{EitherT, OptionT} import cats.effect.IO import cats.instances.future._ -import com.ing.baker.il.petrinet.{ InteractionTransition, Place, Transition } -import com.ing.baker.il.{ CompiledRecipe, EventDescriptor } +import com.ing.baker.il.petrinet.{InteractionTransition, Place, Transition} +import com.ing.baker.il.{CompiledRecipe, EventDescriptor} import com.ing.baker.petrinet.api._ import com.ing.baker.runtime.akka.actor.Util.logging._ import com.ing.baker.runtime.akka.actor.process_index.ProcessIndex._ import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProtocol._ -import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol.ExceptionStrategy.{ BlockTransition, Continue, RetryWithDelay } +import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol.ExceptionStrategy.{BlockTransition, Continue, RetryWithDelay} import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol._ -import com.ing.baker.runtime.akka.actor.process_instance.{ ProcessInstance, ProcessInstanceRuntime } +import com.ing.baker.runtime.akka.actor.process_instance.{ProcessInstance, ProcessInstanceRuntime} import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProtocol._ -import com.ing.baker.runtime.akka.actor.serialization.{ BakerSerializable, Encryption } -import com.ing.baker.runtime.akka.internal.{ InteractionManager, RecipeRuntime } -import com.ing.baker.runtime.akka.{ namedCachedThreadPool, _ } -import com.ing.baker.runtime.scaladsl.{ EventInstance, RecipeInstanceCreated, RecipeInstanceState } +import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable +import com.ing.baker.runtime.akka.internal.{InteractionManager, RecipeRuntime} +import com.ing.baker.runtime.akka.{namedCachedThreadPool, _} +import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeInstanceCreated, RecipeInstanceState} +import com.ing.baker.runtime.serialization.Encryption import com.ing.baker.types.Value + import scala.collection.mutable import scala.concurrent.duration._ -import scala.concurrent.{ Await, ExecutionContext, Future } -import scala.util.{ Failure, Success } +import scala.concurrent.{Await, ExecutionContext, Future} +import scala.util.{Failure, Success} object ProcessIndex { diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexProto.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexProto.scala index f2595d70c..934e37e96 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexProto.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexProto.scala @@ -9,9 +9,10 @@ import com.ing.baker.runtime.akka.actor.ClusterBakerActorProvider.GetShardIndex import com.ing.baker.runtime.akka.actor.process_index.ProcessIndex._ import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProtocol.FireSensoryEventReaction.{NotifyBoth, NotifyOnEvent, NotifyWhenCompleted, NotifyWhenReceived} import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProtocol.{ProcessEventReceivedResponse, _} -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} -import com.ing.baker.runtime.akka.actor.serialization.protomappings.SensoryEventStatusMappingHelper -import com.ing.baker.runtime.akka.actor.serialization.{ProtoMap, SerializersProvider} +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.runtime.serialization.protomappings.SensoryEventStatusMappingHelper +import com.ing.baker.runtime.akka.actor.serialization.SerializersProvider +import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} import scala.concurrent.duration.FiniteDuration import scala.util.{Failure, Success, Try} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstance.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstance.scala index d4fe81db4..17d7d217f 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstance.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstance.scala @@ -15,8 +15,8 @@ import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol import com.ing.baker.runtime.akka.actor.process_instance.internal.ExceptionStrategy.{Continue, RetryWithDelay} import com.ing.baker.runtime.akka.actor.process_instance.internal._ import com.ing.baker.runtime.akka.actor.process_instance.{ProcessInstanceProtocol => protocol} -import com.ing.baker.runtime.akka.actor.serialization.Encryption import com.ing.baker.runtime.scaladsl.RecipeInstanceState +import com.ing.baker.runtime.serialization.Encryption import com.ing.baker.types.PrimitiveValue import scala.concurrent.ExecutionContext diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala index eed684aa6..77500e0b2 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala @@ -8,8 +8,8 @@ import akka.NotUsed import akka.actor.{ActorSystem, NoSerializationVerificationNeeded} import akka.persistence.query.scaladsl.CurrentEventsByPersistenceIdQuery import akka.stream.scaladsl.Source -import com.ing.baker.runtime.akka.actor.serialization.Encryption import com.ing.baker.runtime.akka.actor.serialization.SerializersProvider +import com.ing.baker.runtime.serialization.Encryption object ProcessInstanceEventSourcing { diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProto.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProto.scala index e9c7700ec..65bfe187e 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProto.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProto.scala @@ -7,9 +7,9 @@ import cats.syntax.traverse._ import com.ing.baker.petrinet.api.{Id, Marking, MultiSet} import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol._ import com.ing.baker.runtime.akka.actor.process_instance.protobuf.FailureStrategyMessage.StrategyTypeMessage -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} import com.ing.baker.runtime.akka.actor.serialization.SerializersProvider +import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} import scalapb.GeneratedMessageCompanion import scala.util.{Failure, Success, Try} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceSerialization.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceSerialization.scala index 07c9f664c..538c6731c 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceSerialization.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceSerialization.scala @@ -10,8 +10,8 @@ import com.ing.baker.runtime.akka.actor.process_instance.internal.Instance import com.ing.baker.runtime.akka.actor.process_instance.protobuf.FailureStrategy.StrategyType import com.ing.baker.runtime.akka.actor.process_instance.protobuf._ import com.ing.baker.runtime.akka.actor.protobuf.{ProducedToken, SerializedData} -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto} -import com.ing.baker.runtime.akka.actor.serialization.SerializersProvider +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto} +import com.ing.baker.runtime.serialization.SerializersProvider import scala.util.{Failure, Success} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProto.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProto.scala index 8ae106721..f8e85eb5a 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProto.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProto.scala @@ -5,9 +5,9 @@ import cats.instances.try_._ import cats.syntax.traverse._ import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManager.RecipeAdded import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProtocol._ -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{versioned, ctxFromProto, ctxToProto} +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} import com.ing.baker.runtime.akka.actor.serialization.SerializersProvider +import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} import scala.util.Try diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala index d740c2f2c..e35db3316 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala @@ -12,6 +12,7 @@ import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProto._ import com.ing.baker.runtime.akka.actor.recipe_manager.{RecipeManager, RecipeManagerProtocol} import com.ing.baker.runtime.akka.actor.serialization.BakerTypedProtobufSerializer.BinarySerializable +import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} import com.ing.baker.{il, runtime} import org.slf4j.LoggerFactory diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexSpec.scala index 40377019a..c8c63eb54 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexSpec.scala @@ -14,9 +14,9 @@ import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol._ import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProtocol import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProtocol.{AllRecipes, GetAllRecipes, RecipeInformation} -import com.ing.baker.runtime.akka.actor.serialization.Encryption import com.ing.baker.runtime.akka.internal.InteractionManagerLocal import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeInstanceState} +import com.ing.baker.runtime.serialization.Encryption import com.ing.baker.types import com.ing.baker.types.Value import com.typesafe.config.{Config, ConfigFactory} diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala index 3e6d325fb..720456003 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala @@ -18,9 +18,10 @@ import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProto._ import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProtocol.GetRecipe import com.ing.baker.runtime.akka.actor.recipe_manager.{RecipeManager, RecipeManagerProtocol} import com.ing.baker.runtime.akka.actor.serialization.Encryption.{AESEncryption, NoEncryption} -import com.ing.baker.runtime.akka.actor.serialization.ProtoMap.{ctxFromProto, ctxToProto} +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto} import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.scaladsl.{EventInstance, EventMoment, RecipeInstanceState, SensoryEventResult} +import com.ing.baker.runtime.serialization.ProtoMap import com.ing.baker.types.modules.PrimitiveModuleSpec._ import com.ing.baker.types.{Value, _} import com.ing.baker.{AllTypeRecipe, types} From 1cfd6fe14029efb0733fd2e7974135aad271f4c9 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Wed, 23 Oct 2019 17:53:20 +0200 Subject: [PATCH 31/86] finished baas project separation --- .../ing/baker/baas/javadsl/BakerClient.scala | 5 ++- .../ing/baker/baas/scaladsl/BakerClient.scala | 4 +-- .../com/ing/baker/baas/common/BaaSProto.scala | 6 ++++ .../baker/baas/common/MarshallingUtils.scala | 2 ++ .../com/ing/baker/baas/state/BaaSServer.scala | 2 +- .../com/ing/baker/runtime/javadsl/Baker.scala | 2 +- .../serialization/TokenIdentifier.scala | 23 +++++++++++++ .../protomappings/CompiledRecipeMapping.scala | 4 +-- build.sbt | 17 ++++------ .../InteractionSchedulingProto.scala | 3 +- .../process_index/ProcessIndexProto.scala | 2 +- .../ProcessInstanceEventSourcing.scala | 2 +- .../ProcessInstanceProto.scala | 2 +- .../ProcessInstanceSerialization.scala | 33 +++---------------- .../recipe_manager/RecipeManagerProto.scala | 2 +- .../ProcessInstanceEventSourcingSpec.scala | 6 ++-- .../ProcessInstanceSpec.scala | 2 +- .../EncryptionPropertiesSpec.scala | 2 +- .../serialization/SerializationSpec.scala | 2 +- 19 files changed, 63 insertions(+), 58 deletions(-) create mode 100644 baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TokenIdentifier.scala diff --git a/baas-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala b/baas-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala index 213a3ebef..eab67fe02 100644 --- a/baas-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala +++ b/baas-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala @@ -2,13 +2,12 @@ package com.ing.baker.baas.javadsl import akka.actor.ActorSystem import akka.stream.Materializer -import com.ing.baker.runtime.akka.actor.serialization.Encryption import com.ing.baker.baas.scaladsl.{BakerClient => ScalaRemoteBaker} -import com.ing.baker.runtime.akka.AkkaBaker import com.ing.baker.runtime.javadsl.{Baker => JavaBaker} +import com.ing.baker.runtime.serialization.Encryption object BakerClient { def build(hostname: String, actorSystem: ActorSystem, mat: Materializer, encryption: Encryption = Encryption.NoEncryption): JavaBaker = - AkkaBaker.javaOther(ScalaRemoteBaker.build(hostname, encryption)(actorSystem, mat)) + new JavaBaker(ScalaRemoteBaker.build(hostname, encryption)(actorSystem, mat)) } diff --git a/baas-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala b/baas-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala index b44917f14..4ad11dbb3 100644 --- a/baas-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala +++ b/baas-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala @@ -7,12 +7,12 @@ import akka.http.scaladsl.model.Uri.Path import akka.http.scaladsl.model.{HttpMethods, HttpRequest, MessageEntity, Uri} import akka.stream.Materializer import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} -import com.ing.baker.runtime.akka.actor.serialization.{Encryption, SerializersProvider} import com.ing.baker.baas.common.BaaSProto._ import com.ing.baker.baas.common.BaaSProtocol -import com.ing.baker.runtime.baas.MarshallingUtils._ +import com.ing.baker.baas.common.MarshallingUtils._ import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.scaladsl.{BakerEvent, EventInstance, EventMoment, EventResolutions, InteractionInstance, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult, Baker => ScalaBaker} +import com.ing.baker.runtime.serialization.{Encryption, SerializersProvider} import com.ing.baker.types.Value import scala.concurrent.Future diff --git a/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala b/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala index 8c3a2d142..267488613 100644 --- a/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala +++ b/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala @@ -1,6 +1,12 @@ package com.ing.baker.baas.common +import cats.implicits._ import com.ing.baker.baas.common.BaaSProtocol._ +import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} +import scalapb.GeneratedMessageCompanion +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.runtime.baas.protobuf +import com.ing.baker.runtime.serialization.protomappings.SensoryEventStatusMappingHelper import scala.util.Try diff --git a/baas-common/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala b/baas-common/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala index 423288de7..1cbf4ba8d 100644 --- a/baas-common/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala +++ b/baas-common/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala @@ -7,6 +7,8 @@ import akka.http.scaladsl.server.Route import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshal, Unmarshaller} import akka.stream.Materializer import com.ing.baker.runtime.common.BakerException +import com.ing.baker.runtime.serialization.ProtoMap +import BaaSProto._ import scala.concurrent.{ExecutionContext, Future} diff --git a/baas-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala b/baas-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala index 870f1bfa7..db13d8cfc 100644 --- a/baas-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala +++ b/baas-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala @@ -5,9 +5,9 @@ import akka.http.scaladsl.Http import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import akka.stream.Materializer +import com.ing.baker.baas.common.BaaSProto._ import com.ing.baker.baas.common.BaaSProtocol import com.ing.baker.baas.common.MarshallingUtils._ -import com.ing.baker.runtime.akka.actor.serialization.SerializersProvider import com.ing.baker.runtime.scaladsl.Baker import com.ing.baker.runtime.serialization.{Encryption, SerializersProvider} diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala index 8bcc0a5a8..e4c690701 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala @@ -16,7 +16,7 @@ import scala.collection.JavaConverters._ import scala.compat.java8.FutureConverters import scala.concurrent.Future -class Baker private[runtime](private val baker: scaladsl.Baker) extends common.Baker[CompletableFuture] with JavaApi { +class Baker private[baker](private val baker: scaladsl.Baker) extends common.Baker[CompletableFuture] with JavaApi { override type SensoryEventResultType = SensoryEventResult diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TokenIdentifier.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TokenIdentifier.scala new file mode 100644 index 000000000..f8e4c9674 --- /dev/null +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TokenIdentifier.scala @@ -0,0 +1,23 @@ +package com.ing.baker.runtime.serialization + +import java.security.MessageDigest + +object TokenIdentifier { + + /** + * TODO: + * + * This approach is fragile, the identifier function cannot change ever or recovery breaks + * a more robust alternative is to generate the ids and persist them + */ + def apply(tokenValue: Any): Long = tokenValue match { + case null => -1 + case str: String => sha256(str) + case obj => obj.hashCode() + } + + def sha256(str: String) = { + val sha256Digest: MessageDigest = MessageDigest.getInstance("SHA-256") + BigInt(1, sha256Digest.digest(str.getBytes("UTF-8"))).toLong + } +} diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/CompiledRecipeMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/CompiledRecipeMapping.scala index b37b72b3a..60f78cf26 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/CompiledRecipeMapping.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/CompiledRecipeMapping.scala @@ -9,7 +9,7 @@ import com.ing.baker.runtime.akka.actor.protobuf import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} import com.ing.baker.il.petrinet.{Node, Place, RecipePetriNet, Transition} import com.ing.baker.petrinet.api.Marking -import com.ing.baker.runtime.serialization.ProtoMap +import com.ing.baker.runtime.serialization.{ProtoMap, TokenIdentifier} import com.ing.baker.types.Value import scalax.collection.GraphEdge import scalax.collection.edge.WLDiEdge @@ -123,7 +123,7 @@ class CompiledRecipeMapping(anyMapping: ProtoMap[AnyRef, protobuf.SerializedData case (place, tokens) ⇒ tokens.toSeq.map { case (value, count) ⇒ protobuf.ProducedToken( placeId = Option(place.id), - tokenId = Option(tokenIdentifier(value)), + tokenId = Option(TokenIdentifier(value)), count = Option(count), tokenData = Option(anyMapping.toProto(value.asInstanceOf[AnyRef])) ) diff --git a/build.sbt b/build.sbt index 2e834df56..f4d82dae2 100644 --- a/build.sbt +++ b/build.sbt @@ -76,7 +76,7 @@ lazy val intermediateLanguage = project.in(file("intermediate-language")) ) ++ testDeps(scalaTest, scalaCheck, logback) ).dependsOn(bakertypes) -lazy val interface = project.in(file("baker-interface")) +lazy val `baker-interface` = project.in(file("baker-interface")) .settings(defaultModuleSettings) .settings(noPublishSettings) .settings(scalaPBSettings) @@ -138,7 +138,7 @@ lazy val runtime = project.in(file("runtime")) logback) ++ providedDeps(findbugs) ) - .dependsOn(intermediateLanguage, interface, testScope(recipeDsl), testScope(recipeCompiler), testScope(bakertypes)) + .dependsOn(intermediateLanguage, `baker-interface`, testScope(recipeDsl), testScope(recipeCompiler), testScope(bakertypes)) .enablePlugins(MultiJvmPlugin) .configs(MultiJvm) @@ -206,7 +206,7 @@ lazy val `baas-common` = project.in(file("baas-common")) akkaHttp ) ) - .dependsOn(interface) + .dependsOn(`baker-interface`) lazy val `baas-client` = project.in(file("baas-client")) .settings(defaultModuleSettings) @@ -216,7 +216,7 @@ lazy val `baas-client` = project.in(file("baas-client")) akkaHttp ) ) - .dependsOn(interface, `baas-common`) + .dependsOn(`baker-interface`, `baas-common`) lazy val `baas-state` = project.in(file("baas-state")) .settings(defaultModuleSettings) @@ -264,13 +264,10 @@ lazy val `baas-tests` = project.in(file("baas-tests")) scalaCheck ) ) - .dependsOn(`baas-client`, `baas-state`, `baas-remote-interaction`) + .dependsOn(`baas-client`, `baas-state`, `baas-remote-interaction`, `baas-remote-event-listener`, recipeCompiler) + .aggregate(`baas-client`, `baas-state`, `baas-remote-interaction`, `baas-remote-event-listener`) -//lazy val baas = project - - -lazy val baker = project - .in(file(".")) +lazy val baker = project.in(file(".")) .settings(defaultModuleSettings) .settings(noPublishSettings) .aggregate(bakertypes, runtime, recipeCompiler, recipeDsl, intermediateLanguage, splitBrainResolver) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala index d18ae6cfd..dc706168b 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala @@ -3,10 +3,9 @@ package com.ing.baker.runtime.akka.actor.interaction_scheduling import java.util.UUID import cats.implicits._ -import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolInteractionExecution.{ExecuteInstance, InstanceExecutedSuccessfully, InstanceExecutionFailed, InstanceExecutionTimedOut, InvalidExecution, NoInstanceFound} +import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolInteractionExecution._ import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolPushPullMatching.{AvailableQuest, Pull, Push} import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolQuestCommit.{Commit, Considering, QuestTaken} -import com.ing.baker.runtime.akka.actor.serialization.SerializersProvider import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexProto.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexProto.scala index 934e37e96..65ebfe316 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexProto.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexProto.scala @@ -11,7 +11,7 @@ import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProtocol.FireS import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProtocol.{ProcessEventReceivedResponse, _} import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} import com.ing.baker.runtime.serialization.protomappings.SensoryEventStatusMappingHelper -import com.ing.baker.runtime.akka.actor.serialization.SerializersProvider +import com.ing.baker.runtime.serialization.SerializersProvider import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} import scala.concurrent.duration.FiniteDuration diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala index 77500e0b2..62860441c 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala @@ -8,7 +8,7 @@ import akka.NotUsed import akka.actor.{ActorSystem, NoSerializationVerificationNeeded} import akka.persistence.query.scaladsl.CurrentEventsByPersistenceIdQuery import akka.stream.scaladsl.Source -import com.ing.baker.runtime.akka.actor.serialization.SerializersProvider +import com.ing.baker.runtime.serialization.SerializersProvider import com.ing.baker.runtime.serialization.Encryption object ProcessInstanceEventSourcing { diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProto.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProto.scala index 65bfe187e..be7ec4c52 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProto.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProto.scala @@ -8,7 +8,7 @@ import com.ing.baker.petrinet.api.{Id, Marking, MultiSet} import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol._ import com.ing.baker.runtime.akka.actor.process_instance.protobuf.FailureStrategyMessage.StrategyTypeMessage import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} -import com.ing.baker.runtime.akka.actor.serialization.SerializersProvider +import com.ing.baker.runtime.serialization.SerializersProvider import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} import scalapb.GeneratedMessageCompanion diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceSerialization.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceSerialization.scala index 538c6731c..20c77d729 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceSerialization.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceSerialization.scala @@ -1,40 +1,17 @@ package com.ing.baker.runtime.akka.actor.process_instance -import java.security.MessageDigest - import com.ing.baker.petrinet.api._ import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceEventSourcing._ -import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceSerialization._ import com.ing.baker.runtime.akka.actor.process_instance.internal.ExceptionStrategy.{BlockTransition, RetryWithDelay} import com.ing.baker.runtime.akka.actor.process_instance.internal.Instance import com.ing.baker.runtime.akka.actor.process_instance.protobuf.FailureStrategy.StrategyType import com.ing.baker.runtime.akka.actor.process_instance.protobuf._ import com.ing.baker.runtime.akka.actor.protobuf.{ProducedToken, SerializedData} import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto} -import com.ing.baker.runtime.serialization.SerializersProvider +import com.ing.baker.runtime.serialization.{SerializersProvider, TokenIdentifier} import scala.util.{Failure, Success} -object ProcessInstanceSerialization { - - /** - * TODO: - * - * This approach is fragile, the identifier function cannot change ever or recovery breaks - * a more robust alternative is to generate the ids and persist them - */ - def tokenIdentifier(tokenValue: Any): Long = tokenValue match { - case null => -1 - case str: String => sha256(str) - case obj => obj.hashCode() - } - - def sha256(str: String) = { - val sha256Digest: MessageDigest = MessageDigest.getInstance("SHA-256") - BigInt(1, sha256Digest.digest(str.getBytes("UTF-8"))).toLong - } -} - /** * This class is responsible for translating the EventSourcing.Event to and from the protobuf.Event * @@ -93,7 +70,7 @@ class ProcessInstanceSerialization[P : Identifiable, T : Identifiable, S, E](pro case (placeId, tokens) ⇒ tokens.toSeq.map { case (value, count) ⇒ ProducedToken( placeId = Some(placeId), - tokenId = Some(tokenIdentifier(value)), + tokenId = Some(TokenIdentifier(value)), count = Some(count), tokenData = serializeObject(value) ) @@ -106,7 +83,7 @@ class ProcessInstanceSerialization[P : Identifiable, T : Identifiable, S, E](pro case (placeId, tokens) ⇒ tokens.toSeq.map { case (value, count) ⇒ protobuf.ConsumedToken( placeId = Some(placeId), - tokenId = Some(tokenIdentifier(value)), + tokenId = Some(TokenIdentifier(value)), count = Some(count) ) } @@ -117,8 +94,8 @@ class ProcessInstanceSerialization[P : Identifiable, T : Identifiable, S, E](pro case (accumulated, protobuf.ConsumedToken(Some(placeId), Some(tokenId), Some(count))) ⇒ val place = instance.petriNet.places.getById(placeId, "place in the petrinet") val keySet = instance.marking(place).keySet - val value = keySet.find(e ⇒ tokenIdentifier(e) == tokenId).getOrElse( - throw new IllegalStateException(s"Missing token with id $tokenId, keySet = ${keySet.map(tokenIdentifier)}") + val value = keySet.find(e ⇒ TokenIdentifier(e) == tokenId).getOrElse( + throw new IllegalStateException(s"Missing token with id $tokenId, keySet = ${keySet.map(TokenIdentifier(_))}") ) accumulated.add(placeId, value, count) case _ ⇒ throw new IllegalStateException("Missing data in persisted ConsumedToken") diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProto.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProto.scala index f8e85eb5a..a5137d3d9 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProto.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProto.scala @@ -6,7 +6,7 @@ import cats.syntax.traverse._ import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManager.RecipeAdded import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProtocol._ import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} -import com.ing.baker.runtime.akka.actor.serialization.SerializersProvider +import com.ing.baker.runtime.serialization.SerializersProvider import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} import scala.util.Try diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcingSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcingSpec.scala index 6bcecc828..a9cd24e2f 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcingSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcingSpec.scala @@ -1,6 +1,6 @@ package com.ing.baker.runtime.akka.actor.process_instance -import akka.persistence.inmemory.extension.{ InMemoryJournalStorage, StorageExtension } +import akka.persistence.inmemory.extension.{InMemoryJournalStorage, StorageExtension} import akka.persistence.query.PersistenceQuery import akka.persistence.query.scaladsl._ import akka.stream.ActorMaterializer @@ -13,10 +13,12 @@ import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceEventSou import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol._ import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceSpec._ import com.ing.baker.runtime.akka.actor.process_instance.dsl._ -import com.ing.baker.runtime.akka.actor.serialization.Encryption.NoEncryption import java.util.UUID + +import com.ing.baker.runtime.serialization.Encryption.NoEncryption import org.scalatest.BeforeAndAfterEach import org.scalatest.Matchers._ + import scala.concurrent.ExecutionContext import scala.concurrent.duration._ diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceSpec.scala index 50aceb7ad..b087885cf 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceSpec.scala @@ -18,7 +18,7 @@ import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceSpec._ import com.ing.baker.runtime.akka.actor.process_instance.dsl._ import com.ing.baker.runtime.akka.actor.process_instance.internal.ExceptionStrategy.RetryWithDelay import com.ing.baker.runtime.akka.actor.process_instance.{ProcessInstanceProtocol => protocol} -import com.ing.baker.runtime.akka.actor.serialization.Encryption.NoEncryption +import com.ing.baker.runtime.serialization.Encryption.NoEncryption import com.ing.baker.runtime.akka.namedCachedThreadPool import org.mockito.Matchers._ import org.mockito.Mockito._ diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/EncryptionPropertiesSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/EncryptionPropertiesSpec.scala index 771cc12cf..ad18243af 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/EncryptionPropertiesSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/EncryptionPropertiesSpec.scala @@ -5,7 +5,7 @@ import org.scalacheck.Prop.forAll import org.scalacheck._ import org.scalatest.FunSuite import org.scalatest.prop.Checkers -import com.ing.baker.runtime.akka.actor.serialization.Encryption._ +import com.ing.baker.runtime.serialization.Encryption._ class EncryptionPropertiesSpec extends FunSuite with Checkers { diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala index 720456003..7cb323599 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala @@ -17,7 +17,7 @@ import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManager.RecipeAdded import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProto._ import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProtocol.GetRecipe import com.ing.baker.runtime.akka.actor.recipe_manager.{RecipeManager, RecipeManagerProtocol} -import com.ing.baker.runtime.akka.actor.serialization.Encryption.{AESEncryption, NoEncryption} +import com.ing.baker.runtime.serialization.Encryption.{AESEncryption, NoEncryption} import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto} import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.scaladsl.{EventInstance, EventMoment, RecipeInstanceState, SensoryEventResult} From bc756b71db5771744288109b9abef1fabfd7c294 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Thu, 24 Oct 2019 17:12:19 +0200 Subject: [PATCH 32/86] Massive work on baas project separation and a proper interface for the remote interaction node --- .../ing/baker/baas/javadsl/BakerClient.scala | 0 .../ing/baker/baas/scaladsl/BakerClient.scala | 0 .../baker/baas/akka}/InteractionAgent.scala | 7 +- .../baker/baas/akka/ProtobufSerializer.scala | 59 ++++++++ .../baas/common/BaaSInteractionInstance.scala | 12 ++ .../javadsl/BaaSInteractionInstance.scala | 17 +++ .../scaladsl/BaaSInteractionInstance.scala | 20 +++ .../com/ing/baker/baas/state/BaaSServer.scala | 0 .../src/main/protobuf/baas.proto | 0 .../com/ing/baker/baas/common/BaaSProto.scala | 0 .../ing/baker/baas/common/BaaSProtocol.scala | 0 .../baker/baas/common/MarshallingUtils.scala | 0 .../protobuf/interaction_schedulling.proto | 2 +- .../InteractionSchedulingProto.scala | 10 +- .../ProtocolInteractionExecution.scala | 5 +- .../protocol}/ProtocolPushPullMatching.scala | 5 +- .../baas/protocol}/ProtocolQuestCommit.scala | 5 +- .../serialization/BakerSerializable.scala | 3 + .../TypedProtobufSerializer.scala | 106 ++++++++++++++ build.sbt | 44 +++--- runtime/src/main/resources/reference.conf | 4 +- .../actor/ClusterBakerActorProvider.scala | 3 +- .../QuestMandated.scala | 1 + .../actor/process_index/ProcessIndex.scala | 3 +- .../process_index/ProcessIndexProtocol.scala | 2 +- .../ProcessInstanceProtocol.scala | 2 +- .../actor/recipe_manager/RecipeManager.scala | 2 +- .../RecipeManagerProtocol.scala | 2 +- .../serialization/BakerSerializable.scala | 3 - .../BakerTypedProtobufSerializer.scala | 134 +++--------------- .../akka/internal/InteractionManager.scala | 18 +-- .../serialization/SerializationSpec.scala | 2 +- 32 files changed, 293 insertions(+), 178 deletions(-) rename {baas-client => baas-node-client}/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala (100%) rename {baas-client => baas-node-client}/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala (100%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling => baas-node-interaction/src/main/scala/com/ing/baker/baas/akka}/InteractionAgent.scala (95%) create mode 100644 baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala create mode 100644 baas-node-interaction/src/main/scala/com/ing/baker/baas/common/BaaSInteractionInstance.scala create mode 100644 baas-node-interaction/src/main/scala/com/ing/baker/baas/javadsl/BaaSInteractionInstance.scala create mode 100644 baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala rename {baas-state => baas-node-state}/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala (100%) rename {baas-common => baas-protocol-baker}/src/main/protobuf/baas.proto (100%) rename {baas-common => baas-protocol-baker}/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala (100%) rename {baas-common => baas-protocol-baker}/src/main/scala/com/ing/baker/baas/common/BaaSProtocol.scala (100%) rename {baas-common => baas-protocol-baker}/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala (100%) rename {runtime => baas-protocol-interaction-scheduling}/src/main/protobuf/interaction_schedulling.proto (90%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling => baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol}/InteractionSchedulingProto.scala (94%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling => baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol}/ProtocolInteractionExecution.scala (87%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling => baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol}/ProtocolPushPullMatching.scala (75%) rename {runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling => baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol}/ProtocolQuestCommit.scala (73%) create mode 100644 baker-interface/src/main/scala/com/ing/baker/runtime/serialization/BakerSerializable.scala create mode 100644 baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TypedProtobufSerializer.scala delete mode 100644 runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerSerializable.scala diff --git a/baas-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala b/baas-node-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala similarity index 100% rename from baas-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala rename to baas-node-client/src/main/scala/com/ing/baker/baas/javadsl/BakerClient.scala diff --git a/baas-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala b/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala similarity index 100% rename from baas-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala rename to baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionAgent.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/InteractionAgent.scala similarity index 95% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionAgent.scala rename to baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/InteractionAgent.scala index 1221bea31..09d2e85c9 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionAgent.scala +++ b/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/InteractionAgent.scala @@ -1,16 +1,17 @@ -package com.ing.baker.runtime.akka.actor.interaction_scheduling +package com.ing.baker.baas.akka import java.util.UUID import akka.actor.{Actor, ActorRef, Props} import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} -import com.ing.baker.runtime.akka.actor.interaction_scheduling.InteractionAgent._ +import com.ing.baker.baas.akka.InteractionAgent.{CommitTimeout, log} +import com.ing.baker.baas.protocol.{ProtocolInteractionExecution, ProtocolPushPullMatching, ProtocolQuestCommit} import com.ing.baker.runtime.scaladsl.{EventInstance, InteractionInstance} import org.slf4j.LoggerFactory +import scala.concurrent.duration._ import scala.concurrent.{ExecutionContext, Future} import scala.util.{Failure, Success} -import scala.concurrent.duration._ object InteractionAgent { diff --git a/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala new file mode 100644 index 000000000..613213472 --- /dev/null +++ b/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala @@ -0,0 +1,59 @@ +package com.ing.baker.baas.akka + +import akka.actor.ExtendedActorSystem +import com.ing.baker.baas.protocol.{ProtocolInteractionExecution, ProtocolPushPullMatching, ProtocolQuestCommit} +import com.ing.baker.baas.protocol.InteractionSchedulingProto._ +import com.ing.baker.il +import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeInstanceState} +import com.ing.baker.runtime.serialization.{SerializersProvider, TypedProtobufSerializer} +import com.ing.baker.runtime.serialization.TypedProtobufSerializer.{BinarySerializable, forType} + +object ProtobufSerializer { + + def entries(ev0: SerializersProvider): List[BinarySerializable] = { + implicit val ev = ev0 + commonEntries ++ interactionSchedulingEntries + } + + def commonEntries(implicit ev0: SerializersProvider): List[BinarySerializable] = + List( + forType[com.ing.baker.types.Value] + .register("baker.types.Value"), + forType[com.ing.baker.types.Type] + .register("baker.types.Type"), + forType[EventInstance] + .register("core.RuntimeEvent"), + forType[RecipeInstanceState] + .register("core.ProcessState"), + forType[il.CompiledRecipe] + .register("il.CompiledRecipe") + ) + + def interactionSchedulingEntries(implicit ev0: SerializersProvider): List[BinarySerializable] = + List( + forType[ProtocolInteractionExecution.InstanceExecutedSuccessfully] + .register("InteractionSchedulingProtocols.InstanceExecutedSuccessfully"), + forType[ProtocolInteractionExecution.InstanceExecutionFailed] + .register("InteractionSchedulingProtocols.InstanceExecutionFailed"), + forType[ProtocolInteractionExecution.InstanceExecutionTimedOut] + .register("InteractionSchedulingProtocols.InstanceExecutionTimedOut"), + forType[ProtocolInteractionExecution.NoInstanceFound.type] + .register("InteractionSchedulingProtocols.NoInstanceFound"), + forType[ProtocolInteractionExecution.InvalidExecution] + .register("InteractionSchedulingProtocols.InvalidExecution"), + forType[ProtocolPushPullMatching.Push] + .register("InteractionSchedulingProtocols.Push"), + forType[ProtocolPushPullMatching.Pull] + .register("InteractionSchedulingProtocols.Pull"), + forType[ProtocolPushPullMatching.AvailableQuest] + .register("InteractionSchedulingProtocols.AvailableQuest"), + forType[ProtocolQuestCommit.Considering] + .register("InteractionSchedulingProtocols.Considering"), + forType[ProtocolQuestCommit.Commit] + .register("InteractionSchedulingProtocols.Commit"), + forType[ProtocolQuestCommit.QuestTaken.type] + .register("InteractionSchedulingProtocols.QuestTaken") + ) +} + +class ProtobufSerializer(system: ExtendedActorSystem) extends TypedProtobufSerializer(system, ProtobufSerializer.entries) diff --git a/baas-node-interaction/src/main/scala/com/ing/baker/baas/common/BaaSInteractionInstance.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/common/BaaSInteractionInstance.scala new file mode 100644 index 000000000..766dc0686 --- /dev/null +++ b/baas-node-interaction/src/main/scala/com/ing/baker/baas/common/BaaSInteractionInstance.scala @@ -0,0 +1,12 @@ +package com.ing.baker.baas.common + +import com.ing.baker.runtime.common.InteractionInstance +import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi + +trait BaaSInteractionInstance[F[_]] extends LanguageApi { self => + + type InteractionInstanceType <: InteractionInstance[F] { type Language <: self.Language } + + def load(implementation: InteractionInstanceType*): Unit + +} diff --git a/baas-node-interaction/src/main/scala/com/ing/baker/baas/javadsl/BaaSInteractionInstance.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/javadsl/BaaSInteractionInstance.scala new file mode 100644 index 000000000..7d865b7cb --- /dev/null +++ b/baas-node-interaction/src/main/scala/com/ing/baker/baas/javadsl/BaaSInteractionInstance.scala @@ -0,0 +1,17 @@ +package com.ing.baker.baas.javadsl + +import java.util.concurrent.CompletableFuture + +import akka.actor.ActorSystem +import com.ing.baker.baas.common +import com.ing.baker.baas.scaladsl +import com.ing.baker.runtime.javadsl.InteractionInstance +import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi + +class BaaSInteractionInstance(actorSystem: ActorSystem) extends common.BaaSInteractionInstance[CompletableFuture] with JavaApi { + + override type InteractionInstanceType = InteractionInstance + + override def load(implementation: InteractionInstance*): Unit = + scaladsl.BaaSInteractionInstance(actorSystem).load(implementation.map(_.asScala): _*) +} diff --git a/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala new file mode 100644 index 000000000..f545fe8bf --- /dev/null +++ b/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala @@ -0,0 +1,20 @@ +package com.ing.baker.baas.scaladsl + +import akka.actor.ActorSystem +import com.ing.baker.baas.akka.InteractionAgent +import com.ing.baker.baas.common +import com.ing.baker.runtime.scaladsl.InteractionInstance +import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi + +import scala.concurrent.Future + +case class BaaSInteractionInstance(actorSystem: ActorSystem) extends common.BaaSInteractionInstance[Future] with JavaApi { + + override type InteractionInstanceType = InteractionInstance + + override def load(implementation: InteractionInstance*): Unit = + implementation.foreach { implementation => + actorSystem.actorOf(InteractionAgent(implementation)) + } +} + diff --git a/baas-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala similarity index 100% rename from baas-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala rename to baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala diff --git a/baas-common/src/main/protobuf/baas.proto b/baas-protocol-baker/src/main/protobuf/baas.proto similarity index 100% rename from baas-common/src/main/protobuf/baas.proto rename to baas-protocol-baker/src/main/protobuf/baas.proto diff --git a/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala b/baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala similarity index 100% rename from baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala rename to baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala diff --git a/baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProtocol.scala b/baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/BaaSProtocol.scala similarity index 100% rename from baas-common/src/main/scala/com/ing/baker/baas/common/BaaSProtocol.scala rename to baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/BaaSProtocol.scala diff --git a/baas-common/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala b/baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala similarity index 100% rename from baas-common/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala rename to baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala diff --git a/runtime/src/main/protobuf/interaction_schedulling.proto b/baas-protocol-interaction-scheduling/src/main/protobuf/interaction_schedulling.proto similarity index 90% rename from runtime/src/main/protobuf/interaction_schedulling.proto rename to baas-protocol-interaction-scheduling/src/main/protobuf/interaction_schedulling.proto index 38b658e8d..fe7a0497f 100644 --- a/runtime/src/main/protobuf/interaction_schedulling.proto +++ b/baas-protocol-interaction-scheduling/src/main/protobuf/interaction_schedulling.proto @@ -3,7 +3,7 @@ syntax = "proto2"; import "scalapb/scalapb.proto"; import "common.proto"; -option java_package = "com.ing.baker.runtime.akka.actor.interaction_scheduling.protobuf"; +option java_package = "com.ing.baker.baas.protocol.protobuf"; option (scalapb.options) = { flat_package: true }; diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/InteractionSchedulingProto.scala similarity index 94% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala rename to baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/InteractionSchedulingProto.scala index dc706168b..cf3dd67ca 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InteractionSchedulingProto.scala +++ b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/InteractionSchedulingProto.scala @@ -1,13 +1,13 @@ -package com.ing.baker.runtime.akka.actor.interaction_scheduling +package com.ing.baker.baas.protocol import java.util.UUID import cats.implicits._ -import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolInteractionExecution._ -import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolPushPullMatching.{AvailableQuest, Pull, Push} -import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolQuestCommit.{Commit, Considering, QuestTaken} -import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} +import com.ing.baker.baas.protocol.ProtocolInteractionExecution._ +import com.ing.baker.baas.protocol.ProtocolPushPullMatching._ +import com.ing.baker.baas.protocol.ProtocolQuestCommit._ import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} import scala.util.{Success, Try} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolInteractionExecution.scala b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolInteractionExecution.scala similarity index 87% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolInteractionExecution.scala rename to baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolInteractionExecution.scala index 681ed7ae4..8628e45c4 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolInteractionExecution.scala +++ b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolInteractionExecution.scala @@ -1,6 +1,5 @@ -package com.ing.baker.runtime.akka.actor.interaction_scheduling +package com.ing.baker.baas.protocol -import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance} /** @@ -12,7 +11,7 @@ import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance} * InstanceExecutionFailed or InvalidExecution * */ -sealed trait ProtocolInteractionExecution extends BakerSerializable +sealed trait ProtocolInteractionExecution //extends BakerSerializable object ProtocolInteractionExecution { diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolPushPullMatching.scala b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolPushPullMatching.scala similarity index 75% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolPushPullMatching.scala rename to baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolPushPullMatching.scala index 87efb392a..d20e968c2 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolPushPullMatching.scala +++ b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolPushPullMatching.scala @@ -1,14 +1,13 @@ -package com.ing.baker.runtime.akka.actor.interaction_scheduling +package com.ing.baker.baas.protocol import java.util.UUID import akka.actor.ActorRef -import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable /** * Protocol done to find a possible matching between a QuestMandated and an available InteractionAgent */ -sealed trait ProtocolPushPullMatching extends BakerSerializable +sealed trait ProtocolPushPullMatching //extends BakerSerializable object ProtocolPushPullMatching { diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolQuestCommit.scala b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolQuestCommit.scala similarity index 73% rename from runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolQuestCommit.scala rename to baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolQuestCommit.scala index 894eacfd6..8303a78da 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/ProtocolQuestCommit.scala +++ b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolQuestCommit.scala @@ -1,13 +1,12 @@ -package com.ing.baker.runtime.akka.actor.interaction_scheduling +package com.ing.baker.baas.protocol import akka.actor.ActorRef -import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable /** * A Protocol executed after finding a candidate match between a QuestMandated and an InteractionAgent, it makes sure * that 1 QuestMandated commits with 1 InteractionAgent only and vice versa, without leaving orphan agents. */ -sealed trait ProtocolQuestCommit extends BakerSerializable +sealed trait ProtocolQuestCommit //extends BakerSerializable object ProtocolQuestCommit { diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/BakerSerializable.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/BakerSerializable.scala new file mode 100644 index 000000000..8eddd451e --- /dev/null +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/BakerSerializable.scala @@ -0,0 +1,3 @@ +package com.ing.baker.runtime.serialization + +trait BakerSerializable diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TypedProtobufSerializer.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TypedProtobufSerializer.scala new file mode 100644 index 000000000..4f5577f1e --- /dev/null +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TypedProtobufSerializer.scala @@ -0,0 +1,106 @@ +package com.ing.baker.runtime.serialization + +import akka.actor.ExtendedActorSystem +import akka.serialization.SerializerWithStringManifest +import com.ing.baker.runtime.serialization.TypedProtobufSerializer.BinarySerializable +import org.slf4j.LoggerFactory + +import scala.reflect.ClassTag +import scala.util.Try + +object TypedProtobufSerializer { + + private val log = LoggerFactory.getLogger(classOf[TypedProtobufSerializer]) + + /** Hardcoded serializerId for this serializer. This should not conflict with other serializers. + * Values from 0 to 40 are reserved for Akka internal usage. + */ + val identifier = 101 + + def forType[A <: AnyRef](implicit tag: ClassTag[A]): RegisterFor[A] = new RegisterFor[A](tag) + + class RegisterFor[A <: AnyRef](classTag: ClassTag[A]) { + + def register[P <: scalapb.GeneratedMessage with scalapb.Message[P]](implicit protoMap: ProtoMap[A, P]): BinarySerializable = + register[P](None) + + def register[P <: scalapb.GeneratedMessage with scalapb.Message[P]](overrideName: String)(implicit protoMap: ProtoMap[A, P]): BinarySerializable = + register[P](Some(overrideName)) + + def register[P <: scalapb.GeneratedMessage with scalapb.Message[P]](overrideName: Option[String])(implicit protoMap: ProtoMap[A, P]): BinarySerializable = { + new BinarySerializable { + + override type Type = A + + override val tag: Class[_] = classTag.runtimeClass + + override val manifest: String = overrideName.getOrElse(classTag.runtimeClass.getName) + + override def toBinary(a: Type): Array[Byte] = protoMap.toByteArray(a) + + override def fromBinary(binary: Array[Byte]): Try[Type] = protoMap.fromByteArray(binary) + } + } + } + + trait BinarySerializable { + + type Type <: AnyRef + + val tag: Class[_] + + def manifest: String + + def toBinary(a: Type): Array[Byte] + + // The actor resolver is commented for future Akka Typed implementation + def fromBinary(binary: Array[Byte]/*, resolver: ActorRefResolver*/): Try[Type] + + def isInstance(o: AnyRef): Boolean = + tag.isInstance(o) + + def unsafeToBinary(a: AnyRef): Array[Byte] = + toBinary(a.asInstanceOf[Type]) + + // The actor resolver is commented for future Akka Typed implementation + def fromBinaryAnyRef(binary: Array[Byte]/*, resolver: ActorRefResolver*/): Try[AnyRef] = + fromBinary(binary) + + } +} + +abstract class TypedProtobufSerializer(system: ExtendedActorSystem, entries: SerializersProvider => List[BinarySerializable]) extends SerializerWithStringManifest { + + def serializersProvider: SerializersProvider = + SerializersProvider(system, system.provider) + + lazy val entriesMem: List[BinarySerializable] = + entries(serializersProvider) + + override def identifier: Int = + TypedProtobufSerializer.identifier + + override def manifest(o: AnyRef): String = { + entriesMem + .find(_.isInstance(o)) + .map(_.manifest) + .getOrElse(throw new IllegalStateException(s"Unsupported object of type: ${o.getClass}")) + } + + override def toBinary(o: AnyRef): Array[Byte] = + entriesMem + .find(_.isInstance(o)) + .map(_.unsafeToBinary(o)) + .getOrElse(throw new IllegalStateException(s"Unsupported object of type: ${o.getClass}")) + + override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef = + entriesMem + .find(_.manifest == manifest) + .map(_.fromBinaryAnyRef(bytes)) + .getOrElse(throw new IllegalStateException(s"Unsupported object with manifest $manifest")) + .fold( + { e => TypedProtobufSerializer.log.error(s"Failed to deserialize bytes with manifest $manifest", e); throw e }, + identity + ) +} + diff --git a/build.sbt b/build.sbt index f4d82dae2..381da3bba 100644 --- a/build.sbt +++ b/build.sbt @@ -138,7 +138,7 @@ lazy val runtime = project.in(file("runtime")) logback) ++ providedDeps(findbugs) ) - .dependsOn(intermediateLanguage, `baker-interface`, testScope(recipeDsl), testScope(recipeCompiler), testScope(bakertypes)) + .dependsOn(intermediateLanguage, `baker-interface`, `baas-protocol-interaction-scheduling`, testScope(recipeDsl), testScope(recipeCompiler), testScope(bakertypes)) .enablePlugins(MultiJvmPlugin) .configs(MultiJvm) @@ -196,52 +196,64 @@ lazy val recipeCompiler = project.in(file("compiler")) ) .dependsOn(recipeDsl, intermediateLanguage, testScope(recipeDsl)) -lazy val `baas-common` = project.in(file("baas-common")) +lazy val `baas-protocol-baker` = project.in(file("baas-protocol-baker")) .settings(defaultModuleSettings) .settings(noPublishSettings) .settings(scalaPBSettings) .settings( - moduleName := "baas-common", + moduleName := "baas-protocol-baker", libraryDependencies ++= Seq( akkaHttp ) ) .dependsOn(`baker-interface`) -lazy val `baas-client` = project.in(file("baas-client")) +lazy val `baas-protocol-interaction-scheduling` = project.in(file("baas-protocol-interaction-scheduling")) + .settings(defaultModuleSettings) + .settings(noPublishSettings) + .settings(scalaPBSettings) + .settings( + moduleName := "baas-protocol-interaction-scheduling" + ) + .dependsOn(`baker-interface`) + +lazy val `baas-node-client` = project.in(file("baas-node-client")) .settings(defaultModuleSettings) .settings( - moduleName := "baas-client", + moduleName := "baas-node-client", libraryDependencies ++= Seq( akkaHttp ) ) - .dependsOn(`baker-interface`, `baas-common`) + .dependsOn(`baker-interface`, `baas-protocol-baker`) -lazy val `baas-state` = project.in(file("baas-state")) +lazy val `baas-node-state` = project.in(file("baas-node-state")) .settings(defaultModuleSettings) .settings( - moduleName := "baas-state", + moduleName := "baas-node-state", libraryDependencies ++= Seq( akkaHttp, akkaPersistenceCassandra ) ) - .dependsOn(runtime, `baas-common`, `baas-remote-interaction`) + .dependsOn(runtime, `baas-protocol-baker`, `baas-protocol-interaction-scheduling`) -lazy val `baas-remote-interaction` = project.in(file("baas-remote-interaction")) +lazy val `baas-node-interaction` = project.in(file("baas-node-interaction")) .settings(defaultModuleSettings) .settings( - moduleName := "baas-remote-interaction", + moduleName := "baas-node-interaction", libraryDependencies ++= Seq( - akkaCluster + akkaCluster, + akkaClusterTools, + slf4jApi ) ) + .dependsOn(`baas-protocol-interaction-scheduling`, `baker-interface`) -lazy val `baas-remote-event-listener` = project.in(file("baas-remote-event-listener")) +lazy val `baas-node-event-listener` = project.in(file("baas-node-event-listener")) .settings(defaultModuleSettings) .settings( - moduleName := "baas-remote-event-listener", + moduleName := "baas-node-event-listener", libraryDependencies ++= Seq( akkaCluster ) @@ -264,8 +276,8 @@ lazy val `baas-tests` = project.in(file("baas-tests")) scalaCheck ) ) - .dependsOn(`baas-client`, `baas-state`, `baas-remote-interaction`, `baas-remote-event-listener`, recipeCompiler) - .aggregate(`baas-client`, `baas-state`, `baas-remote-interaction`, `baas-remote-event-listener`) + .dependsOn(`baas-node-client`, `baas-node-state`, `baas-node-interaction`, `baas-node-event-listener`, recipeCompiler) + .aggregate(`baas-node-client`, `baas-node-state`, `baas-node-interaction`, `baas-node-event-listener`) lazy val baker = project.in(file(".")) .settings(defaultModuleSettings) diff --git a/runtime/src/main/resources/reference.conf b/runtime/src/main/resources/reference.conf index 9b18cd939..49a64d688 100644 --- a/runtime/src/main/resources/reference.conf +++ b/runtime/src/main/resources/reference.conf @@ -64,13 +64,13 @@ akka { serializers { - baker-typed-protobuf = "com.ing.baker.runtime.akka.actor.serialization.BakerTypedProtobufSerializer" + baker-typed-protobuf = "com.ing.baker.runtime.serialization.BakerTypedProtobufSerializer" } serialization-bindings { - "com.ing.baker.runtime.akka.actor.serialization.BakerSerializable" = baker-typed-protobuf + "com.ing.baker.runtime.serialization.BakerSerializable" = baker-typed-protobuf "com.ing.baker.types.Value" = baker-typed-protobuf "com.ing.baker.types.Type" = baker-typed-protobuf diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/ClusterBakerActorProvider.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/ClusterBakerActorProvider.scala index 1ed002e7e..fb1c97b01 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/ClusterBakerActorProvider.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/ClusterBakerActorProvider.scala @@ -15,9 +15,8 @@ import com.ing.baker.runtime.akka.actor.process_index.ProcessIndex.ActorMetadata import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProtocol._ import com.ing.baker.runtime.akka.actor.process_index._ import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManager -import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable import com.ing.baker.runtime.akka.internal.InteractionManager -import com.ing.baker.runtime.serialization.Encryption +import com.ing.baker.runtime.serialization.{BakerSerializable, Encryption} import org.slf4j.LoggerFactory import scala.concurrent.duration._ diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/QuestMandated.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/QuestMandated.scala index b0c20f9bc..4c68d2814 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/QuestMandated.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/QuestMandated.scala @@ -9,6 +9,7 @@ import com.ing.baker.runtime.akka.actor.interaction_scheduling.QuestMandated.{Co import com.ing.baker.runtime.scaladsl.IngredientInstance import org.slf4j.LoggerFactory import QuestMandated._ +import com.ing.baker.baas.protocol.{ProtocolInteractionExecution, ProtocolPushPullMatching, ProtocolQuestCommit} object QuestMandated { diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndex.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndex.scala index 629b0da64..eb18e9f36 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndex.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndex.scala @@ -17,11 +17,10 @@ import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol._ import com.ing.baker.runtime.akka.actor.process_instance.{ProcessInstance, ProcessInstanceRuntime} import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProtocol._ -import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable import com.ing.baker.runtime.akka.internal.{InteractionManager, RecipeRuntime} import com.ing.baker.runtime.akka.{namedCachedThreadPool, _} import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeInstanceCreated, RecipeInstanceState} -import com.ing.baker.runtime.serialization.Encryption +import com.ing.baker.runtime.serialization.{BakerSerializable, Encryption} import com.ing.baker.types.Value import scala.collection.mutable diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexProtocol.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexProtocol.scala index ff1f70537..73494b2ed 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexProtocol.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexProtocol.scala @@ -2,9 +2,9 @@ package com.ing.baker.runtime.akka.actor.process_index import akka.actor.ActorRef import com.ing.baker.runtime.akka.actor.process_index.ProcessIndex.ActorMetadata -import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable import com.ing.baker.runtime.scaladsl.{EventInstance, SensoryEventResult} import com.ing.baker.runtime.common.{RejectReason, SensoryEventStatus} +import com.ing.baker.runtime.serialization.BakerSerializable import scala.concurrent.duration.FiniteDuration diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala index 8d0376c38..0572b73fc 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceProtocol.scala @@ -1,7 +1,7 @@ package com.ing.baker.runtime.akka.actor.process_instance import com.ing.baker.petrinet.api._ -import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable +import com.ing.baker.runtime.serialization.BakerSerializable /** * Describes the messages to and from a PetriNetInstance actor. diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManager.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManager.scala index da55a4ca8..b094687e2 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManager.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManager.scala @@ -5,7 +5,7 @@ import akka.persistence.PersistentActor import com.ing.baker.il.CompiledRecipe import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManager._ import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProtocol._ -import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable +import com.ing.baker.runtime.serialization.BakerSerializable import scala.collection.mutable diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProtocol.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProtocol.scala index f64fdfb73..0d84f1c65 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProtocol.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProtocol.scala @@ -1,7 +1,7 @@ package com.ing.baker.runtime.akka.actor.recipe_manager import com.ing.baker.il.CompiledRecipe -import com.ing.baker.runtime.akka.actor.serialization.BakerSerializable +import com.ing.baker.runtime.serialization.BakerSerializable sealed trait RecipeManagerProtocol extends BakerSerializable diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerSerializable.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerSerializable.scala deleted file mode 100644 index 1408c9119..000000000 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerSerializable.scala +++ /dev/null @@ -1,3 +0,0 @@ -package com.ing.baker.runtime.akka.actor.serialization - -trait BakerSerializable diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala index e35db3316..3afb90dc3 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala @@ -1,35 +1,26 @@ package com.ing.baker.runtime.akka.actor.serialization import akka.actor.ExtendedActorSystem -import akka.serialization.SerializerWithStringManifest +import com.ing.baker.baas.protocol.{ProtocolInteractionExecution, ProtocolPushPullMatching, ProtocolQuestCommit} +import com.ing.baker.baas.protocol.InteractionSchedulingProto._ +import com.ing.baker.il import com.ing.baker.runtime.akka.actor.ClusterBakerActorProvider -import com.ing.baker.runtime.akka.actor.interaction_scheduling.InteractionSchedulingProto._ -import com.ing.baker.runtime.akka.actor.interaction_scheduling.{ProtocolInteractionExecution, ProtocolPushPullMatching, ProtocolQuestCommit} -import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProto._ import com.ing.baker.runtime.akka.actor.process_index.{ProcessIndex, ProcessIndexProtocol} -import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProto._ import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol -import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProto._ import com.ing.baker.runtime.akka.actor.recipe_manager.{RecipeManager, RecipeManagerProtocol} -import com.ing.baker.runtime.akka.actor.serialization.BakerTypedProtobufSerializer.BinarySerializable -import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} -import com.ing.baker.{il, runtime} -import org.slf4j.LoggerFactory - -import scala.reflect.ClassTag -import scala.util.Try +import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeInstanceState} +import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider, TypedProtobufSerializer} +import com.ing.baker.runtime.serialization.TypedProtobufSerializer.{BinarySerializable, forType} +import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProto._ +import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProto._ +import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManagerProto._ object BakerTypedProtobufSerializer { - private val log = LoggerFactory.getLogger(classOf[BakerTypedProtobufSerializer]) - - /** Hardcoded serializerId for this serializer. This should not conflict with other serializers. - * Values from 0 to 40 are reserved for Akka internal usage. - */ - val identifier = 101 - - def entries(implicit ev0: SerializersProvider): List[BinarySerializable] = + def entries(ev0: SerializersProvider): List[BinarySerializable] = { + implicit val ev = ev0 commonEntries ++ processIndexEntries ++ processInstanceEntries ++ recipeManagerEntries ++ interactionSchedulingEntries + } def commonEntries(implicit ev0: SerializersProvider): List[BinarySerializable] = List( @@ -37,9 +28,9 @@ object BakerTypedProtobufSerializer { .register("baker.types.Value"), forType[com.ing.baker.types.Type] .register("baker.types.Type"), - forType[runtime.scaladsl.EventInstance] + forType[EventInstance] .register("core.RuntimeEvent"), - forType[runtime.scaladsl.RecipeInstanceState] + forType[RecipeInstanceState] .register("core.ProcessState"), forType[il.CompiledRecipe] .register("il.CompiledRecipe") @@ -133,12 +124,12 @@ object BakerTypedProtobufSerializer { .register("ProcessInstanceProtocol.TransitionFailed"), forType[ProcessInstanceProtocol.TransitionFired] .register("ProcessInstanceProtocol.TransitionFired"), - forType[runtime.akka.actor.process_instance.protobuf.TransitionFired] - .register("TransitionFired")(ProtoMap.identityProtoMap(runtime.akka.actor.process_instance.protobuf.TransitionFired)), - forType[runtime.akka.actor.process_instance.protobuf.TransitionFailed] - .register("TransitionFailed")(ProtoMap.identityProtoMap(runtime.akka.actor.process_instance.protobuf.TransitionFailed)), - forType[runtime.akka.actor.process_instance.protobuf.Initialized] - .register("Initialized")(ProtoMap.identityProtoMap(runtime.akka.actor.process_instance.protobuf.Initialized)) + forType[com.ing.baker.runtime.akka.actor.process_instance.protobuf.TransitionFired] + .register("TransitionFired")(ProtoMap.identityProtoMap(com.ing.baker.runtime.akka.actor.process_instance.protobuf.TransitionFired)), + forType[com.ing.baker.runtime.akka.actor.process_instance.protobuf.TransitionFailed] + .register("TransitionFailed")(ProtoMap.identityProtoMap(com.ing.baker.runtime.akka.actor.process_instance.protobuf.TransitionFailed)), + forType[com.ing.baker.runtime.akka.actor.process_instance.protobuf.Initialized] + .register("Initialized")(ProtoMap.identityProtoMap(com.ing.baker.runtime.akka.actor.process_instance.protobuf.Initialized)) ) def recipeManagerEntries(implicit ev0: SerializersProvider): List[BinarySerializable] = @@ -186,89 +177,6 @@ object BakerTypedProtobufSerializer { forType[ProtocolQuestCommit.QuestTaken.type] .register("InteractionSchedulingProtocols.QuestTaken") ) - - def forType[A <: AnyRef](implicit tag: ClassTag[A]): RegisterFor[A] = new RegisterFor[A](tag) - - class RegisterFor[A <: AnyRef](classTag: ClassTag[A]) { - - def register[P <: scalapb.GeneratedMessage with scalapb.Message[P]](implicit protoMap: ProtoMap[A, P]): BinarySerializable = - register[P](None) - - def register[P <: scalapb.GeneratedMessage with scalapb.Message[P]](overrideName: String)(implicit protoMap: ProtoMap[A, P]): BinarySerializable = - register[P](Some(overrideName)) - - def register[P <: scalapb.GeneratedMessage with scalapb.Message[P]](overrideName: Option[String])(implicit protoMap: ProtoMap[A, P]): BinarySerializable = { - new BinarySerializable { - - override type Type = A - - override val tag: Class[_] = classTag.runtimeClass - - override val manifest: String = overrideName.getOrElse(classTag.runtimeClass.getName) - - override def toBinary(a: Type): Array[Byte] = protoMap.toByteArray(a) - - override def fromBinary(binary: Array[Byte]): Try[Type] = protoMap.fromByteArray(binary) - } - } - } - - trait BinarySerializable { - - type Type <: AnyRef - - val tag: Class[_] - - def manifest: String - - def toBinary(a: Type): Array[Byte] - - // The actor resolver is commented for future Akka Typed implementation - def fromBinary(binary: Array[Byte]/*, resolver: ActorRefResolver*/): Try[Type] - - def isInstance(o: AnyRef): Boolean = - tag.isInstance(o) - - def unsafeToBinary(a: AnyRef): Array[Byte] = - toBinary(a.asInstanceOf[Type]) - - // The actor resolver is commented for future Akka Typed implementation - def fromBinaryAnyRef(binary: Array[Byte]/*, resolver: ActorRefResolver*/): Try[AnyRef] = - fromBinary(binary) - - } -} - -class BakerTypedProtobufSerializer(system: ExtendedActorSystem) extends SerializerWithStringManifest { - - implicit def serializersProvider: SerializersProvider = SerializersProvider(system, system.provider) - - lazy val entriesMem: List[BinarySerializable] = BakerTypedProtobufSerializer.entries - - override def identifier: Int = - BakerTypedProtobufSerializer.identifier - - override def manifest(o: AnyRef): String = { - entriesMem - .find(_.isInstance(o)) - .map(_.manifest) - .getOrElse(throw new IllegalStateException(s"Unsupported object of type: ${o.getClass}")) - } - - override def toBinary(o: AnyRef): Array[Byte] = - entriesMem - .find(_.isInstance(o)) - .map(_.unsafeToBinary(o)) - .getOrElse(throw new IllegalStateException(s"Unsupported object of type: ${o.getClass}")) - - override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef = - entriesMem - .find(_.manifest == manifest) - .map(_.fromBinaryAnyRef(bytes)) - .getOrElse(throw new IllegalStateException(s"Unsupported object with manifest $manifest")) - .fold( - { e => BakerTypedProtobufSerializer.log.error(s"Failed to deserialize bytes with manifest $manifest", e); throw e }, - identity - ) } +class BakerTypedProtobufSerializer(system: ExtendedActorSystem) extends TypedProtobufSerializer(system, BakerTypedProtobufSerializer.entries) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala index e2e85d6b1..33eb4919d 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala @@ -7,7 +7,7 @@ import akka.pattern.ask import akka.util.Timeout import com.ing.baker.il.petrinet.InteractionTransition import com.ing.baker.runtime.akka.actor.interaction_scheduling.QuestMandated.Start -import com.ing.baker.runtime.akka.actor.interaction_scheduling.{InteractionAgent, ProtocolInteractionExecution, QuestMandated} +import com.ing.baker.runtime.akka.actor.interaction_scheduling.QuestMandated import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance, InteractionInstance} import scala.compat.java8.FunctionConverters._ @@ -20,13 +20,6 @@ trait InteractionManager { def executeImplementation(interaction: InteractionTransition, input: Seq[IngredientInstance]): Future[Option[EventInstance]] - /** - * Add an implementation to the InteractionManager - * - * @param implementation - */ - def addImplementation(implementation: InteractionInstance): Unit - } class InteractionManagerDis(system: ActorSystem, postTimeout: Timeout, computationTimeout: Timeout) extends InteractionManager { @@ -44,15 +37,6 @@ class InteractionManagerDis(system: ActorSystem, postTimeout: Timeout, computati } } - /** - * Add an implementation to the InteractionManager - * - * @param implementation - */ - override def addImplementation(implementation: InteractionInstance): Unit = { - system.actorOf(InteractionAgent(implementation)) - } - override def hasImplementation(interaction: InteractionTransition): Boolean = true } diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala index 7cb323599..cab04ef98 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala @@ -21,7 +21,7 @@ import com.ing.baker.runtime.serialization.Encryption.{AESEncryption, NoEncrypti import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto} import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.scaladsl.{EventInstance, EventMoment, RecipeInstanceState, SensoryEventResult} -import com.ing.baker.runtime.serialization.ProtoMap +import com.ing.baker.runtime.serialization.{BakerTypedProtobufSerializer, ProtoMap} import com.ing.baker.types.modules.PrimitiveModuleSpec._ import com.ing.baker.types.{Value, _} import com.ing.baker.{AllTypeRecipe, types} From c9d78c8fa9ad898d92ad04bed1d3a9f586adfa8b Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Fri, 25 Oct 2019 11:35:49 +0200 Subject: [PATCH 33/86] protobuf serialization fix --- .../src/main/resources/reference.conf | 20 +++++++++++++++++++ .../baker/baas/akka/InteractionAgent.scala | 2 +- .../scaladsl/BaaSInteractionInstance.scala | 4 ++-- .../CommonBaaSServerClientSpec.scala | 4 ++-- .../JavaDSLBaaSServerClientSpec.scala | 5 +++-- .../ScalaDSLBaaSServerClientSpec.scala | 2 +- runtime/src/main/resources/reference.conf | 2 +- .../akka/internal/InteractionManager.scala | 5 +++++ 8 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 baas-node-interaction/src/main/resources/reference.conf rename baas-tests/src/test/scala/com/ing/baker/baas/{ => spec}/CommonBaaSServerClientSpec.scala (99%) rename baas-tests/src/test/scala/com/ing/baker/baas/{ => spec}/JavaDSLBaaSServerClientSpec.scala (98%) rename baas-tests/src/test/scala/com/ing/baker/baas/{ => spec}/ScalaDSLBaaSServerClientSpec.scala (88%) diff --git a/baas-node-interaction/src/main/resources/reference.conf b/baas-node-interaction/src/main/resources/reference.conf new file mode 100644 index 000000000..ad61794e3 --- /dev/null +++ b/baas-node-interaction/src/main/resources/reference.conf @@ -0,0 +1,20 @@ + +akka { + + actor { + + allow-java-serialization = off + + serializers { + + baker-typed-protobuf = "com.ing.baker.baas.akka.ProtobufSerializer" + + } + + serialization-bindings { + + "com.ing.baker.runtime.serialization.BakerSerializable" = baker-typed-protobuf + + } + } +} diff --git a/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/InteractionAgent.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/InteractionAgent.scala index 09d2e85c9..4fa75c811 100644 --- a/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/InteractionAgent.scala +++ b/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/InteractionAgent.scala @@ -30,7 +30,7 @@ object InteractionAgent { * @param result outcome of invoking the interaction instance * @param ec execution context to use */ - private[interaction_scheduling] def pipeBackExecutionResponse(agent: ActorRef, mandated: ActorRef)(result: Future[Option[EventInstance]])(implicit ec: ExecutionContext): Unit = { + def pipeBackExecutionResponse(agent: ActorRef, mandated: ActorRef)(result: Future[Option[EventInstance]])(implicit ec: ExecutionContext): Unit = { result.onComplete { case Success(value) => mandated.tell(ProtocolInteractionExecution.InstanceExecutedSuccessfully(value), agent) diff --git a/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala index f545fe8bf..fa079e407 100644 --- a/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala +++ b/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala @@ -3,12 +3,12 @@ package com.ing.baker.baas.scaladsl import akka.actor.ActorSystem import com.ing.baker.baas.akka.InteractionAgent import com.ing.baker.baas.common +import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi import com.ing.baker.runtime.scaladsl.InteractionInstance -import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi import scala.concurrent.Future -case class BaaSInteractionInstance(actorSystem: ActorSystem) extends common.BaaSInteractionInstance[Future] with JavaApi { +case class BaaSInteractionInstance(actorSystem: ActorSystem) extends common.BaaSInteractionInstance[Future] with ScalaApi { override type InteractionInstanceType = InteractionInstance diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/CommonBaaSServerClientSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/spec/CommonBaaSServerClientSpec.scala similarity index 99% rename from baas-tests/src/test/scala/com/ing/baker/baas/CommonBaaSServerClientSpec.scala rename to baas-tests/src/test/scala/com/ing/baker/baas/spec/CommonBaaSServerClientSpec.scala index 5b4a88251..1913248ef 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/CommonBaaSServerClientSpec.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/spec/CommonBaaSServerClientSpec.scala @@ -1,14 +1,14 @@ -package com.ing.baker.baas +package com.ing.baker.baas.spec import java.util.UUID import akka.actor.ActorSystem import akka.stream.{ActorMaterializer, Materializer} import cats.effect.{IO, Timer} -import com.ing.baker.baas.CommonBaaSServerClientSpec._ import com.ing.baker.baas.recipe.CheckoutFlowEvents.ItemsReserved import com.ing.baker.baas.recipe.CheckoutFlowIngredients.{Item, OrderId, ReservedItems, ShippingAddress} import com.ing.baker.baas.recipe._ +import com.ing.baker.baas.spec.CommonBaaSServerClientSpec._ import com.ing.baker.baas.state.BaaSServer import com.ing.baker.compiler.RecipeCompiler import com.ing.baker.il.CompiledRecipe diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/JavaDSLBaaSServerClientSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/spec/JavaDSLBaaSServerClientSpec.scala similarity index 98% rename from baas-tests/src/test/scala/com/ing/baker/baas/JavaDSLBaaSServerClientSpec.scala rename to baas-tests/src/test/scala/com/ing/baker/baas/spec/JavaDSLBaaSServerClientSpec.scala index d31651ec3..aef18fa80 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/JavaDSLBaaSServerClientSpec.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/spec/JavaDSLBaaSServerClientSpec.scala @@ -1,8 +1,9 @@ -package com.ing.baker.baas +package com.ing.baker.baas.spec import java.util.Optional -import com.ing.baker.baas.JavaDSLBaaSServerClientSpec.optionToJava +import com.ing.baker.baas.javadsl +import com.ing.baker.baas.spec.JavaDSLBaaSServerClientSpec.optionToJava import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.scaladsl._ diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/ScalaDSLBaaSServerClientSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/spec/ScalaDSLBaaSServerClientSpec.scala similarity index 88% rename from baas-tests/src/test/scala/com/ing/baker/baas/ScalaDSLBaaSServerClientSpec.scala rename to baas-tests/src/test/scala/com/ing/baker/baas/spec/ScalaDSLBaaSServerClientSpec.scala index 6c99a7d3c..51e09fdb5 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/ScalaDSLBaaSServerClientSpec.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/spec/ScalaDSLBaaSServerClientSpec.scala @@ -1,4 +1,4 @@ -package com.ing.baker.baas +package com.ing.baker.baas.spec import com.ing.baker.baas.scaladsl.BakerClient import com.ing.baker.runtime.serialization.Encryption diff --git a/runtime/src/main/resources/reference.conf b/runtime/src/main/resources/reference.conf index 49a64d688..9aeeb4d31 100644 --- a/runtime/src/main/resources/reference.conf +++ b/runtime/src/main/resources/reference.conf @@ -64,7 +64,7 @@ akka { serializers { - baker-typed-protobuf = "com.ing.baker.runtime.serialization.BakerTypedProtobufSerializer" + baker-typed-protobuf = "com.ing.baker.runtime.akka.actor.serialization.BakerTypedProtobufSerializer" } diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala index 33eb4919d..97b06ebc9 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/internal/InteractionManager.scala @@ -5,6 +5,7 @@ import java.util.concurrent.ConcurrentHashMap import akka.actor.ActorSystem import akka.pattern.ask import akka.util.Timeout +import com.ing.baker.baas.protocol.ProtocolInteractionExecution import com.ing.baker.il.petrinet.InteractionTransition import com.ing.baker.runtime.akka.actor.interaction_scheduling.QuestMandated.Start import com.ing.baker.runtime.akka.actor.interaction_scheduling.QuestMandated @@ -20,6 +21,7 @@ trait InteractionManager { def executeImplementation(interaction: InteractionTransition, input: Seq[IngredientInstance]): Future[Option[EventInstance]] + def addImplementation(interaction: InteractionInstance): Unit } class InteractionManagerDis(system: ActorSystem, postTimeout: Timeout, computationTimeout: Timeout) extends InteractionManager { @@ -38,6 +40,9 @@ class InteractionManagerDis(system: ActorSystem, postTimeout: Timeout, computati } override def hasImplementation(interaction: InteractionTransition): Boolean = true + + override def addImplementation(interaction: InteractionInstance): Unit = + throw new NotImplementedError("addImplementation is not implemented for the distributed interaction manager, please deploy interactions using the baas-node-interaction library") } /** From 30b702f594825847d2ee0bfec6552eacbee70204 Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Fri, 25 Oct 2019 11:47:44 +0200 Subject: [PATCH 34/86] fixed runtime tests --- .../TypedProtobufSerializer.scala | 2 +- .../runtime/akka/BakerExecutionSpec.scala | 1 - .../InstanceSchedulingSpec.scala | 94 ------------------- .../serialization/SerializationSpec.scala | 2 +- 4 files changed, 2 insertions(+), 97 deletions(-) delete mode 100644 runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InstanceSchedulingSpec.scala diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TypedProtobufSerializer.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TypedProtobufSerializer.scala index 4f5577f1e..4624263c8 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TypedProtobufSerializer.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TypedProtobufSerializer.scala @@ -71,7 +71,7 @@ object TypedProtobufSerializer { abstract class TypedProtobufSerializer(system: ExtendedActorSystem, entries: SerializersProvider => List[BinarySerializable]) extends SerializerWithStringManifest { - def serializersProvider: SerializersProvider = + implicit def serializersProvider: SerializersProvider = SerializersProvider(system, system.provider) lazy val entriesMem: List[BinarySerializable] = diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala index 757372d51..1648c872d 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala @@ -227,7 +227,6 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { | auto-down-unreachable-after = 10s | } |} - |baker.interaction-manager = remote """.stripMargin).withFallback(ConfigFactory.load()) val baker = AkkaBaker(config, ActorSystem.apply("remoteTest", config)) diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InstanceSchedulingSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InstanceSchedulingSpec.scala deleted file mode 100644 index b9cf18030..000000000 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/interaction_scheduling/InstanceSchedulingSpec.scala +++ /dev/null @@ -1,94 +0,0 @@ -package com.ing.baker.runtime.akka.actor.interaction_scheduling - -import akka.actor.{ActorRef, ActorSystem} -import akka.testkit.{ImplicitSender, TestKit} -import akka.util.Timeout -import cats.effect.{IO, Timer} -import com.ing.baker.runtime.akka.actor.interaction_scheduling.ProtocolInteractionExecution.InstanceExecutedSuccessfully -import com.ing.baker.runtime.akka.actor.interaction_scheduling.QuestMandated.Start -import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance, InteractionInstance} -import com.ing.baker.types.{CharArray, PrimitiveValue} -import com.typesafe.config.{Config, ConfigFactory} -import org.scalatest.concurrent.Eventually -import org.scalatest.mockito.MockitoSugar -import org.scalatest.{BeforeAndAfter, BeforeAndAfterAll, Matchers, WordSpecLike} - -import scala.concurrent.duration._ - -object InstanceSchedulingSpec { - - val config: Config = ConfigFactory.parseString( - """ - |akka { - | actor { - | provider = "cluster" - | } - | remote { - | log-remote-lifecycle-events = off - | netty.tcp { - | hostname = "127.0.0.1" - | port = 2551 - | } - | } - | - | cluster { - | seed-nodes = ["akka.tcp://InstanceSchedulingSpec@127.0.0.1:2551"] - | auto-down-unreachable-after = 10s - | } - |} - """.stripMargin) -} - -class InstanceSchedulingSpec extends TestKit(ActorSystem("InstanceSchedulingSpec", config = InstanceSchedulingSpec.config)) - with ImplicitSender - with WordSpecLike - with Matchers - with BeforeAndAfterAll - with BeforeAndAfter - with MockitoSugar - with Eventually { - - implicit val timer: Timer[IO] = IO.timer(system.dispatcher) - - val recipeName: String = "TestRecipe" - - def work(str: String): IO[String] = - IO.sleep(1 millis).map(_ => str.toUpperCase()) - - val interaction: InteractionInstance = - InteractionInstance( - "TestInstance", - Seq(CharArray), - ingredients => - work(ingredients.head.value.as[String]).map(res => { - Some(EventInstance("TestDone", Map("upper" -> PrimitiveValue(res)))) - }).unsafeToFuture() - ) - - val jobs: List[String] = - List.fill(1000)("hello") - - def buildAgents(): List[ActorRef] = - List( - system.actorOf(InteractionAgent(interaction)), - system.actorOf(InteractionAgent(interaction)) - ) - - def buildMandated(job: String, manager: ActorRef): ActorRef = - system.actorOf(QuestMandated(Seq(IngredientInstance("test-ingredient", PrimitiveValue(job))), interaction.name, Timeout.durationToTimeout(10 seconds), Timeout.durationToTimeout(60 seconds))) - - "The Instance scheduling protocol" should { - "simple run success" in { - buildAgents() - jobs.foreach(buildMandated(_, self) ! Start) - receiveN(jobs.length).foreach { job => - job.asInstanceOf[InstanceExecutedSuccessfully] match { - case InstanceExecutedSuccessfully(Some(EventInstance("TestDone", map))) => - map("upper").as[String] shouldBe "HELLO" - case other => - fail(other + " is not a successful execution result") - } - } - } - } -} diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala index cab04ef98..7cb323599 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/serialization/SerializationSpec.scala @@ -21,7 +21,7 @@ import com.ing.baker.runtime.serialization.Encryption.{AESEncryption, NoEncrypti import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto} import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.scaladsl.{EventInstance, EventMoment, RecipeInstanceState, SensoryEventResult} -import com.ing.baker.runtime.serialization.{BakerTypedProtobufSerializer, ProtoMap} +import com.ing.baker.runtime.serialization.ProtoMap import com.ing.baker.types.modules.PrimitiveModuleSpec._ import com.ing.baker.types.{Value, _} import com.ing.baker.{AllTypeRecipe, types} From f58cbfef97c1a75c4d874d038fec9311d39bb4fb Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Fri, 25 Oct 2019 16:29:29 +0200 Subject: [PATCH 35/86] Finished work on modules and started work on the distributed recipe event publishing --- .../src/main/resources/reference.conf | 20 +++++++++++ .../baker/baas/akka/EventListenerAgent.scala | 34 +++++++++++++++++++ .../baker/baas/akka/ProtobufSerializer.scala | 21 ++++++++++++ .../baker/baas/common/BaaSEventListener.scala | 12 +++++++ .../baas/javadsl/BaaSEventListener.scala | 16 +++++++++ .../baas/scaladsl/BaaSEventListener.scala | 18 ++++++++++ .../com/ing/baker/baas/state/BaaSServer.scala | 9 ++++- .../ProtocolInteractionExecution.scala | 3 +- .../protocol/ProtocolPushPullMatching.scala | 3 +- .../baas/protocol/ProtocolQuestCommit.scala | 3 +- .../protobuf/recipe_event_publishing.proto | 14 ++++++++ .../DistributedEventPublishingProto.scala | 27 +++++++++++++++ .../ProtocolDistributedEventPublishing.scala | 14 ++++++++ build.sbt | 23 +++++++++++-- runtime/src/main/resources/reference.conf | 3 ++ 15 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 baas-node-event-listener/src/main/resources/reference.conf create mode 100644 baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala create mode 100644 baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala create mode 100644 baas-node-event-listener/src/main/scala/com/ing/baker/baas/common/BaaSEventListener.scala create mode 100644 baas-node-event-listener/src/main/scala/com/ing/baker/baas/javadsl/BaaSEventListener.scala create mode 100644 baas-node-event-listener/src/main/scala/com/ing/baker/baas/scaladsl/BaaSEventListener.scala create mode 100644 baas-protocol-recipe-event-publishing/src/main/protobuf/recipe_event_publishing.proto create mode 100644 baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/DistributedEventPublishingProto.scala create mode 100644 baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/ProtocolDistributedEventPublishing.scala diff --git a/baas-node-event-listener/src/main/resources/reference.conf b/baas-node-event-listener/src/main/resources/reference.conf new file mode 100644 index 000000000..ad61794e3 --- /dev/null +++ b/baas-node-event-listener/src/main/resources/reference.conf @@ -0,0 +1,20 @@ + +akka { + + actor { + + allow-java-serialization = off + + serializers { + + baker-typed-protobuf = "com.ing.baker.baas.akka.ProtobufSerializer" + + } + + serialization-bindings { + + "com.ing.baker.runtime.serialization.BakerSerializable" = baker-typed-protobuf + + } + } +} diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala new file mode 100644 index 000000000..fadb0bce0 --- /dev/null +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala @@ -0,0 +1,34 @@ +package com.ing.baker.baas.akka + +import akka.actor.{Actor, ActorRef, Props} +import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} +import com.ing.baker.baas.protocol.ProtocolDistributedEventPublishing +import com.ing.baker.runtime.scaladsl.EventInstance + +object EventListenerAgent { + + case object CommitTimeout + + def apply(recipeName: String, listenerFunction: (String, EventInstance) => Unit): Props = + Props(new EventListenerAgent(recipeName, listenerFunction)) +} + +class EventListenerAgent(recipeName: String, listenerFunction: (String, EventInstance) => Unit) extends Actor { + + val mediator: ActorRef = + DistributedPubSub(context.system).mediator + + val eventsTopic: String = + ProtocolDistributedEventPublishing.eventsTopic(recipeName) + + def subscribeToEvents(): Unit = + mediator ! DistributedPubSubMediator.Subscribe(eventsTopic, self) + + def unsubscribeToEvents(): Unit = + mediator ! DistributedPubSubMediator.Unsubscribe(eventsTopic, self) + + def receive: Receive = { + case ProtocolDistributedEventPublishing.Event(recipeInstanceId, event) => + listenerFunction(recipeInstanceId, event) + } +} diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala new file mode 100644 index 000000000..a36a23242 --- /dev/null +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala @@ -0,0 +1,21 @@ +package com.ing.baker.baas.akka + +import akka.actor.ExtendedActorSystem +import com.ing.baker.baas.protocol.ProtocolDistributedEventPublishing +import com.ing.baker.runtime.serialization.TypedProtobufSerializer.BinarySerializable +import com.ing.baker.runtime.serialization.{SerializersProvider, TypedProtobufSerializer} +import com.ing.baker.runtime.serialization.TypedProtobufSerializer.forType +import com.ing.baker.baas.protocol.DistributedEventPublishingProto._ + +object ProtobufSerializer { + + def entries(ev0: SerializersProvider): List[BinarySerializable] = { + implicit val ev = ev0 + List( + forType[ProtocolDistributedEventPublishing.Event] + .register("ProtocolDistributedEventPublishing.Event") + ) + } +} + +class ProtobufSerializer(system: ExtendedActorSystem) extends TypedProtobufSerializer(system, ProtobufSerializer.entries) diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/common/BaaSEventListener.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/common/BaaSEventListener.scala new file mode 100644 index 000000000..e012525fc --- /dev/null +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/common/BaaSEventListener.scala @@ -0,0 +1,12 @@ +package com.ing.baker.baas.common + +import com.ing.baker.runtime.common.{EventInstance, InteractionInstance} +import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi + +trait BaaSEventListener[F[_]] extends LanguageApi { self => + + type EventInstanceType <: EventInstance { type Language <: self.Language } + + def registerEventListener(recipeName: String, listenerFunction: language.BiConsumerFunction[String, EventInstanceType]): F[Unit] + +} diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/javadsl/BaaSEventListener.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/javadsl/BaaSEventListener.scala new file mode 100644 index 000000000..d2fa9ec14 --- /dev/null +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/javadsl/BaaSEventListener.scala @@ -0,0 +1,16 @@ +package com.ing.baker.baas.javadsl + +import java.util.concurrent.CompletableFuture +import java.util.function.BiConsumer + +import akka.actor.ActorSystem +import com.ing.baker.baas.common +import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi +import com.ing.baker.runtime.javadsl.EventInstance + +class BaaSEventListener(actorSystem: ActorSystem) extends common.BaaSEventListener[CompletableFuture] with JavaApi { + + override type EventInstanceType = EventInstance + + override def registerEventListener(recipeName: String, listenerFunction: BiConsumer[String, EventInstance]): CompletableFuture[Unit] = ??? +} diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/scaladsl/BaaSEventListener.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/scaladsl/BaaSEventListener.scala new file mode 100644 index 000000000..928893aba --- /dev/null +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/scaladsl/BaaSEventListener.scala @@ -0,0 +1,18 @@ +package com.ing.baker.baas.scaladsl + +import akka.actor.ActorSystem +import com.ing.baker.baas.akka.EventListenerAgent +import com.ing.baker.baas.common +import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi +import com.ing.baker.runtime.scaladsl.EventInstance + +import scala.concurrent.Future + +case class BaaSEventListener(actorSystem: ActorSystem) extends common.BaaSEventListener[Future] with ScalaApi { + + override type EventInstanceType = EventInstance + + override def registerEventListener(recipeName: String, listenerFunction: (String, EventInstance) => Unit): Future[Unit] = + Future.successful { actorSystem.actorOf(EventListenerAgent(recipeName, listenerFunction)) } +} + diff --git a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala index db13d8cfc..addc3c649 100644 --- a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala +++ b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala @@ -8,7 +8,7 @@ import akka.stream.Materializer import com.ing.baker.baas.common.BaaSProto._ import com.ing.baker.baas.common.BaaSProtocol import com.ing.baker.baas.common.MarshallingUtils._ -import com.ing.baker.runtime.scaladsl.Baker +import com.ing.baker.runtime.scaladsl.{Baker, EventInstance} import com.ing.baker.runtime.serialization.{Encryption, SerializersProvider} import scala.concurrent.Future @@ -18,6 +18,13 @@ object BaaSServer { def run(baker: Baker, host: String, port: Int)(implicit system: ActorSystem, mat: Materializer): Future[Http.ServerBinding] = { val encryption = Encryption.NoEncryption val server = new BaaSServer()(system, mat, baker, encryption) + /* + baker.registerEventListener((instanceId: String, event: EventInstance) => { + // Publish an Event() message to the DistributedPublishSubscribe mediator + // We need the recipe id here D: + //event. + }) + */ Http().bindAndHandle(server.route, host, port) } } diff --git a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolInteractionExecution.scala b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolInteractionExecution.scala index 8628e45c4..6d24087ff 100644 --- a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolInteractionExecution.scala +++ b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolInteractionExecution.scala @@ -1,6 +1,7 @@ package com.ing.baker.baas.protocol import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance} +import com.ing.baker.runtime.serialization.BakerSerializable /** * Protocol executed after a match between a QuestMandate and InteractionAgent has been made and after both @@ -11,7 +12,7 @@ import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance} * InstanceExecutionFailed or InvalidExecution * */ -sealed trait ProtocolInteractionExecution //extends BakerSerializable +sealed trait ProtocolInteractionExecution extends BakerSerializable object ProtocolInteractionExecution { diff --git a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolPushPullMatching.scala b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolPushPullMatching.scala index d20e968c2..0e179ee9c 100644 --- a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolPushPullMatching.scala +++ b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolPushPullMatching.scala @@ -3,11 +3,12 @@ package com.ing.baker.baas.protocol import java.util.UUID import akka.actor.ActorRef +import com.ing.baker.runtime.serialization.BakerSerializable /** * Protocol done to find a possible matching between a QuestMandated and an available InteractionAgent */ -sealed trait ProtocolPushPullMatching //extends BakerSerializable +sealed trait ProtocolPushPullMatching extends BakerSerializable object ProtocolPushPullMatching { diff --git a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolQuestCommit.scala b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolQuestCommit.scala index 8303a78da..c412fe7f7 100644 --- a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolQuestCommit.scala +++ b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolQuestCommit.scala @@ -1,12 +1,13 @@ package com.ing.baker.baas.protocol import akka.actor.ActorRef +import com.ing.baker.runtime.serialization.BakerSerializable /** * A Protocol executed after finding a candidate match between a QuestMandated and an InteractionAgent, it makes sure * that 1 QuestMandated commits with 1 InteractionAgent only and vice versa, without leaving orphan agents. */ -sealed trait ProtocolQuestCommit //extends BakerSerializable +sealed trait ProtocolQuestCommit extends BakerSerializable object ProtocolQuestCommit { diff --git a/baas-protocol-recipe-event-publishing/src/main/protobuf/recipe_event_publishing.proto b/baas-protocol-recipe-event-publishing/src/main/protobuf/recipe_event_publishing.proto new file mode 100644 index 000000000..f7b0574d7 --- /dev/null +++ b/baas-protocol-recipe-event-publishing/src/main/protobuf/recipe_event_publishing.proto @@ -0,0 +1,14 @@ +syntax = "proto2"; + +import "scalapb/scalapb.proto"; +import "common.proto"; + +option java_package = "com.ing.baker.baas.protocol.protobuf"; +option (scalapb.options) = { + flat_package: true +}; + +message Event { + optional string recipeInstanceId = 1; + optional RuntimeEvent event = 2; +} diff --git a/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/DistributedEventPublishingProto.scala b/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/DistributedEventPublishingProto.scala new file mode 100644 index 000000000..93aace34e --- /dev/null +++ b/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/DistributedEventPublishingProto.scala @@ -0,0 +1,27 @@ +package com.ing.baker.baas.protocol + +import com.ing.baker.baas.protocol.ProtocolDistributedEventPublishing.Event +import com.ing.baker.runtime.serialization.ProtoMap +import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} + +import scala.util.Try + +object DistributedEventPublishingProto { + + implicit def eventProto: ProtoMap[Event, protobuf.Event] = + new ProtoMap[Event, protobuf.Event] { + + val companion = protobuf.Event + + def toProto(a: Event): protobuf.Event = + protobuf.Event(Some(a.recipeInstanceId), Some(ctxToProto(a.event))) + + def fromProto(message: protobuf.Event): Try[Event] = + for { + recipeInstanceId <- versioned(message.recipeInstanceId, "recipeInstanceId") + eventProto <- versioned(message.event, "event") + event <- ctxFromProto(eventProto) + } yield Event(recipeInstanceId, event) + } + +} diff --git a/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/ProtocolDistributedEventPublishing.scala b/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/ProtocolDistributedEventPublishing.scala new file mode 100644 index 000000000..6d683c1c7 --- /dev/null +++ b/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/ProtocolDistributedEventPublishing.scala @@ -0,0 +1,14 @@ +package com.ing.baker.baas.protocol + +import com.ing.baker.runtime.scaladsl.EventInstance +import com.ing.baker.runtime.serialization.BakerSerializable + +sealed trait ProtocolDistributedEventPublishing extends BakerSerializable + +object ProtocolDistributedEventPublishing { + + def eventsTopic(recipeName: String): String = + s"recipe-event-publishing:$recipeName:event" + + case class Event(recipeInstanceId: String, event: EventInstance) extends ProtocolDistributedEventPublishing +} diff --git a/build.sbt b/build.sbt index 381da3bba..1f9b22f28 100644 --- a/build.sbt +++ b/build.sbt @@ -138,7 +138,14 @@ lazy val runtime = project.in(file("runtime")) logback) ++ providedDeps(findbugs) ) - .dependsOn(intermediateLanguage, `baker-interface`, `baas-protocol-interaction-scheduling`, testScope(recipeDsl), testScope(recipeCompiler), testScope(bakertypes)) + .dependsOn( + intermediateLanguage, + `baker-interface`, + `baas-protocol-interaction-scheduling`, + `baas-protocol-recipe-event-publishing`, + testScope(recipeDsl), + testScope(recipeCompiler), + testScope(bakertypes)) .enablePlugins(MultiJvmPlugin) .configs(MultiJvm) @@ -217,6 +224,15 @@ lazy val `baas-protocol-interaction-scheduling` = project.in(file("baas-protocol ) .dependsOn(`baker-interface`) +lazy val `baas-protocol-recipe-event-publishing` = project.in(file("baas-protocol-recipe-event-publishing")) + .settings(defaultModuleSettings) + .settings(noPublishSettings) + .settings(scalaPBSettings) + .settings( + moduleName := "baas-protocol-recipe-event-publishing" + ) + .dependsOn(`baker-interface`) + lazy val `baas-node-client` = project.in(file("baas-node-client")) .settings(defaultModuleSettings) .settings( @@ -255,9 +271,12 @@ lazy val `baas-node-event-listener` = project.in(file("baas-node-event-listener" .settings( moduleName := "baas-node-event-listener", libraryDependencies ++= Seq( - akkaCluster + akkaCluster, + akkaClusterTools, + slf4jApi ) ) + .dependsOn(`baas-protocol-recipe-event-publishing`, `baker-interface`) lazy val `baas-tests` = project.in(file("baas-tests")) .settings(defaultModuleSettings) diff --git a/runtime/src/main/resources/reference.conf b/runtime/src/main/resources/reference.conf index 9aeeb4d31..599a31728 100644 --- a/runtime/src/main/resources/reference.conf +++ b/runtime/src/main/resources/reference.conf @@ -52,6 +52,9 @@ baker { # if enabled = on, a secret should be set # secret = ??? } + + # use "local" unless you are configuring a BaaS environment, then you will need "remote" + interaction-manager = "local" } akka { From 5c07f50a48e9dbba19eab6e5138d31c1be800e8f Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Fri, 1 Nov 2019 16:12:10 +0100 Subject: [PATCH 36/86] quick fix --- runtime/src/main/protobuf/process_instance.proto | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/src/main/protobuf/process_instance.proto b/runtime/src/main/protobuf/process_instance.proto index 81576e04d..886a8e670 100644 --- a/runtime/src/main/protobuf/process_instance.proto +++ b/runtime/src/main/protobuf/process_instance.proto @@ -18,14 +18,14 @@ message ConsumedToken { message Initialized { - option (scalapb.message).extends = "com.ing.baker.runtime.akka.actor.serialization.BakerSerializable"; + option (scalapb.message).extends = "com.ing.baker.runtime.serialization.BakerSerializable"; repeated ProducedToken initial_marking = 1; optional SerializedData initial_state = 2; } message TransitionFired { - option (scalapb.message).extends = "com.ing.baker.runtime.akka.actor.serialization.BakerSerializable"; + option (scalapb.message).extends = "com.ing.baker.runtime.serialization.BakerSerializable"; optional int64 job_id = 1; optional string correlation_id = 9; @@ -50,7 +50,7 @@ message FailureStrategy { message TransitionFailed { - option (scalapb.message).extends = "com.ing.baker.runtime.akka.actor.serialization.BakerSerializable"; + option (scalapb.message).extends = "com.ing.baker.runtime.serialization.BakerSerializable"; optional int64 job_id = 1; optional string correlation_id = 10; From b7ede2a1c15a89c4ca5c302584037c017f2a33b2 Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Mon, 4 Nov 2019 13:31:51 +0100 Subject: [PATCH 37/86] added the RecipeEventMEtadata data structure to event listeners, which should give enough information to the event listener to allow remote event listeners --- .../ing/baker/baas/scaladsl/BakerClient.scala | 6 +++--- .../spec/JavaDSLBaaSServerClientSpec.scala | 4 ++-- .../com/ing/baker/runtime/common/Baker.scala | 6 ++++-- .../runtime/common/RecipeEventMetadata.scala | 13 ++++++++++++ .../com/ing/baker/runtime/javadsl/Baker.scala | 15 +++++++------ .../runtime/javadsl/RecipeEventMetadata.scala | 21 +++++++++++++++++++ .../ing/baker/runtime/scaladsl/Baker.scala | 2 ++ .../scaladsl/RecipeEventMetadata.scala | 15 +++++++++++++ .../ing/baker/runtime/akka/AkkaBaker.scala | 18 ++++++++-------- .../runtime/akka/BakerExecutionSpec.scala | 14 ++++++------- 10 files changed, 83 insertions(+), 31 deletions(-) create mode 100644 baker-interface/src/main/scala/com/ing/baker/runtime/common/RecipeEventMetadata.scala create mode 100644 baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeEventMetadata.scala create mode 100644 baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeEventMetadata.scala diff --git a/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala b/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala index 4ad11dbb3..681af35e8 100644 --- a/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala +++ b/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala @@ -11,7 +11,7 @@ import com.ing.baker.baas.common.BaaSProto._ import com.ing.baker.baas.common.BaaSProtocol import com.ing.baker.baas.common.MarshallingUtils._ import com.ing.baker.runtime.common.SensoryEventStatus -import com.ing.baker.runtime.scaladsl.{BakerEvent, EventInstance, EventMoment, EventResolutions, InteractionInstance, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult, Baker => ScalaBaker} +import com.ing.baker.runtime.scaladsl.{BakerEvent, EventInstance, EventMoment, EventResolutions, InteractionInstance, RecipeEventMetadata, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult, Baker => ScalaBaker} import com.ing.baker.runtime.serialization.{Encryption, SerializersProvider} import com.ing.baker.types.Value @@ -250,7 +250,7 @@ case class BakerClient(hostname: Uri, encryption: Encryption = Encryption.NoEncr * * Note that the delivery guarantee is *AT MOST ONCE*. Do not use it for critical functionality */ - override def registerEventListener(recipeName: String, listenerFunction: (String, EventInstance) => Unit): Future[Unit] = + override def registerEventListener(recipeName: String, listenerFunction: (RecipeEventMetadata, EventInstance) => Unit): Future[Unit] = throw new NotImplementedError("registerEventListener is not implemented for client bakers") /** @@ -258,7 +258,7 @@ case class BakerClient(hostname: Uri, encryption: Encryption = Encryption.NoEncr * * Note that the delivery guarantee is *AT MOST ONCE*. Do not use it for critical functionality */ - override def registerEventListener(listenerFunction: (String, EventInstance) => Unit): Future[Unit] = + override def registerEventListener(listenerFunction: (RecipeEventMetadata, EventInstance) => Unit): Future[Unit] = throw new NotImplementedError("registerEventListener is not implemented for client bakers") /** diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/spec/JavaDSLBaaSServerClientSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/spec/JavaDSLBaaSServerClientSpec.scala index aef18fa80..727fe08fd 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/spec/JavaDSLBaaSServerClientSpec.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/spec/JavaDSLBaaSServerClientSpec.scala @@ -96,9 +96,9 @@ class JavaDSLBaaSServerClientSpec extends CommonBaaSServerClientSpec( .recoverWith { case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) } - override def registerEventListener(recipeName: String, listenerFunction: (String, EventInstance) => Unit): Future[Unit] = + override def registerEventListener(recipeName: String, listenerFunction: (RecipeEventMetadata, EventInstance) => Unit): Future[Unit] = ??? - override def registerEventListener(listenerFunction: (String, EventInstance) => Unit): Future[Unit] = + override def registerEventListener(listenerFunction: (RecipeEventMetadata, EventInstance) => Unit): Future[Unit] = ??? override def registerBakerEventListener(listenerFunction: BakerEvent => Unit): Future[Unit] = ??? diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/common/Baker.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/Baker.scala index db80f412a..98fa9dd5c 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/common/Baker.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/common/Baker.scala @@ -30,6 +30,8 @@ trait Baker[F[_]] extends LanguageApi { type EventMomentType <: EventMoment { type Language <: self.Language} + type RecipeMetadataType <: RecipeEventMetadata { type Language <: self.Language } + /** * Adds a recipe to baker and returns a recipeId for the recipe. * @@ -279,14 +281,14 @@ trait Baker[F[_]] extends LanguageApi { * * Note that the delivery guarantee is *AT MOST ONCE*. Do not use it for critical functionality */ - def registerEventListener(recipeName: String, listenerFunction: language.BiConsumerFunction[String, EventInstanceType]): F[Unit] + def registerEventListener(recipeName: String, listenerFunction: language.BiConsumerFunction[RecipeMetadataType, EventInstanceType]): F[Unit] /** * Registers a listener to all runtime events for all recipes that run in this Baker instance. * * Note that the delivery guarantee is *AT MOST ONCE*. Do not use it for critical functionality */ - def registerEventListener(listenerFunction: language.BiConsumerFunction[String, EventInstanceType]): F[Unit] + def registerEventListener(listenerFunction: language.BiConsumerFunction[RecipeMetadataType, EventInstanceType]): F[Unit] /** * Registers a listener function that listens to all BakerEvents diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/common/RecipeEventMetadata.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/common/RecipeEventMetadata.scala new file mode 100644 index 000000000..34f5b1f4c --- /dev/null +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/common/RecipeEventMetadata.scala @@ -0,0 +1,13 @@ +package com.ing.baker.runtime.common + +import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi + +trait RecipeEventMetadata extends LanguageApi { + + def recipeId: String + + def recipeName: String + + def recipeInstanceId: String + +} diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala index e4c690701..58df4170d 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/Baker.scala @@ -36,6 +36,8 @@ class Baker private[baker](private val baker: scaladsl.Baker) extends common.Bak override type EventMomentType = EventMoment + override type RecipeMetadataType = RecipeEventMetadata + /** * Adds a recipe to baker and returns a recipeId for the recipe. * @@ -254,10 +256,9 @@ class Baker private[baker](private val baker: scaladsl.Baker) extends common.Bak * @param recipeName the name of all recipes this event listener should be triggered for * @param listenerFunction The listener to subscribe to events. */ - override def registerEventListener(@Nonnull recipeName: String, @Nonnull listenerFunction: BiConsumer[String, EventInstance]): CompletableFuture[Unit] = + override def registerEventListener(@Nonnull recipeName: String, @Nonnull listenerFunction: BiConsumer[RecipeEventMetadata, EventInstance]): CompletableFuture[Unit] = toCompletableFuture(baker.registerEventListener(recipeName, - (recipeInstanceId: String, event: scaladsl.EventInstance) => listenerFunction.accept(recipeInstanceId, event.asJava))) - + (recipeEventMetadata: scaladsl.RecipeEventMetadata, event: scaladsl.EventInstance) => listenerFunction.accept(recipeEventMetadata.asJava, event.asJava))) /** * Registers a listener function to all runtime events for this baker instance. @@ -276,10 +277,9 @@ class Baker private[baker](private val baker: scaladsl.Baker) extends common.Bak * * @param listenerFunction The listener function that is called once these events occur */ - override def registerEventListener(@Nonnull listenerFunction: BiConsumer[String, EventInstance]): CompletableFuture[Unit] = + override def registerEventListener(@Nonnull listenerFunction: BiConsumer[RecipeEventMetadata, EventInstance]): CompletableFuture[Unit] = toCompletableFuture(baker.registerEventListener( - (recipeInstanceId: String, event: scaladsl.EventInstance) => listenerFunction.accept(recipeInstanceId, event.asJava))) - + (recipeEventMetadata: scaladsl.RecipeEventMetadata, event: scaladsl.EventInstance) => listenerFunction.accept(recipeEventMetadata.asJava, event.asJava))) /** * Registers a listener function to all runtime events for this baker instance. @@ -300,8 +300,7 @@ class Baker private[baker](private val baker: scaladsl.Baker) extends common.Bak */ @deprecated(message = "Replaced with the consumer function variant", since = "3.0.0") def registerEventListener(@Nonnull eventListener: EventListener): Future[Unit] = - baker.registerEventListener((recipeInstanceId: String, runtimeEvent: scaladsl.EventInstance) => eventListener.processEvent(recipeInstanceId, runtimeEvent.asJava)) - + baker.registerEventListener((recipeEventMetadata: scaladsl.RecipeEventMetadata, runtimeEvent: scaladsl.EventInstance) => eventListener.processEvent(recipeEventMetadata.recipeInstanceId, runtimeEvent.asJava)) /** * Registers a listener that listens to all Baker events diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeEventMetadata.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeEventMetadata.scala new file mode 100644 index 000000000..8dd1b5c55 --- /dev/null +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/javadsl/RecipeEventMetadata.scala @@ -0,0 +1,21 @@ +package com.ing.baker.runtime.javadsl + +import com.ing.baker.runtime.common +import com.ing.baker.runtime.scaladsl +import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi + +case class RecipeEventMetadata(recipeId: String, recipeName: String, recipeInstanceId: String) extends common.RecipeEventMetadata with JavaApi { + + def getRecipeId: String = recipeId + + def getRecipeName: String = recipeName + + def getRecipeInstanceId: String = recipeInstanceId + + def asScala: scaladsl.RecipeEventMetadata = + scaladsl.RecipeEventMetadata( + recipeId = recipeId, + recipeName = recipeName, + recipeInstanceId = recipeInstanceId + ) +} diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala index 9770cd60d..da0d0d715 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/Baker.scala @@ -30,6 +30,8 @@ trait Baker extends common.Baker[Future] with ScalaApi { override type EventMomentType = EventMoment + override type RecipeMetadataType = RecipeEventMetadata + override def fireEventAndResolveWhenReceived(recipeInstanceId: String, event: EventInstance): Future[SensoryEventStatus] = fireEventAndResolveWhenReceived(recipeInstanceId, event, None) diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeEventMetadata.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeEventMetadata.scala new file mode 100644 index 000000000..fb37f161c --- /dev/null +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/scaladsl/RecipeEventMetadata.scala @@ -0,0 +1,15 @@ +package com.ing.baker.runtime.scaladsl + +import com.ing.baker.runtime.common +import com.ing.baker.runtime.javadsl +import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi + +case class RecipeEventMetadata(recipeId: String, recipeName: String, recipeInstanceId: String) extends common.RecipeEventMetadata with ScalaApi { + + def asJava: javadsl.RecipeEventMetadata = + javadsl.RecipeEventMetadata( + recipeId = recipeId, + recipeName = recipeName, + recipeInstanceId = recipeInstanceId + ) +} diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala index 60b449f58..d29d13389 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBaker.scala @@ -375,14 +375,14 @@ class AkkaBaker private[runtime](config: AkkaBakerConfig) extends scaladsl.Baker } yield response } - private def doRegisterEventListener(listenerFunction: (String, EventInstance) => Unit, processFilter: String => Boolean): Future[Unit] = { + private def doRegisterEventListener(listenerFunction: (RecipeEventMetadata, EventInstance) => Unit, processFilter: String => Boolean): Future[Unit] = { registerBakerEventListener { - case EventReceived(_, recipeName, _, recipeInstanceId, _, event) if processFilter(recipeName) => - listenerFunction.apply(recipeInstanceId, event) - case InteractionCompleted(_, _, recipeName, _, recipeInstanceId, _, Some(event)) if processFilter(recipeName) => - listenerFunction.apply(recipeInstanceId, event) - case InteractionFailed(_, _, recipeName, _, recipeInstanceId, _, _, _, ExceptionStrategyOutcome.Continue(eventName)) if processFilter(recipeName) => - listenerFunction.apply(recipeInstanceId, EventInstance(eventName, Map.empty)) + case EventReceived(_, recipeName, recipeId, recipeInstanceId, _, event) if processFilter(recipeName) => + listenerFunction.apply(RecipeEventMetadata(recipeId = recipeId, recipeName = recipeName, recipeInstanceId = recipeInstanceId), event) + case InteractionCompleted(_, _, recipeName, recipeId, recipeInstanceId, _, Some(event)) if processFilter(recipeName) => + listenerFunction.apply(RecipeEventMetadata(recipeId = recipeId, recipeName = recipeName, recipeInstanceId = recipeInstanceId), event) + case InteractionFailed(_, _, recipeName, recipeId, recipeInstanceId, _, _, _, ExceptionStrategyOutcome.Continue(eventName)) if processFilter(recipeName) => + listenerFunction.apply(RecipeEventMetadata(recipeId = recipeId, recipeName = recipeName, recipeInstanceId = recipeInstanceId), EventInstance(eventName, Map.empty)) case _ => () } } @@ -392,7 +392,7 @@ class AkkaBaker private[runtime](config: AkkaBakerConfig) extends scaladsl.Baker * * Note that the delivery guarantee is *AT MOST ONCE*. Do not use it for critical functionality */ - override def registerEventListener(recipeName: String, listenerFunction: (String, EventInstance) => Unit): Future[Unit] = + override def registerEventListener(recipeName: String, listenerFunction: (RecipeEventMetadata, EventInstance) => Unit): Future[Unit] = doRegisterEventListener(listenerFunction, _ == recipeName) /** @@ -401,7 +401,7 @@ class AkkaBaker private[runtime](config: AkkaBakerConfig) extends scaladsl.Baker * Note that the delivery guarantee is *AT MOST ONCE*. Do not use it for critical functionality */ // @deprecated("Use event bus instead", "1.4.0") - override def registerEventListener(listenerFunction: (String, EventInstance) => Unit): Future[Unit] = + override def registerEventListener(listenerFunction: (RecipeEventMetadata, EventInstance) => Unit): Future[Unit] = doRegisterEventListener(listenerFunction, _ => true) /** diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala index 1648c872d..dc2395586 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala @@ -16,7 +16,7 @@ import com.ing.baker.recipe.common.InteractionFailureStrategy.FireEventAfterFail import com.ing.baker.recipe.scaladsl.{Event, Ingredient, Interaction, Recipe} import com.ing.baker.runtime.common.BakerException._ import com.ing.baker.runtime.common._ -import com.ing.baker.runtime.scaladsl.{Baker, EventInstance, InteractionInstance} +import com.ing.baker.runtime.scaladsl.{Baker, EventInstance, InteractionInstance, RecipeEventMetadata} import com.ing.baker.types.{CharArray, Int32, PrimitiveValue} import com.typesafe.config.{Config, ConfigFactory} import org.mockito.Matchers.{eq => mockitoEq, _} @@ -600,7 +600,7 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { } "notify a registered event listener of events" in { - val listenerMock = mock[(String, EventInstance) => Unit] + val listenerMock = mock[(RecipeEventMetadata, EventInstance) => Unit] when(testInteractionOneMock.apply(anyString(), anyString())).thenReturn(Future.successful(InteractionOneSuccessful(interactionOneIngredientValue))) val recipe = Recipe("EventListenerRecipe") @@ -613,8 +613,8 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { recipeInstanceId = UUID.randomUUID().toString _ <- baker.bake(recipeId, recipeInstanceId) _ <- baker.fireEventAndResolveWhenCompleted(recipeInstanceId, EventInstance.unsafeFrom(InitialEvent(initialIngredientValue))) - _ = verify(listenerMock).apply(mockitoEq(recipeInstanceId.toString), argThat(new RuntimeEventMatcher(EventInstance.unsafeFrom(InitialEvent(initialIngredientValue))))) - _ = verify(listenerMock).apply(mockitoEq(recipeInstanceId.toString), argThat(new RuntimeEventMatcher(EventInstance.unsafeFrom(InteractionOneSuccessful(interactionOneIngredientValue))))) + _ = verify(listenerMock).apply(mockitoEq(RecipeEventMetadata(recipeId, recipe.name, recipeInstanceId.toString)), argThat(new RuntimeEventMatcher(EventInstance.unsafeFrom(InitialEvent(initialIngredientValue))))) + _ = verify(listenerMock).apply(mockitoEq(RecipeEventMetadata(recipeId, recipe.name, recipeInstanceId.toString)), argThat(new RuntimeEventMatcher(EventInstance.unsafeFrom(InteractionOneSuccessful(interactionOneIngredientValue))))) } yield succeed } @@ -1010,7 +1010,7 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { for { (baker, recipeId) <- setupBakerWithRecipe(recipe, mockImplementations) - listenerMock = mock[(String, EventInstance) => Unit] + listenerMock = mock[(RecipeEventMetadata, EventInstance) => Unit] _ <- baker.registerEventListener("ImmediateFailureEvent", listenerMock) recipeInstanceId = UUID.randomUUID().toString @@ -1021,8 +1021,8 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { _ <- Future { Thread.sleep(50) } - _ = verify(listenerMock).apply(mockitoEq(recipeInstanceId.toString), argThat(new RuntimeEventMatcher(EventInstance.unsafeFrom(InitialEvent(initialIngredientValue))))) - _ = verify(listenerMock).apply(mockitoEq(recipeInstanceId.toString), argThat(new RuntimeEventMatcher(EventInstance(interactionOne.retryExhaustedEventName, Map.empty)))) + _ = verify(listenerMock).apply(mockitoEq(RecipeEventMetadata(recipeId, recipe.name, recipeInstanceId.toString)), argThat(new RuntimeEventMatcher(EventInstance.unsafeFrom(InitialEvent(initialIngredientValue))))) + _ = verify(listenerMock).apply(mockitoEq(RecipeEventMetadata(recipeId, recipe.name, recipeInstanceId.toString)), argThat(new RuntimeEventMatcher(EventInstance(interactionOne.retryExhaustedEventName, Map.empty)))) state <- baker.getRecipeInstanceState(recipeInstanceId) } yield state.eventNames should contain(interactionOne.retryExhaustedEventName) From f611a189ce9f791511c97fa8eabd8ce6aa04f847 Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Mon, 4 Nov 2019 17:21:25 +0100 Subject: [PATCH 38/86] Massive improvements on integration tests of baas --- .../ing/baker/baas/scaladsl/BakerClient.scala | 6 +- .../baker/baas/akka/EventListenerAgent.scala | 10 +- .../baas/javadsl/BaaSEventListener.scala | 14 +- .../BaaSEventListener.scala | 8 +- .../baas/scaladsl/BaaSEventListener.scala | 10 +- .../javadsl/BaaSInteractionInstance.scala | 4 +- .../BaaSInteractionInstance.scala | 2 +- .../scaladsl/BaaSInteractionInstance.scala | 4 +- .../com/ing/baker/baas/state/BaaSServer.scala | 42 ++-- .../src/main/protobuf/baas.proto | 2 +- .../baas/{common => protocol}/BaaSProto.scala | 5 +- .../{common => protocol}/BaaSProtocol.scala | 2 +- .../MarshallingUtils.scala | 2 +- .../protobuf/recipe_event_publishing.proto | 2 +- .../DistributedEventPublishingProto.scala | 7 +- .../ProtocolDistributedEventPublishing.scala | 4 +- .../src/test/resources/application.conf | 93 ++++++++ ...ntSpec.scala => BaaSIntegrationSpec.scala} | 213 +++++++++++------- .../spec/JavaDSLBaaSServerClientSpec.scala | 140 ------------ .../spec/ScalaDSLBaaSServerClientSpec.scala | 9 - .../src/main/protobuf/common.proto | 6 + .../runtime/serialization/ProtoMap.scala | 3 + .../RecipeEventMetadataMapping.scala | 24 ++ runtime/src/main/resources/reference.conf | 1 + .../BakerTypedProtobufSerializer.scala | 4 +- 25 files changed, 339 insertions(+), 278 deletions(-) rename baas-node-event-listener/src/main/scala/com/ing/baker/baas/{common => protocol}/BaaSEventListener.scala (58%) rename baas-node-interaction/src/main/scala/com/ing/baker/baas/{common => protocol}/BaaSInteractionInstance.scala (90%) rename baas-protocol-baker/src/main/scala/com/ing/baker/baas/{common => protocol}/BaaSProto.scala (99%) rename baas-protocol-baker/src/main/scala/com/ing/baker/baas/{common => protocol}/BaaSProtocol.scala (98%) rename baas-protocol-baker/src/main/scala/com/ing/baker/baas/{common => protocol}/MarshallingUtils.scala (98%) create mode 100644 baas-tests/src/test/resources/application.conf rename baas-tests/src/test/scala/com/ing/baker/baas/spec/{CommonBaaSServerClientSpec.scala => BaaSIntegrationSpec.scala} (63%) delete mode 100644 baas-tests/src/test/scala/com/ing/baker/baas/spec/JavaDSLBaaSServerClientSpec.scala delete mode 100644 baas-tests/src/test/scala/com/ing/baker/baas/spec/ScalaDSLBaaSServerClientSpec.scala create mode 100644 baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/RecipeEventMetadataMapping.scala diff --git a/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala b/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala index 681af35e8..5d4273765 100644 --- a/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala +++ b/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala @@ -7,9 +7,9 @@ import akka.http.scaladsl.model.Uri.Path import akka.http.scaladsl.model.{HttpMethods, HttpRequest, MessageEntity, Uri} import akka.stream.Materializer import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} -import com.ing.baker.baas.common.BaaSProto._ -import com.ing.baker.baas.common.BaaSProtocol -import com.ing.baker.baas.common.MarshallingUtils._ +import com.ing.baker.baas.protocol.BaaSProto._ +import com.ing.baker.baas.protocol.BaaSProtocol +import com.ing.baker.baas.protocol.MarshallingUtils._ import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.scaladsl.{BakerEvent, EventInstance, EventMoment, EventResolutions, InteractionInstance, RecipeEventMetadata, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult, Baker => ScalaBaker} import com.ing.baker.runtime.serialization.{Encryption, SerializersProvider} diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala index fadb0bce0..70cd77fa4 100644 --- a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala @@ -3,17 +3,17 @@ package com.ing.baker.baas.akka import akka.actor.{Actor, ActorRef, Props} import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} import com.ing.baker.baas.protocol.ProtocolDistributedEventPublishing -import com.ing.baker.runtime.scaladsl.EventInstance +import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeEventMetadata} object EventListenerAgent { case object CommitTimeout - def apply(recipeName: String, listenerFunction: (String, EventInstance) => Unit): Props = + def apply(recipeName: String, listenerFunction: (RecipeEventMetadata, EventInstance) => Unit): Props = Props(new EventListenerAgent(recipeName, listenerFunction)) } -class EventListenerAgent(recipeName: String, listenerFunction: (String, EventInstance) => Unit) extends Actor { +class EventListenerAgent(recipeName: String, listenerFunction: (RecipeEventMetadata, EventInstance) => Unit) extends Actor { val mediator: ActorRef = DistributedPubSub(context.system).mediator @@ -28,7 +28,7 @@ class EventListenerAgent(recipeName: String, listenerFunction: (String, EventIns mediator ! DistributedPubSubMediator.Unsubscribe(eventsTopic, self) def receive: Receive = { - case ProtocolDistributedEventPublishing.Event(recipeInstanceId, event) => - listenerFunction(recipeInstanceId, event) + case ProtocolDistributedEventPublishing.Event(recipeEventMetadata, event) => + listenerFunction(recipeEventMetadata, event) } } diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/javadsl/BaaSEventListener.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/javadsl/BaaSEventListener.scala index d2fa9ec14..12ee382ab 100644 --- a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/javadsl/BaaSEventListener.scala +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/javadsl/BaaSEventListener.scala @@ -4,13 +4,19 @@ import java.util.concurrent.CompletableFuture import java.util.function.BiConsumer import akka.actor.ActorSystem -import com.ing.baker.baas.common +import com.ing.baker.baas.protocol +import com.ing.baker.baas.scaladsl import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi -import com.ing.baker.runtime.javadsl.EventInstance +import com.ing.baker.runtime.javadsl.{EventInstance, RecipeEventMetadata} -class BaaSEventListener(actorSystem: ActorSystem) extends common.BaaSEventListener[CompletableFuture] with JavaApi { +import scala.compat.java8.FutureConverters + +class BaaSEventListener(actorSystem: ActorSystem) extends protocol.BaaSEventListener[CompletableFuture] with JavaApi { override type EventInstanceType = EventInstance - override def registerEventListener(recipeName: String, listenerFunction: BiConsumer[String, EventInstance]): CompletableFuture[Unit] = ??? + override type RecipeEventMetadataType = RecipeEventMetadata + + override def registerEventListener(recipeName: String, listenerFunction: BiConsumer[RecipeEventMetadata, EventInstance]): CompletableFuture[Unit] = + FutureConverters.toJava(scaladsl.BaaSEventListener(actorSystem).registerEventListener(recipeName, (metadata, event) => listenerFunction.accept(metadata.asJava, event.asJava))).toCompletableFuture } diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/common/BaaSEventListener.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/protocol/BaaSEventListener.scala similarity index 58% rename from baas-node-event-listener/src/main/scala/com/ing/baker/baas/common/BaaSEventListener.scala rename to baas-node-event-listener/src/main/scala/com/ing/baker/baas/protocol/BaaSEventListener.scala index e012525fc..f40b1768c 100644 --- a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/common/BaaSEventListener.scala +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/protocol/BaaSEventListener.scala @@ -1,12 +1,14 @@ -package com.ing.baker.baas.common +package com.ing.baker.baas.protocol -import com.ing.baker.runtime.common.{EventInstance, InteractionInstance} +import com.ing.baker.runtime.common.{EventInstance, InteractionInstance, RecipeEventMetadata} import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi trait BaaSEventListener[F[_]] extends LanguageApi { self => type EventInstanceType <: EventInstance { type Language <: self.Language } - def registerEventListener(recipeName: String, listenerFunction: language.BiConsumerFunction[String, EventInstanceType]): F[Unit] + type RecipeEventMetadataType <: RecipeEventMetadata { type Language <: self.Language } + + def registerEventListener(recipeName: String, listenerFunction: language.BiConsumerFunction[RecipeEventMetadataType, EventInstanceType]): F[Unit] } diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/scaladsl/BaaSEventListener.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/scaladsl/BaaSEventListener.scala index 928893aba..fac63de86 100644 --- a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/scaladsl/BaaSEventListener.scala +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/scaladsl/BaaSEventListener.scala @@ -2,17 +2,19 @@ package com.ing.baker.baas.scaladsl import akka.actor.ActorSystem import com.ing.baker.baas.akka.EventListenerAgent -import com.ing.baker.baas.common +import com.ing.baker.baas.protocol import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi -import com.ing.baker.runtime.scaladsl.EventInstance +import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeEventMetadata} import scala.concurrent.Future -case class BaaSEventListener(actorSystem: ActorSystem) extends common.BaaSEventListener[Future] with ScalaApi { +case class BaaSEventListener(actorSystem: ActorSystem) extends protocol.BaaSEventListener[Future] with ScalaApi { override type EventInstanceType = EventInstance - override def registerEventListener(recipeName: String, listenerFunction: (String, EventInstance) => Unit): Future[Unit] = + override type RecipeEventMetadataType = RecipeEventMetadata + + override def registerEventListener(recipeName: String, listenerFunction: (RecipeEventMetadata, EventInstance) => Unit): Future[Unit] = Future.successful { actorSystem.actorOf(EventListenerAgent(recipeName, listenerFunction)) } } diff --git a/baas-node-interaction/src/main/scala/com/ing/baker/baas/javadsl/BaaSInteractionInstance.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/javadsl/BaaSInteractionInstance.scala index 7d865b7cb..c092fd140 100644 --- a/baas-node-interaction/src/main/scala/com/ing/baker/baas/javadsl/BaaSInteractionInstance.scala +++ b/baas-node-interaction/src/main/scala/com/ing/baker/baas/javadsl/BaaSInteractionInstance.scala @@ -3,12 +3,12 @@ package com.ing.baker.baas.javadsl import java.util.concurrent.CompletableFuture import akka.actor.ActorSystem -import com.ing.baker.baas.common +import com.ing.baker.baas.protocol import com.ing.baker.baas.scaladsl import com.ing.baker.runtime.javadsl.InteractionInstance import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi -class BaaSInteractionInstance(actorSystem: ActorSystem) extends common.BaaSInteractionInstance[CompletableFuture] with JavaApi { +class BaaSInteractionInstance(actorSystem: ActorSystem) extends protocol.BaaSInteractionInstance[CompletableFuture] with JavaApi { override type InteractionInstanceType = InteractionInstance diff --git a/baas-node-interaction/src/main/scala/com/ing/baker/baas/common/BaaSInteractionInstance.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/protocol/BaaSInteractionInstance.scala similarity index 90% rename from baas-node-interaction/src/main/scala/com/ing/baker/baas/common/BaaSInteractionInstance.scala rename to baas-node-interaction/src/main/scala/com/ing/baker/baas/protocol/BaaSInteractionInstance.scala index 766dc0686..d85c3b9d1 100644 --- a/baas-node-interaction/src/main/scala/com/ing/baker/baas/common/BaaSInteractionInstance.scala +++ b/baas-node-interaction/src/main/scala/com/ing/baker/baas/protocol/BaaSInteractionInstance.scala @@ -1,4 +1,4 @@ -package com.ing.baker.baas.common +package com.ing.baker.baas.protocol import com.ing.baker.runtime.common.InteractionInstance import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi diff --git a/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala index fa079e407..03220e888 100644 --- a/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala +++ b/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala @@ -2,13 +2,13 @@ package com.ing.baker.baas.scaladsl import akka.actor.ActorSystem import com.ing.baker.baas.akka.InteractionAgent -import com.ing.baker.baas.common +import com.ing.baker.baas.protocol import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi import com.ing.baker.runtime.scaladsl.InteractionInstance import scala.concurrent.Future -case class BaaSInteractionInstance(actorSystem: ActorSystem) extends common.BaaSInteractionInstance[Future] with ScalaApi { +case class BaaSInteractionInstance(actorSystem: ActorSystem) extends protocol.BaaSInteractionInstance[Future] with ScalaApi { override type InteractionInstanceType = InteractionInstance diff --git a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala index addc3c649..a6b3bf573 100644 --- a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala +++ b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala @@ -1,32 +1,44 @@ package com.ing.baker.baas.state import akka.actor.ActorSystem +import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} import akka.http.scaladsl.Http import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import akka.stream.Materializer -import com.ing.baker.baas.common.BaaSProto._ -import com.ing.baker.baas.common.BaaSProtocol -import com.ing.baker.baas.common.MarshallingUtils._ +import com.ing.baker.baas.protocol.BaaSProto._ +import com.ing.baker.baas.protocol.BaaSProtocol +import com.ing.baker.baas.protocol.MarshallingUtils._ +import com.ing.baker.baas.protocol.ProtocolDistributedEventPublishing import com.ing.baker.runtime.scaladsl.{Baker, EventInstance} import com.ing.baker.runtime.serialization.{Encryption, SerializersProvider} -import scala.concurrent.Future +import scala.concurrent.{ExecutionContext, Future} object BaaSServer { def run(baker: Baker, host: String, port: Int)(implicit system: ActorSystem, mat: Materializer): Future[Http.ServerBinding] = { + import system.dispatcher val encryption = Encryption.NoEncryption val server = new BaaSServer()(system, mat, baker, encryption) - /* - baker.registerEventListener((instanceId: String, event: EventInstance) => { - // Publish an Event() message to the DistributedPublishSubscribe mediator - // We need the recipe id here D: - //event. - }) - */ - Http().bindAndHandle(server.route, host, port) + for { + _ <- initializeEventListeners(baker, system) + binding <- Http().bindAndHandle(server.route, host, port) + } yield binding } + + private[state] def registerEventListenerForRemote(recipeName: String, baker: Baker, system: ActorSystem): Future[Unit] = + baker.registerEventListener(recipeName, (metadata, event) => { + val eventsTopic: String = + ProtocolDistributedEventPublishing.eventsTopic(recipeName) + DistributedPubSub(system).mediator ! DistributedPubSubMediator.Publish(eventsTopic, ProtocolDistributedEventPublishing.Event(metadata, event)) + }) + + private[state] def initializeEventListeners(baker: Baker, system: ActorSystem)(implicit ec: ExecutionContext): Future[Unit] = + for { + recipes <- baker.getAllRecipes + _ <- Future.traverse(recipes.toList) { case (_, recipe) => registerEventListenerForRemote(recipe.compiledRecipe.name, baker, system) } + } yield () } class BaaSServer(implicit system: ActorSystem, mat: Materializer, baker: Baker, encryption: Encryption) { @@ -44,7 +56,11 @@ class BaaSServer(implicit system: ActorSystem, mat: Materializer, baker: Baker, private def addRecipe: Route = post(path("addRecipe") { entity(as[BaaSProtocol.AddRecipeRequest]) { request => - completeWithBakerFailures(baker.addRecipe(request.compiledRecipe).map(BaaSProtocol.AddRecipeResponse)) + val result = for { + recipeId <- baker.addRecipe(request.compiledRecipe) + _ <- BaaSServer.registerEventListenerForRemote(request.compiledRecipe.name, baker, system) + } yield BaaSProtocol.AddRecipeResponse(recipeId) + completeWithBakerFailures(result) } }) diff --git a/baas-protocol-baker/src/main/protobuf/baas.proto b/baas-protocol-baker/src/main/protobuf/baas.proto index 02e04719f..e7c263194 100644 --- a/baas-protocol-baker/src/main/protobuf/baas.proto +++ b/baas-protocol-baker/src/main/protobuf/baas.proto @@ -3,7 +3,7 @@ syntax = "proto2"; import "scalapb/scalapb.proto"; import "common.proto"; -option java_package = "com.ing.baker.runtime.baas.protobuf"; +option java_package = "com.ing.baker.baas.protocol.protobuf"; option (scalapb.options) = { flat_package: true }; diff --git a/baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala b/baas-protocol-baker/src/main/scala/com/ing/baker/baas/protocol/BaaSProto.scala similarity index 99% rename from baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala rename to baas-protocol-baker/src/main/scala/com/ing/baker/baas/protocol/BaaSProto.scala index 267488613..ceabee45b 100644 --- a/baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/BaaSProto.scala +++ b/baas-protocol-baker/src/main/scala/com/ing/baker/baas/protocol/BaaSProto.scala @@ -1,11 +1,10 @@ -package com.ing.baker.baas.common +package com.ing.baker.baas.protocol import cats.implicits._ -import com.ing.baker.baas.common.BaaSProtocol._ +import com.ing.baker.baas.protocol.BaaSProtocol._ import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider} import scalapb.GeneratedMessageCompanion import com.ing.baker.runtime.serialization.ProtoMap.{ctxFromProto, ctxToProto, versioned} -import com.ing.baker.runtime.baas.protobuf import com.ing.baker.runtime.serialization.protomappings.SensoryEventStatusMappingHelper import scala.util.Try diff --git a/baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/BaaSProtocol.scala b/baas-protocol-baker/src/main/scala/com/ing/baker/baas/protocol/BaaSProtocol.scala similarity index 98% rename from baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/BaaSProtocol.scala rename to baas-protocol-baker/src/main/scala/com/ing/baker/baas/protocol/BaaSProtocol.scala index a2a70d4a2..d4c5a8731 100644 --- a/baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/BaaSProtocol.scala +++ b/baas-protocol-baker/src/main/scala/com/ing/baker/baas/protocol/BaaSProtocol.scala @@ -1,4 +1,4 @@ -package com.ing.baker.baas.common +package com.ing.baker.baas.protocol import com.ing.baker.il.CompiledRecipe import com.ing.baker.runtime.common.{BakerException, SensoryEventStatus} diff --git a/baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala b/baas-protocol-baker/src/main/scala/com/ing/baker/baas/protocol/MarshallingUtils.scala similarity index 98% rename from baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala rename to baas-protocol-baker/src/main/scala/com/ing/baker/baas/protocol/MarshallingUtils.scala index 1cbf4ba8d..79dd21603 100644 --- a/baas-protocol-baker/src/main/scala/com/ing/baker/baas/common/MarshallingUtils.scala +++ b/baas-protocol-baker/src/main/scala/com/ing/baker/baas/protocol/MarshallingUtils.scala @@ -1,4 +1,4 @@ -package com.ing.baker.baas.common +package com.ing.baker.baas.protocol import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller} import akka.http.scaladsl.model.{ContentTypes, HttpResponse, MediaTypes, StatusCodes} diff --git a/baas-protocol-recipe-event-publishing/src/main/protobuf/recipe_event_publishing.proto b/baas-protocol-recipe-event-publishing/src/main/protobuf/recipe_event_publishing.proto index f7b0574d7..2119eab3a 100644 --- a/baas-protocol-recipe-event-publishing/src/main/protobuf/recipe_event_publishing.proto +++ b/baas-protocol-recipe-event-publishing/src/main/protobuf/recipe_event_publishing.proto @@ -9,6 +9,6 @@ option (scalapb.options) = { }; message Event { - optional string recipeInstanceId = 1; + optional RecipeEventMetadata recipeEventMetadata = 1; optional RuntimeEvent event = 2; } diff --git a/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/DistributedEventPublishingProto.scala b/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/DistributedEventPublishingProto.scala index 93aace34e..d0fe1af9b 100644 --- a/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/DistributedEventPublishingProto.scala +++ b/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/DistributedEventPublishingProto.scala @@ -14,14 +14,15 @@ object DistributedEventPublishingProto { val companion = protobuf.Event def toProto(a: Event): protobuf.Event = - protobuf.Event(Some(a.recipeInstanceId), Some(ctxToProto(a.event))) + protobuf.Event(Some(ctxToProto(a.recipeEventMetadata)), Some(ctxToProto(a.event))) def fromProto(message: protobuf.Event): Try[Event] = for { - recipeInstanceId <- versioned(message.recipeInstanceId, "recipeInstanceId") + recipeEventMetadataProto <- versioned(message.recipeEventMetadata, "recipeEventMetadata") + recipeEventMetadata <- ctxFromProto(recipeEventMetadataProto) eventProto <- versioned(message.event, "event") event <- ctxFromProto(eventProto) - } yield Event(recipeInstanceId, event) + } yield Event(recipeEventMetadata, event) } } diff --git a/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/ProtocolDistributedEventPublishing.scala b/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/ProtocolDistributedEventPublishing.scala index 6d683c1c7..4e25145b8 100644 --- a/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/ProtocolDistributedEventPublishing.scala +++ b/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/ProtocolDistributedEventPublishing.scala @@ -1,6 +1,6 @@ package com.ing.baker.baas.protocol -import com.ing.baker.runtime.scaladsl.EventInstance +import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeEventMetadata} import com.ing.baker.runtime.serialization.BakerSerializable sealed trait ProtocolDistributedEventPublishing extends BakerSerializable @@ -10,5 +10,5 @@ object ProtocolDistributedEventPublishing { def eventsTopic(recipeName: String): String = s"recipe-event-publishing:$recipeName:event" - case class Event(recipeInstanceId: String, event: EventInstance) extends ProtocolDistributedEventPublishing + case class Event(recipeEventMetadata: RecipeEventMetadata, event: EventInstance) extends ProtocolDistributedEventPublishing } diff --git a/baas-tests/src/test/resources/application.conf b/baas-tests/src/test/resources/application.conf new file mode 100644 index 000000000..14b0925f8 --- /dev/null +++ b/baas-tests/src/test/resources/application.conf @@ -0,0 +1,93 @@ +baker { + + config-file-included = true + + actor { + # the id of the journal to read events from + read-journal-plugin = "inmemory-read-journal" + + # either "local" or "cluster-sharded" + provider = "cluster-sharded" + + # the recommended nr is number-of-cluster-nodes * 10 + cluster.nr-of-shards = 10 + + # the time that inactive actors (processes) stay in memory + idle-timeout = 5 minutes + + # The interval that a check is done of processes should be deleted + retention-check-interval = 1 minutes + } + + # the default timeout for Baker.bake(..) process creation calls + bake-timeout = 10 seconds + + # the timeout for refreshing the local recipe cache + process-index-update-cache-timeout = 5 seconds + + # the default timeout for Baker.processEvent(..) + process-event-timeout = 10 seconds + + # the default timeout for inquires on Baker, this means getIngredients(..) & getEvents(..) + process-inquire-timeout = 10 seconds + + # when baker starts up, it attempts to 'initialize' the journal connection, this may take some time + journal-initialize-timeout = 30 seconds + + # the default timeout for adding a recipe to Baker + add-recipe-timeout = 10 seconds + + # the time to wait for a gracefull shutdown + shutdown-timeout = 30 seconds + + # The ingredients that are filtered out when getting the process instance. + # This should be used if there are big ingredients to improve performance and memory usage. + # The ingredients will be in the ingredients map but there value will be an empty String. + filtered-ingredient-values = [] + + # encryption settings + encryption { + + # whether to encrypt data stored in the journal, off or on + enabled = off + + # if enabled = on, a secret should be set + # secret = ??? + } + + # use "local" unless you are configuring a BaaS environment, then you will need "remote" + interaction-manager = "remote" +} + +akka { + + cluster { + jmx.multi-mbeans-in-same-jvm = on + sharding.state-store-mode = persistence + } + + persistence { + journal.plugin = "inmemory-journal" + snapshot-store.plugin = "inmemory-snapshot-store" + } + + actor { + provider = "cluster" + idle-timeout = 1 minute + allow-java-serialization = off + + serializers { + baker-typed-protobuf = "com.ing.baker.runtime.akka.actor.serialization.BakerTypedProtobufSerializer" + } + + serialization-bindings { + "com.ing.baker.runtime.serialization.BakerSerializable" = baker-typed-protobuf + "com.ing.baker.types.Value" = baker-typed-protobuf + "com.ing.baker.types.Type" = baker-typed-protobuf + "com.ing.baker.il.CompiledRecipe" = baker-typed-protobuf + "com.ing.baker.runtime.scaladsl.EventInstance" = baker-typed-protobuf + "com.ing.baker.runtime.scaladsl.RecipeInstanceState" = baker-typed-protobuf + "com.ing.baker.runtime.scaladsl.RecipeEventMetadata" = baker-typed-protobuf + } + } +} diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/spec/CommonBaaSServerClientSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/spec/BaaSIntegrationSpec.scala similarity index 63% rename from baas-tests/src/test/scala/com/ing/baker/baas/spec/CommonBaaSServerClientSpec.scala rename to baas-tests/src/test/scala/com/ing/baker/baas/spec/BaaSIntegrationSpec.scala index 1913248ef..64164abb0 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/spec/CommonBaaSServerClientSpec.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/spec/BaaSIntegrationSpec.scala @@ -3,12 +3,16 @@ package com.ing.baker.baas.spec import java.util.UUID import akka.actor.ActorSystem +import akka.http.scaladsl.Http import akka.stream.{ActorMaterializer, Materializer} +import cats.data.StateT import cats.effect.{IO, Timer} +import cats.implicits._ import com.ing.baker.baas.recipe.CheckoutFlowEvents.ItemsReserved import com.ing.baker.baas.recipe.CheckoutFlowIngredients.{Item, OrderId, ReservedItems, ShippingAddress} import com.ing.baker.baas.recipe._ -import com.ing.baker.baas.spec.CommonBaaSServerClientSpec._ +import com.ing.baker.baas.scaladsl.{BaaSInteractionInstance, BakerClient} +import com.ing.baker.baas.spec.BaaSIntegrationSpec._ import com.ing.baker.baas.state.BaaSServer import com.ing.baker.compiler.RecipeCompiler import com.ing.baker.il.CompiledRecipe @@ -17,51 +21,38 @@ import com.ing.baker.runtime.akka.AkkaBaker import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi import com.ing.baker.runtime.common.{BakerException, SensoryEventStatus} import com.ing.baker.runtime.scaladsl.{EventInstance, InteractionInstance, Baker => ScalaBaker} +import com.ing.baker.runtime.serialization.Encryption +import com.typesafe.config.{Config, ConfigFactory} +import org.jboss.netty.channel.ChannelException import org.scalatest._ import scala.concurrent.{ExecutionContext, Future} -abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Materializer) => ScalaBaker) +class BaaSIntegrationSpec extends AsyncFunSpec with Matchers with BeforeAndAfterAll with BeforeAndAfterEach { - val test: ClientServerTest = CommonBaaSServerClientSpec.testWith(clientBaker) + val test: IntegrationTest = BaaSIntegrationSpec.testWith implicit val timer: Timer[IO] = IO.timer(executionContext) describe("Baker Client-Server") { it("Baker.addRecipe") { - test { (client, server) => + test { (client, server, interactionNode) => for { - compiledRecipe <- setupHappyPath(server) + compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) recipeInformation <- server.getRecipe(recipeId) } yield recipeInformation.compiledRecipe shouldBe compiledRecipe } } - it("Baker.addRecipe (fail with ImplementationsException)") { - test { (client, _) => - val badRecipe = Recipe("BadRecipe") - .withInteraction(CheckoutFlowInteractions.ShipItemsInteraction) - val expectedException = - BakerException.ImplementationsException("No implementation provided for interaction: ShipItems") - val compiledRecipe = RecipeCompiler - .compileRecipe(badRecipe) - for { - e <- client.addRecipe(compiledRecipe) - .map(_ => None) - .recover { case e: BakerException => Some(e) } - } yield e shouldBe Some(expectedException) - } - } - it("Baker.getRecipe") { - test { (client, server) => + test { (client, _, interactionNode) => for { - compiledRecipe <- setupHappyPath(server) + compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) recipeInformation <- client.getRecipe(recipeId) } yield recipeInformation.compiledRecipe shouldBe compiledRecipe @@ -69,7 +60,7 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.getRecipe (fail with NoSuchRecipeException)") { - test { (client, _) => + test { (client, _, _) => for { e <- client .getRecipe("non-existent") @@ -80,9 +71,9 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.getAllRecipes") { - test { (client, server) => + test { (client, server, interactionNode) => for { - compiledRecipe <- setupHappyPath(server) + compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) recipes <- client.getAllRecipes } yield recipes.get(recipeId).map(_.compiledRecipe) shouldBe Some(compiledRecipe) @@ -90,10 +81,10 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.bake") { - test { (client, server) => + test { (client, server, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString for { - compiledRecipe <- setupHappyPath(server) + compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) state <- server.getRecipeInstanceState(recipeInstanceId) @@ -102,10 +93,10 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.bake (fail with ProcessAlreadyExistsException)") { - test { (client, server) => + test { (client, server, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString for { - compiledRecipe <- setupHappyPath(server) + compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) e <- client @@ -121,7 +112,7 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.bake (fail with NoSuchRecipeException)") { - test { (client, _) => + test { (client, _, _) => val recipeInstanceId: String = UUID.randomUUID().toString for { e <- client @@ -133,7 +124,7 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.getRecipeInstanceState (fails with NoSuchProcessException)") { - test { (_, server) => + test { (_, server, _) => for { e <- server .getRecipeInstanceState("non-existent") @@ -144,12 +135,12 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.fireEventAndResolveWhenReceived") { - test { (client, server) => + test { (client, server, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress("address"))) for { - compiledRecipe <- setupHappyPath(server) + compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) status <- client.fireEventAndResolveWhenReceived(recipeInstanceId, event) @@ -158,12 +149,12 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.fireEventAndResolveWhenCompleted") { - test { (client, server) => + test { (client, server, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress("address"))) for { - compiledRecipe <- setupHappyPath(server) + compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) result <- client.fireEventAndResolveWhenCompleted(recipeInstanceId, event) @@ -176,11 +167,11 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.fireEventAndResolveWhenCompleted (fails with IllegalEventException)") { - test { (client, server) => + test { (client, server, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance("non-existent", Map.empty) for { - compiledRecipe <- setupHappyPath(server) + compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) result <- client @@ -196,12 +187,12 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.fireEventAndResolveOnEvent") { - test { (client, server) => + test { (client, server, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress("address"))) for { - compiledRecipe <- setupHappyPath(server) + compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) result <- client.fireEventAndResolveOnEvent(recipeInstanceId, event, "ShippingAddressReceived") @@ -214,10 +205,10 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.getAllRecipeInstancesMetadata") { - test { (client, server) => + test { (client, server, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString for { - compiledRecipe <- setupHappyPath(server) + compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) clientMetadata <- client.getAllRecipeInstancesMetadata @@ -227,10 +218,10 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.getVisualState") { - test { (client, server) => + test { (client, server, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString for { - compiledRecipe <- setupHappyPath(server) + compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) clientState <- client.getVisualState(recipeInstanceId) @@ -240,12 +231,12 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.retryInteraction") { - test { (client, server) => + test { (client, _, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.OrderPlaced(orderId = OrderId("order1"), List.empty)) for { - compiledRecipe <- setupFailingOnceReserveItems(server) + compiledRecipe <- setupFailingOnceReserveItems(interactionNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) _ <- client.fireEventAndResolveWhenCompleted(recipeInstanceId, event) @@ -262,7 +253,7 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.resolveInteraction") { - test { (client, server) => + test { (client, _, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.OrderPlaced(orderId = OrderId("order1"), List.empty)) @@ -270,7 +261,7 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat ItemsReserved(reservedItems = ReservedItems(items = List(Item("item1")), data = Array.empty)) ) for { - compiledRecipe <- setupFailingOnceReserveItems(server) + compiledRecipe <- setupFailingOnceReserveItems(interactionNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) _ <- client.fireEventAndResolveWhenCompleted(recipeInstanceId, event) @@ -290,12 +281,12 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } it("Baker.stopRetryingInteraction") { - test { (client, server) => + test { (client, _, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.OrderPlaced(orderId = OrderId("order1"), List.empty)) for { - compiledRecipe <- setupFailingWithRetryReserveItems(server) + compiledRecipe <- setupFailingWithRetryReserveItems(interactionNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) _ <- client.fireEventAndResolveWhenReceived(recipeInstanceId, event) @@ -314,67 +305,131 @@ abstract class CommonBaaSServerClientSpec(clientBaker: (String, ActorSystem, Mat } } -object CommonBaaSServerClientSpec { +object BaaSIntegrationSpec { - def setupHappyPath(serverBaker: ScalaBaker)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { + def setupHappyPath(serverBaker: BaaSInteractionInstance)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { val makePaymentInstance = InteractionInstance.unsafeFrom(new MakePaymentInstance()) val reserveItemsInstance = InteractionInstance.unsafeFrom(new ReserveItemsInstance()) val shipItemsInstance = InteractionInstance.unsafeFrom(new ShipItemsInstance()) val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) for { - _ <- serverBaker.addInteractionInstances(Seq(makePaymentInstance, reserveItemsInstance, shipItemsInstance)) + _ <- Future { serverBaker.load(makePaymentInstance, reserveItemsInstance, shipItemsInstance) } } yield compiledRecipe } - def setupFailingOnceReserveItems(serverBaker: ScalaBaker)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { + def setupFailingOnceReserveItems(serverBaker: BaaSInteractionInstance)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { val makePaymentInstance = InteractionInstance.unsafeFrom(new MakePaymentInstance()) val reserveItemsInstance = InteractionInstance.unsafeFrom(new FailingOnceReserveItemsInstance()) val shipItemsInstance = InteractionInstance.unsafeFrom(new ShipItemsInstance()) val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipeWithBlockingStrategy) for { - _ <- serverBaker.addInteractionInstances(Seq(makePaymentInstance, reserveItemsInstance, shipItemsInstance)) + _ <- Future { serverBaker.load(makePaymentInstance, reserveItemsInstance, shipItemsInstance) } } yield compiledRecipe } - def setupFailingWithRetryReserveItems(serverBaker: ScalaBaker)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { + def setupFailingWithRetryReserveItems(serverBaker: BaaSInteractionInstance)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { val makePaymentInstance = InteractionInstance.unsafeFrom(new MakePaymentInstance()) val reserveItemsInstance = InteractionInstance.unsafeFrom(new FailingReserveItemsInstance()) val shipItemsInstance = InteractionInstance.unsafeFrom(new ShipItemsInstance()) val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) for { - _ <- serverBaker.addInteractionInstances(Seq(makePaymentInstance, reserveItemsInstance, shipItemsInstance)) + _ <- Future { serverBaker.load(makePaymentInstance, reserveItemsInstance, shipItemsInstance) } } yield compiledRecipe } - type ClientServerTest = ((ScalaBaker, ScalaBaker) => Future[Assertion]) => Future[Assertion] + type IntegrationTest = ((ScalaBaker, ScalaBaker, BaaSInteractionInstance) => Future[Assertion]) => Future[Assertion] - val allPorts: Stream[Int] = Stream.from(50000, 1) + type WithOpenPort[A] = StateT[Future, Stream[Int], A] def testWith[F[_], Lang <: LanguageApi] - (clientBaker: (String, ActorSystem, Materializer) => ScalaBaker) - (t: (ScalaBaker, ScalaBaker) => Future[Assertion]) + (test: (ScalaBaker, ScalaBaker, BaaSInteractionInstance) => Future[Assertion]) (implicit ec: ExecutionContext): Future[Assertion] = { val testId: UUID = UUID.randomUUID() - implicit val system: ActorSystem = ActorSystem("ScalaDSLBaaSServerClientSpec-" + testId) - implicit val materializer: Materializer = ActorMaterializer() - val host: String = "localhost" - val serverBaker = AkkaBaker.localDefault(system) - for { - (client, shutdown) <- buildFromStream(allPorts, { port: Int => - val client = clientBaker(s"http://$host:$port/", system, materializer) - val shutdown = BaaSServer.run(serverBaker, host, port) - shutdown.map(s => (client, s)) - }) - a <- t(client, serverBaker) - _ <- shutdown.unbind() - _ <- serverBaker.gracefulShutdown() + val systemName: String = "ScalaDSLBaaSServerClientSpec-" + testId + val allPorts: Stream[Int] = Stream.from(50000, 1) + val program = for { + clientServerQuadruple <- buildBaaSClientServer(systemName) + (clientBaker, stateNodeBaker, stateNodePort, httpServerBinding) = clientServerQuadruple + interactionNodeTriplet <- buildClusterActorSystem(systemName, seedPortCandidate = stateNodePort) + (interactionNodeSystem, _, _) = interactionNodeTriplet + interactionNode = BaaSInteractionInstance(interactionNodeSystem) + a <- liftF(test(clientBaker, stateNodeBaker, interactionNode)) + _ <- liftF(interactionNodeSystem.terminate()) + _ <- liftF(httpServerBinding.unbind()) + _ <- liftF(stateNodeBaker.gracefulShutdown()) } yield a + program.run(allPorts).map(_._2) } - private def buildFromStream[S, T](ports: Stream[S], f: S => Future[T])(implicit ec: ExecutionContext): Future[T] = - ports match { - case #::(port, tail) => f(port).recoverWith { - case _: java.net.BindException => buildFromStream(tail, f) - } + private def buildBaaSClientServer + (systemName: String) + (implicit ec: ExecutionContext): WithOpenPort[(ScalaBaker, ScalaBaker, Int, Http.ServerBinding)] = { + for { + clusterTriplet <- buildClusterActorSystem(systemName, seedPortCandidate = 0) + (stateNodeSystem, serverConfig, stateNodePort) = clusterTriplet + materializer = ActorMaterializer()(stateNodeSystem) + stateNodeBaker = AkkaBaker(serverConfig, stateNodeSystem) + httpPortAndBinding <- runStateNodeHttpServer(stateNodeBaker, stateNodeSystem, materializer) + (httpPort, httpServerBinding) = httpPortAndBinding + clientBaker = BakerClient.build(s"http://localhost:$httpPort/", Encryption.NoEncryption)(stateNodeSystem, materializer) + } yield (clientBaker, stateNodeBaker, stateNodePort, httpServerBinding) + } + + private def buildClusterActorSystem(systemName: String, seedPortCandidate: Int)(implicit ec: ExecutionContext): WithOpenPort[(ActorSystem, Config, Int)] = + withOpenPort { port => + val config = genClusterConfig(systemName, port, seedPortCandidate) + Future { (ActorSystem(systemName, config), config, port) } } + + private def runStateNodeHttpServer(stateNodeBaker: ScalaBaker, stateNodeSystem: ActorSystem, materializer: Materializer)(implicit ec: ExecutionContext): WithOpenPort[(Int, Http.ServerBinding)] = + withOpenPort(port => BaaSServer.run(stateNodeBaker, "localhost", port)(stateNodeSystem, materializer).map(port -> _)) + + private def withOpenPort[T](f: Int => Future[T])(implicit ec: ExecutionContext): WithOpenPort[T] = { + def search(ports: Stream[Int]): Future[(Stream[Int], T)] = + ports match { + case #::(port, tail) => f(port).map(tail -> _).recoverWith { + case _: java.net.BindException => search(tail) + case _: ChannelException => search(tail) + case other => println("REVIEW withOpenPort function implementation, uncaught exception: " + Console.RED + other + Console.RESET); Future.failed(other) + } + } + StateT(search) + } + + private def liftF[A](fa: Future[A])(implicit ec: ExecutionContext): WithOpenPort[A] = + StateT.liftF[Future, Stream[Int], A](fa) + + private def genClusterConfig(systemName: String, port: Int, seedPortCandidate: Int): Config = { + val seedPort: Int = if(seedPortCandidate == 0) port else seedPortCandidate + ConfigFactory.parseString( + s""" + |baker { + | cluster { + | seed-nodes = [ + | "akka.tcp://"$systemName"@localhost:"$seedPort] + | } + |} + | + |akka { + | + | remote { + | log-remote-lifecycle-events = off + | netty.tcp { + | hostname = "localhost" + | port = $port + | } + | } + | + | cluster { + | + | seed-nodes = [ + | "akka.tcp://"$systemName"@localhost:"$seedPort] + | + | # auto downing is NOT safe for production deployments. + | # you may want to use it during development, read more about it in the akka docs. + | auto-down-unreachable-after = 10s + | } + |} + |""".stripMargin).withFallback(ConfigFactory.load()) + } } \ No newline at end of file diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/spec/JavaDSLBaaSServerClientSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/spec/JavaDSLBaaSServerClientSpec.scala deleted file mode 100644 index 727fe08fd..000000000 --- a/baas-tests/src/test/scala/com/ing/baker/baas/spec/JavaDSLBaaSServerClientSpec.scala +++ /dev/null @@ -1,140 +0,0 @@ -package com.ing.baker.baas.spec - -import java.util.Optional - -import com.ing.baker.baas.javadsl -import com.ing.baker.baas.spec.JavaDSLBaaSServerClientSpec.optionToJava -import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} -import com.ing.baker.runtime.common.SensoryEventStatus -import com.ing.baker.runtime.scaladsl._ -import com.ing.baker.types.Value - -import scala.collection.JavaConverters._ -import scala.compat.java8.FutureConverters -import scala.concurrent.Future - -class JavaDSLBaaSServerClientSpec extends CommonBaaSServerClientSpec( - (host, as, mat) => { - import as.dispatcher - val javaBaker = javadsl.BakerClient.build(host, as, mat) - new com.ing.baker.runtime.scaladsl.Baker { - override def addRecipe(compiledRecipe: CompiledRecipe): Future[String] = - FutureConverters.toScala(javaBaker.addRecipe(compiledRecipe)) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def getRecipe(recipeId: String): Future[RecipeInformation] = - FutureConverters.toScala(javaBaker.getRecipe(recipeId)).map(_.asScala) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def getAllRecipes: Future[Map[String, RecipeInformation]] = - FutureConverters.toScala(javaBaker.getAllRecipes).map(_.asScala.mapValues(_.asScala).toMap) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def bake(recipeId: String, recipeInstanceId: String): Future[Unit] = - FutureConverters.toScala(javaBaker.bake(recipeId, recipeInstanceId)) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def fireEventAndResolveWhenReceived(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): Future[SensoryEventStatus] = - FutureConverters.toScala(javaBaker.fireEventAndResolveWhenReceived(recipeInstanceId, event.asJava, optionToJava(correlationId))) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def fireEventAndResolveWhenCompleted(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): Future[SensoryEventResult] = - FutureConverters.toScala(javaBaker.fireEventAndResolveWhenCompleted(recipeInstanceId, event.asJava, optionToJava(correlationId))).map(_.asScala) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def fireEventAndResolveOnEvent(recipeInstanceId: String, event: EventInstance, onEvent: String, correlationId: Option[String]): Future[SensoryEventResult] = - FutureConverters.toScala(javaBaker.fireEventAndResolveOnEvent(recipeInstanceId, event.asJava, onEvent, optionToJava(correlationId))).map(_.asScala) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def fireEvent(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): EventResolutions = { - val res = javaBaker.fireEvent(recipeInstanceId, event.asJava, optionToJava(correlationId)) - com.ing.baker.runtime.scaladsl.EventResolutions( - FutureConverters.toScala(res.resolveWhenReceived) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - }, - FutureConverters.toScala(res.resolveWhenCompleted).map(_.asScala) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - ) - } - override def getAllRecipeInstancesMetadata: Future[Set[RecipeInstanceMetadata]] = - FutureConverters.toScala(javaBaker.getAllRecipeInstancesMetadata).map(_.asScala.toSet.map((x: com.ing.baker.runtime.javadsl.RecipeInstanceMetadata) => x.asScala)) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def getRecipeInstanceState(recipeInstanceId: String): Future[RecipeInstanceState] = - FutureConverters.toScala(javaBaker.getRecipeInstanceState(recipeInstanceId)).map(_.asScala) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def getIngredients(recipeInstanceId: String): Future[Map[String, Value]] = - FutureConverters.toScala(javaBaker.getIngredients(recipeInstanceId)).map(_.asScala.toMap) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def getEvents(recipeInstanceId: String): Future[Seq[EventMoment]] = - FutureConverters.toScala(javaBaker.getEvents(recipeInstanceId)).map(_.asScala.map(_.asScala)) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def getEventNames(recipeInstanceId: String): Future[Seq[String]] = - FutureConverters.toScala(javaBaker.getEventNames(recipeInstanceId)).map(_.asScala) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def getVisualState(recipeInstanceId: String, style: RecipeVisualStyle): Future[String] = - FutureConverters.toScala(javaBaker.getVisualState(recipeInstanceId, style)) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def registerEventListener(recipeName: String, listenerFunction: (RecipeEventMetadata, EventInstance) => Unit): Future[Unit] = - ??? - override def registerEventListener(listenerFunction: (RecipeEventMetadata, EventInstance) => Unit): Future[Unit] = - ??? - override def registerBakerEventListener(listenerFunction: BakerEvent => Unit): Future[Unit] = - ??? - override def addInteractionInstance(implementation: InteractionInstance): Future[Unit] = - ??? - override def addInteractionInstances(implementations: Seq[InteractionInstance]): Future[Unit] = - ??? - override def gracefulShutdown(): Future[Unit] = - FutureConverters.toScala(javaBaker.gracefulShutdown()) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def retryInteraction(recipeInstanceId: String, interactionName: String): Future[Unit] = - FutureConverters.toScala(javaBaker.retryInteraction(recipeInstanceId, interactionName)) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def resolveInteraction(recipeInstanceId: String, interactionName: String, event: EventInstance): Future[Unit] = - FutureConverters.toScala(javaBaker.resolveInteraction(recipeInstanceId, interactionName, event.asJava)) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - override def stopRetryingInteraction(recipeInstanceId: String, interactionName: String): Future[Unit] = - FutureConverters.toScala(javaBaker.stopRetryingInteraction(recipeInstanceId, interactionName)) - .recoverWith { - case e: java.util.concurrent.CompletionException => Future.failed(e.getCause) - } - } - } -) - -object JavaDSLBaaSServerClientSpec { - - def optionToJava[A](option: Option[A]): Optional[A] = - option match { - case Some(a) => Optional.of(a) - case None => Optional.empty() - } -} \ No newline at end of file diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/spec/ScalaDSLBaaSServerClientSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/spec/ScalaDSLBaaSServerClientSpec.scala deleted file mode 100644 index 51e09fdb5..000000000 --- a/baas-tests/src/test/scala/com/ing/baker/baas/spec/ScalaDSLBaaSServerClientSpec.scala +++ /dev/null @@ -1,9 +0,0 @@ -package com.ing.baker.baas.spec - -import com.ing.baker.baas.scaladsl.BakerClient -import com.ing.baker.runtime.serialization.Encryption - -class ScalaDSLBaaSServerClientSpec extends CommonBaaSServerClientSpec( - (host, as, mat) => BakerClient.build(host, Encryption.NoEncryption)(as, mat) -) - diff --git a/baker-interface/src/main/protobuf/common.proto b/baker-interface/src/main/protobuf/common.proto index 1d46a938c..04fccf804 100644 --- a/baker-interface/src/main/protobuf/common.proto +++ b/baker-interface/src/main/protobuf/common.proto @@ -170,6 +170,12 @@ message SensoryEventResult { map ingredients = 3; } +message RecipeEventMetadata { + optional string recipeId = 1; + optional string recipeName = 2; + optional string recipeInstanceId = 3; +} + enum SensoryEventStatus { RECEIVED = 1; COMPLETED = 2; diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/ProtoMap.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/ProtoMap.scala index b3379656d..96a4b2bd4 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/ProtoMap.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/ProtoMap.scala @@ -80,6 +80,9 @@ object ProtoMap { implicit val processStateMapping: ProtoMap[RecipeInstanceState, protobuf.ProcessState] = new ProcessStateMapping + implicit val recipeEventMetadataMapping: ProtoMap[RecipeEventMetadata, protobuf.RecipeEventMetadata] = + new RecipeEventMetadataMapping + implicit val eventMomentMapping: ProtoMap[EventMoment, protobuf.EventMoment] = new EventMomentMapping diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/RecipeEventMetadataMapping.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/RecipeEventMetadataMapping.scala new file mode 100644 index 000000000..8c7ba06b5 --- /dev/null +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/protomappings/RecipeEventMetadataMapping.scala @@ -0,0 +1,24 @@ +package com.ing.baker.runtime.serialization.protomappings + +import com.ing.baker.runtime.akka.actor.{protobuf => proto} +import com.ing.baker.runtime.scaladsl.RecipeEventMetadata +import com.ing.baker.runtime.serialization.ProtoMap +import com.ing.baker.runtime.serialization.ProtoMap.versioned + +import scala.util.Try + +class RecipeEventMetadataMapping extends ProtoMap[RecipeEventMetadata, proto.RecipeEventMetadata] { + + val companion = proto.RecipeEventMetadata + + def toProto(a: RecipeEventMetadata): proto.RecipeEventMetadata = { + proto.RecipeEventMetadata(Some(a.recipeId), Some(a.recipeName), Some(a.recipeInstanceId)) + } + + def fromProto(message: proto.RecipeEventMetadata): Try[RecipeEventMetadata] = + for { + recipeId <- versioned(message.recipeId, "recipeId") + recipeName <- versioned(message.recipeName, "recipeName") + recipeInstanceId <- versioned(message.recipeInstanceId, "recipeInstanceId") + } yield RecipeEventMetadata(recipeId, recipeName, recipeInstanceId) +} diff --git a/runtime/src/main/resources/reference.conf b/runtime/src/main/resources/reference.conf index 599a31728..12db14010 100644 --- a/runtime/src/main/resources/reference.conf +++ b/runtime/src/main/resources/reference.conf @@ -80,6 +80,7 @@ akka { "com.ing.baker.il.CompiledRecipe" = baker-typed-protobuf "com.ing.baker.runtime.scaladsl.EventInstance" = baker-typed-protobuf "com.ing.baker.runtime.scaladsl.RecipeInstanceState" = baker-typed-protobuf + "com.ing.baker.runtime.scaladsl.RecipeEventMetadata" = baker-typed-protobuf } } diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala index 3afb90dc3..17d187841 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala @@ -8,7 +8,7 @@ import com.ing.baker.runtime.akka.actor.ClusterBakerActorProvider import com.ing.baker.runtime.akka.actor.process_index.{ProcessIndex, ProcessIndexProtocol} import com.ing.baker.runtime.akka.actor.process_instance.ProcessInstanceProtocol import com.ing.baker.runtime.akka.actor.recipe_manager.{RecipeManager, RecipeManagerProtocol} -import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeInstanceState} +import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeEventMetadata, RecipeInstanceState} import com.ing.baker.runtime.serialization.{ProtoMap, SerializersProvider, TypedProtobufSerializer} import com.ing.baker.runtime.serialization.TypedProtobufSerializer.{BinarySerializable, forType} import com.ing.baker.runtime.akka.actor.process_index.ProcessIndexProto._ @@ -32,6 +32,8 @@ object BakerTypedProtobufSerializer { .register("core.RuntimeEvent"), forType[RecipeInstanceState] .register("core.ProcessState"), + forType[RecipeEventMetadata] + .register("core.RecipeEventMetadata"), forType[il.CompiledRecipe] .register("il.CompiledRecipe") ) From cdd583f7381c159dd624c44568e879591955a91b Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Tue, 5 Nov 2019 11:50:11 +0100 Subject: [PATCH 39/86] Fixed integration tests with the interaction node --- .../src/test/resources/application.conf | 1 + .../baker/baas/spec/BaaSIntegrationSpec.scala | 85 ++++++++----------- 2 files changed, 37 insertions(+), 49 deletions(-) diff --git a/baas-tests/src/test/resources/application.conf b/baas-tests/src/test/resources/application.conf index 14b0925f8..154996751 100644 --- a/baas-tests/src/test/resources/application.conf +++ b/baas-tests/src/test/resources/application.conf @@ -74,6 +74,7 @@ akka { actor { provider = "cluster" idle-timeout = 1 minute + serialize-messages = on allow-java-serialization = off serializers { diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/spec/BaaSIntegrationSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/spec/BaaSIntegrationSpec.scala index 64164abb0..677a7373f 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/spec/BaaSIntegrationSpec.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/spec/BaaSIntegrationSpec.scala @@ -16,7 +16,6 @@ import com.ing.baker.baas.spec.BaaSIntegrationSpec._ import com.ing.baker.baas.state.BaaSServer import com.ing.baker.compiler.RecipeCompiler import com.ing.baker.il.CompiledRecipe -import com.ing.baker.recipe.scaladsl.Recipe import com.ing.baker.runtime.akka.AkkaBaker import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi import com.ing.baker.runtime.common.{BakerException, SensoryEventStatus} @@ -40,11 +39,11 @@ class BaaSIntegrationSpec describe("Baker Client-Server") { it("Baker.addRecipe") { - test { (client, server, interactionNode) => + test { (client, stateNode, interactionNode) => for { compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) - recipeInformation <- server.getRecipe(recipeId) + recipeInformation <- stateNode.getRecipe(recipeId) } yield recipeInformation.compiledRecipe shouldBe compiledRecipe } } @@ -71,7 +70,7 @@ class BaaSIntegrationSpec } it("Baker.getAllRecipes") { - test { (client, server, interactionNode) => + test { (client, stateNode, interactionNode) => for { compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) @@ -81,19 +80,19 @@ class BaaSIntegrationSpec } it("Baker.bake") { - test { (client, server, interactionNode) => + test { (client, stateNode, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString for { compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) - state <- server.getRecipeInstanceState(recipeInstanceId) + state <- stateNode.getRecipeInstanceState(recipeInstanceId) } yield state.recipeInstanceId shouldBe recipeInstanceId } } it("Baker.bake (fail with ProcessAlreadyExistsException)") { - test { (client, server, interactionNode) => + test { (client, stateNode, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString for { compiledRecipe <- setupHappyPath(interactionNode) @@ -103,7 +102,7 @@ class BaaSIntegrationSpec .bake(recipeId, recipeInstanceId) .map(_ => None) .recover { case e: BakerException => Some(e) } - state <- server.getRecipeInstanceState(recipeInstanceId) + state <- stateNode.getRecipeInstanceState(recipeInstanceId) } yield { e shouldBe Some(BakerException.ProcessAlreadyExistsException(recipeInstanceId)) state.recipeInstanceId shouldBe recipeInstanceId @@ -124,9 +123,9 @@ class BaaSIntegrationSpec } it("Baker.getRecipeInstanceState (fails with NoSuchProcessException)") { - test { (_, server, _) => + test { (_, stateNode, _) => for { - e <- server + e <- stateNode .getRecipeInstanceState("non-existent") .map(_ => None) .recover { case e: BakerException => Some(e) } @@ -135,7 +134,7 @@ class BaaSIntegrationSpec } it("Baker.fireEventAndResolveWhenReceived") { - test { (client, server, interactionNode) => + test { (client, _, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress("address"))) @@ -149,7 +148,7 @@ class BaaSIntegrationSpec } it("Baker.fireEventAndResolveWhenCompleted") { - test { (client, server, interactionNode) => + test { (client, stateNode, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress("address"))) @@ -158,7 +157,7 @@ class BaaSIntegrationSpec recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) result <- client.fireEventAndResolveWhenCompleted(recipeInstanceId, event) - serverState <- server.getRecipeInstanceState(recipeInstanceId) + serverState <- stateNode.getRecipeInstanceState(recipeInstanceId) } yield { result.eventNames should contain("ShippingAddressReceived") serverState.events.map(_.name) should contain("ShippingAddressReceived") @@ -167,7 +166,7 @@ class BaaSIntegrationSpec } it("Baker.fireEventAndResolveWhenCompleted (fails with IllegalEventException)") { - test { (client, server, interactionNode) => + test { (client, stateNode, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance("non-existent", Map.empty) for { @@ -178,7 +177,7 @@ class BaaSIntegrationSpec .fireEventAndResolveWhenCompleted(recipeInstanceId, event) .map(_ => None) .recover { case e: BakerException => Some(e) } - serverState <- server.getRecipeInstanceState(recipeInstanceId) + serverState <- stateNode.getRecipeInstanceState(recipeInstanceId) } yield { result shouldBe Some(BakerException.IllegalEventException("No event with name 'non-existent' found in recipe 'Webshop'")) serverState.events.map(_.name) should not contain("ShippingAddressReceived") @@ -187,7 +186,7 @@ class BaaSIntegrationSpec } it("Baker.fireEventAndResolveOnEvent") { - test { (client, server, interactionNode) => + test { (client, stateNode, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress("address"))) @@ -196,7 +195,7 @@ class BaaSIntegrationSpec recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) result <- client.fireEventAndResolveOnEvent(recipeInstanceId, event, "ShippingAddressReceived") - serverState <- server.getRecipeInstanceState(recipeInstanceId) + serverState <- stateNode.getRecipeInstanceState(recipeInstanceId) } yield { result.eventNames should contain("ShippingAddressReceived") serverState.events.map(_.name) should contain("ShippingAddressReceived") @@ -205,27 +204,27 @@ class BaaSIntegrationSpec } it("Baker.getAllRecipeInstancesMetadata") { - test { (client, server, interactionNode) => + test { (client, stateNode, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString for { compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) clientMetadata <- client.getAllRecipeInstancesMetadata - serverMetadata <- server.getAllRecipeInstancesMetadata + serverMetadata <- stateNode.getAllRecipeInstancesMetadata } yield clientMetadata shouldBe serverMetadata } } it("Baker.getVisualState") { - test { (client, server, interactionNode) => + test { (client, stateNode, interactionNode) => val recipeInstanceId: String = UUID.randomUUID().toString for { compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) clientState <- client.getVisualState(recipeInstanceId) - serverState <- server.getVisualState(recipeInstanceId) + serverState <- stateNode.getVisualState(recipeInstanceId) } yield clientState shouldBe serverState } } @@ -307,33 +306,33 @@ class BaaSIntegrationSpec object BaaSIntegrationSpec { - def setupHappyPath(serverBaker: BaaSInteractionInstance)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { + def setupHappyPath(interactionNode: BaaSInteractionInstance)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { val makePaymentInstance = InteractionInstance.unsafeFrom(new MakePaymentInstance()) val reserveItemsInstance = InteractionInstance.unsafeFrom(new ReserveItemsInstance()) val shipItemsInstance = InteractionInstance.unsafeFrom(new ShipItemsInstance()) val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) for { - _ <- Future { serverBaker.load(makePaymentInstance, reserveItemsInstance, shipItemsInstance) } + _ <- Future { interactionNode.load(makePaymentInstance, reserveItemsInstance, shipItemsInstance) } } yield compiledRecipe } - def setupFailingOnceReserveItems(serverBaker: BaaSInteractionInstance)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { + def setupFailingOnceReserveItems(interactionNode: BaaSInteractionInstance)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { val makePaymentInstance = InteractionInstance.unsafeFrom(new MakePaymentInstance()) val reserveItemsInstance = InteractionInstance.unsafeFrom(new FailingOnceReserveItemsInstance()) val shipItemsInstance = InteractionInstance.unsafeFrom(new ShipItemsInstance()) val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipeWithBlockingStrategy) for { - _ <- Future { serverBaker.load(makePaymentInstance, reserveItemsInstance, shipItemsInstance) } + _ <- Future { interactionNode.load(makePaymentInstance, reserveItemsInstance, shipItemsInstance) } } yield compiledRecipe } - def setupFailingWithRetryReserveItems(serverBaker: BaaSInteractionInstance)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { + def setupFailingWithRetryReserveItems(interactionNode: BaaSInteractionInstance)(implicit ec: ExecutionContext, timer: Timer[IO]): Future[CompiledRecipe] = { val makePaymentInstance = InteractionInstance.unsafeFrom(new MakePaymentInstance()) val reserveItemsInstance = InteractionInstance.unsafeFrom(new FailingReserveItemsInstance()) val shipItemsInstance = InteractionInstance.unsafeFrom(new ShipItemsInstance()) val compiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) for { - _ <- Future { serverBaker.load(makePaymentInstance, reserveItemsInstance, shipItemsInstance) } + _ <- Future { interactionNode.load(makePaymentInstance, reserveItemsInstance, shipItemsInstance) } } yield compiledRecipe } @@ -348,37 +347,25 @@ object BaaSIntegrationSpec { val systemName: String = "ScalaDSLBaaSServerClientSpec-" + testId val allPorts: Stream[Int] = Stream.from(50000, 1) val program = for { - clientServerQuadruple <- buildBaaSClientServer(systemName) - (clientBaker, stateNodeBaker, stateNodePort, httpServerBinding) = clientServerQuadruple - interactionNodeTriplet <- buildClusterActorSystem(systemName, seedPortCandidate = stateNodePort) - (interactionNodeSystem, _, _) = interactionNodeTriplet - interactionNode = BaaSInteractionInstance(interactionNodeSystem) - a <- liftF(test(clientBaker, stateNodeBaker, interactionNode)) - _ <- liftF(interactionNodeSystem.terminate()) - _ <- liftF(httpServerBinding.unbind()) - _ <- liftF(stateNodeBaker.gracefulShutdown()) - } yield a - program.run(allPorts).map(_._2) - } - - private def buildBaaSClientServer - (systemName: String) - (implicit ec: ExecutionContext): WithOpenPort[(ScalaBaker, ScalaBaker, Int, Http.ServerBinding)] = { - for { - clusterTriplet <- buildClusterActorSystem(systemName, seedPortCandidate = 0) - (stateNodeSystem, serverConfig, stateNodePort) = clusterTriplet + clusterTuple <- buildClusterActorSystem(systemName, seedPortCandidate = 0) + (stateNodeSystem, serverConfig) = clusterTuple materializer = ActorMaterializer()(stateNodeSystem) stateNodeBaker = AkkaBaker(serverConfig, stateNodeSystem) httpPortAndBinding <- runStateNodeHttpServer(stateNodeBaker, stateNodeSystem, materializer) (httpPort, httpServerBinding) = httpPortAndBinding clientBaker = BakerClient.build(s"http://localhost:$httpPort/", Encryption.NoEncryption)(stateNodeSystem, materializer) - } yield (clientBaker, stateNodeBaker, stateNodePort, httpServerBinding) + interactionNode = BaaSInteractionInstance(stateNodeSystem) + a <- liftF(test(clientBaker, stateNodeBaker, interactionNode)) + _ <- liftF(httpServerBinding.unbind()) + _ <- liftF(stateNodeBaker.gracefulShutdown()) + } yield a + program.run(allPorts).map(_._2) } - private def buildClusterActorSystem(systemName: String, seedPortCandidate: Int)(implicit ec: ExecutionContext): WithOpenPort[(ActorSystem, Config, Int)] = + private def buildClusterActorSystem(systemName: String, seedPortCandidate: Int)(implicit ec: ExecutionContext): WithOpenPort[(ActorSystem, Config)] = withOpenPort { port => val config = genClusterConfig(systemName, port, seedPortCandidate) - Future { (ActorSystem(systemName, config), config, port) } + Future { (ActorSystem(systemName, config), config) } } private def runStateNodeHttpServer(stateNodeBaker: ScalaBaker, stateNodeSystem: ActorSystem, materializer: Materializer)(implicit ec: ExecutionContext): WithOpenPort[(Int, Http.ServerBinding)] = From 3a163d78c4efcdafb21348000b13865806683db5 Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Tue, 5 Nov 2019 14:34:03 +0100 Subject: [PATCH 40/86] finished testing the remote event listeners --- .../baker/baas/akka/EventListenerAgent.scala | 2 + .../src/test/resources/application.conf | 1 - .../baker/baas/spec/BaaSIntegrationSpec.scala | 72 +++++++++++++------ 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala index 70cd77fa4..6a4080ee2 100644 --- a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala @@ -27,6 +27,8 @@ class EventListenerAgent(recipeName: String, listenerFunction: (RecipeEventMetad def unsubscribeToEvents(): Unit = mediator ! DistributedPubSubMediator.Unsubscribe(eventsTopic, self) + subscribeToEvents() + def receive: Receive = { case ProtocolDistributedEventPublishing.Event(recipeEventMetadata, event) => listenerFunction(recipeEventMetadata, event) diff --git a/baas-tests/src/test/resources/application.conf b/baas-tests/src/test/resources/application.conf index 154996751..14b0925f8 100644 --- a/baas-tests/src/test/resources/application.conf +++ b/baas-tests/src/test/resources/application.conf @@ -74,7 +74,6 @@ akka { actor { provider = "cluster" idle-timeout = 1 minute - serialize-messages = on allow-java-serialization = off serializers { diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/spec/BaaSIntegrationSpec.scala b/baas-tests/src/test/scala/com/ing/baker/baas/spec/BaaSIntegrationSpec.scala index 677a7373f..77600547b 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/spec/BaaSIntegrationSpec.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/spec/BaaSIntegrationSpec.scala @@ -11,7 +11,7 @@ import cats.implicits._ import com.ing.baker.baas.recipe.CheckoutFlowEvents.ItemsReserved import com.ing.baker.baas.recipe.CheckoutFlowIngredients.{Item, OrderId, ReservedItems, ShippingAddress} import com.ing.baker.baas.recipe._ -import com.ing.baker.baas.scaladsl.{BaaSInteractionInstance, BakerClient} +import com.ing.baker.baas.scaladsl.{BaaSEventListener, BaaSInteractionInstance, BakerClient} import com.ing.baker.baas.spec.BaaSIntegrationSpec._ import com.ing.baker.baas.state.BaaSServer import com.ing.baker.compiler.RecipeCompiler @@ -25,6 +25,7 @@ import com.typesafe.config.{Config, ConfigFactory} import org.jboss.netty.channel.ChannelException import org.scalatest._ +import scala.collection.mutable import scala.concurrent.{ExecutionContext, Future} class BaaSIntegrationSpec @@ -39,7 +40,7 @@ class BaaSIntegrationSpec describe("Baker Client-Server") { it("Baker.addRecipe") { - test { (client, stateNode, interactionNode) => + test { (client, stateNode, interactionNode, _) => for { compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) @@ -49,7 +50,7 @@ class BaaSIntegrationSpec } it("Baker.getRecipe") { - test { (client, _, interactionNode) => + test { (client, _, interactionNode, _) => for { compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) @@ -59,7 +60,7 @@ class BaaSIntegrationSpec } it("Baker.getRecipe (fail with NoSuchRecipeException)") { - test { (client, _, _) => + test { (client, _, _, _) => for { e <- client .getRecipe("non-existent") @@ -70,7 +71,7 @@ class BaaSIntegrationSpec } it("Baker.getAllRecipes") { - test { (client, stateNode, interactionNode) => + test { (client, stateNode, interactionNode, _) => for { compiledRecipe <- setupHappyPath(interactionNode) recipeId <- client.addRecipe(compiledRecipe) @@ -80,19 +81,23 @@ class BaaSIntegrationSpec } it("Baker.bake") { - test { (client, stateNode, interactionNode) => + test { (client, stateNode, interactionNode, eventListenerNode) => val recipeInstanceId: String = UUID.randomUUID().toString for { compiledRecipe <- setupHappyPath(interactionNode) + events <- setupEventListener(compiledRecipe, eventListenerNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) state <- stateNode.getRecipeInstanceState(recipeInstanceId) - } yield state.recipeInstanceId shouldBe recipeInstanceId + } yield { + events.toList shouldBe List.empty + state.recipeInstanceId shouldBe recipeInstanceId + } } } it("Baker.bake (fail with ProcessAlreadyExistsException)") { - test { (client, stateNode, interactionNode) => + test { (client, stateNode, interactionNode, _) => val recipeInstanceId: String = UUID.randomUUID().toString for { compiledRecipe <- setupHappyPath(interactionNode) @@ -111,7 +116,7 @@ class BaaSIntegrationSpec } it("Baker.bake (fail with NoSuchRecipeException)") { - test { (client, _, _) => + test { (client, _, _, _) => val recipeInstanceId: String = UUID.randomUUID().toString for { e <- client @@ -123,7 +128,7 @@ class BaaSIntegrationSpec } it("Baker.getRecipeInstanceState (fails with NoSuchProcessException)") { - test { (_, stateNode, _) => + test { (_, stateNode, _, _) => for { e <- stateNode .getRecipeInstanceState("non-existent") @@ -134,7 +139,7 @@ class BaaSIntegrationSpec } it("Baker.fireEventAndResolveWhenReceived") { - test { (client, _, interactionNode) => + test { (client, _, interactionNode, _) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress("address"))) @@ -148,12 +153,13 @@ class BaaSIntegrationSpec } it("Baker.fireEventAndResolveWhenCompleted") { - test { (client, stateNode, interactionNode) => + test { (client, stateNode, interactionNode, eventListenerNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress("address"))) for { compiledRecipe <- setupHappyPath(interactionNode) + events <- setupEventListener(compiledRecipe, eventListenerNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) result <- client.fireEventAndResolveWhenCompleted(recipeInstanceId, event) @@ -161,12 +167,13 @@ class BaaSIntegrationSpec } yield { result.eventNames should contain("ShippingAddressReceived") serverState.events.map(_.name) should contain("ShippingAddressReceived") + events.toList.map(_.name) should contain("ShippingAddressReceived") } } } it("Baker.fireEventAndResolveWhenCompleted (fails with IllegalEventException)") { - test { (client, stateNode, interactionNode) => + test { (client, stateNode, interactionNode, _) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance("non-existent", Map.empty) for { @@ -186,12 +193,13 @@ class BaaSIntegrationSpec } it("Baker.fireEventAndResolveOnEvent") { - test { (client, stateNode, interactionNode) => + test { (client, stateNode, interactionNode, eventListenerNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress("address"))) for { compiledRecipe <- setupHappyPath(interactionNode) + events <- setupEventListener(compiledRecipe, eventListenerNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) result <- client.fireEventAndResolveOnEvent(recipeInstanceId, event, "ShippingAddressReceived") @@ -199,12 +207,13 @@ class BaaSIntegrationSpec } yield { result.eventNames should contain("ShippingAddressReceived") serverState.events.map(_.name) should contain("ShippingAddressReceived") + events.toList.map(_.name) should contain("ShippingAddressReceived") } } } it("Baker.getAllRecipeInstancesMetadata") { - test { (client, stateNode, interactionNode) => + test { (client, stateNode, interactionNode, _) => val recipeInstanceId: String = UUID.randomUUID().toString for { compiledRecipe <- setupHappyPath(interactionNode) @@ -217,7 +226,7 @@ class BaaSIntegrationSpec } it("Baker.getVisualState") { - test { (client, stateNode, interactionNode) => + test { (client, stateNode, interactionNode, _) => val recipeInstanceId: String = UUID.randomUUID().toString for { compiledRecipe <- setupHappyPath(interactionNode) @@ -230,12 +239,13 @@ class BaaSIntegrationSpec } it("Baker.retryInteraction") { - test { (client, _, interactionNode) => + test { (client, _, interactionNode, eventListenerNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.OrderPlaced(orderId = OrderId("order1"), List.empty)) for { compiledRecipe <- setupFailingOnceReserveItems(interactionNode) + events <- setupEventListener(compiledRecipe, eventListenerNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) _ <- client.fireEventAndResolveWhenCompleted(recipeInstanceId, event) @@ -247,12 +257,14 @@ class BaaSIntegrationSpec state1 should not contain("ItemsReserved") state2 should contain("OrderPlaced") state2 should contain("ItemsReserved") + events.toList.map(_.name) should contain("OrderPlaced") + events.toList.map(_.name) should contain("ItemsReserved") } } } it("Baker.resolveInteraction") { - test { (client, _, interactionNode) => + test { (client, _, interactionNode, eventListenerNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.OrderPlaced(orderId = OrderId("order1"), List.empty)) @@ -261,6 +273,7 @@ class BaaSIntegrationSpec ) for { compiledRecipe <- setupFailingOnceReserveItems(interactionNode) + events <- setupEventListener(compiledRecipe, eventListenerNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) _ <- client.fireEventAndResolveWhenCompleted(recipeInstanceId, event) @@ -275,17 +288,20 @@ class BaaSIntegrationSpec state2 should contain("OrderPlaced") state2 should contain("ItemsReserved") eventState shouldBe Some("item1") + events.toList.map(_.name) should contain("OrderPlaced") + events.toList.map(_.name) should not contain("ItemsReserved") // Manually resolving an interaction does not fire the event to the listeners? } } } it("Baker.stopRetryingInteraction") { - test { (client, _, interactionNode) => + test { (client, _, interactionNode, eventListenerNode) => val recipeInstanceId: String = UUID.randomUUID().toString val event = EventInstance.unsafeFrom( CheckoutFlowEvents.OrderPlaced(orderId = OrderId("order1"), List.empty)) for { compiledRecipe <- setupFailingWithRetryReserveItems(interactionNode) + events <- setupEventListener(compiledRecipe, eventListenerNode) recipeId <- client.addRecipe(compiledRecipe) _ <- client.bake(recipeId, recipeInstanceId) _ <- client.fireEventAndResolveWhenReceived(recipeInstanceId, event) @@ -298,6 +314,8 @@ class BaaSIntegrationSpec state1 should not contain("ItemsReserved") state2 should contain("OrderPlaced") state2 should not contain("ItemsReserved") + events.toList.map(_.name) should contain("OrderPlaced") + events.toList.map(_.name) should not contain("ItemsReserved") } } } @@ -336,15 +354,22 @@ object BaaSIntegrationSpec { } yield compiledRecipe } - type IntegrationTest = ((ScalaBaker, ScalaBaker, BaaSInteractionInstance) => Future[Assertion]) => Future[Assertion] + def setupEventListener(recipe: CompiledRecipe, eventListenerNode: BaaSEventListener)(implicit ec: ExecutionContext): Future[mutable.MutableList[EventInstance]] = { + val buffer = mutable.MutableList.empty[EventInstance] + eventListenerNode.registerEventListener(recipe.name, (_, event) => { + buffer.+=(event) + }).map(_ => buffer) + } + + type IntegrationTest = ((ScalaBaker, ScalaBaker, BaaSInteractionInstance, BaaSEventListener) => Future[Assertion]) => Future[Assertion] type WithOpenPort[A] = StateT[Future, Stream[Int], A] def testWith[F[_], Lang <: LanguageApi] - (test: (ScalaBaker, ScalaBaker, BaaSInteractionInstance) => Future[Assertion]) + (test: (ScalaBaker, ScalaBaker, BaaSInteractionInstance, BaaSEventListener) => Future[Assertion]) (implicit ec: ExecutionContext): Future[Assertion] = { val testId: UUID = UUID.randomUUID() - val systemName: String = "ScalaDSLBaaSServerClientSpec-" + testId + val systemName: String = "BaaSIntegrationSpec-" + testId val allPorts: Stream[Int] = Stream.from(50000, 1) val program = for { clusterTuple <- buildClusterActorSystem(systemName, seedPortCandidate = 0) @@ -355,7 +380,8 @@ object BaaSIntegrationSpec { (httpPort, httpServerBinding) = httpPortAndBinding clientBaker = BakerClient.build(s"http://localhost:$httpPort/", Encryption.NoEncryption)(stateNodeSystem, materializer) interactionNode = BaaSInteractionInstance(stateNodeSystem) - a <- liftF(test(clientBaker, stateNodeBaker, interactionNode)) + eventListenerNode = BaaSEventListener(stateNodeSystem) + a <- liftF(test(clientBaker, stateNodeBaker, interactionNode, eventListenerNode)) _ <- liftF(httpServerBinding.unbind()) _ <- liftF(stateNodeBaker.gracefulShutdown()) } yield a From 969da97a4894a7d4548d2bb162fd33462911faa0 Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Tue, 19 Nov 2019 17:49:03 +0100 Subject: [PATCH 41/86] Setup of playground --- .../src/main/resources/application.conf | 100 +++++++++++++++++ .../src/main/resources/logback.xml | 15 +++ .../com/ing/baker/baas/state/BaaSServer.scala | 9 +- .../scala/com/ing/baker/baas/state/Main.scala | 29 +++++ build.sbt | 44 +++++++- .../src/main/java/webshop/simple/JMain.java | 4 +- .../src/main/resources/haproxy/haproxy.cfg | 6 +- .../main/scala/webshop/webservice/Main.scala | 3 +- .../com/ing/baker/playground/ColorPrint.scala | 44 ++++++++ .../com/ing/baker/playground/Command.scala | 80 ++++++++++++++ .../ing/baker/playground/DockerCommands.scala | 38 +++++++ .../scala/com/ing/baker/playground/Main.scala | 103 ++++++++++++++++++ .../ing/baker/playground/PlaygroundApp.scala | 54 +++++++++ project/plugins.sbt | 2 +- 14 files changed, 516 insertions(+), 15 deletions(-) create mode 100644 baas-node-state/src/main/resources/application.conf create mode 100644 baas-node-state/src/main/resources/logback.xml create mode 100644 baas-node-state/src/main/scala/com/ing/baker/baas/state/Main.scala create mode 100644 playground/src/main/scala/com/ing/baker/playground/ColorPrint.scala create mode 100644 playground/src/main/scala/com/ing/baker/playground/Command.scala create mode 100644 playground/src/main/scala/com/ing/baker/playground/DockerCommands.scala create mode 100644 playground/src/main/scala/com/ing/baker/playground/Main.scala create mode 100644 playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala diff --git a/baas-node-state/src/main/resources/application.conf b/baas-node-state/src/main/resources/application.conf new file mode 100644 index 000000000..4d6717141 --- /dev/null +++ b/baas-node-state/src/main/resources/application.conf @@ -0,0 +1,100 @@ +include "baker.conf" + +service { + + actorSystemName = "BaaS" + actorSystemName = ${?ACTOR_SYSTEM_NAME} + + clusterHost = "127.0.0.1" + clusterHost = ${?CLUSTER_HOST} + + clusterPort = 2551 + clusterPort = ${?CLUSTER_PORT} + + seedHost = "127.0.0.1" + seedHost = ${?CLUSTER_SEED_HOST} + + seedPort = 2551 + seedPort = ${?CLUSTER_SEED_PORT} + + httpServerPort = 8080 + httpServerPort = ${?HTTP_SERVER_PORT} + + memory-dump-path = "/home/demiourgos728/memdump" + memory-dump-path = ${?APP_MEMORY_DUMP_PATH} +} + +baker { + + interaction-manager = "remote" + + actor { + provider = "cluster-sharded" + idle-timeout = 1 minute + } + + cluster { + nr-of-shards = 52 + seed-nodes = [ + "akka.tcp://"${service.actorSystemName}"@"${service.seedHost}":"${service.seedPort}] + } +} + +cassandra-journal.contact-points.0 = "127.0.0.1" +cassandra-journal.contact-points.0 = ${?CASSANDRA_CONTACT_POINTS_0} + +cassandra-snapshot-store.contact-points.0 = "127.0.0.1" +cassandra-snapshot-store.contact-points.0 = ${?CASSANDRA_CONTACT_POINTS_0} + +akka.actor.allow-java-serialization = on + +akka { + + actor { + provider = "cluster" + } + + persistence { + # See https://doc.akka.io/docs/akka-persistence-cassandra/current/journal.html#configuration + journal.plugin = "cassandra-journal" + # See https://doc.akka.io/docs/akka-persistence-cassandra/current/snapshots.html#configuration + snapshot-store.plugin = "cassandra-snapshot-store" + } + + remote { + log-remote-lifecycle-events = off + netty.tcp { + hostname = ${service.clusterHost} + port = ${service.clusterPort} + } + } + + cluster { + + seed-nodes = [ + "akka.tcp://"${service.actorSystemName}"@"${service.seedHost}":"${service.seedPort}] + + # auto downing is NOT safe for production deployments. + # you may want to use it during development, read more about it in the docs. + # + # auto-down-unreachable-after = 10s + } +} + +kamon.instrumentation.akka.filters { + + actors.track { + includes = [ ${service.actorSystemName}"/user/*" ] + excludes = [] + # ${service.actorSystemName}"/system/**", ${service.actorSystemName}"/user/worker-helper" + #] + } + + dispatchers { + includes = [ ${service.actorSystemName}"/akka.actor.default-dispatcher" ] + } + + routers { + includes = [ ${service.actorSystemName}"/user/*" ] + } +} diff --git a/baas-node-state/src/main/resources/logback.xml b/baas-node-state/src/main/resources/logback.xml new file mode 100644 index 000000000..417dc94e9 --- /dev/null +++ b/baas-node-state/src/main/resources/logback.xml @@ -0,0 +1,15 @@ + + + + + + + + + + %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + + + + + \ No newline at end of file diff --git a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala index a6b3bf573..ffb899344 100644 --- a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala +++ b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala @@ -7,10 +7,9 @@ import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import akka.stream.Materializer import com.ing.baker.baas.protocol.BaaSProto._ -import com.ing.baker.baas.protocol.BaaSProtocol import com.ing.baker.baas.protocol.MarshallingUtils._ -import com.ing.baker.baas.protocol.ProtocolDistributedEventPublishing -import com.ing.baker.runtime.scaladsl.{Baker, EventInstance} +import com.ing.baker.baas.protocol.{BaaSProtocol, ProtocolDistributedEventPublishing} +import com.ing.baker.runtime.scaladsl.Baker import com.ing.baker.runtime.serialization.{Encryption, SerializersProvider} import scala.concurrent.{ExecutionContext, Future} @@ -48,12 +47,14 @@ class BaaSServer(implicit system: ActorSystem, mat: Materializer, baker: Baker, implicit private val serializersProvider: SerializersProvider = SerializersProvider(system, encryption) - def route: Route = pathPrefix("api" / "v3")(concat(addRecipe, getRecipe, getAllRecipes, bake, + def route: Route = pathPrefix("api" / "v3")(concat(health, addRecipe, getRecipe, getAllRecipes, bake, fireEventAndResolveWhenReceived, fireEventAndResolveWhenCompleted, fireEventAndResolveOnEvent, fireEvent, getAllRecipeInstancesMetadata, getRecipeInstanceState, getVisualState, retryInteraction, resolveInteraction, stopRetryingInteraction )) + private def health: Route = get(complete("Ok")) + private def addRecipe: Route = post(path("addRecipe") { entity(as[BaaSProtocol.AddRecipeRequest]) { request => val result = for { diff --git a/baas-node-state/src/main/scala/com/ing/baker/baas/state/Main.scala b/baas-node-state/src/main/scala/com/ing/baker/baas/state/Main.scala new file mode 100644 index 000000000..e7459a05f --- /dev/null +++ b/baas-node-state/src/main/scala/com/ing/baker/baas/state/Main.scala @@ -0,0 +1,29 @@ +package com.ing.baker.baas.state + +import akka.actor.ActorSystem +import akka.stream.ActorMaterializer +import com.ing.baker.runtime.akka.AkkaBaker +import com.typesafe.config.ConfigFactory + +import scala.concurrent.duration._ +import scala.concurrent.Await + +object Main extends App { + + println(Console.YELLOW + "Starting State Node..." + Console.RESET) + + val config = ConfigFactory.load() + val systemName = config.getString("service.actorSystemName") + val httpServerPort = config.getInt("service.httpServerPort") + val stateNodeSystem = ActorSystem(systemName) + val stateNodeBaker = AkkaBaker(config, stateNodeSystem) + val materializer = ActorMaterializer()(stateNodeSystem) + + import stateNodeSystem.dispatcher + + BaaSServer.run(stateNodeBaker, "0.0.0.0", httpServerPort)(stateNodeSystem, materializer).map { hook => + println(Console.GREEN + "State Node started..." + Console.RESET) + println(hook.localAddress) + sys.addShutdownHook(Await.result(hook.unbind(), 20.seconds)) + } +} diff --git a/build.sbt b/build.sbt index 1f9b22f28..e935edbc8 100644 --- a/build.sbt +++ b/build.sbt @@ -78,7 +78,6 @@ lazy val intermediateLanguage = project.in(file("intermediate-language")) lazy val `baker-interface` = project.in(file("baker-interface")) .settings(defaultModuleSettings) - .settings(noPublishSettings) .settings(scalaPBSettings) .settings( moduleName := "baker-interface", @@ -205,7 +204,6 @@ lazy val recipeCompiler = project.in(file("compiler")) lazy val `baas-protocol-baker` = project.in(file("baas-protocol-baker")) .settings(defaultModuleSettings) - .settings(noPublishSettings) .settings(scalaPBSettings) .settings( moduleName := "baas-protocol-baker", @@ -217,7 +215,6 @@ lazy val `baas-protocol-baker` = project.in(file("baas-protocol-baker")) lazy val `baas-protocol-interaction-scheduling` = project.in(file("baas-protocol-interaction-scheduling")) .settings(defaultModuleSettings) - .settings(noPublishSettings) .settings(scalaPBSettings) .settings( moduleName := "baas-protocol-interaction-scheduling" @@ -226,7 +223,6 @@ lazy val `baas-protocol-interaction-scheduling` = project.in(file("baas-protocol lazy val `baas-protocol-recipe-event-publishing` = project.in(file("baas-protocol-recipe-event-publishing")) .settings(defaultModuleSettings) - .settings(noPublishSettings) .settings(scalaPBSettings) .settings( moduleName := "baas-protocol-recipe-event-publishing" @@ -244,14 +240,24 @@ lazy val `baas-node-client` = project.in(file("baas-node-client")) .dependsOn(`baker-interface`, `baas-protocol-baker`) lazy val `baas-node-state` = project.in(file("baas-node-state")) - .settings(defaultModuleSettings) + .enablePlugins(JavaAppPackaging) + .settings(commonSettings) .settings( moduleName := "baas-node-state", + scalacOptions ++= Seq( + "-Ypartial-unification" + ), libraryDependencies ++= Seq( akkaHttp, akkaPersistenceCassandra ) ) + .settings( + maintainer in Docker := "The Apollo Squad", + packageSummary in Docker := "The core node", + packageName in Docker := "apollo.docker.ing.net/baas-node-state", + dockerExposedPorts := Seq(8080) + ) .dependsOn(runtime, `baas-protocol-baker`, `baas-protocol-interaction-scheduling`) lazy val `baas-node-interaction` = project.in(file("baas-node-interaction")) @@ -325,6 +331,34 @@ lazy val integration = project.in(file("integration")) .enablePlugins(MultiJvmPlugin) .configs(MultiJvm) +lazy val playground = project + .in(file("playground")) + .settings( + name := "baker-playground", + version := "0.1.0", + organization := "com.ing.baker", + scalaVersion := "2.12.4", + libraryDependencies ++= Seq( + "org.typelevel" %% "cats-effect" % "2.0.0", + "dev.profunktor" %% "console4cats" % "0.8.0", + "org.scalatest" %% "scalatest" % "3.0.8" % "test", + "org.scalacheck" %% "scalacheck" % "1.14.1" % "test" + ), + scalacOptions := Seq( + "-unchecked", + "-deprecation", + "-feature", + "-Ywarn-dead-code", + "-language:higherKinds", + "-language:existentials", + "-language:implicitConversions", + "-language:postfixOps", + "-encoding", "utf8", + s"-target:jvm-$jvmV", + "-Xfatal-warnings" + ) + ) + lazy val examples = project .in(file("examples")) .enablePlugins(JavaAppPackaging) diff --git a/examples/src/main/java/webshop/simple/JMain.java b/examples/src/main/java/webshop/simple/JMain.java index 58ca3859a..8c8f1143f 100644 --- a/examples/src/main/java/webshop/simple/JMain.java +++ b/examples/src/main/java/webshop/simple/JMain.java @@ -3,7 +3,9 @@ import akka.actor.ActorSystem; import com.ing.baker.compiler.RecipeCompiler; import com.ing.baker.il.CompiledRecipe; +import com.ing.baker.runtime.akka.AkkaBaker; import com.ing.baker.runtime.javadsl.*; +import com.typesafe.config.ConfigFactory; import java.util.ArrayList; import java.util.List; @@ -16,7 +18,7 @@ public class JMain { static public void main_ignore(String[] args) { ActorSystem actorSystem = ActorSystem.create("WebshopSystem"); - Baker baker = Baker.akkaLocalDefault(actorSystem); + Baker baker = AkkaBaker.java(ConfigFactory.load(), actorSystem); List items = new ArrayList<>(2); items.add("item1"); diff --git a/examples/src/main/resources/haproxy/haproxy.cfg b/examples/src/main/resources/haproxy/haproxy.cfg index cbe29a7df..99d668eb4 100644 --- a/examples/src/main/resources/haproxy/haproxy.cfg +++ b/examples/src/main/resources/haproxy/haproxy.cfg @@ -37,6 +37,6 @@ backend nodes http-request set-header X-Forwarded-Port %[dst_port] http-request add-header X-Forwarded-Proto https if { ssl_fc } option httpchk HEAD / HTTP/1.1 - server web01 host.docker.internal:8081 check - server web02 host.docker.internal:8082 check - server web03 host.docker.internal:8083 check + server web01 state-node-1:8080 check + server web02 state-node-2:8080 check + server web03 state-node-3:8080 check diff --git a/examples/src/main/scala/webshop/webservice/Main.scala b/examples/src/main/scala/webshop/webservice/Main.scala index 0b4455ce1..be79ed900 100644 --- a/examples/src/main/scala/webshop/webservice/Main.scala +++ b/examples/src/main/scala/webshop/webservice/Main.scala @@ -5,6 +5,7 @@ import akka.cluster.Cluster import cats.effect.concurrent.Ref import cats.effect.{ExitCode, IO, IOApp, Resource} import cats.implicits._ +import com.ing.baker.runtime.akka.AkkaBaker import com.ing.baker.runtime.scaladsl._ import com.typesafe.config.ConfigFactory import kamon.Kamon @@ -24,7 +25,7 @@ object Main extends IOApp { for { actorSystem <- IO { ActorSystem("CheckoutService") } config <- IO { ConfigFactory.load() } - baker <- IO { Baker.akka(config, actorSystem) } + baker <- IO { AkkaBaker(config, actorSystem) } checkoutRecipeId <- WebShopBaker.initRecipes(baker)(timer, actorSystem.dispatcher) sd <- Ref.of[IO, Boolean](false) webShopBaker = new WebShopBaker(baker, checkoutRecipeId)(actorSystem.dispatcher) diff --git a/playground/src/main/scala/com/ing/baker/playground/ColorPrint.scala b/playground/src/main/scala/com/ing/baker/playground/ColorPrint.scala new file mode 100644 index 000000000..162c45371 --- /dev/null +++ b/playground/src/main/scala/com/ing/baker/playground/ColorPrint.scala @@ -0,0 +1,44 @@ +package com.ing.baker.playground + +import cats.effect.IO + +import scala.util.Random + +object ColorPrint { + + private val colors: Array[String] = Array( + Console.MAGENTA, + Console.RED, + Console.YELLOW, + Console.GREEN, + Console.CYAN, + Console.BLUE + ) + + implicit class PrettyColorPrint[A](a: A) { + + def print: IO[Unit] = + IO { println(a.toString) } + + def magenta: String = + Console.MAGENTA + a.toString + Console.RESET + + def green: String = + Console.GREEN + a.toString + Console.RESET + + def red: String = + Console.RED + a.toString + Console.RESET + + def yellow: String = + Console.YELLOW + a.toString + Console.RESET + + def randomColor: String = + colors(Random.nextInt(colors.length)) + a.toString + Console.RESET + + def prompt(prepend: String): String = + a.toString.lines.map(prepend + _).mkString("\n") + + def notice: String = + " [>>>] " + a.toString + " [<<<] " + } +} diff --git a/playground/src/main/scala/com/ing/baker/playground/Command.scala b/playground/src/main/scala/com/ing/baker/playground/Command.scala new file mode 100644 index 000000000..2ad81f43d --- /dev/null +++ b/playground/src/main/scala/com/ing/baker/playground/Command.scala @@ -0,0 +1,80 @@ +package com.ing.baker.playground + +import cats.effect.IO +import ColorPrint._ +import scala.sys.process._ + +trait Command { + + def raw: String = "unmatched command, fix me" + + def help: String = "No help for this command" +} + +object Command { + + val commands: List[Command] = + List( + Help, + RunCassandra + ) + + case object Help extends Command { + + override def raw: String = "help" + + override def help: String = "Displays this help menu" + } + + case object RunCassandra extends Command { + + override def raw: String = "run-cassandra" + + override def help: String = "Runs Cassandra on default ports within the playground network" + } + + def execPrint(process: ProcessBuilder, prompt: String): IO[Unit] = { + val p = prompt.randomColor + exec(process, ProcessLogger( + _.prompt(p + " | ").print.unsafeRunSync(), + _.prompt((prompt + " [ERROR]").red + " | ").print.unsafeRunSync() + )).flatMap { running => + val exitValue = running.exitValue() + if (exitValue == 0) IO(()) + else IO.raiseError(new Exception(s"Command $process exited with non zero value $exitValue")) + } + } + + def execPrintAndWaitForMatch(process: ProcessBuilder, prompt: String, condition: String => Boolean): IO[Process] = { + IO.async { callback => + val p = prompt.randomColor + var running: Process = null + var matched: Boolean = false + running = process.run(ProcessLogger( + { line => + line.prompt(p + " | ").print.unsafeRunSync() + if(condition(line) && !matched) { + matched = true + callback(Right(running)) + } + }, + { line => + line.prompt((prompt + " [ERROR]").red + " | ").print.unsafeRunSync() + if(condition(line) && !matched) { + matched = true + callback(Right(running)) + } + } + )) + } + } + + def execBlock(process: ProcessBuilder): IO[String] = + IO { process.!!<.trim } + + def exec(process: ProcessBuilder, logger: ProcessLogger): IO[Process] = + IO { process.run(logger) } + + def failIO(reason: String): IO[Nothing] = + IO.raiseError(new Exception(reason)) +} diff --git a/playground/src/main/scala/com/ing/baker/playground/DockerCommands.scala b/playground/src/main/scala/com/ing/baker/playground/DockerCommands.scala new file mode 100644 index 000000000..6ba82f000 --- /dev/null +++ b/playground/src/main/scala/com/ing/baker/playground/DockerCommands.scala @@ -0,0 +1,38 @@ +package com.ing.baker.playground + +import cats.implicits._ +import cats.effect.IO +import Command._ + +import scala.sys.process._ +import scala.util.matching.Regex + +object DockerCommands { + + def networkName: String = "baker-playground-network" + + def checkForDockerVersion: IO[Unit] = { + val DockerVersionReg: Regex = """Docker version (\d\d).*, build .+""".r + val requiredVersion: Int = 19 + execBlock(Process(Seq("docker", "--version"))).map { + case DockerVersionReg(version) => + if (version.toInt >= requiredVersion) IO(()) + else failIO(s"Docker version is $version but $requiredVersion or greater is required.") + case _ => + failIO("Bad input for function isRequiredVersion") + } + } + + def terminate(name: String): IO[Unit] = + execPrint(Process(s"docker kill $name"), s"Terminate $name").attempt.void *> + execBlock(Process(s"docker rm $name")).attempt.void + + def createDockerNetwork: IO[Unit] = + execPrint(Process(s"docker network create $networkName"), "Docker Network").attempt.void + + def deleteDockerNetwork: IO[Unit] = + execPrint(Process(s"docker network rm $networkName"), "Remove Docker Network") + + def dockerPull(image: String): IO[Unit] = + execPrint(Process(s"docker pull $image"), s"Pull $image Image").void +} diff --git a/playground/src/main/scala/com/ing/baker/playground/Main.scala b/playground/src/main/scala/com/ing/baker/playground/Main.scala new file mode 100644 index 000000000..c3cafc451 --- /dev/null +++ b/playground/src/main/scala/com/ing/baker/playground/Main.scala @@ -0,0 +1,103 @@ +package com.ing.baker.playground + +import cats.effect.{ExitCode, IO, IOApp} + +object Main extends IOApp { + + override def run(args: List[String]): IO[ExitCode] = { + PlaygroundApp.loop.map(_ => ExitCode.Success) + } + + /* + def baasBasicCluster: IO[Unit] = { + val baasStateNodeVersion = "3.0.2-SNAPSHOT" + scenario { + for { + //_ <- dockerPullStateNode(baasStateNodeVersion) + node1 <- runStateNode(baasStateNodeVersion, 1, "self") + node2 <- runStateNode(baasStateNodeVersion, 2, node1) + node3 <- runStateNode(baasStateNodeVersion, 3, node1) + _ <- IO { scala.io.StdIn.readLine() } + _ <- terminate(node1) + _ <- terminate(node2) + _ <- terminate(node3) + } yield () + } + } + + def scenario(program: IO[Unit]): IO[Unit] = + for { + _ <- dockerIsRequiredVersion + _ <- createEnvironment.bracket(_ => program)(cleanEnvironment) + } yield () + + case class Environment(cassandra: Process, haproxy: Process) + + def createEnvironment: IO[Environment] = + for { + _ <- terminateHaproxy + _ <- terminateCassandra + _ <- createDockerNetwork + //_ <- dockerPullCassandra + //_ <- dockerPullHaproxy + haproxy <- runHaproxy + cassandra <- runCassandra + } yield Environment(cassandra, haproxy) + + def cleanEnvironment(env: Environment): IO[Unit] = + for { + _ <- terminateHaproxy + _ <- terminateCassandra + _ <- deleteDockerNetwork + } yield () + */ + + /* + def networkName: String = "baker-playground-network" + + def runCassandra: IO[Process] = + execPrintAndWaitForMatch( + process = Process(s"docker run --name baker-cassandra --network $networkName -p 9042:9042 -p 9160:9160 cassandra:latest"), + prompt = "Cassandra", + condition = _.matches("""INFO \[OptionalTasks:1\] (.+) CassandraRoleManager\.java:372 - Created default superuser role 'cassandra'""") + ) + + def runHaproxy: IO[Process] = + execPrintAndWaitForMatch( + process = Process(s"docker run --name baker-haproxy --network $networkName -p 8080:8080 baker-haproxy:latest"), + prompt = "Haproxy", + condition = _ => true + ) + + def runStateNode(version: String, node: Int, seedHost: String): IO[String] = { + val containerName: String = s"state-node-$node" + val seedHostname: String = if(seedHost == "self") containerName else seedHost + val envVars = Map( + "CLUSTER_HOST" -> containerName, + "CLUSTER_SEED_HOST" -> seedHostname, + "CASSANDRA_CONTACT_POINTS_0" -> "baker-cassandra" + ) + .map { case (env, value) => s"-e $env=$value"} + .mkString(" ") + val cmd = s"docker run --name $containerName --network $networkName $envVars apollo.docker.ing.net/baas-node-state:$version" + execPrintAndWaitForMatch( + process = Process(cmd), + prompt = s"state-node:$version:$node", + condition = _.contains(s"State Node started...") + ).map(_ => containerName) + } + + def terminateHaproxy: IO[Unit] = + terminate("baker-haproxy") + + def dockerPullCassandra: IO[Unit] = + dockerPull("cassandra") + + def dockerPullHaproxy: IO[Unit] = + dockerPull("apollo.docker.ing.net/baker-haproxy:latest") + + def dockerPullStateNode(version: String): IO[Unit] = + dockerPull(s"apollo.docker.ing.net/baas-node-state:$version") + */ + +} diff --git a/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala b/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala new file mode 100644 index 000000000..17f0f579f --- /dev/null +++ b/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala @@ -0,0 +1,54 @@ +package com.ing.baker.playground + +import cats.implicits._ +import cats.effect.IO +import cats.effect.Console.io._ +import Command._ +import DockerCommands._ + +import scala.sys.process._ + +object PlaygroundApp { + + def loop: IO[Unit] = + for { + _ <- putStr("playground> ") + line <- readLn + _ <- exec(line) + _ <- if (line == "exit") IO.unit else loop + } yield () + + def exec(raw: String): IO[Unit] = + if (raw == Command.Help.raw) + commandHelp + else if (raw == Command.RunCassandra.raw) + commandRunCassandra.void + else if (raw == "exit") + cleanup *> putStrLn("Bye bye! I hope you had fun :D") + else if (raw == "") + IO.unit + else + putStrLn(s"Unknown command '$raw'") + + def commandHelp: IO[Unit] = + putStrLn("") *> + Command.commands.traverse { command => + val spaces = List.fill(20 - command.raw.length)(".").mkString + putStrLn(command.raw + " " + spaces + " " + command.help) + } *> + putStrLn("") + + def cassandraName: String = "baker-cassandra" + + def commandRunCassandra: IO[Process] = + DockerCommands.createDockerNetwork *> + execPrintAndWaitForMatch( + process = Process(s"docker run --name $cassandraName --network $networkName -p 9042:9042 -p 9160:9160 cassandra:latest"), + prompt = "Cassandra", + condition = _.matches("""INFO \[OptionalTasks:1\] (.+) CassandraRoleManager\.java:372 - Created default superuser role 'cassandra'""") + ) + + def cleanup: IO[Unit] = + terminate(cassandraName) *> + DockerCommands.deleteDockerNetwork.attempt.void +} diff --git a/project/plugins.sbt b/project/plugins.sbt index ca64b6491..d3cd11bb4 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -18,7 +18,7 @@ addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.1") addSbtPlugin("com.typesafe.sbt" % "sbt-multi-jvm" % "0.4.0") -addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.25") +addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.4.0") libraryDependencies += "org.slf4j" % "slf4j-nop" % "1.7.25" From 62e2a152c082b2e553b976acbc2252988620083f Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Wed, 20 Nov 2019 15:42:42 +0100 Subject: [PATCH 42/86] moved example package to fit other examples and improved on the playground app --- .../com/ing/baker/baas/state/BaaSServer.scala | 7 ++- build.sbt | 2 +- .../src/main/java/webshop/simple/JMain.java | 0 .../java/webshop/simple/JWebshopRecipe.java | 0 .../webshop/simple/ReserveItemsInstance.java | 0 .../src/main/resources/application.conf | 0 .../src/main/resources/docker-compose.yaml | 0 .../webservice/CheckoutFlowSimulation.scala | 0 .../src/main/resources/grafana/Dockerfile | 0 .../src/main/resources/grafana/config.ini | 0 .../grafana/dashboards/akka_metrics.json | 0 .../grafana/provisioning/dashboards/all.yaml | 0 .../grafana/provisioning/datasources/all.yaml | 0 .../src/main/resources/haproxy/Dockerfile | 0 .../src/main/resources/haproxy/haproxy.cfg | 2 +- .../src/main/resources/logback.xml | 0 .../src/main/resources/prometheus/Dockerfile | 0 .../main/resources/prometheus/prometheus.yaml | 0 .../simple/SimpleWebshopInstances.scala | 0 .../SimpleWebshopInstancesReflection.scala | 0 .../webshop/simple/SimpleWebshopRecipe.scala | 0 .../SimpleWebshopRecipeReflection.scala | 0 .../webservice/CheckoutFlowRecipe.scala | 0 .../main/scala/webshop/webservice/Main.scala | 0 .../webservice/MakePaymentInstance.scala | 0 .../webshop/webservice/OrderStatus.scala | 0 .../webservice/ReserveItemsInstance.scala | 0 .../webservice/ShipItemsInstance.scala | 0 .../scala/webshop/webservice/WebShop.scala | 0 .../webshop/webservice/WebShopBaker.scala | 0 .../webshop/webservice/WebShopService.scala | 0 .../java/webshop/JWebshopRecipeTests.java | 0 .../webshop/simple/WebshopRecipeSpec.scala | 0 .../com/ing/baker/playground/AppMonad.scala | 43 ++++++++++++++++ .../ing/baker/playground/BaaSCommands.scala | 45 ++++++++++++++++ .../com/ing/baker/playground/Command.scala | 18 ++++++- .../ing/baker/playground/DockerCommands.scala | 22 +++++--- .../playground/EnvironmentCommands.scala | 31 +++++++++++ .../scala/com/ing/baker/playground/Main.scala | 7 ++- .../ing/baker/playground/PlaygroundApp.scala | 51 ++++++++----------- 40 files changed, 184 insertions(+), 44 deletions(-) rename examples/{ => baker-example}/src/main/java/webshop/simple/JMain.java (100%) rename examples/{ => baker-example}/src/main/java/webshop/simple/JWebshopRecipe.java (100%) rename examples/{ => baker-example}/src/main/java/webshop/simple/ReserveItemsInstance.java (100%) rename examples/{ => baker-example}/src/main/resources/application.conf (100%) rename examples/{ => baker-example}/src/main/resources/docker-compose.yaml (100%) rename examples/{ => baker-example}/src/main/resources/gatling/webshop/webservice/CheckoutFlowSimulation.scala (100%) rename examples/{ => baker-example}/src/main/resources/grafana/Dockerfile (100%) rename examples/{ => baker-example}/src/main/resources/grafana/config.ini (100%) rename examples/{ => baker-example}/src/main/resources/grafana/dashboards/akka_metrics.json (100%) rename examples/{ => baker-example}/src/main/resources/grafana/provisioning/dashboards/all.yaml (100%) rename examples/{ => baker-example}/src/main/resources/grafana/provisioning/datasources/all.yaml (100%) rename examples/{ => baker-example}/src/main/resources/haproxy/Dockerfile (100%) rename examples/{ => baker-example}/src/main/resources/haproxy/haproxy.cfg (95%) rename examples/{ => baker-example}/src/main/resources/logback.xml (100%) rename examples/{ => baker-example}/src/main/resources/prometheus/Dockerfile (100%) rename examples/{ => baker-example}/src/main/resources/prometheus/prometheus.yaml (100%) rename examples/{ => baker-example}/src/main/scala/webshop/simple/SimpleWebshopInstances.scala (100%) rename examples/{ => baker-example}/src/main/scala/webshop/simple/SimpleWebshopInstancesReflection.scala (100%) rename examples/{ => baker-example}/src/main/scala/webshop/simple/SimpleWebshopRecipe.scala (100%) rename examples/{ => baker-example}/src/main/scala/webshop/simple/SimpleWebshopRecipeReflection.scala (100%) rename examples/{ => baker-example}/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala (100%) rename examples/{ => baker-example}/src/main/scala/webshop/webservice/Main.scala (100%) rename examples/{ => baker-example}/src/main/scala/webshop/webservice/MakePaymentInstance.scala (100%) rename examples/{ => baker-example}/src/main/scala/webshop/webservice/OrderStatus.scala (100%) rename examples/{ => baker-example}/src/main/scala/webshop/webservice/ReserveItemsInstance.scala (100%) rename examples/{ => baker-example}/src/main/scala/webshop/webservice/ShipItemsInstance.scala (100%) rename examples/{ => baker-example}/src/main/scala/webshop/webservice/WebShop.scala (100%) rename examples/{ => baker-example}/src/main/scala/webshop/webservice/WebShopBaker.scala (100%) rename examples/{ => baker-example}/src/main/scala/webshop/webservice/WebShopService.scala (100%) rename examples/{ => baker-example}/src/test/java/webshop/JWebshopRecipeTests.java (100%) rename examples/{ => baker-example}/src/test/scala/webshop/simple/WebshopRecipeSpec.scala (100%) create mode 100644 playground/src/main/scala/com/ing/baker/playground/AppMonad.scala create mode 100644 playground/src/main/scala/com/ing/baker/playground/BaaSCommands.scala create mode 100644 playground/src/main/scala/com/ing/baker/playground/EnvironmentCommands.scala diff --git a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala index ffb899344..a7135ee30 100644 --- a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala +++ b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala @@ -3,6 +3,7 @@ package com.ing.baker.baas.state import akka.actor.ActorSystem import akka.cluster.pubsub.{DistributedPubSub, DistributedPubSubMediator} import akka.http.scaladsl.Http +import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import akka.stream.Materializer @@ -47,11 +48,13 @@ class BaaSServer(implicit system: ActorSystem, mat: Materializer, baker: Baker, implicit private val serializersProvider: SerializersProvider = SerializersProvider(system, encryption) - def route: Route = pathPrefix("api" / "v3")(concat(health, addRecipe, getRecipe, getAllRecipes, bake, + def route: Route = concat(haproxyCheck, pathPrefix("api" / "v3")(concat(health, addRecipe, getRecipe, getAllRecipes, bake, fireEventAndResolveWhenReceived, fireEventAndResolveWhenCompleted, fireEventAndResolveOnEvent, fireEvent, getAllRecipeInstancesMetadata, getRecipeInstanceState, getVisualState, retryInteraction, resolveInteraction, stopRetryingInteraction - )) + ))) + + private def haproxyCheck: Route = pathSingleSlash(get(complete(StatusCodes.OK))) private def health: Route = get(complete("Ok")) diff --git a/build.sbt b/build.sbt index e935edbc8..23a0b01f5 100644 --- a/build.sbt +++ b/build.sbt @@ -360,7 +360,7 @@ lazy val playground = project ) lazy val examples = project - .in(file("examples")) + .in(file("examples/baker-example")) .enablePlugins(JavaAppPackaging) .settings(commonSettings) .settings(noPublishSettings) diff --git a/examples/src/main/java/webshop/simple/JMain.java b/examples/baker-example/src/main/java/webshop/simple/JMain.java similarity index 100% rename from examples/src/main/java/webshop/simple/JMain.java rename to examples/baker-example/src/main/java/webshop/simple/JMain.java diff --git a/examples/src/main/java/webshop/simple/JWebshopRecipe.java b/examples/baker-example/src/main/java/webshop/simple/JWebshopRecipe.java similarity index 100% rename from examples/src/main/java/webshop/simple/JWebshopRecipe.java rename to examples/baker-example/src/main/java/webshop/simple/JWebshopRecipe.java diff --git a/examples/src/main/java/webshop/simple/ReserveItemsInstance.java b/examples/baker-example/src/main/java/webshop/simple/ReserveItemsInstance.java similarity index 100% rename from examples/src/main/java/webshop/simple/ReserveItemsInstance.java rename to examples/baker-example/src/main/java/webshop/simple/ReserveItemsInstance.java diff --git a/examples/src/main/resources/application.conf b/examples/baker-example/src/main/resources/application.conf similarity index 100% rename from examples/src/main/resources/application.conf rename to examples/baker-example/src/main/resources/application.conf diff --git a/examples/src/main/resources/docker-compose.yaml b/examples/baker-example/src/main/resources/docker-compose.yaml similarity index 100% rename from examples/src/main/resources/docker-compose.yaml rename to examples/baker-example/src/main/resources/docker-compose.yaml diff --git a/examples/src/main/resources/gatling/webshop/webservice/CheckoutFlowSimulation.scala b/examples/baker-example/src/main/resources/gatling/webshop/webservice/CheckoutFlowSimulation.scala similarity index 100% rename from examples/src/main/resources/gatling/webshop/webservice/CheckoutFlowSimulation.scala rename to examples/baker-example/src/main/resources/gatling/webshop/webservice/CheckoutFlowSimulation.scala diff --git a/examples/src/main/resources/grafana/Dockerfile b/examples/baker-example/src/main/resources/grafana/Dockerfile similarity index 100% rename from examples/src/main/resources/grafana/Dockerfile rename to examples/baker-example/src/main/resources/grafana/Dockerfile diff --git a/examples/src/main/resources/grafana/config.ini b/examples/baker-example/src/main/resources/grafana/config.ini similarity index 100% rename from examples/src/main/resources/grafana/config.ini rename to examples/baker-example/src/main/resources/grafana/config.ini diff --git a/examples/src/main/resources/grafana/dashboards/akka_metrics.json b/examples/baker-example/src/main/resources/grafana/dashboards/akka_metrics.json similarity index 100% rename from examples/src/main/resources/grafana/dashboards/akka_metrics.json rename to examples/baker-example/src/main/resources/grafana/dashboards/akka_metrics.json diff --git a/examples/src/main/resources/grafana/provisioning/dashboards/all.yaml b/examples/baker-example/src/main/resources/grafana/provisioning/dashboards/all.yaml similarity index 100% rename from examples/src/main/resources/grafana/provisioning/dashboards/all.yaml rename to examples/baker-example/src/main/resources/grafana/provisioning/dashboards/all.yaml diff --git a/examples/src/main/resources/grafana/provisioning/datasources/all.yaml b/examples/baker-example/src/main/resources/grafana/provisioning/datasources/all.yaml similarity index 100% rename from examples/src/main/resources/grafana/provisioning/datasources/all.yaml rename to examples/baker-example/src/main/resources/grafana/provisioning/datasources/all.yaml diff --git a/examples/src/main/resources/haproxy/Dockerfile b/examples/baker-example/src/main/resources/haproxy/Dockerfile similarity index 100% rename from examples/src/main/resources/haproxy/Dockerfile rename to examples/baker-example/src/main/resources/haproxy/Dockerfile diff --git a/examples/src/main/resources/haproxy/haproxy.cfg b/examples/baker-example/src/main/resources/haproxy/haproxy.cfg similarity index 95% rename from examples/src/main/resources/haproxy/haproxy.cfg rename to examples/baker-example/src/main/resources/haproxy/haproxy.cfg index 99d668eb4..70a1b0d7b 100644 --- a/examples/src/main/resources/haproxy/haproxy.cfg +++ b/examples/baker-example/src/main/resources/haproxy/haproxy.cfg @@ -36,7 +36,7 @@ backend nodes option forwardfor http-request set-header X-Forwarded-Port %[dst_port] http-request add-header X-Forwarded-Proto https if { ssl_fc } - option httpchk HEAD / HTTP/1.1 + option httpchk GET / HTTP/1.1\r\nHost:localhost server web01 state-node-1:8080 check server web02 state-node-2:8080 check server web03 state-node-3:8080 check diff --git a/examples/src/main/resources/logback.xml b/examples/baker-example/src/main/resources/logback.xml similarity index 100% rename from examples/src/main/resources/logback.xml rename to examples/baker-example/src/main/resources/logback.xml diff --git a/examples/src/main/resources/prometheus/Dockerfile b/examples/baker-example/src/main/resources/prometheus/Dockerfile similarity index 100% rename from examples/src/main/resources/prometheus/Dockerfile rename to examples/baker-example/src/main/resources/prometheus/Dockerfile diff --git a/examples/src/main/resources/prometheus/prometheus.yaml b/examples/baker-example/src/main/resources/prometheus/prometheus.yaml similarity index 100% rename from examples/src/main/resources/prometheus/prometheus.yaml rename to examples/baker-example/src/main/resources/prometheus/prometheus.yaml diff --git a/examples/src/main/scala/webshop/simple/SimpleWebshopInstances.scala b/examples/baker-example/src/main/scala/webshop/simple/SimpleWebshopInstances.scala similarity index 100% rename from examples/src/main/scala/webshop/simple/SimpleWebshopInstances.scala rename to examples/baker-example/src/main/scala/webshop/simple/SimpleWebshopInstances.scala diff --git a/examples/src/main/scala/webshop/simple/SimpleWebshopInstancesReflection.scala b/examples/baker-example/src/main/scala/webshop/simple/SimpleWebshopInstancesReflection.scala similarity index 100% rename from examples/src/main/scala/webshop/simple/SimpleWebshopInstancesReflection.scala rename to examples/baker-example/src/main/scala/webshop/simple/SimpleWebshopInstancesReflection.scala diff --git a/examples/src/main/scala/webshop/simple/SimpleWebshopRecipe.scala b/examples/baker-example/src/main/scala/webshop/simple/SimpleWebshopRecipe.scala similarity index 100% rename from examples/src/main/scala/webshop/simple/SimpleWebshopRecipe.scala rename to examples/baker-example/src/main/scala/webshop/simple/SimpleWebshopRecipe.scala diff --git a/examples/src/main/scala/webshop/simple/SimpleWebshopRecipeReflection.scala b/examples/baker-example/src/main/scala/webshop/simple/SimpleWebshopRecipeReflection.scala similarity index 100% rename from examples/src/main/scala/webshop/simple/SimpleWebshopRecipeReflection.scala rename to examples/baker-example/src/main/scala/webshop/simple/SimpleWebshopRecipeReflection.scala diff --git a/examples/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala b/examples/baker-example/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala similarity index 100% rename from examples/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala rename to examples/baker-example/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala diff --git a/examples/src/main/scala/webshop/webservice/Main.scala b/examples/baker-example/src/main/scala/webshop/webservice/Main.scala similarity index 100% rename from examples/src/main/scala/webshop/webservice/Main.scala rename to examples/baker-example/src/main/scala/webshop/webservice/Main.scala diff --git a/examples/src/main/scala/webshop/webservice/MakePaymentInstance.scala b/examples/baker-example/src/main/scala/webshop/webservice/MakePaymentInstance.scala similarity index 100% rename from examples/src/main/scala/webshop/webservice/MakePaymentInstance.scala rename to examples/baker-example/src/main/scala/webshop/webservice/MakePaymentInstance.scala diff --git a/examples/src/main/scala/webshop/webservice/OrderStatus.scala b/examples/baker-example/src/main/scala/webshop/webservice/OrderStatus.scala similarity index 100% rename from examples/src/main/scala/webshop/webservice/OrderStatus.scala rename to examples/baker-example/src/main/scala/webshop/webservice/OrderStatus.scala diff --git a/examples/src/main/scala/webshop/webservice/ReserveItemsInstance.scala b/examples/baker-example/src/main/scala/webshop/webservice/ReserveItemsInstance.scala similarity index 100% rename from examples/src/main/scala/webshop/webservice/ReserveItemsInstance.scala rename to examples/baker-example/src/main/scala/webshop/webservice/ReserveItemsInstance.scala diff --git a/examples/src/main/scala/webshop/webservice/ShipItemsInstance.scala b/examples/baker-example/src/main/scala/webshop/webservice/ShipItemsInstance.scala similarity index 100% rename from examples/src/main/scala/webshop/webservice/ShipItemsInstance.scala rename to examples/baker-example/src/main/scala/webshop/webservice/ShipItemsInstance.scala diff --git a/examples/src/main/scala/webshop/webservice/WebShop.scala b/examples/baker-example/src/main/scala/webshop/webservice/WebShop.scala similarity index 100% rename from examples/src/main/scala/webshop/webservice/WebShop.scala rename to examples/baker-example/src/main/scala/webshop/webservice/WebShop.scala diff --git a/examples/src/main/scala/webshop/webservice/WebShopBaker.scala b/examples/baker-example/src/main/scala/webshop/webservice/WebShopBaker.scala similarity index 100% rename from examples/src/main/scala/webshop/webservice/WebShopBaker.scala rename to examples/baker-example/src/main/scala/webshop/webservice/WebShopBaker.scala diff --git a/examples/src/main/scala/webshop/webservice/WebShopService.scala b/examples/baker-example/src/main/scala/webshop/webservice/WebShopService.scala similarity index 100% rename from examples/src/main/scala/webshop/webservice/WebShopService.scala rename to examples/baker-example/src/main/scala/webshop/webservice/WebShopService.scala diff --git a/examples/src/test/java/webshop/JWebshopRecipeTests.java b/examples/baker-example/src/test/java/webshop/JWebshopRecipeTests.java similarity index 100% rename from examples/src/test/java/webshop/JWebshopRecipeTests.java rename to examples/baker-example/src/test/java/webshop/JWebshopRecipeTests.java diff --git a/examples/src/test/scala/webshop/simple/WebshopRecipeSpec.scala b/examples/baker-example/src/test/scala/webshop/simple/WebshopRecipeSpec.scala similarity index 100% rename from examples/src/test/scala/webshop/simple/WebshopRecipeSpec.scala rename to examples/baker-example/src/test/scala/webshop/simple/WebshopRecipeSpec.scala diff --git a/playground/src/main/scala/com/ing/baker/playground/AppMonad.scala b/playground/src/main/scala/com/ing/baker/playground/AppMonad.scala new file mode 100644 index 000000000..a29417a68 --- /dev/null +++ b/playground/src/main/scala/com/ing/baker/playground/AppMonad.scala @@ -0,0 +1,43 @@ +package com.ing.baker.playground + +import cats.Show +import cats.data.StateT +import cats.effect.IO +import cats.implicits._ +import cats.effect.Console.{ io => console } + +object AppMonad { + + case class Environment(runningImages: List[String]) + + type App[A] = StateT[IO, Environment, A] + + implicit class AppIO[A](io: IO[A]) { + + def app: App[A] = StateT.liftF(io) + } + + def modify(f: Environment => Environment): App[Unit] = + StateT.modify[IO, Environment](f) + + def getState: App[Environment] = + StateT.get[IO, Environment] + + def addRunningImage(imageName: String): App[Unit] = + modify(state => state.copy(runningImages = imageName :: state.runningImages)) + + def doNothing: App[Unit] = + StateT.pure[IO, Environment, Unit](()) + + def print(message: String): App[Unit] = + console.putStr(message).app + + def printLn(message: String): App[Unit] = + console.putStrLn(message).app + + def printLnA[A: Show](a: A): App[Unit] = + print(a.show) + + def readLn: App[String] = + console.readLn.app +} diff --git a/playground/src/main/scala/com/ing/baker/playground/BaaSCommands.scala b/playground/src/main/scala/com/ing/baker/playground/BaaSCommands.scala new file mode 100644 index 000000000..784dbad28 --- /dev/null +++ b/playground/src/main/scala/com/ing/baker/playground/BaaSCommands.scala @@ -0,0 +1,45 @@ +package com.ing.baker.playground + +import scala.sys.process._ +import DockerCommands._ +import Command._ +import AppMonad._ + +object BaaSCommands { + + val baasStateNodeVersion = "3.0.2-SNAPSHOT" + + def startBaaS: App[Unit] = + for { + _ <- createDockerNetwork + _ <- EnvironmentCommands.runCassandra + node1 <- runStateNode(baasStateNodeVersion, 1, "self") + node2 <- runStateNode(baasStateNodeVersion, 2, node1) + node3 <- runStateNode(baasStateNodeVersion, 3, node1) + _ <- EnvironmentCommands.runHaproxy + } yield () + + def runStateNode(version: String, node: Int, seedHost: String): App[String] = { + val containerName: String = s"state-node-$node" + val seedHostname: String = if(seedHost == "self") containerName else seedHost + val envVars = Map( + "CLUSTER_HOST" -> containerName, + "CLUSTER_SEED_HOST" -> seedHostname, + "CASSANDRA_CONTACT_POINTS_0" -> "baker-cassandra" + ) + .map { case (env, value) => s"-e $env=$value"} + .mkString(" ") + val cmd = s"docker run --name $containerName --network $networkName $envVars apollo.docker.ing.net/baas-node-state:$version" + val runNode = execPrintAndWaitForMatch( + process = Process(cmd), + prompt = s"state-node:$version:$node", + condition = _.contains(s"State Node started...") + ).map(_ => containerName) + for { + nodeName <- runNode.app + _ <- printLn(s"Node: $nodeName successfully started") + _ <- addRunningImage(nodeName) + } yield nodeName + } + +} diff --git a/playground/src/main/scala/com/ing/baker/playground/Command.scala b/playground/src/main/scala/com/ing/baker/playground/Command.scala index 2ad81f43d..e388f3861 100644 --- a/playground/src/main/scala/com/ing/baker/playground/Command.scala +++ b/playground/src/main/scala/com/ing/baker/playground/Command.scala @@ -16,7 +16,9 @@ object Command { val commands: List[Command] = List( Help, - RunCassandra + RunCassandra, + RunBaaSStateNode, + StartBaaS ) case object Help extends Command { @@ -33,6 +35,20 @@ object Command { override def help: String = "Runs Cassandra on default ports within the playground network" } + case object RunBaaSStateNode extends Command { + + override def raw: String = "run-baas-state-node" + + override def help: String = "Runs a single BaaS state node (the one with the http server and state of the recipe instance) within the playground network" + } + + case object StartBaaS extends Command { + + override def raw: String = "start-baas" + + override def help: String = "Starts Cassandra, Haproxy and a cluster of 3 baas state nodes" + } + def execPrint(process: ProcessBuilder, prompt: String): IO[Unit] = { val p = prompt.randomColor exec(process, ProcessLogger( diff --git a/playground/src/main/scala/com/ing/baker/playground/DockerCommands.scala b/playground/src/main/scala/com/ing/baker/playground/DockerCommands.scala index 6ba82f000..c53b4848f 100644 --- a/playground/src/main/scala/com/ing/baker/playground/DockerCommands.scala +++ b/playground/src/main/scala/com/ing/baker/playground/DockerCommands.scala @@ -3,6 +3,7 @@ package com.ing.baker.playground import cats.implicits._ import cats.effect.IO import Command._ +import AppMonad._ import scala.sys.process._ import scala.util.matching.Regex @@ -23,15 +24,22 @@ object DockerCommands { } } - def terminate(name: String): IO[Unit] = - execPrint(Process(s"docker kill $name"), s"Terminate $name").attempt.void *> - execBlock(Process(s"docker rm $name")).attempt.void + def terminateAllImages: App[Unit] = + for { + env <- getState + _ <- env.runningImages.traverse(terminate) + _ <- modify(_.copy(runningImages = List.empty)) + } yield () - def createDockerNetwork: IO[Unit] = - execPrint(Process(s"docker network create $networkName"), "Docker Network").attempt.void + def terminate(name: String): App[Unit] = + (execPrint(Process(s"docker kill $name"), s"Terminate $name").attempt.void *> + execBlock(Process(s"docker rm $name")).attempt.void).app - def deleteDockerNetwork: IO[Unit] = - execPrint(Process(s"docker network rm $networkName"), "Remove Docker Network") + def createDockerNetwork: App[Unit] = + execPrint(Process(s"docker network create $networkName"), "Docker Network").attempt.void.app + + def deleteDockerNetwork: App[Unit] = + execPrint(Process(s"docker network rm $networkName"), "Remove Docker Network").attempt.void.app def dockerPull(image: String): IO[Unit] = execPrint(Process(s"docker pull $image"), s"Pull $image Image").void diff --git a/playground/src/main/scala/com/ing/baker/playground/EnvironmentCommands.scala b/playground/src/main/scala/com/ing/baker/playground/EnvironmentCommands.scala new file mode 100644 index 000000000..3342399b1 --- /dev/null +++ b/playground/src/main/scala/com/ing/baker/playground/EnvironmentCommands.scala @@ -0,0 +1,31 @@ +package com.ing.baker.playground + +import cats.implicits._ +import com.ing.baker.playground.Command.execPrintAndWaitForMatch +import com.ing.baker.playground.DockerCommands.networkName +import AppMonad._ + +import scala.sys.process.Process + +object EnvironmentCommands { + + def cassandraName: String = "baker-cassandra" + + def haproxyName: String = "baker-haproxy" + + def runCassandra: App[Unit] = + execPrintAndWaitForMatch( + process = Process(s"docker run --name $cassandraName --network $networkName -p 9042:9042 -p 9160:9160 cassandra:latest"), + prompt = "Cassandra", + condition = _.matches("""INFO \[OptionalTasks:1\] (.+) CassandraRoleManager\.java:372 - Created default superuser role 'cassandra'""") + ).app *> + addRunningImage(cassandraName) + + def runHaproxy: App[Unit] = + execPrintAndWaitForMatch( + process = Process(s"docker run --name $haproxyName --network $networkName -p 8080:8080 baker-haproxy:latest"), + prompt = "HAProxy", + condition = _ => true + ).app *> + addRunningImage(haproxyName) +} diff --git a/playground/src/main/scala/com/ing/baker/playground/Main.scala b/playground/src/main/scala/com/ing/baker/playground/Main.scala index c3cafc451..0fe39bda7 100644 --- a/playground/src/main/scala/com/ing/baker/playground/Main.scala +++ b/playground/src/main/scala/com/ing/baker/playground/Main.scala @@ -5,7 +5,12 @@ import cats.effect.{ExitCode, IO, IOApp} object Main extends IOApp { override def run(args: List[String]): IO[ExitCode] = { - PlaygroundApp.loop.map(_ => ExitCode.Success) + PlaygroundApp.loop + .run(AppMonad.Environment(List.empty)) + .map { case (finalState, _) => + println(s"Finishing with final state $finalState") + ExitCode.Success + } } /* diff --git a/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala b/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala index 17f0f579f..e49a390d0 100644 --- a/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala +++ b/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala @@ -1,54 +1,43 @@ package com.ing.baker.playground import cats.implicits._ -import cats.effect.IO -import cats.effect.Console.io._ -import Command._ -import DockerCommands._ - -import scala.sys.process._ +import AppMonad._ object PlaygroundApp { - def loop: IO[Unit] = + def loop: App[Unit] = for { - _ <- putStr("playground> ") + _ <- print("playground> ") line <- readLn _ <- exec(line) - _ <- if (line == "exit") IO.unit else loop + _ <- if (line == "exit") doNothing else loop } yield () - def exec(raw: String): IO[Unit] = + def exec(raw: String): App[Unit] = if (raw == Command.Help.raw) commandHelp else if (raw == Command.RunCassandra.raw) - commandRunCassandra.void + EnvironmentCommands.runCassandra + else if (raw == Command.RunBaaSStateNode.raw) + BaaSCommands.runStateNode("3.0.2-SNAPSHOT", 1, "self").void + else if (raw == Command.StartBaaS.raw) + BaaSCommands.startBaaS else if (raw == "exit") - cleanup *> putStrLn("Bye bye! I hope you had fun :D") + cleanup *> printLn("Bye bye! I hope you had fun :D") else if (raw == "") - IO.unit + doNothing else - putStrLn(s"Unknown command '$raw'") + printLn(s"Unknown command '$raw'") - def commandHelp: IO[Unit] = - putStrLn("") *> + def commandHelp: App[Unit] = + printLn("") *> Command.commands.traverse { command => val spaces = List.fill(20 - command.raw.length)(".").mkString - putStrLn(command.raw + " " + spaces + " " + command.help) + printLn(command.raw + " " + spaces + " " + command.help) } *> - putStrLn("") - - def cassandraName: String = "baker-cassandra" - - def commandRunCassandra: IO[Process] = - DockerCommands.createDockerNetwork *> - execPrintAndWaitForMatch( - process = Process(s"docker run --name $cassandraName --network $networkName -p 9042:9042 -p 9160:9160 cassandra:latest"), - prompt = "Cassandra", - condition = _.matches("""INFO \[OptionalTasks:1\] (.+) CassandraRoleManager\.java:372 - Created default superuser role 'cassandra'""") - ) + printLn("") - def cleanup: IO[Unit] = - terminate(cassandraName) *> - DockerCommands.deleteDockerNetwork.attempt.void + def cleanup: App[Unit] = + DockerCommands.terminateAllImages *> + DockerCommands.deleteDockerNetwork } From c89bd1b50451924dc5b85efcaf26b50903e227a3 Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Wed, 20 Nov 2019 15:56:05 +0100 Subject: [PATCH 43/86] fixed tests --- build.sbt | 2 +- .../akka/actor/recipe_manager/RecipeManagerProtoSpec.scala | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index 23a0b01f5..2242ade9a 100644 --- a/build.sbt +++ b/build.sbt @@ -307,7 +307,7 @@ lazy val `baas-tests` = project.in(file("baas-tests")) lazy val baker = project.in(file(".")) .settings(defaultModuleSettings) .settings(noPublishSettings) - .aggregate(bakertypes, runtime, recipeCompiler, recipeDsl, intermediateLanguage, splitBrainResolver) + .aggregate(bakertypes, runtime, recipeCompiler, recipeDsl, intermediateLanguage, splitBrainResolver, `baas-tests`) lazy val integration = project.in(file("integration")) .dependsOn(testScope(runtime)) diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProtoSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProtoSpec.scala index 27b966abe..94f0c4a12 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProtoSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/recipe_manager/RecipeManagerProtoSpec.scala @@ -2,8 +2,8 @@ package com.ing.baker.runtime.akka.actor.recipe_manager import com.ing.baker.BakerRuntimeTestBase import com.ing.baker.runtime.akka.actor.recipe_manager.RecipeManager.RecipeAdded -import com.ing.baker.runtime.akka.actor.serialization.{Encryption, SerializationSpec, SerializersProvider} - +import com.ing.baker.runtime.akka.actor.serialization.SerializationSpec +import com.ing.baker.runtime.serialization.{Encryption, SerializersProvider} import org.scalatest.TryValues._ class RecipeManagerProtoSpec extends BakerRuntimeTestBase { From 6499b40d5d3fcfec671cb2c8eebc723dcc411834 Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Wed, 20 Nov 2019 18:32:28 +0100 Subject: [PATCH 44/86] added example modules and improved playground app --- .../ing/baker/baas/scaladsl/BakerClient.scala | 2 +- build.sbt | 93 ++++++++++++- .../src/main/resources/application.conf | 3 + .../src/main/resources/logback.xml | 19 +++ .../webservice/CheckoutFlowRecipe.scala | 122 +++++++++++++++++ .../main/scala/webshop/webservice/Main.scala | 58 ++++++++ .../webshop/webservice/OrderStatus.scala | 30 +++++ .../scala/webshop/webservice/WebShop.scala | 17 +++ .../webshop/webservice/WebShopBaker.scala | 99 ++++++++++++++ .../webshop/webservice/WebShopService.scala | 124 ++++++++++++++++++ .../webservice/CheckoutFlowRecipe.scala | 62 +++++++++ .../webservice/MakePaymentInstance.scala | 20 +++ .../webservice/ReserveItemsInstance.scala | 19 +++ .../webservice/ShipItemsInstance.scala | 20 +++ .../com/ing/baker/playground/AppMonad.scala | 43 ------ .../com/ing/baker/playground/AppUtils.scala | 96 ++++++++++++++ .../com/ing/baker/playground/ColorPrint.scala | 44 ------- .../com/ing/baker/playground/Command.scala | 87 +++--------- .../ing/baker/playground/DockerCommands.scala | 46 ------- .../playground/EnvironmentCommands.scala | 31 ----- .../scala/com/ing/baker/playground/Main.scala | 95 +------------- .../ing/baker/playground/PlaygroundApp.scala | 39 +++--- .../BaaS.scala} | 35 +++-- .../baker/playground/commands/Docker.scala | 43 ++++++ .../playground/commands/EnvSystems.scala | 28 ++++ .../baker/playground/commands/Terminal.scala | 52 ++++++++ 26 files changed, 956 insertions(+), 371 deletions(-) create mode 100644 examples/baas-client-example/src/main/resources/application.conf create mode 100644 examples/baas-client-example/src/main/resources/logback.xml create mode 100644 examples/baas-client-example/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala create mode 100644 examples/baas-client-example/src/main/scala/webshop/webservice/Main.scala create mode 100644 examples/baas-client-example/src/main/scala/webshop/webservice/OrderStatus.scala create mode 100644 examples/baas-client-example/src/main/scala/webshop/webservice/WebShop.scala create mode 100644 examples/baas-client-example/src/main/scala/webshop/webservice/WebShopBaker.scala create mode 100644 examples/baas-client-example/src/main/scala/webshop/webservice/WebShopService.scala create mode 100644 examples/baas-interactions-example/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala create mode 100644 examples/baas-interactions-example/src/main/scala/webshop/webservice/MakePaymentInstance.scala create mode 100644 examples/baas-interactions-example/src/main/scala/webshop/webservice/ReserveItemsInstance.scala create mode 100644 examples/baas-interactions-example/src/main/scala/webshop/webservice/ShipItemsInstance.scala delete mode 100644 playground/src/main/scala/com/ing/baker/playground/AppMonad.scala create mode 100644 playground/src/main/scala/com/ing/baker/playground/AppUtils.scala delete mode 100644 playground/src/main/scala/com/ing/baker/playground/ColorPrint.scala delete mode 100644 playground/src/main/scala/com/ing/baker/playground/DockerCommands.scala delete mode 100644 playground/src/main/scala/com/ing/baker/playground/EnvironmentCommands.scala rename playground/src/main/scala/com/ing/baker/playground/{BaaSCommands.scala => commands/BaaS.scala} (53%) create mode 100644 playground/src/main/scala/com/ing/baker/playground/commands/Docker.scala create mode 100644 playground/src/main/scala/com/ing/baker/playground/commands/EnvSystems.scala create mode 100644 playground/src/main/scala/com/ing/baker/playground/commands/Terminal.scala diff --git a/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala b/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala index 5d4273765..a610cdc2b 100644 --- a/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala +++ b/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala @@ -292,7 +292,7 @@ case class BakerClient(hostname: Uri, encryption: Encryption = Encryption.NoEncr * Attempts to gracefully shutdown the baker system. */ override def gracefulShutdown(): Future[Unit] = - throw new NotImplementedError("registerBakerEventListener is not yet implemented for client bakers") + system.terminate().map(_ => ()) /** * Retries a blocked interaction. diff --git a/build.sbt b/build.sbt index 2242ade9a..f21622e3f 100644 --- a/build.sbt +++ b/build.sbt @@ -359,13 +359,13 @@ lazy val playground = project ) ) -lazy val examples = project +lazy val `baker-example` = project .in(file("examples/baker-example")) .enablePlugins(JavaAppPackaging) .settings(commonSettings) .settings(noPublishSettings) .settings( - moduleName := "examples", + moduleName := "baker-example", scalacOptions ++= Seq( "-Ypartial-unification" ), @@ -399,3 +399,92 @@ lazy val examples = project dockerExposedPorts := Seq(8080) ) .dependsOn(bakertypes, runtime, recipeCompiler, recipeDsl, intermediateLanguage) + +lazy val `baas-client-example` = project + .in(file("examples/baas-client-example")) + .enablePlugins(JavaAppPackaging) + .settings(commonSettings) + .settings(noPublishSettings) + .settings( + moduleName := "baas-client-example", + scalacOptions ++= Seq( + "-Ypartial-unification" + ), + libraryDependencies ++= + compileDeps( + slf4jApi, + slf4jSimple, + http4s, + http4sDsl, + http4sServer, + http4sCirce, + circe, + circeGeneric + ) ++ testDeps( + scalaTest, + scalaCheck + ) + ) + .settings( + maintainer in Docker := "The Apollo Squad", + packageSummary in Docker := "A web-shop checkout service example running on baas", + packageName in Docker := "apollo.docker.ing.net/baas-client-example", + dockerExposedPorts := Seq(8080) + ) + .dependsOn(bakertypes, `baas-node-client`, recipeCompiler, recipeDsl) + +lazy val `baas-interactions-example` = project + .in(file("examples/baas-interactions-example")) + .enablePlugins(JavaAppPackaging) + .settings(commonSettings) + .settings(noPublishSettings) + .settings( + moduleName := "baas-interactions-example", + scalacOptions ++= Seq( + "-Ypartial-unification" + ), + libraryDependencies ++= + compileDeps( + slf4jApi, + slf4jSimple, + catsEffect + ) ++ testDeps( + scalaTest, + scalaCheck + ) + ) + .settings( + maintainer in Docker := "The Apollo Squad", + packageSummary in Docker := "A web-shop checkout service interaction instances example running on baas", + packageName in Docker := "apollo.docker.ing.net/baas-interactions-example", + dockerExposedPorts := Seq(2551) + ) + .dependsOn(`baas-node-interaction`) + +lazy val `baas-event-listener-example` = project + .in(file("examples/baas-event-listener-example")) + .enablePlugins(JavaAppPackaging) + .settings(commonSettings) + .settings(noPublishSettings) + .settings( + moduleName := "baas-event-listener-example", + scalacOptions ++= Seq( + "-Ypartial-unification" + ), + libraryDependencies ++= + compileDeps( + slf4jApi, + slf4jSimple, + catsEffect + ) ++ testDeps( + scalaTest, + scalaCheck + ) + ) + .settings( + maintainer in Docker := "The Apollo Squad", + packageSummary in Docker := "A web-shop checkout service interaction instances example running on baas", + packageName in Docker := "apollo.docker.ing.net/baas-event-listener-example", + dockerExposedPorts := Seq(2551) + ) + .dependsOn(`baas-node-event-listener`) diff --git a/examples/baas-client-example/src/main/resources/application.conf b/examples/baas-client-example/src/main/resources/application.conf new file mode 100644 index 000000000..baf5e1e39 --- /dev/null +++ b/examples/baas-client-example/src/main/resources/application.conf @@ -0,0 +1,3 @@ +include "baker.conf" + +baas.hostname = "baker-haproxy" diff --git a/examples/baas-client-example/src/main/resources/logback.xml b/examples/baas-client-example/src/main/resources/logback.xml new file mode 100644 index 000000000..cee31bf6b --- /dev/null +++ b/examples/baas-client-example/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + + + + + \ No newline at end of file diff --git a/examples/baas-client-example/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala b/examples/baas-client-example/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala new file mode 100644 index 000000000..4f75e8d80 --- /dev/null +++ b/examples/baas-client-example/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala @@ -0,0 +1,122 @@ +package webshop.webservice + +import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff +import com.ing.baker.recipe.scaladsl.{Event, Ingredient, Interaction, Recipe} +import CheckoutFlowIngredients._ +import CheckoutFlowEvents._ +import CheckoutFlowInteractions._ +import com.ing.baker.recipe.common.InteractionFailureStrategy.RetryWithIncrementalBackoff.UntilMaximumRetries + +import scala.concurrent.Future +import scala.concurrent.duration._ + +object CheckoutFlowIngredients { + + case class OrderId(orderId: String) + + case class Item(itemId: String) + + case class ReservedItems(items: List[Item], data: Array[Byte]) + + case class ShippingAddress(address: String) + + case class PaymentInformation(info: String) + + case class ShippingOrder(items: List[Item], data: Array[Byte], address: ShippingAddress) +} + +object CheckoutFlowEvents { + + case class OrderPlaced(orderId: OrderId, items: List[Item]) + + case class PaymentInformationReceived(paymentInformation: PaymentInformation) + + case class ShippingAddressReceived(shippingAddress: ShippingAddress) + + sealed trait ReserveItemsOutput + + case class OrderHadUnavailableItems(unavailableItems: List[Item]) extends ReserveItemsOutput + + case class ItemsReserved(reservedItems: ReservedItems) extends ReserveItemsOutput + + sealed trait MakePaymentOutput + + case class PaymentSuccessful(shippingOrder: ShippingOrder) extends MakePaymentOutput + + case class PaymentFailed() extends MakePaymentOutput + + case class ShippingConfirmed() +} + +object CheckoutFlowInteractions { + + trait ReserveItems { + + def apply(orderId: OrderId, items: List[Item]): Future[ReserveItemsOutput] + } + + def ReserveItemsInteraction = Interaction( + name = "ReserveItems", + inputIngredients = Seq( + Ingredient[OrderId]("orderId"), + Ingredient[List[Item]]("items") + ), + output = Seq( + Event[OrderHadUnavailableItems], + Event[ItemsReserved] + ) + ) + + trait MakePayment { + + def apply(processId: String, items: ReservedItems, address: ShippingAddress, payment: PaymentInformation): Future[MakePaymentOutput] + } + + def MakePaymentInteraction = Interaction( + name = "MakePayment", + inputIngredients = Seq( + com.ing.baker.recipe.scaladsl.recipeInstanceId, + Ingredient[ReservedItems]("reservedItems"), + Ingredient[ShippingAddress]("shippingAddress"), + Ingredient[PaymentInformation]("paymentInformation") + ), + output = Seq( + Event[PaymentSuccessful], + Event[PaymentFailed] + ) + ) + + trait ShipItems { + + def apply(order: ShippingOrder): Future[ShippingConfirmed] + } + + def ShipItemsInteraction = Interaction( + name = "ShipItems", + inputIngredients = Seq( + Ingredient[ShippingOrder]("shippingOrder") + ), + output = Seq( + Event[ShippingConfirmed] + ) + ) +} + +object CheckoutFlowRecipe { + + def recipe: Recipe = Recipe("Webshop") + .withSensoryEvents( + Event[OrderPlaced], + Event[PaymentInformationReceived], + Event[ShippingAddressReceived]) + .withInteractions( + ReserveItemsInteraction, + MakePaymentInteraction, + ShipItemsInteraction) + .withDefaultFailureStrategy( + RetryWithIncrementalBackoff + .builder() + .withInitialDelay(1.second) + .withUntil(Some(UntilMaximumRetries(5))) + .build()) +} diff --git a/examples/baas-client-example/src/main/scala/webshop/webservice/Main.scala b/examples/baas-client-example/src/main/scala/webshop/webservice/Main.scala new file mode 100644 index 000000000..8c426ed17 --- /dev/null +++ b/examples/baas-client-example/src/main/scala/webshop/webservice/Main.scala @@ -0,0 +1,58 @@ +package webshop.webservice + +import akka.actor.ActorSystem +import akka.http.scaladsl.model.Uri +import akka.stream.ActorMaterializer +import cats.effect.concurrent.Ref +import cats.effect.{ExitCode, IO, IOApp, Resource} +import cats.implicits._ +import com.ing.baker.baas.scaladsl.BakerClient +import com.ing.baker.runtime.scaladsl._ +import com.typesafe.config.ConfigFactory +import org.http4s.server.blaze.BlazeServerBuilder +import org.log4s.Logger + +object Main extends IOApp { + + case class SystemResources(actorSystem: ActorSystem, baker: Baker, app: WebShopService, port: Int, shuttingDown: Ref[IO, Boolean]) + + val logger: Logger = org.log4s.getLogger + + val system: Resource[IO, SystemResources] = + Resource.make( + for { + actorSystem <- IO { ActorSystem("CheckoutService") } + config <- IO { ConfigFactory.load() } + materializer = ActorMaterializer()(actorSystem) + baasHostname = config.getString("baas.hostname") + baker <- IO { BakerClient(Uri.parseAbsolute(baasHostname))(actorSystem, materializer) } + checkoutRecipeId <- WebShopBaker.initRecipes(baker)(timer, actorSystem.dispatcher) + sd <- Ref.of[IO, Boolean](false) + webShopBaker = new WebShopBaker(baker, checkoutRecipeId)(actorSystem.dispatcher) + memoryDumpPath = config.getString("service.memory-dump-path") + httpPort = config.getInt("service.httpServerPort") + app = new WebShopService(webShopBaker, memoryDumpPath) + resources = SystemResources(actorSystem, baker, app, httpPort, sd) + } yield resources + )(resources => + IO(logger.info("Shutting down the Checkout Service...")) *> + terminateActorSystem(resources) + ) + + def terminateActorSystem(resources: SystemResources): IO[Unit] = + IO.fromFuture(IO { resources.actorSystem.terminate() }).void + + override def run(args: List[String]): IO[ExitCode] = { + system.flatMap { r => + + println(Console.GREEN + "Example client app started...") + sys.addShutdownHook(r.baker.gracefulShutdown()) + + BlazeServerBuilder[IO] + .bindHttp(r.port, "0.0.0.0") + .withHttpApp(r.app.buildHttpService(r.shuttingDown)) + .resource + }.use(_ => IO.never).as(ExitCode.Success) + } + +} diff --git a/examples/baas-client-example/src/main/scala/webshop/webservice/OrderStatus.scala b/examples/baas-client-example/src/main/scala/webshop/webservice/OrderStatus.scala new file mode 100644 index 000000000..6a89e4bef --- /dev/null +++ b/examples/baas-client-example/src/main/scala/webshop/webservice/OrderStatus.scala @@ -0,0 +1,30 @@ +package webshop.webservice + +import webshop.webservice.OrderStatus._ + +trait OrderStatus { + + override def toString: String = this match { + case InfoPending(pending) => "info-pending:" + pending.mkString(",") + case UnavailableItems(items) => "unavailable-items:" + items.length + case PaymentFailed => "payment-failed" + case ShippingItems => "shipping-items" + case ProcessingPayment => "processing-payment" + case Complete => "complete" + } +} + +object OrderStatus { + + case class InfoPending(pending: List[String]) extends OrderStatus + + case class UnavailableItems(items: List[String]) extends OrderStatus + + case object PaymentFailed extends OrderStatus + + case object ShippingItems extends OrderStatus + + case object ProcessingPayment extends OrderStatus + + case object Complete extends OrderStatus +} diff --git a/examples/baas-client-example/src/main/scala/webshop/webservice/WebShop.scala b/examples/baas-client-example/src/main/scala/webshop/webservice/WebShop.scala new file mode 100644 index 000000000..aa2d4b459 --- /dev/null +++ b/examples/baas-client-example/src/main/scala/webshop/webservice/WebShop.scala @@ -0,0 +1,17 @@ +package webshop.webservice + +import cats.effect.IO + +trait WebShop { + + def createCheckoutOrder(items: List[String]): IO[String] + + def addCheckoutAddressInfo(orderId: String, address: String): IO[Option[String]] + + def addCheckoutPaymentInfo(orderId: String, paymentInfo: String): IO[Option[String]] + + def pollOrderStatus(orderId: String): IO[OrderStatus] + + def gracefulShutdown: IO[Unit] +} + diff --git a/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopBaker.scala b/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopBaker.scala new file mode 100644 index 000000000..092e19b8c --- /dev/null +++ b/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopBaker.scala @@ -0,0 +1,99 @@ +package webshop.webservice + +import java.util.UUID + +import cats.effect.{IO, Timer} +import com.ing.baker.compiler.RecipeCompiler +import com.ing.baker.il.CompiledRecipe +import com.ing.baker.runtime.scaladsl.{Baker, EventInstance, InteractionInstance} +import org.log4s.{Logger, getLogger} +import webshop.webservice.CheckoutFlowIngredients.{Item, OrderId, PaymentInformation, ShippingAddress} + +import scala.concurrent.ExecutionContext + +object WebShopBaker { + + val logger: Logger = getLogger("webshop.webservice") + + val checkoutFlowCompiledRecipe: CompiledRecipe = + RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) + + def initRecipes(baker: Baker)(implicit time: Timer[IO], ec: ExecutionContext): IO[String] = { + IO.fromFuture(IO(for { + checkoutRecipeId <- baker.addRecipe(checkoutFlowCompiledRecipe) + _ = println(Console.GREEN + "V3 Checkout Recipe ID :: " + checkoutRecipeId + Console.RESET) + } yield checkoutRecipeId)) + } +} + +class WebShopBaker(baker: Baker, checkoutRecipeId: String)(implicit ec: ExecutionContext) extends WebShop { + + import WebShopBaker.logger + + override def createCheckoutOrder(items: List[String]): IO[String] = + IO.fromFuture(IO { + val orderId: String = UUID.randomUUID().toString + val event = EventInstance.unsafeFrom( + CheckoutFlowEvents.OrderPlaced(OrderId(orderId), items.map(Item))) + for { + _ <- baker.bake(checkoutRecipeId, orderId) + status <- baker.fireEventAndResolveWhenReceived(orderId, event) + _ = logger.info(s"${event.name}[$orderId]: $status") + } yield orderId + }) + + override def addCheckoutAddressInfo(orderId: String, address: String): IO[Option[String]] = + IO.fromFuture(IO { + val event = EventInstance.unsafeFrom( + CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress(address))) + for { + status <- baker.fireEventAndResolveWhenReceived(orderId, event) + _ = logger.info(s"${event.name}[$orderId]: $status") + } yield None + }) + + override def addCheckoutPaymentInfo(orderId: String, paymentInfo: String): IO[Option[String]] = + IO.fromFuture(IO { + val event = EventInstance.unsafeFrom( + CheckoutFlowEvents.PaymentInformationReceived(PaymentInformation(paymentInfo))) + for { + status <- baker.fireEventAndResolveWhenReceived(orderId, event) + _ = logger.info(s"${event.name}[$orderId]: $status") + } yield None + }) + + override def pollOrderStatus(orderId: String): IO[OrderStatus] = + IO.fromFuture(IO { + for { + state <- baker.getRecipeInstanceState(orderId) + /* + _ = println + _ = println("EVENTS") + _ = state.events.foreach(println) + _ = println + _ = println("INGREDIENTS") + _ = state.ingredients.foreach(println) + */ + eventNames = state.events.map(_.name) + status = { + if(eventNames.contains("ShippingConfirmed")) + OrderStatus.Complete + else if(eventNames.contains("PaymentFailed")) + OrderStatus.PaymentFailed + else if(eventNames.contains("OrderHadUnavailableItems")) + OrderStatus.UnavailableItems(state.ingredients("unavailableItems").as[List[Item]].map(_.itemId)) + else if(eventNames.containsSlice(List("ShippingAddressReceived", "PaymentInformationReceived"))) + OrderStatus.ProcessingPayment + else if(eventNames.contains("PaymentSuccessful")) + OrderStatus.ShippingItems + else + OrderStatus.InfoPending(List("ShippingAddressReceived", "PaymentInformationReceived") + .filterNot(eventNames.contains) + .map(_.replace("Received", ""))) + } + } yield status + }) + + override def gracefulShutdown: IO[Unit] = + IO { baker.gracefulShutdown() } +} diff --git a/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopService.scala b/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopService.scala new file mode 100644 index 000000000..d344d8053 --- /dev/null +++ b/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopService.scala @@ -0,0 +1,124 @@ +package webshop.webservice + +import java.io.File +import java.util.concurrent.Executors + +import cats.data.Kleisli +import cats.effect.{ContextShift, IO, Timer} +import cats.implicits._ +import io.circe.generic.auto._ +import io.circe.syntax._ +import org.http4s._ +import org.http4s.circe._ +import org.http4s.dsl.io._ +import org.http4s.implicits._ +import org.http4s.server.Router +import fs2.io.file +import java.util.UUID + +import cats.effect.concurrent.{MVar, Ref} + +import scala.concurrent.ExecutionContext + +object WebShopService { + + case class PlaceOrderRequest(items: List[String]) + case class PlaceOrderResponse(orderId: String) + + case class AddAddressRequest(address: String) + case class AddPaymentRequest(payment: String) + + case class PollPaymentStatusResponse(status: String) +} + +class WebShopService(webshop: WebShop, memoryDumpPath: String)(implicit timer: Timer[IO], cs: ContextShift[IO]) { + + import WebShopService._ + + implicit val placeOrderRequestDecoder: EntityDecoder[IO, PlaceOrderRequest] = + jsonOf[IO, PlaceOrderRequest] + implicit val addAddressRequestDecoder: EntityDecoder[IO, AddAddressRequest] = + jsonOf[IO, AddAddressRequest] + implicit val addPaymentRequestDecoder: EntityDecoder[IO, AddPaymentRequest] = + jsonOf[IO, AddPaymentRequest] + + val blockingEc = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) + + def buildHttpService(shuttingDown: Ref[IO, Boolean]): Kleisli[IO, Request[IO], Response[IO]] = + (Router("/" -> HttpRoutes.of[IO] { + + case GET -> Root => Ok("Ok") + + case HEAD -> Root => + shuttingDown.get.flatMap { + case true => NotFound() + case false => Ok() + } + + }) <+> + Router("/admin" -> HttpRoutes.of[IO] { + + case GET -> Root / "shutdown" => + println(Console.GREEN + "SHUTTING DOWN" + Console.RESET) + println(Console.GREEN + "====================" + Console.RESET) + for { + _ <- shuttingDown.modify(_ => (true, ())) + _ <- webshop.gracefulShutdown + response <- Ok("down") + } yield response + + case GET -> Root / "memdump.hprof" => + val path = memoryDumpPath + "-" + UUID.randomUUID().toString + ".hprof" + dumpHeap(path, live = true).as( + Response[IO]( + Status.Ok, + body = file.readAll[IO](java.nio.file.Paths.get(path), blockingEc, chunkSize = 4096), + headers = Headers(headers.`Content-Type`(MediaType.application.`octet-stream`, Charset.`UTF-8`).pure[List])) + ) + + }) <+> + Router("/api" -> HttpRoutes.of[IO] { + + case GET -> Root => + Ok("Ok") + + case req@POST -> Root / "order" => + for { + request <- req.as[PlaceOrderRequest] + orderId <- webshop.createCheckoutOrder(request.items) + response <- Ok(PlaceOrderResponse(orderId).asJson) + } yield response + + case req@PUT -> Root / "order" / orderId / "address" => + for { + request <- req.as[AddAddressRequest] + _ <- webshop.addCheckoutAddressInfo(orderId, request.address) + response <- Ok() + } yield response + + case req@PUT -> Root / "order" / orderId / "payment" => + for { + request <- req.as[AddPaymentRequest] + _ <- webshop.addCheckoutPaymentInfo(orderId, request.payment) + response <- Ok() + } yield response + + case GET -> Root / "order" / orderId => + for { + status <- webshop.pollOrderStatus(orderId) + response <- Ok(PollPaymentStatusResponse(status.toString).asJson) + } yield response + + })).orNotFound + + import com.sun.management.HotSpotDiagnosticMXBean + import java.lang.management.ManagementFactory + + def dumpHeap(filePath: String, live: Boolean): IO[Unit] = IO { + val file = new File(filePath) + if (file.exists()) file.delete() + val server = ManagementFactory.getPlatformMBeanServer + val mxBean = ManagementFactory.newPlatformMXBeanProxy(server, "com.sun.management:type=HotSpotDiagnostic", classOf[HotSpotDiagnosticMXBean]) + mxBean.dumpHeap(filePath, live) + } +} diff --git a/examples/baas-interactions-example/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala b/examples/baas-interactions-example/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala new file mode 100644 index 000000000..c2df108fa --- /dev/null +++ b/examples/baas-interactions-example/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala @@ -0,0 +1,62 @@ +package webshop.webservice + +import CheckoutFlowIngredients._ +import CheckoutFlowEvents._ + +import scala.concurrent.Future + +object CheckoutFlowIngredients { + + case class OrderId(orderId: String) + + case class Item(itemId: String) + + case class ReservedItems(items: List[Item], data: Array[Byte]) + + case class ShippingAddress(address: String) + + case class PaymentInformation(info: String) + + case class ShippingOrder(items: List[Item], data: Array[Byte], address: ShippingAddress) +} + +object CheckoutFlowEvents { + + case class OrderPlaced(orderId: OrderId, items: List[Item]) + + case class PaymentInformationReceived(paymentInformation: PaymentInformation) + + case class ShippingAddressReceived(shippingAddress: ShippingAddress) + + sealed trait ReserveItemsOutput + + case class OrderHadUnavailableItems(unavailableItems: List[Item]) extends ReserveItemsOutput + + case class ItemsReserved(reservedItems: ReservedItems) extends ReserveItemsOutput + + sealed trait MakePaymentOutput + + case class PaymentSuccessful(shippingOrder: ShippingOrder) extends MakePaymentOutput + + case class PaymentFailed() extends MakePaymentOutput + + case class ShippingConfirmed() +} + +object CheckoutFlowInteractions { + + trait ReserveItems { + + def apply(orderId: OrderId, items: List[Item]): Future[ReserveItemsOutput] + } + + trait MakePayment { + + def apply(processId: String, items: ReservedItems, address: ShippingAddress, payment: PaymentInformation): Future[MakePaymentOutput] + } + + trait ShipItems { + + def apply(order: ShippingOrder): Future[ShippingConfirmed] + } +} diff --git a/examples/baas-interactions-example/src/main/scala/webshop/webservice/MakePaymentInstance.scala b/examples/baas-interactions-example/src/main/scala/webshop/webservice/MakePaymentInstance.scala new file mode 100644 index 000000000..3618100f0 --- /dev/null +++ b/examples/baas-interactions-example/src/main/scala/webshop/webservice/MakePaymentInstance.scala @@ -0,0 +1,20 @@ +package webshop.webservice + +import cats.effect.{IO, Timer} +import webshop.webservice.CheckoutFlowEvents.MakePaymentOutput +import webshop.webservice.CheckoutFlowIngredients.{PaymentInformation, ReservedItems, ShippingAddress, ShippingOrder} +import webshop.webservice.CheckoutFlowInteractions.MakePayment + +import scala.concurrent.Future +import scala.concurrent.duration._ + +class MakePaymentInstance(implicit timer: Timer[IO]) extends MakePayment { + + override def apply(processId: String, items: ReservedItems, address: ShippingAddress, payment: PaymentInformation): Future[MakePaymentOutput] = { + IO.sleep(5 second) + .map(_ => println(Console.GREEN + processId + Console.RESET)) + .map(_ => CheckoutFlowEvents.PaymentSuccessful(ShippingOrder(items.items, items.data, address))) + .unsafeToFuture() + } +} + diff --git a/examples/baas-interactions-example/src/main/scala/webshop/webservice/ReserveItemsInstance.scala b/examples/baas-interactions-example/src/main/scala/webshop/webservice/ReserveItemsInstance.scala new file mode 100644 index 000000000..552d800f6 --- /dev/null +++ b/examples/baas-interactions-example/src/main/scala/webshop/webservice/ReserveItemsInstance.scala @@ -0,0 +1,19 @@ +package webshop.webservice + +import cats.effect.{IO, Timer} +import cats.implicits._ +import webshop.webservice.CheckoutFlowEvents.ReserveItemsOutput +import webshop.webservice.CheckoutFlowIngredients.{Item, OrderId, ReservedItems} +import webshop.webservice.CheckoutFlowInteractions.ReserveItems + +import scala.concurrent.Future +import scala.concurrent.duration._ + +class ReserveItemsInstance(implicit timer: Timer[IO]) extends ReserveItems { + + override def apply(orderId: OrderId, items: List[Item]): Future[ReserveItemsOutput] = { + IO.sleep(1 second) + .as(CheckoutFlowEvents.ItemsReserved(ReservedItems(items, Array.fill(1000)(Byte.MaxValue)))) + .unsafeToFuture() + } +} diff --git a/examples/baas-interactions-example/src/main/scala/webshop/webservice/ShipItemsInstance.scala b/examples/baas-interactions-example/src/main/scala/webshop/webservice/ShipItemsInstance.scala new file mode 100644 index 000000000..3756f0aee --- /dev/null +++ b/examples/baas-interactions-example/src/main/scala/webshop/webservice/ShipItemsInstance.scala @@ -0,0 +1,20 @@ +package webshop.webservice + +import cats.effect.{IO, Timer} +import cats.implicits._ +import webshop.webservice.CheckoutFlowEvents.ShippingConfirmed +import webshop.webservice.CheckoutFlowIngredients.ShippingOrder +import webshop.webservice.CheckoutFlowInteractions.ShipItems + +import scala.concurrent.Future +import scala.concurrent.duration._ + +class ShipItemsInstance(implicit timer: Timer[IO]) extends ShipItems { + + override def apply(order: ShippingOrder): Future[ShippingConfirmed] = { + IO.sleep(500 millis) + .as(ShippingConfirmed()) + .unsafeToFuture() + } +} + diff --git a/playground/src/main/scala/com/ing/baker/playground/AppMonad.scala b/playground/src/main/scala/com/ing/baker/playground/AppMonad.scala deleted file mode 100644 index a29417a68..000000000 --- a/playground/src/main/scala/com/ing/baker/playground/AppMonad.scala +++ /dev/null @@ -1,43 +0,0 @@ -package com.ing.baker.playground - -import cats.Show -import cats.data.StateT -import cats.effect.IO -import cats.implicits._ -import cats.effect.Console.{ io => console } - -object AppMonad { - - case class Environment(runningImages: List[String]) - - type App[A] = StateT[IO, Environment, A] - - implicit class AppIO[A](io: IO[A]) { - - def app: App[A] = StateT.liftF(io) - } - - def modify(f: Environment => Environment): App[Unit] = - StateT.modify[IO, Environment](f) - - def getState: App[Environment] = - StateT.get[IO, Environment] - - def addRunningImage(imageName: String): App[Unit] = - modify(state => state.copy(runningImages = imageName :: state.runningImages)) - - def doNothing: App[Unit] = - StateT.pure[IO, Environment, Unit](()) - - def print(message: String): App[Unit] = - console.putStr(message).app - - def printLn(message: String): App[Unit] = - console.putStrLn(message).app - - def printLnA[A: Show](a: A): App[Unit] = - print(a.show) - - def readLn: App[String] = - console.readLn.app -} diff --git a/playground/src/main/scala/com/ing/baker/playground/AppUtils.scala b/playground/src/main/scala/com/ing/baker/playground/AppUtils.scala new file mode 100644 index 000000000..1700ea2d2 --- /dev/null +++ b/playground/src/main/scala/com/ing/baker/playground/AppUtils.scala @@ -0,0 +1,96 @@ +package com.ing.baker.playground + +import cats.Show +import cats.data.StateT +import cats.effect.IO +import cats.implicits._ +import cats.effect.Console.{io => console} + +import scala.util.Random + +object AppUtils { + + case class Environment(runningImages: List[String]) + + type App[A] = StateT[IO, Environment, A] + + implicit class AppIO[A](io: IO[A]) { + + def app: App[A] = StateT.liftF(io) + } + + implicit class AppOps[A](app: App[A]) { + + def tryForget: App[Unit] = + AppUtils.tryForget(app) + } + + def pure[A](a: A): App[A] = StateT.pure(a) + + def fail[A](e: Throwable): App[A] = IO.raiseError(e).app + + def fail[A](e: String): App[A] = IO.raiseError(new Exception(e)).app + + def tryForget[A](program: App[A]): App[Unit] = + StateT { state => program.run(state).attempt.map(_ => state -> ()) } + + def modify(f: Environment => Environment): App[Unit] = + StateT.modify[IO, Environment](f) + + def getState: App[Environment] = + StateT.get[IO, Environment] + + def addRunningImage(imageName: String): App[Unit] = + modify(state => state.copy(runningImages = imageName :: state.runningImages)) + + def doNothing: App[Unit] = + StateT.pure[IO, Environment, Unit](()) + + def print(message: String): App[Unit] = + console.putStr(message).app + + def printLn(message: String): App[Unit] = + console.putStrLn(message).app + + def printLnA[A: Show](a: A): App[Unit] = + print(a.show) + + def readLn: App[String] = + console.readLn.app + + private val colors: Array[String] = Array( + Console.MAGENTA, + Console.RED, + Console.YELLOW, + Console.GREEN, + Console.CYAN, + Console.BLUE + ) + + implicit class PrettyColorPrint[A](a: A) { + + def print: IO[Unit] = + IO { println(a.toString) } + + def magenta: String = + Console.MAGENTA + a.toString + Console.RESET + + def green: String = + Console.GREEN + a.toString + Console.RESET + + def red: String = + Console.RED + a.toString + Console.RESET + + def yellow: String = + Console.YELLOW + a.toString + Console.RESET + + def randomColor: String = + colors(Random.nextInt(colors.length)) + a.toString + Console.RESET + + def prompt(prepend: String): String = + a.toString.lines.map(prepend + _).mkString("\n") + + def notice: String = + " [>>>] " + a.toString + " [<<<] " + } +} diff --git a/playground/src/main/scala/com/ing/baker/playground/ColorPrint.scala b/playground/src/main/scala/com/ing/baker/playground/ColorPrint.scala deleted file mode 100644 index 162c45371..000000000 --- a/playground/src/main/scala/com/ing/baker/playground/ColorPrint.scala +++ /dev/null @@ -1,44 +0,0 @@ -package com.ing.baker.playground - -import cats.effect.IO - -import scala.util.Random - -object ColorPrint { - - private val colors: Array[String] = Array( - Console.MAGENTA, - Console.RED, - Console.YELLOW, - Console.GREEN, - Console.CYAN, - Console.BLUE - ) - - implicit class PrettyColorPrint[A](a: A) { - - def print: IO[Unit] = - IO { println(a.toString) } - - def magenta: String = - Console.MAGENTA + a.toString + Console.RESET - - def green: String = - Console.GREEN + a.toString + Console.RESET - - def red: String = - Console.RED + a.toString + Console.RESET - - def yellow: String = - Console.YELLOW + a.toString + Console.RESET - - def randomColor: String = - colors(Random.nextInt(colors.length)) + a.toString + Console.RESET - - def prompt(prepend: String): String = - a.toString.lines.map(prepend + _).mkString("\n") - - def notice: String = - " [>>>] " + a.toString + " [<<<] " - } -} diff --git a/playground/src/main/scala/com/ing/baker/playground/Command.scala b/playground/src/main/scala/com/ing/baker/playground/Command.scala index e388f3861..227e2adf2 100644 --- a/playground/src/main/scala/com/ing/baker/playground/Command.scala +++ b/playground/src/main/scala/com/ing/baker/playground/Command.scala @@ -1,96 +1,49 @@ package com.ing.baker.playground -import cats.effect.IO -import ColorPrint._ -import scala.sys.process._ +import cats.implicits._ +import com.ing.baker.playground.AppUtils._ +import com.ing.baker.playground.Command.RunCommand +import com.ing.baker.playground.commands.BaaS trait Command { - - def raw: String = "unmatched command, fix me" - + def name: String def help: String = "No help for this command" + def run: RunCommand } object Command { + type RunCommand = PartialFunction[String, App[Unit]] + val commands: List[Command] = List( Help, - RunCassandra, - RunBaaSStateNode, StartBaaS ) case object Help extends Command { - override def raw: String = "help" + override def name: String = "help" override def help: String = "Displays this help menu" - } - - case object RunCassandra extends Command { - - override def raw: String = "run-cassandra" - - override def help: String = "Runs Cassandra on default ports within the playground network" - } - - case object RunBaaSStateNode extends Command { - - override def raw: String = "run-baas-state-node" - override def help: String = "Runs a single BaaS state node (the one with the http server and state of the recipe instance) within the playground network" + override def run: RunCommand = { + case "help" => + printLn("") *> + commands.traverse { command => + val spaces = List.fill(20 - command.name.length)(".").mkString + printLn(command.name + " " + spaces + " " + command.help) + } *> + printLn("") + } } case object StartBaaS extends Command { - override def raw: String = "start-baas" + override def name: String = "start-baas" override def help: String = "Starts Cassandra, Haproxy and a cluster of 3 baas state nodes" - } - def execPrint(process: ProcessBuilder, prompt: String): IO[Unit] = { - val p = prompt.randomColor - exec(process, ProcessLogger( - _.prompt(p + " | ").print.unsafeRunSync(), - _.prompt((prompt + " [ERROR]").red + " | ").print.unsafeRunSync() - )).flatMap { running => - val exitValue = running.exitValue() - if (exitValue == 0) IO(()) - else IO.raiseError(new Exception(s"Command $process exited with non zero value $exitValue")) - } + override def run: RunCommand = { case "start-baas" => BaaS.startBaaS } } - - def execPrintAndWaitForMatch(process: ProcessBuilder, prompt: String, condition: String => Boolean): IO[Process] = { - IO.async { callback => - val p = prompt.randomColor - var running: Process = null - var matched: Boolean = false - running = process.run(ProcessLogger( - { line => - line.prompt(p + " | ").print.unsafeRunSync() - if(condition(line) && !matched) { - matched = true - callback(Right(running)) - } - }, - { line => - line.prompt((prompt + " [ERROR]").red + " | ").print.unsafeRunSync() - if(condition(line) && !matched) { - matched = true - callback(Right(running)) - } - } - )) - } - } - - def execBlock(process: ProcessBuilder): IO[String] = - IO { process.!!<.trim } - - def exec(process: ProcessBuilder, logger: ProcessLogger): IO[Process] = - IO { process.run(logger) } - - def failIO(reason: String): IO[Nothing] = - IO.raiseError(new Exception(reason)) } diff --git a/playground/src/main/scala/com/ing/baker/playground/DockerCommands.scala b/playground/src/main/scala/com/ing/baker/playground/DockerCommands.scala deleted file mode 100644 index c53b4848f..000000000 --- a/playground/src/main/scala/com/ing/baker/playground/DockerCommands.scala +++ /dev/null @@ -1,46 +0,0 @@ -package com.ing.baker.playground - -import cats.implicits._ -import cats.effect.IO -import Command._ -import AppMonad._ - -import scala.sys.process._ -import scala.util.matching.Regex - -object DockerCommands { - - def networkName: String = "baker-playground-network" - - def checkForDockerVersion: IO[Unit] = { - val DockerVersionReg: Regex = """Docker version (\d\d).*, build .+""".r - val requiredVersion: Int = 19 - execBlock(Process(Seq("docker", "--version"))).map { - case DockerVersionReg(version) => - if (version.toInt >= requiredVersion) IO(()) - else failIO(s"Docker version is $version but $requiredVersion or greater is required.") - case _ => - failIO("Bad input for function isRequiredVersion") - } - } - - def terminateAllImages: App[Unit] = - for { - env <- getState - _ <- env.runningImages.traverse(terminate) - _ <- modify(_.copy(runningImages = List.empty)) - } yield () - - def terminate(name: String): App[Unit] = - (execPrint(Process(s"docker kill $name"), s"Terminate $name").attempt.void *> - execBlock(Process(s"docker rm $name")).attempt.void).app - - def createDockerNetwork: App[Unit] = - execPrint(Process(s"docker network create $networkName"), "Docker Network").attempt.void.app - - def deleteDockerNetwork: App[Unit] = - execPrint(Process(s"docker network rm $networkName"), "Remove Docker Network").attempt.void.app - - def dockerPull(image: String): IO[Unit] = - execPrint(Process(s"docker pull $image"), s"Pull $image Image").void -} diff --git a/playground/src/main/scala/com/ing/baker/playground/EnvironmentCommands.scala b/playground/src/main/scala/com/ing/baker/playground/EnvironmentCommands.scala deleted file mode 100644 index 3342399b1..000000000 --- a/playground/src/main/scala/com/ing/baker/playground/EnvironmentCommands.scala +++ /dev/null @@ -1,31 +0,0 @@ -package com.ing.baker.playground - -import cats.implicits._ -import com.ing.baker.playground.Command.execPrintAndWaitForMatch -import com.ing.baker.playground.DockerCommands.networkName -import AppMonad._ - -import scala.sys.process.Process - -object EnvironmentCommands { - - def cassandraName: String = "baker-cassandra" - - def haproxyName: String = "baker-haproxy" - - def runCassandra: App[Unit] = - execPrintAndWaitForMatch( - process = Process(s"docker run --name $cassandraName --network $networkName -p 9042:9042 -p 9160:9160 cassandra:latest"), - prompt = "Cassandra", - condition = _.matches("""INFO \[OptionalTasks:1\] (.+) CassandraRoleManager\.java:372 - Created default superuser role 'cassandra'""") - ).app *> - addRunningImage(cassandraName) - - def runHaproxy: App[Unit] = - execPrintAndWaitForMatch( - process = Process(s"docker run --name $haproxyName --network $networkName -p 8080:8080 baker-haproxy:latest"), - prompt = "HAProxy", - condition = _ => true - ).app *> - addRunningImage(haproxyName) -} diff --git a/playground/src/main/scala/com/ing/baker/playground/Main.scala b/playground/src/main/scala/com/ing/baker/playground/Main.scala index 0fe39bda7..b68855a84 100644 --- a/playground/src/main/scala/com/ing/baker/playground/Main.scala +++ b/playground/src/main/scala/com/ing/baker/playground/Main.scala @@ -6,103 +6,10 @@ object Main extends IOApp { override def run(args: List[String]): IO[ExitCode] = { PlaygroundApp.loop - .run(AppMonad.Environment(List.empty)) + .run(AppUtils.Environment(List.empty)) .map { case (finalState, _) => println(s"Finishing with final state $finalState") ExitCode.Success } } - - /* - def baasBasicCluster: IO[Unit] = { - val baasStateNodeVersion = "3.0.2-SNAPSHOT" - scenario { - for { - //_ <- dockerPullStateNode(baasStateNodeVersion) - node1 <- runStateNode(baasStateNodeVersion, 1, "self") - node2 <- runStateNode(baasStateNodeVersion, 2, node1) - node3 <- runStateNode(baasStateNodeVersion, 3, node1) - _ <- IO { scala.io.StdIn.readLine() } - _ <- terminate(node1) - _ <- terminate(node2) - _ <- terminate(node3) - } yield () - } - } - - def scenario(program: IO[Unit]): IO[Unit] = - for { - _ <- dockerIsRequiredVersion - _ <- createEnvironment.bracket(_ => program)(cleanEnvironment) - } yield () - - case class Environment(cassandra: Process, haproxy: Process) - - def createEnvironment: IO[Environment] = - for { - _ <- terminateHaproxy - _ <- terminateCassandra - _ <- createDockerNetwork - //_ <- dockerPullCassandra - //_ <- dockerPullHaproxy - haproxy <- runHaproxy - cassandra <- runCassandra - } yield Environment(cassandra, haproxy) - - def cleanEnvironment(env: Environment): IO[Unit] = - for { - _ <- terminateHaproxy - _ <- terminateCassandra - _ <- deleteDockerNetwork - } yield () - */ - - /* - def networkName: String = "baker-playground-network" - - def runCassandra: IO[Process] = - execPrintAndWaitForMatch( - process = Process(s"docker run --name baker-cassandra --network $networkName -p 9042:9042 -p 9160:9160 cassandra:latest"), - prompt = "Cassandra", - condition = _.matches("""INFO \[OptionalTasks:1\] (.+) CassandraRoleManager\.java:372 - Created default superuser role 'cassandra'""") - ) - - def runHaproxy: IO[Process] = - execPrintAndWaitForMatch( - process = Process(s"docker run --name baker-haproxy --network $networkName -p 8080:8080 baker-haproxy:latest"), - prompt = "Haproxy", - condition = _ => true - ) - - def runStateNode(version: String, node: Int, seedHost: String): IO[String] = { - val containerName: String = s"state-node-$node" - val seedHostname: String = if(seedHost == "self") containerName else seedHost - val envVars = Map( - "CLUSTER_HOST" -> containerName, - "CLUSTER_SEED_HOST" -> seedHostname, - "CASSANDRA_CONTACT_POINTS_0" -> "baker-cassandra" - ) - .map { case (env, value) => s"-e $env=$value"} - .mkString(" ") - val cmd = s"docker run --name $containerName --network $networkName $envVars apollo.docker.ing.net/baas-node-state:$version" - execPrintAndWaitForMatch( - process = Process(cmd), - prompt = s"state-node:$version:$node", - condition = _.contains(s"State Node started...") - ).map(_ => containerName) - } - - def terminateHaproxy: IO[Unit] = - terminate("baker-haproxy") - - def dockerPullCassandra: IO[Unit] = - dockerPull("cassandra") - - def dockerPullHaproxy: IO[Unit] = - dockerPull("apollo.docker.ing.net/baker-haproxy:latest") - - def dockerPullStateNode(version: String): IO[Unit] = - dockerPull(s"apollo.docker.ing.net/baas-node-state:$version") - */ - } diff --git a/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala b/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala index e49a390d0..77e09f3a9 100644 --- a/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala +++ b/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala @@ -1,7 +1,9 @@ package com.ing.baker.playground import cats.implicits._ -import AppMonad._ +import com.ing.baker.playground.AppUtils._ +import com.ing.baker.playground.Command.RunCommand +import com.ing.baker.playground.commands.Docker object PlaygroundApp { @@ -14,30 +16,19 @@ object PlaygroundApp { } yield () def exec(raw: String): App[Unit] = - if (raw == Command.Help.raw) - commandHelp - else if (raw == Command.RunCassandra.raw) - EnvironmentCommands.runCassandra - else if (raw == Command.RunBaaSStateNode.raw) - BaaSCommands.runStateNode("3.0.2-SNAPSHOT", 1, "self").void - else if (raw == Command.StartBaaS.raw) - BaaSCommands.startBaaS - else if (raw == "exit") - cleanup *> printLn("Bye bye! I hope you had fun :D") - else if (raw == "") - doNothing - else - printLn(s"Unknown command '$raw'") + tryOneCommand.applyOrElse(raw, other => printLn(s"Unknown command '$other'")) - def commandHelp: App[Unit] = - printLn("") *> - Command.commands.traverse { command => - val spaces = List.fill(20 - command.raw.length)(".").mkString - printLn(command.raw + " " + spaces + " " + command.help) - } *> - printLn("") + def tryOneCommand: RunCommand = + Command.commands.foldRight({ + case "exit" => + cleanup *> printLn("Bye bye! I hope you had fun :D") + case "clean" => + cleanup *> printLn("Clean") + case "" => + doNothing + })(_.run.orElse(_)) def cleanup: App[Unit] = - DockerCommands.terminateAllImages *> - DockerCommands.deleteDockerNetwork + Docker.terminateAllImages *> + Docker.deleteDockerNetwork } diff --git a/playground/src/main/scala/com/ing/baker/playground/BaaSCommands.scala b/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala similarity index 53% rename from playground/src/main/scala/com/ing/baker/playground/BaaSCommands.scala rename to playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala index 784dbad28..f6b842a66 100644 --- a/playground/src/main/scala/com/ing/baker/playground/BaaSCommands.scala +++ b/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala @@ -1,22 +1,20 @@ -package com.ing.baker.playground +package com.ing.baker.playground.commands -import scala.sys.process._ -import DockerCommands._ -import Command._ -import AppMonad._ +import com.ing.baker.playground.AppUtils._ +import Docker.{createDockerNetwork, networkName} -object BaaSCommands { +object BaaS { val baasStateNodeVersion = "3.0.2-SNAPSHOT" def startBaaS: App[Unit] = for { _ <- createDockerNetwork - _ <- EnvironmentCommands.runCassandra + _ <- EnvSystems.runCassandra node1 <- runStateNode(baasStateNodeVersion, 1, "self") - node2 <- runStateNode(baasStateNodeVersion, 2, node1) - node3 <- runStateNode(baasStateNodeVersion, 3, node1) - _ <- EnvironmentCommands.runHaproxy + _ <- runStateNode(baasStateNodeVersion, 2, node1) + _ <- runStateNode(baasStateNodeVersion, 3, node1) + _ <- EnvSystems.runHaproxy } yield () def runStateNode(version: String, node: Int, seedHost: String): App[String] = { @@ -30,16 +28,15 @@ object BaaSCommands { .map { case (env, value) => s"-e $env=$value"} .mkString(" ") val cmd = s"docker run --name $containerName --network $networkName $envVars apollo.docker.ing.net/baas-node-state:$version" - val runNode = execPrintAndWaitForMatch( - process = Process(cmd), - prompt = s"state-node:$version:$node", - condition = _.contains(s"State Node started...") - ).map(_ => containerName) for { - nodeName <- runNode.app - _ <- printLn(s"Node: $nodeName successfully started") - _ <- addRunningImage(nodeName) - } yield nodeName + _ <- Terminal.execAndWait( + command = cmd, + prompt = s"state-node:$version:$node", + condition = _.contains(s"State Node started...") + ) + _ <- printLn(s"Node: $containerName successfully started") + _ <- addRunningImage(containerName) + } yield containerName } } diff --git a/playground/src/main/scala/com/ing/baker/playground/commands/Docker.scala b/playground/src/main/scala/com/ing/baker/playground/commands/Docker.scala new file mode 100644 index 000000000..df40e8dbd --- /dev/null +++ b/playground/src/main/scala/com/ing/baker/playground/commands/Docker.scala @@ -0,0 +1,43 @@ +package com.ing.baker.playground.commands + +import cats.implicits._ +import com.ing.baker.playground.AppUtils._ + +import scala.util.matching.Regex + +object Docker { + + def networkName: String = "baker-playground-network" + + def checkForDockerVersion: App[Unit] = { + val DockerVersionReg: Regex = """Docker version (\d\d).*, build .+""".r + val requiredVersion: Int = 19 + Terminal.execBlock("docker --version").flatMap { + case DockerVersionReg(version) => + if (version.toInt >= requiredVersion) doNothing + else fail(s"Docker version is $version but $requiredVersion or greater is required.") + case _ => + fail("Bad input for function isRequiredVersion") + } + } + + def terminateAllImages: App[Unit] = + for { + env <- getState + _ <- env.runningImages.traverse(terminate) + _ <- modify(_.copy(runningImages = List.empty)) + } yield () + + def terminate(name: String): App[Unit] = + Terminal.exec(s"docker kill $name", s"Terminate $name").tryForget *> + Terminal.execBlock(s"docker rm $name").tryForget + + def createDockerNetwork: App[Unit] = + Terminal.exec(s"docker network create $networkName", "Docker Network").tryForget + + def deleteDockerNetwork: App[Unit] = + Terminal.exec(s"docker network rm $networkName", "Remove Docker Network").tryForget + + def dockerPull(image: String): App[Unit] = + Terminal.exec(s"docker pull $image", s"Pull $image Image").void +} diff --git a/playground/src/main/scala/com/ing/baker/playground/commands/EnvSystems.scala b/playground/src/main/scala/com/ing/baker/playground/commands/EnvSystems.scala new file mode 100644 index 000000000..2249ba1cf --- /dev/null +++ b/playground/src/main/scala/com/ing/baker/playground/commands/EnvSystems.scala @@ -0,0 +1,28 @@ +package com.ing.baker.playground.commands + +import cats.implicits._ +import com.ing.baker.playground.AppUtils.{App, addRunningImage} +import com.ing.baker.playground.commands.Docker.networkName + +object EnvSystems { + + def cassandraName: String = "baker-cassandra" + + def haproxyName: String = "baker-haproxy" + + def runCassandra: App[Unit] = + Terminal.execAndWait( + command = s"docker run --name $cassandraName --network $networkName -p 9042:9042 -p 9160:9160 cassandra:latest", + prompt = "Cassandra", + condition = _.matches("""INFO \[OptionalTasks:1\] (.+) CassandraRoleManager\.java:372 - Created default superuser role 'cassandra'""") + ) *> + addRunningImage(cassandraName) + + def runHaproxy: App[Unit] = + Terminal.execAndWait( + command = s"docker run --name $haproxyName --network $networkName -p 8080:8080 baker-haproxy:latest", + prompt = "HAProxy", + condition = _ => true + ) *> + addRunningImage(haproxyName) +} diff --git a/playground/src/main/scala/com/ing/baker/playground/commands/Terminal.scala b/playground/src/main/scala/com/ing/baker/playground/commands/Terminal.scala new file mode 100644 index 000000000..c36a29585 --- /dev/null +++ b/playground/src/main/scala/com/ing/baker/playground/commands/Terminal.scala @@ -0,0 +1,52 @@ +package com.ing.baker.playground.commands + +import cats.effect.IO + +import scala.sys.process._ +import com.ing.baker.playground.AppUtils._ + +object Terminal { + + def exec(command: String, prompt: String): App[Unit] = { + val p = prompt.randomColor + execWithLogger(command, ProcessLogger( + _.prompt(p + " | ").print.unsafeRunSync(), + _.prompt((prompt + " [ERROR]").red + " | ").print.unsafeRunSync() + )).flatMap { running => + val exitValue = running.exitValue() + if (exitValue == 0) doNothing + else fail(new Exception(s"Command $command exited with non zero value $exitValue")) + } + } + + def execAndWait(command: String, prompt: String, condition: String => Boolean): App[Process] = { + val process = Process(command) + IO.async { callback => + val p = prompt.randomColor + var running: Process = null + var matched: Boolean = false + running = process.run(ProcessLogger( + { line => + line.prompt(p + " | ").print.unsafeRunSync() + if(condition(line) && !matched) { + matched = true + callback(Right(running)) + } + }, + { line => + line.prompt((prompt + " [ERROR]").red + " | ").print.unsafeRunSync() + if(condition(line) && !matched) { + matched = true + callback(Right(running)) + } + } + )) + } + }.app + + def execBlock(command: String): App[String] = + IO { Process(command).!!<.trim }.app + + def execWithLogger(command: String, logger: ProcessLogger): App[Process] = + IO { Process(command).run(logger) }.app +} From 1064b42a9a2616266c7f24cd3096ffac03f0b6bd Mon Sep 17 00:00:00 2001 From: Francisco Aramburo Date: Fri, 22 Nov 2019 15:39:10 +0100 Subject: [PATCH 45/86] work on the playground --- .../resources/haproxy-state-nodes/Dockerfile | 14 +++++++ .../resources/haproxy-state-nodes/haproxy.cfg | 42 +++++++++++++++++++ .../com/ing/baker/playground/AppUtils.scala | 12 +++++- .../com/ing/baker/playground/Command.scala | 16 ++++++- .../scala/com/ing/baker/playground/Main.scala | 2 +- .../ing/baker/playground/PlaygroundApp.scala | 10 ++++- .../ing/baker/playground/commands/BaaS.scala | 8 ++++ .../baker/playground/commands/Docker.scala | 3 ++ .../baker/playground/commands/Terminal.scala | 42 ++++++++++++++++++- 9 files changed, 141 insertions(+), 8 deletions(-) create mode 100644 playground/src/main/resources/haproxy-state-nodes/Dockerfile create mode 100644 playground/src/main/resources/haproxy-state-nodes/haproxy.cfg diff --git a/playground/src/main/resources/haproxy-state-nodes/Dockerfile b/playground/src/main/resources/haproxy-state-nodes/Dockerfile new file mode 100644 index 000000000..ebf71cf99 --- /dev/null +++ b/playground/src/main/resources/haproxy-state-nodes/Dockerfile @@ -0,0 +1,14 @@ +FROM haproxy:1.7 + +ENV HAPROXY_USER haproxy + +RUN groupadd --system ${HAPROXY_USER} && \ + useradd --system --gid ${HAPROXY_USER} ${HAPROXY_USER} && \ + mkdir --parents /var/lib/${HAPROXY_USER} && \ + chown -R ${HAPROXY_USER}:${HAPROXY_USER} /var/lib/${HAPROXY_USER} + +RUN mkdir /run/haproxy/ + +COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg + +CMD ["haproxy", "-db", "-f", "/usr/local/etc/haproxy/haproxy.cfg"] \ No newline at end of file diff --git a/playground/src/main/resources/haproxy-state-nodes/haproxy.cfg b/playground/src/main/resources/haproxy-state-nodes/haproxy.cfg new file mode 100644 index 000000000..70a1b0d7b --- /dev/null +++ b/playground/src/main/resources/haproxy-state-nodes/haproxy.cfg @@ -0,0 +1,42 @@ +global + log /dev/log local0 + log /dev/log local1 notice + chroot /var/lib/haproxy + stats socket /run/haproxy/admin.sock mode 660 level admin + stats timeout 30s + user haproxy + group haproxy + daemon + + # Default SSL material locations + ca-base /etc/ssl/certs + crt-base /etc/ssl/private + + # Default ciphers to use on SSL-enabled listening sockets. + # For more information, see ciphers(1SSL). + ssl-default-bind-ciphers kEECDH+aRSA+AES:kRSA+AES:+AES256:RC4-SHA:!kEDH:!LOW:!EXP:!MD5:!aNULL:!eNULL + +defaults + log global + mode http + option httplog + option dontlognull + timeout connect 5000 + timeout client 50000 + timeout server 50000 + +frontend localnodes + bind *:8080 + mode http + default_backend nodes + +backend nodes + mode http + balance roundrobin + option forwardfor + http-request set-header X-Forwarded-Port %[dst_port] + http-request add-header X-Forwarded-Proto https if { ssl_fc } + option httpchk GET / HTTP/1.1\r\nHost:localhost + server web01 state-node-1:8080 check + server web02 state-node-2:8080 check + server web03 state-node-3:8080 check diff --git a/playground/src/main/scala/com/ing/baker/playground/AppUtils.scala b/playground/src/main/scala/com/ing/baker/playground/AppUtils.scala index 1700ea2d2..0335fdf7f 100644 --- a/playground/src/main/scala/com/ing/baker/playground/AppUtils.scala +++ b/playground/src/main/scala/com/ing/baker/playground/AppUtils.scala @@ -10,7 +10,12 @@ import scala.util.Random object AppUtils { - case class Environment(runningImages: List[String]) + case class Environment(runningImages: List[String], bakerLocation: Option[String]) + + object Environment { + + def empty: Environment = Environment(List.empty, None) + } type App[A] = StateT[IO, Environment, A] @@ -32,7 +37,7 @@ object AppUtils { def fail[A](e: String): App[A] = IO.raiseError(new Exception(e)).app def tryForget[A](program: App[A]): App[Unit] = - StateT { state => program.run(state).attempt.map(_ => state -> ()) } + StateT { state => program.run(state).attempt.map(_ => (state, ())) } def modify(f: Environment => Environment): App[Unit] = StateT.modify[IO, Environment](f) @@ -43,6 +48,9 @@ object AppUtils { def addRunningImage(imageName: String): App[Unit] = modify(state => state.copy(runningImages = imageName :: state.runningImages)) + def addBakerLocation(location: String): App[Unit] = + modify(state => state.copy(bakerLocation = Some(location))) + def doNothing: App[Unit] = StateT.pure[IO, Environment, Unit](()) diff --git a/playground/src/main/scala/com/ing/baker/playground/Command.scala b/playground/src/main/scala/com/ing/baker/playground/Command.scala index 227e2adf2..6d0af6038 100644 --- a/playground/src/main/scala/com/ing/baker/playground/Command.scala +++ b/playground/src/main/scala/com/ing/baker/playground/Command.scala @@ -3,7 +3,7 @@ package com.ing.baker.playground import cats.implicits._ import com.ing.baker.playground.AppUtils._ import com.ing.baker.playground.Command.RunCommand -import com.ing.baker.playground.commands.BaaS +import com.ing.baker.playground.commands.{BaaS, Terminal} trait Command { def name: String @@ -18,7 +18,8 @@ object Command { val commands: List[Command] = List( Help, - StartBaaS + StartBaaS, + BuildImage ) case object Help extends Command { @@ -46,4 +47,15 @@ object Command { override def run: RunCommand = { case "start-baas" => BaaS.startBaaS } } + + case object BuildImage extends Command { + + override def name: String = "build" + + override def help: String = "Builds all playground required images from the baker repository" + + override def run: RunCommand = { + case "build" => Terminal.cd("/") *> Terminal.pwd >>= printLn //BaaS.buildStateNodesHAProxyImage + } + } } diff --git a/playground/src/main/scala/com/ing/baker/playground/Main.scala b/playground/src/main/scala/com/ing/baker/playground/Main.scala index b68855a84..0273e7219 100644 --- a/playground/src/main/scala/com/ing/baker/playground/Main.scala +++ b/playground/src/main/scala/com/ing/baker/playground/Main.scala @@ -6,7 +6,7 @@ object Main extends IOApp { override def run(args: List[String]): IO[ExitCode] = { PlaygroundApp.loop - .run(AppUtils.Environment(List.empty)) + .run(AppUtils.Environment.empty) .map { case (finalState, _) => println(s"Finishing with final state $finalState") ExitCode.Success diff --git a/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala b/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala index 77e09f3a9..9f372f52e 100644 --- a/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala +++ b/playground/src/main/scala/com/ing/baker/playground/PlaygroundApp.scala @@ -16,10 +16,16 @@ object PlaygroundApp { } yield () def exec(raw: String): App[Unit] = - tryOneCommand.applyOrElse(raw, other => printLn(s"Unknown command '$other'")) + tryOneCommand + .applyOrElse(raw, (other: String) => printLn(s"Unknown command '$other'")) + .attempt + .flatMap { + case Left(e) => printLn(e.getMessage) + case Right(_) => doNothing + } def tryOneCommand: RunCommand = - Command.commands.foldRight({ + Command.commands.foldRight[RunCommand]({ case "exit" => cleanup *> printLn("Bye bye! I hope you had fun :D") case "clean" => diff --git a/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala b/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala index f6b842a66..dca4d9178 100644 --- a/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala +++ b/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala @@ -1,5 +1,6 @@ package com.ing.baker.playground.commands +import cats.implicits._ import com.ing.baker.playground.AppUtils._ import Docker.{createDockerNetwork, networkName} @@ -7,6 +8,8 @@ object BaaS { val baasStateNodeVersion = "3.0.2-SNAPSHOT" + val haproxyStateNodesImage = "apollo.docker.ing.net/playground-haproxy-state-nodes:latest" + def startBaaS: App[Unit] = for { _ <- createDockerNetwork @@ -39,4 +42,9 @@ object BaaS { } yield containerName } + def buildStateNodesHAProxyImage: App[Unit] = + Terminal.moveToBakerLocation *> Docker.buildImage( + "./playground/src/main/resources/haproxy-state-nodes", + haproxyStateNodesImage + ) } diff --git a/playground/src/main/scala/com/ing/baker/playground/commands/Docker.scala b/playground/src/main/scala/com/ing/baker/playground/commands/Docker.scala index df40e8dbd..6165816db 100644 --- a/playground/src/main/scala/com/ing/baker/playground/commands/Docker.scala +++ b/playground/src/main/scala/com/ing/baker/playground/commands/Docker.scala @@ -9,6 +9,9 @@ object Docker { def networkName: String = "baker-playground-network" + def buildImage(path: String, tag: String): App[Unit] = + Terminal.exec(s"docker build $path -t $tag", s"Build $tag") + def checkForDockerVersion: App[Unit] = { val DockerVersionReg: Regex = """Docker version (\d\d).*, build .+""".r val requiredVersion: Int = 19 diff --git a/playground/src/main/scala/com/ing/baker/playground/commands/Terminal.scala b/playground/src/main/scala/com/ing/baker/playground/commands/Terminal.scala index c36a29585..1db6e7673 100644 --- a/playground/src/main/scala/com/ing/baker/playground/commands/Terminal.scala +++ b/playground/src/main/scala/com/ing/baker/playground/commands/Terminal.scala @@ -1,5 +1,6 @@ package com.ing.baker.playground.commands +import cats.implicits._ import cats.effect.IO import scala.sys.process._ @@ -7,6 +8,45 @@ import com.ing.baker.playground.AppUtils._ object Terminal { + def moveToBakerLocation: App[Unit] = { + for { + state <- getState + location <- state.bakerLocation match { + case None => confirmBakerProjectLocation + case Some(location0) => pure(location0) + } + _ <- cd(location) + } yield () + } + + private def confirmBakerProjectLocation: App[String] = { + def confirm(path: String): App[String] = + for { + answer <- query(s"Is $path the baker project location? input yes or the correct absolute path") + realPath <- answer match { + case "yes" | "y" | "ye" => + pure(path) + case path0 => + confirm(path0) + } + } yield realPath + pwd >>= confirm + } + + def pwd: App[String] = + execBlock("pwd") + + def cd(location: String): App[Unit] = + execBlock(s"cd $location").attempt.flatMap { + case Left(e) => + fail(s"Could not move to directory $location... reason: ${e.getMessage}") + case Right(_) => + doNothing + } + + def query(question: String): App[String] = + printLn(question + ": ") *> readLn + def exec(command: String, prompt: String): App[Unit] = { val p = prompt.randomColor execWithLogger(command, ProcessLogger( @@ -21,7 +61,7 @@ object Terminal { def execAndWait(command: String, prompt: String, condition: String => Boolean): App[Process] = { val process = Process(command) - IO.async { callback => + IO.async[Process] { callback => val p = prompt.randomColor var running: Process = null var matched: Boolean = false From f1aaf7e3df6a28202e7f3ad860d6bb603ac867c0 Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Fri, 22 Nov 2019 22:28:23 +0100 Subject: [PATCH 46/86] Working basic baas example on the playground --- .../src/main/resources/reference.conf | 20 ------ .../baker/baas/akka/EventListenerAgent.scala | 1 + .../com/ing/baker/baas/state/BaaSServer.scala | 4 +- .../scala/com/ing/baker/baas/state/Main.scala | 4 +- .../src/main/resources/reference.conf | 15 ++++ ...ractionSchedulingProtocolsSerializer.scala | 40 +++++++++++ .../ProtocolInteractionExecution.scala | 3 +- .../protocol/ProtocolPushPullMatching.scala | 3 +- .../baas/protocol/ProtocolQuestCommit.scala | 3 +- .../src/main/resources/reference.conf | 13 ++++ ...DistributedEventPublishingSerializer.scala | 9 ++- .../ProtocolDistributedEventPublishing.scala | 3 +- build.sbt | 2 + .../src/main/resources/application.conf | 5 +- .../main/scala/webshop/webservice/Main.scala | 5 +- .../webshop/webservice/WebShopService.scala | 4 +- .../src/main/resources/application.conf | 47 +++++++++++++ .../main/scala/webshop/webservice/Main.scala | 14 ++++ .../src/main/resources/application.conf | 47 +++++++++++++ .../main/scala/webshop/webservice/Main.scala | 23 +++++++ .../resources/haproxy-state-nodes/haproxy.cfg | 4 +- .../com/ing/baker/playground/Command.scala | 2 +- .../ing/baker/playground/commands/BaaS.scala | 69 +++++++++++++++++-- .../playground/commands/EnvSystems.scala | 2 +- project/Dependencies.scala | 4 +- 25 files changed, 294 insertions(+), 52 deletions(-) delete mode 100644 baas-node-event-listener/src/main/resources/reference.conf create mode 100644 baas-protocol-interaction-scheduling/src/main/resources/reference.conf create mode 100644 baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/akka/InteractionSchedulingProtocolsSerializer.scala create mode 100644 baas-protocol-recipe-event-publishing/src/main/resources/reference.conf rename baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala => baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/akka/ProtocolDistributedEventPublishingSerializer.scala (69%) create mode 100644 examples/baas-event-listener-example/src/main/resources/application.conf create mode 100644 examples/baas-event-listener-example/src/main/scala/webshop/webservice/Main.scala create mode 100644 examples/baas-interactions-example/src/main/resources/application.conf create mode 100644 examples/baas-interactions-example/src/main/scala/webshop/webservice/Main.scala diff --git a/baas-node-event-listener/src/main/resources/reference.conf b/baas-node-event-listener/src/main/resources/reference.conf deleted file mode 100644 index ad61794e3..000000000 --- a/baas-node-event-listener/src/main/resources/reference.conf +++ /dev/null @@ -1,20 +0,0 @@ - -akka { - - actor { - - allow-java-serialization = off - - serializers { - - baker-typed-protobuf = "com.ing.baker.baas.akka.ProtobufSerializer" - - } - - serialization-bindings { - - "com.ing.baker.runtime.serialization.BakerSerializable" = baker-typed-protobuf - - } - } -} diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala index 6a4080ee2..df27c7612 100644 --- a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala @@ -28,6 +28,7 @@ class EventListenerAgent(recipeName: String, listenerFunction: (RecipeEventMetad mediator ! DistributedPubSubMediator.Unsubscribe(eventsTopic, self) subscribeToEvents() + println(Console.YELLOW + "Subscribing for: " + recipeName + Console.RESET) def receive: Receive = { case ProtocolDistributedEventPublishing.Event(recipeEventMetadata, event) => diff --git a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala index a7135ee30..c38102fe9 100644 --- a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala +++ b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala @@ -27,12 +27,14 @@ object BaaSServer { } yield binding } - private[state] def registerEventListenerForRemote(recipeName: String, baker: Baker, system: ActorSystem): Future[Unit] = + private[state] def registerEventListenerForRemote(recipeName: String, baker: Baker, system: ActorSystem): Future[Unit] = { + println(Console.YELLOW + s"Event listener for: $recipeName" + Console.RESET) baker.registerEventListener(recipeName, (metadata, event) => { val eventsTopic: String = ProtocolDistributedEventPublishing.eventsTopic(recipeName) DistributedPubSub(system).mediator ! DistributedPubSubMediator.Publish(eventsTopic, ProtocolDistributedEventPublishing.Event(metadata, event)) }) + } private[state] def initializeEventListeners(baker: Baker, system: ActorSystem)(implicit ec: ExecutionContext): Future[Unit] = for { diff --git a/baas-node-state/src/main/scala/com/ing/baker/baas/state/Main.scala b/baas-node-state/src/main/scala/com/ing/baker/baas/state/Main.scala index e7459a05f..ec2dce78f 100644 --- a/baas-node-state/src/main/scala/com/ing/baker/baas/state/Main.scala +++ b/baas-node-state/src/main/scala/com/ing/baker/baas/state/Main.scala @@ -21,9 +21,9 @@ object Main extends App { import stateNodeSystem.dispatcher - BaaSServer.run(stateNodeBaker, "0.0.0.0", httpServerPort)(stateNodeSystem, materializer).map { hook => + Await.result(BaaSServer.run(stateNodeBaker, "0.0.0.0", httpServerPort)(stateNodeSystem, materializer).map { hook => println(Console.GREEN + "State Node started..." + Console.RESET) println(hook.localAddress) sys.addShutdownHook(Await.result(hook.unbind(), 20.seconds)) - } + }, 20.seconds) } diff --git a/baas-protocol-interaction-scheduling/src/main/resources/reference.conf b/baas-protocol-interaction-scheduling/src/main/resources/reference.conf new file mode 100644 index 000000000..9c3844d9f --- /dev/null +++ b/baas-protocol-interaction-scheduling/src/main/resources/reference.conf @@ -0,0 +1,15 @@ + +akka { + actor { + + serializers { + interaction-scheduling-protobuf = "com.ing.baker.baas.akka.InteractionSchedulingProtocolsSerializer" + } + + serialization-bindings { + "com.ing.baker.baas.protocol.ProtocolInteractionExecution" = interaction-scheduling-protobuf + "com.ing.baker.baas.protocol.ProtocolPushPullMatching" = interaction-scheduling-protobuf + "com.ing.baker.baas.protocol.ProtocolQuestCommit" = interaction-scheduling-protobuf + } + } +} diff --git a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/akka/InteractionSchedulingProtocolsSerializer.scala b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/akka/InteractionSchedulingProtocolsSerializer.scala new file mode 100644 index 000000000..4191c1082 --- /dev/null +++ b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/akka/InteractionSchedulingProtocolsSerializer.scala @@ -0,0 +1,40 @@ +package com.ing.baker.baas.akka + +import akka.actor.ExtendedActorSystem +import com.ing.baker.runtime.serialization.{SerializersProvider, TypedProtobufSerializer} +import com.ing.baker.runtime.serialization.TypedProtobufSerializer.{BinarySerializable, forType} +import com.ing.baker.baas.protocol.InteractionSchedulingProto._ + +object InteractionSchedulingProtocolsSerializer { + + def entries(ev0: SerializersProvider): List[BinarySerializable] = { + implicit val ev = ev0 + List( + forType[com.ing.baker.baas.protocol.ProtocolInteractionExecution.ExecuteInstance] + .register("com.ing.baker.baas.protocol.ProtocolInteractionExecution.ExecuteInstance"), + forType[com.ing.baker.baas.protocol.ProtocolInteractionExecution.InstanceExecutedSuccessfully] + .register("com.ing.baker.baas.protocol.ProtocolInteractionExecution.InstanceExecutedSuccessfully"), + forType[com.ing.baker.baas.protocol.ProtocolInteractionExecution.InstanceExecutionFailed] + .register("com.ing.baker.baas.protocol.ProtocolInteractionExecution.InstanceExecutionFailed"), + forType[com.ing.baker.baas.protocol.ProtocolInteractionExecution.InstanceExecutionTimedOut] + .register("com.ing.baker.baas.protocol.ProtocolInteractionExecution.InstanceExecutionTimedOut"), + forType[com.ing.baker.baas.protocol.ProtocolInteractionExecution.NoInstanceFound.type] + .register("com.ing.baker.baas.protocol.ProtocolInteractionExecution.NoInstanceFound"), + forType[com.ing.baker.baas.protocol.ProtocolInteractionExecution.InvalidExecution] + .register("com.ing.baker.baas.protocol.ProtocolInteractionExecution.InvalidExecution"), + forType[com.ing.baker.baas.protocol.ProtocolPushPullMatching.Push] + .register("com.ing.baker.baas.protocol.ProtocolPushPullMatching.Push"), + forType[com.ing.baker.baas.protocol.ProtocolPushPullMatching.Pull] + .register("com.ing.baker.baas.protocol.ProtocolPushPullMatching.Pull"), + forType[com.ing.baker.baas.protocol.ProtocolPushPullMatching.AvailableQuest] + .register("com.ing.baker.baas.protocol.ProtocolPushPullMatching.AvailableQuest"), + forType[com.ing.baker.baas.protocol.ProtocolQuestCommit.Considering] + .register("com.ing.baker.baas.protocol.ProtocolQuestCommit.Considering"), + forType[com.ing.baker.baas.protocol.ProtocolQuestCommit.Commit] + .register("com.ing.baker.baas.protocol.ProtocolQuestCommit.Commit"), + forType[com.ing.baker.baas.protocol.ProtocolQuestCommit.QuestTaken.type] + .register("com.ing.baker.baas.protocol.ProtocolQuestCommit.QuestTaken") + ) + } +} +class InteractionSchedulingProtocolsSerializer(system: ExtendedActorSystem) extends TypedProtobufSerializer(system, InteractionSchedulingProtocolsSerializer.entries) diff --git a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolInteractionExecution.scala b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolInteractionExecution.scala index 6d24087ff..e6e7d0968 100644 --- a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolInteractionExecution.scala +++ b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolInteractionExecution.scala @@ -1,7 +1,6 @@ package com.ing.baker.baas.protocol import com.ing.baker.runtime.scaladsl.{EventInstance, IngredientInstance} -import com.ing.baker.runtime.serialization.BakerSerializable /** * Protocol executed after a match between a QuestMandate and InteractionAgent has been made and after both @@ -12,7 +11,7 @@ import com.ing.baker.runtime.serialization.BakerSerializable * InstanceExecutionFailed or InvalidExecution * */ -sealed trait ProtocolInteractionExecution extends BakerSerializable +sealed trait ProtocolInteractionExecution object ProtocolInteractionExecution { diff --git a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolPushPullMatching.scala b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolPushPullMatching.scala index 0e179ee9c..dbf8c2e74 100644 --- a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolPushPullMatching.scala +++ b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolPushPullMatching.scala @@ -3,12 +3,11 @@ package com.ing.baker.baas.protocol import java.util.UUID import akka.actor.ActorRef -import com.ing.baker.runtime.serialization.BakerSerializable /** * Protocol done to find a possible matching between a QuestMandated and an available InteractionAgent */ -sealed trait ProtocolPushPullMatching extends BakerSerializable +sealed trait ProtocolPushPullMatching object ProtocolPushPullMatching { diff --git a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolQuestCommit.scala b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolQuestCommit.scala index c412fe7f7..05e621f7a 100644 --- a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolQuestCommit.scala +++ b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/protocol/ProtocolQuestCommit.scala @@ -1,13 +1,12 @@ package com.ing.baker.baas.protocol import akka.actor.ActorRef -import com.ing.baker.runtime.serialization.BakerSerializable /** * A Protocol executed after finding a candidate match between a QuestMandated and an InteractionAgent, it makes sure * that 1 QuestMandated commits with 1 InteractionAgent only and vice versa, without leaving orphan agents. */ -sealed trait ProtocolQuestCommit extends BakerSerializable +sealed trait ProtocolQuestCommit object ProtocolQuestCommit { diff --git a/baas-protocol-recipe-event-publishing/src/main/resources/reference.conf b/baas-protocol-recipe-event-publishing/src/main/resources/reference.conf new file mode 100644 index 000000000..c667dbef4 --- /dev/null +++ b/baas-protocol-recipe-event-publishing/src/main/resources/reference.conf @@ -0,0 +1,13 @@ + +akka { + actor { + + serializers { + event-publishing-protobuf = "com.ing.baker.baas.akka.ProtocolDistributedEventPublishingSerializer" + } + + serialization-bindings { + "com.ing.baker.baas.protocol.ProtocolDistributedEventPublishing" = event-publishing-protobuf + } + } +} diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala b/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/akka/ProtocolDistributedEventPublishingSerializer.scala similarity index 69% rename from baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala rename to baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/akka/ProtocolDistributedEventPublishingSerializer.scala index a36a23242..515ef5240 100644 --- a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala +++ b/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/akka/ProtocolDistributedEventPublishingSerializer.scala @@ -1,13 +1,12 @@ package com.ing.baker.baas.akka import akka.actor.ExtendedActorSystem +import com.ing.baker.baas.protocol.DistributedEventPublishingProto._ import com.ing.baker.baas.protocol.ProtocolDistributedEventPublishing -import com.ing.baker.runtime.serialization.TypedProtobufSerializer.BinarySerializable +import com.ing.baker.runtime.serialization.TypedProtobufSerializer.{BinarySerializable, forType} import com.ing.baker.runtime.serialization.{SerializersProvider, TypedProtobufSerializer} -import com.ing.baker.runtime.serialization.TypedProtobufSerializer.forType -import com.ing.baker.baas.protocol.DistributedEventPublishingProto._ -object ProtobufSerializer { +object ProtocolDistributedEventPublishingSerializer { def entries(ev0: SerializersProvider): List[BinarySerializable] = { implicit val ev = ev0 @@ -18,4 +17,4 @@ object ProtobufSerializer { } } -class ProtobufSerializer(system: ExtendedActorSystem) extends TypedProtobufSerializer(system, ProtobufSerializer.entries) +class ProtocolDistributedEventPublishingSerializer(system: ExtendedActorSystem) extends TypedProtobufSerializer(system, ProtocolDistributedEventPublishingSerializer.entries) diff --git a/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/ProtocolDistributedEventPublishing.scala b/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/ProtocolDistributedEventPublishing.scala index 4e25145b8..29d19b2ba 100644 --- a/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/ProtocolDistributedEventPublishing.scala +++ b/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/protocol/ProtocolDistributedEventPublishing.scala @@ -1,9 +1,8 @@ package com.ing.baker.baas.protocol import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeEventMetadata} -import com.ing.baker.runtime.serialization.BakerSerializable -sealed trait ProtocolDistributedEventPublishing extends BakerSerializable +sealed trait ProtocolDistributedEventPublishing object ProtocolDistributedEventPublishing { diff --git a/build.sbt b/build.sbt index f21622e3f..a5167753a 100644 --- a/build.sbt +++ b/build.sbt @@ -208,6 +208,7 @@ lazy val `baas-protocol-baker` = project.in(file("baas-protocol-baker")) .settings( moduleName := "baas-protocol-baker", libraryDependencies ++= Seq( + akkaStream, akkaHttp ) ) @@ -234,6 +235,7 @@ lazy val `baas-node-client` = project.in(file("baas-node-client")) .settings( moduleName := "baas-node-client", libraryDependencies ++= Seq( + akkaStream, akkaHttp ) ) diff --git a/examples/baas-client-example/src/main/resources/application.conf b/examples/baas-client-example/src/main/resources/application.conf index baf5e1e39..4f6dc7192 100644 --- a/examples/baas-client-example/src/main/resources/application.conf +++ b/examples/baas-client-example/src/main/resources/application.conf @@ -1,3 +1,4 @@ -include "baker.conf" +baas.hostname = "http://baker-haproxy:8080" +baas.hostname = ${?BAAS_HOSTNAME} -baas.hostname = "baker-haproxy" +service.httpServerPort = 8080 diff --git a/examples/baas-client-example/src/main/scala/webshop/webservice/Main.scala b/examples/baas-client-example/src/main/scala/webshop/webservice/Main.scala index 8c426ed17..ab66742c8 100644 --- a/examples/baas-client-example/src/main/scala/webshop/webservice/Main.scala +++ b/examples/baas-client-example/src/main/scala/webshop/webservice/Main.scala @@ -29,9 +29,8 @@ object Main extends IOApp { checkoutRecipeId <- WebShopBaker.initRecipes(baker)(timer, actorSystem.dispatcher) sd <- Ref.of[IO, Boolean](false) webShopBaker = new WebShopBaker(baker, checkoutRecipeId)(actorSystem.dispatcher) - memoryDumpPath = config.getString("service.memory-dump-path") httpPort = config.getInt("service.httpServerPort") - app = new WebShopService(webShopBaker, memoryDumpPath) + app = new WebShopService(webShopBaker) resources = SystemResources(actorSystem, baker, app, httpPort, sd) } yield resources )(resources => @@ -45,7 +44,7 @@ object Main extends IOApp { override def run(args: List[String]): IO[ExitCode] = { system.flatMap { r => - println(Console.GREEN + "Example client app started...") + println(Console.GREEN + "Example client app started..." + Console.RESET) sys.addShutdownHook(r.baker.gracefulShutdown()) BlazeServerBuilder[IO] diff --git a/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopService.scala b/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopService.scala index d344d8053..639ee8313 100644 --- a/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopService.scala +++ b/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopService.scala @@ -31,7 +31,7 @@ object WebShopService { case class PollPaymentStatusResponse(status: String) } -class WebShopService(webshop: WebShop, memoryDumpPath: String)(implicit timer: Timer[IO], cs: ContextShift[IO]) { +class WebShopService(webshop: WebShop)(implicit timer: Timer[IO], cs: ContextShift[IO]) { import WebShopService._ @@ -67,6 +67,7 @@ class WebShopService(webshop: WebShop, memoryDumpPath: String)(implicit timer: T response <- Ok("down") } yield response + /* case GET -> Root / "memdump.hprof" => val path = memoryDumpPath + "-" + UUID.randomUUID().toString + ".hprof" dumpHeap(path, live = true).as( @@ -75,6 +76,7 @@ class WebShopService(webshop: WebShop, memoryDumpPath: String)(implicit timer: T body = file.readAll[IO](java.nio.file.Paths.get(path), blockingEc, chunkSize = 4096), headers = Headers(headers.`Content-Type`(MediaType.application.`octet-stream`, Charset.`UTF-8`).pure[List])) ) + */ }) <+> Router("/api" -> HttpRoutes.of[IO] { diff --git a/examples/baas-event-listener-example/src/main/resources/application.conf b/examples/baas-event-listener-example/src/main/resources/application.conf new file mode 100644 index 000000000..790ddda09 --- /dev/null +++ b/examples/baas-event-listener-example/src/main/resources/application.conf @@ -0,0 +1,47 @@ + +service { + + actorSystemName = "BaaS" + actorSystemName = ${?ACTOR_SYSTEM_NAME} + + clusterHost = "127.0.0.1" + clusterHost = ${?CLUSTER_HOST} + + clusterPort = 2551 + clusterPort = ${?CLUSTER_PORT} + + seedHost = "127.0.0.1" + seedHost = ${?CLUSTER_SEED_HOST} + + seedPort = 2551 + seedPort = ${?CLUSTER_SEED_PORT} +} + +akka.actor.allow-java-serialization = on +akka.cluster.configuration-compatibility-check.enforce-on-join = off + +akka { + + actor { + provider = "cluster" + } + + remote { + log-remote-lifecycle-events = off + netty.tcp { + hostname = ${service.clusterHost} + port = ${service.clusterPort} + } + } + + cluster { + + seed-nodes = [ + "akka.tcp://"${service.actorSystemName}"@"${service.seedHost}":"${service.seedPort}] + + # auto downing is NOT safe for production deployments. + # you may want to use it during development, read more about it in the docs. + # + # auto-down-unreachable-after = 10s + } +} diff --git a/examples/baas-event-listener-example/src/main/scala/webshop/webservice/Main.scala b/examples/baas-event-listener-example/src/main/scala/webshop/webservice/Main.scala new file mode 100644 index 000000000..e162dd14e --- /dev/null +++ b/examples/baas-event-listener-example/src/main/scala/webshop/webservice/Main.scala @@ -0,0 +1,14 @@ +package webshop.webservice + +import akka.actor.ActorSystem +import com.ing.baker.baas.scaladsl.BaaSEventListener + +object Main extends App { + + val actorSystem = ActorSystem("BaaS") // This should be done by the BaaSInteractionInstance ecosystem to ease the configuration and improve the UX + val ecosystem = BaaSEventListener(actorSystem) + + ecosystem.registerEventListener("Webshop", (metadata, event) => { + println(metadata.recipeName + " [" + metadata.recipeInstanceId + "] " + event.name) + }) +} diff --git a/examples/baas-interactions-example/src/main/resources/application.conf b/examples/baas-interactions-example/src/main/resources/application.conf new file mode 100644 index 000000000..790ddda09 --- /dev/null +++ b/examples/baas-interactions-example/src/main/resources/application.conf @@ -0,0 +1,47 @@ + +service { + + actorSystemName = "BaaS" + actorSystemName = ${?ACTOR_SYSTEM_NAME} + + clusterHost = "127.0.0.1" + clusterHost = ${?CLUSTER_HOST} + + clusterPort = 2551 + clusterPort = ${?CLUSTER_PORT} + + seedHost = "127.0.0.1" + seedHost = ${?CLUSTER_SEED_HOST} + + seedPort = 2551 + seedPort = ${?CLUSTER_SEED_PORT} +} + +akka.actor.allow-java-serialization = on +akka.cluster.configuration-compatibility-check.enforce-on-join = off + +akka { + + actor { + provider = "cluster" + } + + remote { + log-remote-lifecycle-events = off + netty.tcp { + hostname = ${service.clusterHost} + port = ${service.clusterPort} + } + } + + cluster { + + seed-nodes = [ + "akka.tcp://"${service.actorSystemName}"@"${service.seedHost}":"${service.seedPort}] + + # auto downing is NOT safe for production deployments. + # you may want to use it during development, read more about it in the docs. + # + # auto-down-unreachable-after = 10s + } +} diff --git a/examples/baas-interactions-example/src/main/scala/webshop/webservice/Main.scala b/examples/baas-interactions-example/src/main/scala/webshop/webservice/Main.scala new file mode 100644 index 000000000..a08b8d447 --- /dev/null +++ b/examples/baas-interactions-example/src/main/scala/webshop/webservice/Main.scala @@ -0,0 +1,23 @@ +package webshop.webservice + +import akka.actor.ActorSystem +import cats.effect.IO +import com.ing.baker.baas.scaladsl.BaaSInteractionInstance +import com.ing.baker.runtime.scaladsl.InteractionInstance + +object Main extends App { + + val actorSystem = ActorSystem("BaaS") // This should be done by the BaaSInteractionInstance ecosystem to ease the configuration and improve the UX + val ecosystem = BaaSInteractionInstance(actorSystem) + val timer = IO.timer(actorSystem.dispatcher) + + import actorSystem.dispatcher + + val instances = InteractionInstance.unsafeFromList(List( + new MakePaymentInstance()(timer), + new ReserveItemsInstance()(timer), + new ShipItemsInstance()(timer) + )) + + ecosystem.load(instances: _*) +} diff --git a/playground/src/main/resources/haproxy-state-nodes/haproxy.cfg b/playground/src/main/resources/haproxy-state-nodes/haproxy.cfg index 70a1b0d7b..42e31d398 100644 --- a/playground/src/main/resources/haproxy-state-nodes/haproxy.cfg +++ b/playground/src/main/resources/haproxy-state-nodes/haproxy.cfg @@ -38,5 +38,5 @@ backend nodes http-request add-header X-Forwarded-Proto https if { ssl_fc } option httpchk GET / HTTP/1.1\r\nHost:localhost server web01 state-node-1:8080 check - server web02 state-node-2:8080 check - server web03 state-node-3:8080 check + #server web02 state-node-2:8080 check + #server web03 state-node-3:8080 check diff --git a/playground/src/main/scala/com/ing/baker/playground/Command.scala b/playground/src/main/scala/com/ing/baker/playground/Command.scala index 6d0af6038..93da53268 100644 --- a/playground/src/main/scala/com/ing/baker/playground/Command.scala +++ b/playground/src/main/scala/com/ing/baker/playground/Command.scala @@ -55,7 +55,7 @@ object Command { override def help: String = "Builds all playground required images from the baker repository" override def run: RunCommand = { - case "build" => Terminal.cd("/") *> Terminal.pwd >>= printLn //BaaS.buildStateNodesHAProxyImage + case "build" => BaaS.buildStateNodesHAProxyImage } } } diff --git a/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala b/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala index dca4d9178..519294000 100644 --- a/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala +++ b/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala @@ -6,7 +6,7 @@ import Docker.{createDockerNetwork, networkName} object BaaS { - val baasStateNodeVersion = "3.0.2-SNAPSHOT" + val baasVersion = "3.0.2-SNAPSHOT" val haproxyStateNodesImage = "apollo.docker.ing.net/playground-haproxy-state-nodes:latest" @@ -14,10 +14,13 @@ object BaaS { for { _ <- createDockerNetwork _ <- EnvSystems.runCassandra - node1 <- runStateNode(baasStateNodeVersion, 1, "self") - _ <- runStateNode(baasStateNodeVersion, 2, node1) - _ <- runStateNode(baasStateNodeVersion, 3, node1) + node1 <- runStateNode(baasVersion, 1, "self") + //_ <- runStateNode(baasVersion, 2, node1) + //_ <- runStateNode(baasVersion, 3, node1) _ <- EnvSystems.runHaproxy + _ <- runInteractionNode(baasVersion, 1, node1) + _ <- runEventListenerNode(baasVersion, 1, node1) + _ <- runClientApp(baasVersion, 1, "http://" + EnvSystems.haproxyName + ":8080") } yield () def runStateNode(version: String, node: Int, seedHost: String): App[String] = { @@ -42,6 +45,64 @@ object BaaS { } yield containerName } + def runInteractionNode(version: String, node: Int, seedHost: String): App[String] = { + val containerName: String = s"interaction-node-$node" + val seedHostname: String = if(seedHost == "self") containerName else seedHost + val envVars = Map( + "CLUSTER_HOST" -> containerName, + "CLUSTER_SEED_HOST" -> seedHostname + ) + .map { case (env, value) => s"-e $env=$value"} + .mkString(" ") + val cmd = s"docker run --name $containerName --network $networkName $envVars apollo.docker.ing.net/baas-interactions-example:$version" + for { + _ <- Terminal.execAndWait( + command = cmd, + prompt = s"interactions-node:$version:$node", + condition = _ => true + ) + _ <- addRunningImage(containerName) + } yield containerName + } + + def runEventListenerNode(version: String, node: Int, seedHost: String): App[String] = { + val containerName: String = s"event-listener-node-$node" + val seedHostname: String = if(seedHost == "self") containerName else seedHost + val envVars = Map( + "CLUSTER_HOST" -> containerName, + "CLUSTER_SEED_HOST" -> seedHostname + ) + .map { case (env, value) => s"-e $env=$value"} + .mkString(" ") + val cmd = s"docker run --name $containerName --network $networkName $envVars apollo.docker.ing.net/baas-event-listener-example:$version" + for { + _ <- Terminal.execAndWait( + command = cmd, + prompt = s"event-listener-node:$version:$node", + condition = _ => true + ) + _ <- addRunningImage(containerName) + } yield containerName + } + + def runClientApp(version: String, node: Int, baasHostname: String): App[String] = { + val containerName: String = s"client-app-$node" + val envVars = Map( + "BAAS_HOSTNAME" -> baasHostname + ) + .map { case (env, value) => s"-e $env=$value"} + .mkString(" ") + val cmd = s"docker run --name $containerName --network $networkName $envVars -p 8080:8080 apollo.docker.ing.net/baas-client-example:$version" + for { + _ <- Terminal.execAndWait( + command = cmd, + prompt = s"client-app:$version:$node", + condition = _ => true + ) + _ <- addRunningImage(containerName) + } yield containerName + } + def buildStateNodesHAProxyImage: App[Unit] = Terminal.moveToBakerLocation *> Docker.buildImage( "./playground/src/main/resources/haproxy-state-nodes", diff --git a/playground/src/main/scala/com/ing/baker/playground/commands/EnvSystems.scala b/playground/src/main/scala/com/ing/baker/playground/commands/EnvSystems.scala index 2249ba1cf..d1df706c2 100644 --- a/playground/src/main/scala/com/ing/baker/playground/commands/EnvSystems.scala +++ b/playground/src/main/scala/com/ing/baker/playground/commands/EnvSystems.scala @@ -20,7 +20,7 @@ object EnvSystems { def runHaproxy: App[Unit] = Terminal.execAndWait( - command = s"docker run --name $haproxyName --network $networkName -p 8080:8080 baker-haproxy:latest", + command = s"docker run --name $haproxyName --network $networkName ${BaaS.haproxyStateNodesImage}", prompt = "HAProxy", condition = _ => true ) *> diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 13060b0d7..ad43e860f 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -3,7 +3,7 @@ import sbt._ //noinspection TypeAnnotation object Dependencies { - val akkaVersion = "2.5.22" + val akkaVersion = "2.5.23" val http4sVersion = "0.20.0" val circeVersion = "0.11.1" @@ -37,7 +37,7 @@ object Dependencies { val akkaTestKit = "com.typesafe.akka" %% "akka-testkit" % akkaVersion val akkaStreamTestKit = "com.typesafe.akka" %% "akka-stream-testkit" % akkaVersion val akkaMultiNodeTestkit = "com.typesafe.akka" %% "akka-multi-node-testkit" % akkaVersion - val akkaHttp = "com.typesafe.akka" %% "akka-http" % "10.0.10" + val akkaHttp = "com.typesafe.akka" %% "akka-http" % "10.1.10" val akkaBoostrap = "com.lightbend.akka.management" %% "akka-management-cluster-bootstrap" % "1.0.5" val levelDB = "org.iq80.leveldb" % "leveldb" % "0.7" val levelDBJni = "org.fusesource.leveldbjni" % "leveldbjni-all" % "1.8" From 869d548d2d128342cbede9909510c8ac4cfd35eb Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Mon, 25 Nov 2019 14:06:57 +0100 Subject: [PATCH 47/86] Working on the kubernetes setup --- .../src/main/resources/application.conf | 6 -- .../src/main/resources/kubernetes.conf | 69 ++++++++++++++++++ build.sbt | 5 +- examples/baas-minikube-setup/Readme.md | 19 +++++ .../createMinikubeNamespace.sh | 34 +++++++++ examples/baas-minikube-setup/updateBAAS.sh | 72 +++++++++++++++++++ project/Dependencies.scala | 3 + 7 files changed, 201 insertions(+), 7 deletions(-) create mode 100644 baas-node-state/src/main/resources/kubernetes.conf create mode 100644 examples/baas-minikube-setup/Readme.md create mode 100755 examples/baas-minikube-setup/createMinikubeNamespace.sh create mode 100644 examples/baas-minikube-setup/updateBAAS.sh diff --git a/baas-node-state/src/main/resources/application.conf b/baas-node-state/src/main/resources/application.conf index 4d6717141..8f4fd1531 100644 --- a/baas-node-state/src/main/resources/application.conf +++ b/baas-node-state/src/main/resources/application.conf @@ -32,12 +32,6 @@ baker { provider = "cluster-sharded" idle-timeout = 1 minute } - - cluster { - nr-of-shards = 52 - seed-nodes = [ - "akka.tcp://"${service.actorSystemName}"@"${service.seedHost}":"${service.seedPort}] - } } cassandra-journal.contact-points.0 = "127.0.0.1" diff --git a/baas-node-state/src/main/resources/kubernetes.conf b/baas-node-state/src/main/resources/kubernetes.conf new file mode 100644 index 000000000..3915b3a88 --- /dev/null +++ b/baas-node-state/src/main/resources/kubernetes.conf @@ -0,0 +1,69 @@ + +baker { + + interaction-manager = "remote" + + actor { + provider = "cluster-sharded" + idle-timeout = 1 minute + } +} + +cassandra-journal.contact-points.0 = "127.0.0.1" +cassandra-journal.contact-points.0 = ${?CASSANDRA_CONTACT_POINTS_0} + +cassandra-snapshot-store.contact-points.0 = "127.0.0.1" +cassandra-snapshot-store.contact-points.0 = ${?CASSANDRA_CONTACT_POINTS_0} + +akka.actor.allow-java-serialization = on + +akka { + + actor { + provider = "cluster" + } + + persistence { + # See https://doc.akka.io/docs/akka-persistence-cassandra/current/journal.html#configuration + journal.plugin = "cassandra-journal" + # See https://doc.akka.io/docs/akka-persistence-cassandra/current/snapshots.html#configuration + snapshot-store.plugin = "cassandra-snapshot-store" + } + + remote { + log-remote-lifecycle-events = off + netty.tcp { + hostname = ${service.clusterHost} + port = ${service.clusterPort} + } + } + + cluster { + + seed-nodes = [ + "akka.tcp://"${service.actorSystemName}"@"${service.seedHost}":"${service.seedPort}] + + # auto downing is NOT safe for production deployments. + # you may want to use it during development, read more about it in the docs. + # + # auto-down-unreachable-after = 10s + } +} + +kamon.instrumentation.akka.filters { + + actors.track { + includes = [ ${service.actorSystemName}"/user/*" ] + excludes = [] + # ${service.actorSystemName}"/system/**", ${service.actorSystemName}"/user/worker-helper" + #] + } + + dispatchers { + includes = [ ${service.actorSystemName}"/akka.actor.default-dispatcher" ] + } + + routers { + includes = [ ${service.actorSystemName}"/user/*" ] + } +} diff --git a/build.sbt b/build.sbt index a5167753a..9a3991654 100644 --- a/build.sbt +++ b/build.sbt @@ -251,7 +251,10 @@ lazy val `baas-node-state` = project.in(file("baas-node-state")) ), libraryDependencies ++= Seq( akkaHttp, - akkaPersistenceCassandra + akkaPersistenceCassandra, + akkaManagementHttp, + akkaClusterBoostrap, + akkaDiscoveryKube ) ) .settings( diff --git a/examples/baas-minikube-setup/Readme.md b/examples/baas-minikube-setup/Readme.md new file mode 100644 index 000000000..cbee36017 --- /dev/null +++ b/examples/baas-minikube-setup/Readme.md @@ -0,0 +1,19 @@ +# Running minikube locally + +## Install docker +https://docs.docker.com/install/ + +##Install VirtualBox +https://www.virtualbox.org/wiki/Downloads + +##Install Minikube +https://kubernetes.io/docs/tasks/tools/install-minikube/ + +##Create and start minikube cluster via VirtualBox +Execute `/baas-openshift-scripts/minikube/createMinikubeNamespace.sh` + +##Deploy POD to minikube +Execute `/baas-openshift-scripts/minikube/refresh_minikube.sh` + +##Run minikube dashboard +Execute `minikube dashboard` \ No newline at end of file diff --git a/examples/baas-minikube-setup/createMinikubeNamespace.sh b/examples/baas-minikube-setup/createMinikubeNamespace.sh new file mode 100755 index 000000000..f088cf70d --- /dev/null +++ b/examples/baas-minikube-setup/createMinikubeNamespace.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +########################################################################### +#Script Name : createMinikubeNamespace.sh +#Description : Creates and runs new minikube instance using preproxy +#Args : Not supported +#Bash Version : GNU bash, version 3.x.XX +########################################################################### + +set -o errexit +set -eo pipefail +set -o nounset +#set -o xtrace + +RED='\033[0;31m' +NC='\033[0m' # No Color + +echo -e "Creating minikube cluster locally ${RED}(takes up to 10 minutes)${NC}" +minikube delete || echo "Ignoring delete for non existed minikube cluster" + +minikube --vm-driver virtualbox --memory 8192 --cpus 4 start --insecure-registry=registry-all.docker.ing.net + +hostIp=$(minikube ssh "route -n | grep ^0.0.0.0 | awk '{ print \$2 }'") + +#Removes last \r symbol +hostIp=${hostIp%?} + +dockerVars="--insecure-registry=registry-all.docker.ing.net --docker-env http_proxy=${hostIp}:3128 --docker-env https_proxy=${hostIp}:3128" + +minikube stop + +minikube --vm-driver virtualbox --memory 8192 --cpus 4 start --insecure-registry=registry-all.docker.ing.net ${dockerVars} + +kubectl api-resources \ No newline at end of file diff --git a/examples/baas-minikube-setup/updateBAAS.sh b/examples/baas-minikube-setup/updateBAAS.sh new file mode 100644 index 000000000..0003923dd --- /dev/null +++ b/examples/baas-minikube-setup/updateBAAS.sh @@ -0,0 +1,72 @@ +set -eo pipefail +set -o nounset +#set -o xtrace + +projectRoot=`pwd` + +# clean up first +app_name=baas +app_context=baas +app_name_lower=`echo $app_name | awk '{print tolower($0)}'` +image_name=apollo.docker.ing.net/${app_name_lower} +namespace_name=default +targetDir=${projectRoot}/.target + + +if [ -d "$targetDir" ]; then rm -Rf $targetDir; fi + +mkdir "$targetDir" + + +function log () { + echo -e "\n $1 \n" +} + +log "Delete current deployments" +set +e +kubectl delete deployment $app_name_lower --namespace=$namespace_name | echo "Ignoring deletion of non existed" +set -e + +#TODO: build images + +log "Check status of Minikube & start if stopped" + +mini_running=$(minikube status | grep 'host:' | awk '{print $2}') + +echo $mini_running + +if [[ $mini_running == "Stopped" ]] + then + sh ./createMinikubeNamespace.sh + echo "Started minikube" +fi + +log "Set to minikube env" + +eval $(minikube docker-env) +kubectl config use-context minikube + +log "Remove old image" +docker rmi $app_name_lower --force || echo "Ignoring docker proxy error" + +log "Build new image" +# make sure minikube can access registry run : minikube delete && minikube start --insecure-registry=registry-all.docker.ing.net +docker build -t $app_name_lower -f Dockerfile . + + +# Build baas example images +# Assuming current working directory is: ../baker/examples/baas-minikube-setup +cd ../.. +sbt baas-node-state/docker:publish +sbt baas-client-example/docker:publish +sbt baas-interactions-example/docker:publish +sbt baas-event-listener-example/docker:publish + +#TODO configmaps + + +#TODO namespace + + + + diff --git a/project/Dependencies.scala b/project/Dependencies.scala index ad43e860f..bef7f19b2 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -37,6 +37,9 @@ object Dependencies { val akkaTestKit = "com.typesafe.akka" %% "akka-testkit" % akkaVersion val akkaStreamTestKit = "com.typesafe.akka" %% "akka-stream-testkit" % akkaVersion val akkaMultiNodeTestkit = "com.typesafe.akka" %% "akka-multi-node-testkit" % akkaVersion + val akkaManagementHttp = "com.lightbend.akka.management" %% "akka-management-cluster-http" % "1.0.5" + val akkaClusterBoostrap = "com.lightbend.akka.management" %% "akka-management-cluster-bootstrap" % "1.0.5" + val akkaDiscoveryKube = "com.lightbend.akka.discovery" %% "akka-discovery-kubernetes-api" % "1.0.5" val akkaHttp = "com.typesafe.akka" %% "akka-http" % "10.1.10" val akkaBoostrap = "com.lightbend.akka.management" %% "akka-management-cluster-bootstrap" % "1.0.5" val levelDB = "org.iq80.leveldb" % "leveldb" % "0.7" From db787fe2966bf01007c52e3fa63e61c49c0f3c6a Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Mon, 25 Nov 2019 18:05:05 +0100 Subject: [PATCH 48/86] fixed tests --- .../ing/baker/baas/scaladsl/BakerClient.scala | 4 +- .../baker/baas/akka/EventListenerAgent.scala | 1 - .../BaaSEventListener.scala | 2 +- .../baas/javadsl/BaaSEventListener.scala | 4 +- .../baas/scaladsl/BaaSEventListener.scala | 4 +- .../src/main/resources/reference.conf | 20 ------- .../baker/baas/akka/ProtobufSerializer.scala | 59 ------------------- .../BaaSInteractionInstance.scala | 2 +- .../javadsl/BaaSInteractionInstance.scala | 4 +- .../scaladsl/BaaSInteractionInstance.scala | 4 +- .../com/ing/baker/baas/state/BaaSServer.scala | 2 +- ...ractionSchedulingProtocolsSerializer.scala | 5 +- .../src/main/resources/reference.conf | 2 +- ...edEventPublishingProtocolSerializer.scala} | 10 +++- .../TypedProtobufSerializer.scala | 9 +-- .../BakerTypedProtobufSerializer.scala | 37 +++--------- 16 files changed, 35 insertions(+), 134 deletions(-) rename baas-node-event-listener/src/main/scala/com/ing/baker/baas/{protocol => common}/BaaSEventListener.scala (93%) delete mode 100644 baas-node-interaction/src/main/resources/reference.conf delete mode 100644 baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala rename baas-node-interaction/src/main/scala/com/ing/baker/baas/{protocol => common}/BaaSInteractionInstance.scala (90%) rename baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/akka/{ProtocolDistributedEventPublishingSerializer.scala => DistributedEventPublishingProtocolSerializer.scala} (66%) diff --git a/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala b/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala index a610cdc2b..be2194fb0 100644 --- a/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala +++ b/baas-node-client/src/main/scala/com/ing/baker/baas/scaladsl/BakerClient.scala @@ -6,10 +6,10 @@ import akka.http.scaladsl.marshalling.Marshal import akka.http.scaladsl.model.Uri.Path import akka.http.scaladsl.model.{HttpMethods, HttpRequest, MessageEntity, Uri} import akka.stream.Materializer -import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} -import com.ing.baker.baas.protocol.BaaSProto._ import com.ing.baker.baas.protocol.BaaSProtocol +import com.ing.baker.baas.protocol.BaaSProto._ import com.ing.baker.baas.protocol.MarshallingUtils._ +import com.ing.baker.il.{CompiledRecipe, RecipeVisualStyle} import com.ing.baker.runtime.common.SensoryEventStatus import com.ing.baker.runtime.scaladsl.{BakerEvent, EventInstance, EventMoment, EventResolutions, InteractionInstance, RecipeEventMetadata, RecipeInformation, RecipeInstanceMetadata, RecipeInstanceState, SensoryEventResult, Baker => ScalaBaker} import com.ing.baker.runtime.serialization.{Encryption, SerializersProvider} diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala index df27c7612..6a4080ee2 100644 --- a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/akka/EventListenerAgent.scala @@ -28,7 +28,6 @@ class EventListenerAgent(recipeName: String, listenerFunction: (RecipeEventMetad mediator ! DistributedPubSubMediator.Unsubscribe(eventsTopic, self) subscribeToEvents() - println(Console.YELLOW + "Subscribing for: " + recipeName + Console.RESET) def receive: Receive = { case ProtocolDistributedEventPublishing.Event(recipeEventMetadata, event) => diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/protocol/BaaSEventListener.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/common/BaaSEventListener.scala similarity index 93% rename from baas-node-event-listener/src/main/scala/com/ing/baker/baas/protocol/BaaSEventListener.scala rename to baas-node-event-listener/src/main/scala/com/ing/baker/baas/common/BaaSEventListener.scala index f40b1768c..a3c5beec6 100644 --- a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/protocol/BaaSEventListener.scala +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/common/BaaSEventListener.scala @@ -1,4 +1,4 @@ -package com.ing.baker.baas.protocol +package com.ing.baker.baas.common import com.ing.baker.runtime.common.{EventInstance, InteractionInstance, RecipeEventMetadata} import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/javadsl/BaaSEventListener.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/javadsl/BaaSEventListener.scala index 12ee382ab..698914388 100644 --- a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/javadsl/BaaSEventListener.scala +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/javadsl/BaaSEventListener.scala @@ -4,14 +4,14 @@ import java.util.concurrent.CompletableFuture import java.util.function.BiConsumer import akka.actor.ActorSystem -import com.ing.baker.baas.protocol +import com.ing.baker.baas.common import com.ing.baker.baas.scaladsl import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi import com.ing.baker.runtime.javadsl.{EventInstance, RecipeEventMetadata} import scala.compat.java8.FutureConverters -class BaaSEventListener(actorSystem: ActorSystem) extends protocol.BaaSEventListener[CompletableFuture] with JavaApi { +class BaaSEventListener(actorSystem: ActorSystem) extends common.BaaSEventListener[CompletableFuture] with JavaApi { override type EventInstanceType = EventInstance diff --git a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/scaladsl/BaaSEventListener.scala b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/scaladsl/BaaSEventListener.scala index fac63de86..8fdcf65e3 100644 --- a/baas-node-event-listener/src/main/scala/com/ing/baker/baas/scaladsl/BaaSEventListener.scala +++ b/baas-node-event-listener/src/main/scala/com/ing/baker/baas/scaladsl/BaaSEventListener.scala @@ -2,13 +2,13 @@ package com.ing.baker.baas.scaladsl import akka.actor.ActorSystem import com.ing.baker.baas.akka.EventListenerAgent -import com.ing.baker.baas.protocol +import com.ing.baker.baas.common import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeEventMetadata} import scala.concurrent.Future -case class BaaSEventListener(actorSystem: ActorSystem) extends protocol.BaaSEventListener[Future] with ScalaApi { +case class BaaSEventListener(actorSystem: ActorSystem) extends common.BaaSEventListener[Future] with ScalaApi { override type EventInstanceType = EventInstance diff --git a/baas-node-interaction/src/main/resources/reference.conf b/baas-node-interaction/src/main/resources/reference.conf deleted file mode 100644 index ad61794e3..000000000 --- a/baas-node-interaction/src/main/resources/reference.conf +++ /dev/null @@ -1,20 +0,0 @@ - -akka { - - actor { - - allow-java-serialization = off - - serializers { - - baker-typed-protobuf = "com.ing.baker.baas.akka.ProtobufSerializer" - - } - - serialization-bindings { - - "com.ing.baker.runtime.serialization.BakerSerializable" = baker-typed-protobuf - - } - } -} diff --git a/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala deleted file mode 100644 index 613213472..000000000 --- a/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/ProtobufSerializer.scala +++ /dev/null @@ -1,59 +0,0 @@ -package com.ing.baker.baas.akka - -import akka.actor.ExtendedActorSystem -import com.ing.baker.baas.protocol.{ProtocolInteractionExecution, ProtocolPushPullMatching, ProtocolQuestCommit} -import com.ing.baker.baas.protocol.InteractionSchedulingProto._ -import com.ing.baker.il -import com.ing.baker.runtime.scaladsl.{EventInstance, RecipeInstanceState} -import com.ing.baker.runtime.serialization.{SerializersProvider, TypedProtobufSerializer} -import com.ing.baker.runtime.serialization.TypedProtobufSerializer.{BinarySerializable, forType} - -object ProtobufSerializer { - - def entries(ev0: SerializersProvider): List[BinarySerializable] = { - implicit val ev = ev0 - commonEntries ++ interactionSchedulingEntries - } - - def commonEntries(implicit ev0: SerializersProvider): List[BinarySerializable] = - List( - forType[com.ing.baker.types.Value] - .register("baker.types.Value"), - forType[com.ing.baker.types.Type] - .register("baker.types.Type"), - forType[EventInstance] - .register("core.RuntimeEvent"), - forType[RecipeInstanceState] - .register("core.ProcessState"), - forType[il.CompiledRecipe] - .register("il.CompiledRecipe") - ) - - def interactionSchedulingEntries(implicit ev0: SerializersProvider): List[BinarySerializable] = - List( - forType[ProtocolInteractionExecution.InstanceExecutedSuccessfully] - .register("InteractionSchedulingProtocols.InstanceExecutedSuccessfully"), - forType[ProtocolInteractionExecution.InstanceExecutionFailed] - .register("InteractionSchedulingProtocols.InstanceExecutionFailed"), - forType[ProtocolInteractionExecution.InstanceExecutionTimedOut] - .register("InteractionSchedulingProtocols.InstanceExecutionTimedOut"), - forType[ProtocolInteractionExecution.NoInstanceFound.type] - .register("InteractionSchedulingProtocols.NoInstanceFound"), - forType[ProtocolInteractionExecution.InvalidExecution] - .register("InteractionSchedulingProtocols.InvalidExecution"), - forType[ProtocolPushPullMatching.Push] - .register("InteractionSchedulingProtocols.Push"), - forType[ProtocolPushPullMatching.Pull] - .register("InteractionSchedulingProtocols.Pull"), - forType[ProtocolPushPullMatching.AvailableQuest] - .register("InteractionSchedulingProtocols.AvailableQuest"), - forType[ProtocolQuestCommit.Considering] - .register("InteractionSchedulingProtocols.Considering"), - forType[ProtocolQuestCommit.Commit] - .register("InteractionSchedulingProtocols.Commit"), - forType[ProtocolQuestCommit.QuestTaken.type] - .register("InteractionSchedulingProtocols.QuestTaken") - ) -} - -class ProtobufSerializer(system: ExtendedActorSystem) extends TypedProtobufSerializer(system, ProtobufSerializer.entries) diff --git a/baas-node-interaction/src/main/scala/com/ing/baker/baas/protocol/BaaSInteractionInstance.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/common/BaaSInteractionInstance.scala similarity index 90% rename from baas-node-interaction/src/main/scala/com/ing/baker/baas/protocol/BaaSInteractionInstance.scala rename to baas-node-interaction/src/main/scala/com/ing/baker/baas/common/BaaSInteractionInstance.scala index d85c3b9d1..766dc0686 100644 --- a/baas-node-interaction/src/main/scala/com/ing/baker/baas/protocol/BaaSInteractionInstance.scala +++ b/baas-node-interaction/src/main/scala/com/ing/baker/baas/common/BaaSInteractionInstance.scala @@ -1,4 +1,4 @@ -package com.ing.baker.baas.protocol +package com.ing.baker.baas.common import com.ing.baker.runtime.common.InteractionInstance import com.ing.baker.runtime.common.LanguageDataStructures.LanguageApi diff --git a/baas-node-interaction/src/main/scala/com/ing/baker/baas/javadsl/BaaSInteractionInstance.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/javadsl/BaaSInteractionInstance.scala index c092fd140..7d865b7cb 100644 --- a/baas-node-interaction/src/main/scala/com/ing/baker/baas/javadsl/BaaSInteractionInstance.scala +++ b/baas-node-interaction/src/main/scala/com/ing/baker/baas/javadsl/BaaSInteractionInstance.scala @@ -3,12 +3,12 @@ package com.ing.baker.baas.javadsl import java.util.concurrent.CompletableFuture import akka.actor.ActorSystem -import com.ing.baker.baas.protocol +import com.ing.baker.baas.common import com.ing.baker.baas.scaladsl import com.ing.baker.runtime.javadsl.InteractionInstance import com.ing.baker.runtime.common.LanguageDataStructures.JavaApi -class BaaSInteractionInstance(actorSystem: ActorSystem) extends protocol.BaaSInteractionInstance[CompletableFuture] with JavaApi { +class BaaSInteractionInstance(actorSystem: ActorSystem) extends common.BaaSInteractionInstance[CompletableFuture] with JavaApi { override type InteractionInstanceType = InteractionInstance diff --git a/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala index 03220e888..fa079e407 100644 --- a/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala +++ b/baas-node-interaction/src/main/scala/com/ing/baker/baas/scaladsl/BaaSInteractionInstance.scala @@ -2,13 +2,13 @@ package com.ing.baker.baas.scaladsl import akka.actor.ActorSystem import com.ing.baker.baas.akka.InteractionAgent -import com.ing.baker.baas.protocol +import com.ing.baker.baas.common import com.ing.baker.runtime.common.LanguageDataStructures.ScalaApi import com.ing.baker.runtime.scaladsl.InteractionInstance import scala.concurrent.Future -case class BaaSInteractionInstance(actorSystem: ActorSystem) extends protocol.BaaSInteractionInstance[Future] with ScalaApi { +case class BaaSInteractionInstance(actorSystem: ActorSystem) extends common.BaaSInteractionInstance[Future] with ScalaApi { override type InteractionInstanceType = InteractionInstance diff --git a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala index c38102fe9..b0e4f5a3a 100644 --- a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala +++ b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala @@ -7,9 +7,9 @@ import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import akka.stream.Materializer +import com.ing.baker.baas.protocol.{BaaSProtocol, ProtocolDistributedEventPublishing} import com.ing.baker.baas.protocol.BaaSProto._ import com.ing.baker.baas.protocol.MarshallingUtils._ -import com.ing.baker.baas.protocol.{BaaSProtocol, ProtocolDistributedEventPublishing} import com.ing.baker.runtime.scaladsl.Baker import com.ing.baker.runtime.serialization.{Encryption, SerializersProvider} diff --git a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/akka/InteractionSchedulingProtocolsSerializer.scala b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/akka/InteractionSchedulingProtocolsSerializer.scala index 4191c1082..43aeb9375 100644 --- a/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/akka/InteractionSchedulingProtocolsSerializer.scala +++ b/baas-protocol-interaction-scheduling/src/main/scala/com/ing/baker/baas/akka/InteractionSchedulingProtocolsSerializer.scala @@ -7,6 +7,8 @@ import com.ing.baker.baas.protocol.InteractionSchedulingProto._ object InteractionSchedulingProtocolsSerializer { + val identifier: Int = 102 + def entries(ev0: SerializersProvider): List[BinarySerializable] = { implicit val ev = ev0 List( @@ -37,4 +39,5 @@ object InteractionSchedulingProtocolsSerializer { ) } } -class InteractionSchedulingProtocolsSerializer(system: ExtendedActorSystem) extends TypedProtobufSerializer(system, InteractionSchedulingProtocolsSerializer.entries) + +class InteractionSchedulingProtocolsSerializer(system: ExtendedActorSystem) extends TypedProtobufSerializer(system, InteractionSchedulingProtocolsSerializer.identifier ,InteractionSchedulingProtocolsSerializer.entries) diff --git a/baas-protocol-recipe-event-publishing/src/main/resources/reference.conf b/baas-protocol-recipe-event-publishing/src/main/resources/reference.conf index c667dbef4..b82403e45 100644 --- a/baas-protocol-recipe-event-publishing/src/main/resources/reference.conf +++ b/baas-protocol-recipe-event-publishing/src/main/resources/reference.conf @@ -3,7 +3,7 @@ akka { actor { serializers { - event-publishing-protobuf = "com.ing.baker.baas.akka.ProtocolDistributedEventPublishingSerializer" + event-publishing-protobuf = "com.ing.baker.baas.akka.DistributedEventPublishingProtocolSerializer" } serialization-bindings { diff --git a/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/akka/ProtocolDistributedEventPublishingSerializer.scala b/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/akka/DistributedEventPublishingProtocolSerializer.scala similarity index 66% rename from baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/akka/ProtocolDistributedEventPublishingSerializer.scala rename to baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/akka/DistributedEventPublishingProtocolSerializer.scala index 515ef5240..a8b87d4ac 100644 --- a/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/akka/ProtocolDistributedEventPublishingSerializer.scala +++ b/baas-protocol-recipe-event-publishing/src/main/scala/com/ing/baker/baas/akka/DistributedEventPublishingProtocolSerializer.scala @@ -6,7 +6,9 @@ import com.ing.baker.baas.protocol.ProtocolDistributedEventPublishing import com.ing.baker.runtime.serialization.TypedProtobufSerializer.{BinarySerializable, forType} import com.ing.baker.runtime.serialization.{SerializersProvider, TypedProtobufSerializer} -object ProtocolDistributedEventPublishingSerializer { +object DistributedEventPublishingProtocolSerializer { + + val identifier: Int = 103 def entries(ev0: SerializersProvider): List[BinarySerializable] = { implicit val ev = ev0 @@ -17,4 +19,8 @@ object ProtocolDistributedEventPublishingSerializer { } } -class ProtocolDistributedEventPublishingSerializer(system: ExtendedActorSystem) extends TypedProtobufSerializer(system, ProtocolDistributedEventPublishingSerializer.entries) +class DistributedEventPublishingProtocolSerializer(system: ExtendedActorSystem) extends TypedProtobufSerializer( + system, + DistributedEventPublishingProtocolSerializer.identifier, + DistributedEventPublishingProtocolSerializer.entries +) diff --git a/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TypedProtobufSerializer.scala b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TypedProtobufSerializer.scala index 4624263c8..de3041130 100644 --- a/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TypedProtobufSerializer.scala +++ b/baker-interface/src/main/scala/com/ing/baker/runtime/serialization/TypedProtobufSerializer.scala @@ -12,11 +12,6 @@ object TypedProtobufSerializer { private val log = LoggerFactory.getLogger(classOf[TypedProtobufSerializer]) - /** Hardcoded serializerId for this serializer. This should not conflict with other serializers. - * Values from 0 to 40 are reserved for Akka internal usage. - */ - val identifier = 101 - def forType[A <: AnyRef](implicit tag: ClassTag[A]): RegisterFor[A] = new RegisterFor[A](tag) class RegisterFor[A <: AnyRef](classTag: ClassTag[A]) { @@ -69,7 +64,7 @@ object TypedProtobufSerializer { } } -abstract class TypedProtobufSerializer(system: ExtendedActorSystem, entries: SerializersProvider => List[BinarySerializable]) extends SerializerWithStringManifest { +abstract class TypedProtobufSerializer(system: ExtendedActorSystem, _indentifier: Int, entries: SerializersProvider => List[BinarySerializable]) extends SerializerWithStringManifest { implicit def serializersProvider: SerializersProvider = SerializersProvider(system, system.provider) @@ -78,7 +73,7 @@ abstract class TypedProtobufSerializer(system: ExtendedActorSystem, entries: Ser entries(serializersProvider) override def identifier: Int = - TypedProtobufSerializer.identifier + _indentifier override def manifest(o: AnyRef): String = { entriesMem diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala index 17d187841..918615d3b 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/serialization/BakerTypedProtobufSerializer.scala @@ -1,8 +1,6 @@ package com.ing.baker.runtime.akka.actor.serialization import akka.actor.ExtendedActorSystem -import com.ing.baker.baas.protocol.{ProtocolInteractionExecution, ProtocolPushPullMatching, ProtocolQuestCommit} -import com.ing.baker.baas.protocol.InteractionSchedulingProto._ import com.ing.baker.il import com.ing.baker.runtime.akka.actor.ClusterBakerActorProvider import com.ing.baker.runtime.akka.actor.process_index.{ProcessIndex, ProcessIndexProtocol} @@ -19,9 +17,14 @@ object BakerTypedProtobufSerializer { def entries(ev0: SerializersProvider): List[BinarySerializable] = { implicit val ev = ev0 - commonEntries ++ processIndexEntries ++ processInstanceEntries ++ recipeManagerEntries ++ interactionSchedulingEntries + commonEntries ++ processIndexEntries ++ processInstanceEntries ++ recipeManagerEntries } + /** Hardcoded serializerId for this serializer. This should not conflict with other serializers. + * Values from 0 to 40 are reserved for Akka internal usage. + */ + val identifier = 101 + def commonEntries(implicit ev0: SerializersProvider): List[BinarySerializable] = List( forType[com.ing.baker.types.Value] @@ -153,32 +156,6 @@ object BakerTypedProtobufSerializer { forType[RecipeManager.RecipeAdded] .register("RecipeManager.RecipeAdded") ) - - def interactionSchedulingEntries(implicit ev0: SerializersProvider): List[BinarySerializable] = - List( - forType[ProtocolInteractionExecution.InstanceExecutedSuccessfully] - .register("InteractionSchedulingProtocols.InstanceExecutedSuccessfully"), - forType[ProtocolInteractionExecution.InstanceExecutionFailed] - .register("InteractionSchedulingProtocols.InstanceExecutionFailed"), - forType[ProtocolInteractionExecution.InstanceExecutionTimedOut] - .register("InteractionSchedulingProtocols.InstanceExecutionTimedOut"), - forType[ProtocolInteractionExecution.NoInstanceFound.type] - .register("InteractionSchedulingProtocols.NoInstanceFound"), - forType[ProtocolInteractionExecution.InvalidExecution] - .register("InteractionSchedulingProtocols.InvalidExecution"), - forType[ProtocolPushPullMatching.Push] - .register("InteractionSchedulingProtocols.Push"), - forType[ProtocolPushPullMatching.Pull] - .register("InteractionSchedulingProtocols.Pull"), - forType[ProtocolPushPullMatching.AvailableQuest] - .register("InteractionSchedulingProtocols.AvailableQuest"), - forType[ProtocolQuestCommit.Considering] - .register("InteractionSchedulingProtocols.Considering"), - forType[ProtocolQuestCommit.Commit] - .register("InteractionSchedulingProtocols.Commit"), - forType[ProtocolQuestCommit.QuestTaken.type] - .register("InteractionSchedulingProtocols.QuestTaken") - ) } -class BakerTypedProtobufSerializer(system: ExtendedActorSystem) extends TypedProtobufSerializer(system, BakerTypedProtobufSerializer.entries) +class BakerTypedProtobufSerializer(system: ExtendedActorSystem) extends TypedProtobufSerializer(system, BakerTypedProtobufSerializer.identifier, BakerTypedProtobufSerializer.entries) From caf3e854ce6efaa87024af911a0b303bcf91262b Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Tue, 26 Nov 2019 11:08:07 +0100 Subject: [PATCH 49/86] added baas kubernetes example --- .../src/main/resources/kubernetes.conf | 69 ------------------- build.sbt | 19 +++++ .../src/main/resources/kubernetes.conf | 55 +++++++++++++++ 3 files changed, 74 insertions(+), 69 deletions(-) delete mode 100644 baas-node-state/src/main/resources/kubernetes.conf create mode 100644 examples/baas-node-state-kube/src/main/resources/kubernetes.conf diff --git a/baas-node-state/src/main/resources/kubernetes.conf b/baas-node-state/src/main/resources/kubernetes.conf deleted file mode 100644 index 3915b3a88..000000000 --- a/baas-node-state/src/main/resources/kubernetes.conf +++ /dev/null @@ -1,69 +0,0 @@ - -baker { - - interaction-manager = "remote" - - actor { - provider = "cluster-sharded" - idle-timeout = 1 minute - } -} - -cassandra-journal.contact-points.0 = "127.0.0.1" -cassandra-journal.contact-points.0 = ${?CASSANDRA_CONTACT_POINTS_0} - -cassandra-snapshot-store.contact-points.0 = "127.0.0.1" -cassandra-snapshot-store.contact-points.0 = ${?CASSANDRA_CONTACT_POINTS_0} - -akka.actor.allow-java-serialization = on - -akka { - - actor { - provider = "cluster" - } - - persistence { - # See https://doc.akka.io/docs/akka-persistence-cassandra/current/journal.html#configuration - journal.plugin = "cassandra-journal" - # See https://doc.akka.io/docs/akka-persistence-cassandra/current/snapshots.html#configuration - snapshot-store.plugin = "cassandra-snapshot-store" - } - - remote { - log-remote-lifecycle-events = off - netty.tcp { - hostname = ${service.clusterHost} - port = ${service.clusterPort} - } - } - - cluster { - - seed-nodes = [ - "akka.tcp://"${service.actorSystemName}"@"${service.seedHost}":"${service.seedPort}] - - # auto downing is NOT safe for production deployments. - # you may want to use it during development, read more about it in the docs. - # - # auto-down-unreachable-after = 10s - } -} - -kamon.instrumentation.akka.filters { - - actors.track { - includes = [ ${service.actorSystemName}"/user/*" ] - excludes = [] - # ${service.actorSystemName}"/system/**", ${service.actorSystemName}"/user/worker-helper" - #] - } - - dispatchers { - includes = [ ${service.actorSystemName}"/akka.actor.default-dispatcher" ] - } - - routers { - includes = [ ${service.actorSystemName}"/user/*" ] - } -} diff --git a/build.sbt b/build.sbt index 9a3991654..7abdf4b91 100644 --- a/build.sbt +++ b/build.sbt @@ -265,6 +265,25 @@ lazy val `baas-node-state` = project.in(file("baas-node-state")) ) .dependsOn(runtime, `baas-protocol-baker`, `baas-protocol-interaction-scheduling`) +lazy val `baas-node-state-kube` = project.in(file("examples/baas-node-state-kube")) + .enablePlugins(JavaAppPackaging) + .settings(commonSettings) + .settings( + moduleName := "baas-node-state-kube", + scalacOptions ++= Seq( + "-Ypartial-unification" + ), + javaOptions in Universal ++= Seq("-Dconfig.resource=kubernetes.conf"), + mainClass in Compile := Some("com.ing.baker.baas.state.Main") + ) + .settings( + maintainer in Docker := "The Apollo Squad", + packageSummary in Docker := "The core node", + packageName in Docker := "apollo.docker.ing.net/baas-node-state-kube", + dockerExposedPorts := Seq(8080) + ) + .dependsOn(`baas-node-state`) + lazy val `baas-node-interaction` = project.in(file("baas-node-interaction")) .settings(defaultModuleSettings) .settings( diff --git a/examples/baas-node-state-kube/src/main/resources/kubernetes.conf b/examples/baas-node-state-kube/src/main/resources/kubernetes.conf new file mode 100644 index 000000000..35ec18186 --- /dev/null +++ b/examples/baas-node-state-kube/src/main/resources/kubernetes.conf @@ -0,0 +1,55 @@ +include "baker.conf" + +service { + + actorSystemName = "BaaS" + actorSystemName = ${?ACTOR_SYSTEM_NAME} + + httpServerPort = 8080 + httpServerPort = ${?HTTP_SERVER_PORT} +} + + +baker { + + interaction-manager = "remote" + + actor { + provider = "cluster-sharded" + idle-timeout = 1 minute + } +} + +cassandra-journal.contact-points.0 = "127.0.0.1" +cassandra-journal.contact-points.0 = ${?CASSANDRA_CONTACT_POINTS_0} + +cassandra-snapshot-store.contact-points.0 = "127.0.0.1" +cassandra-snapshot-store.contact-points.0 = ${?CASSANDRA_CONTACT_POINTS_0} + +#akka.actor.allow-java-serialization = on + +akka { + + actor { + provider = "cluster" + } + + persistence { + # See https://doc.akka.io/docs/akka-persistence-cassandra/current/journal.html#configuration + journal.plugin = "cassandra-journal" + # See https://doc.akka.io/docs/akka-persistence-cassandra/current/snapshots.html#configuration + snapshot-store.plugin = "cassandra-snapshot-store" + } + + management { + cluster.bootstrap { + contact-point-discovery { + # For the kubernetes API this value is substributed into the %s in pod-label-selector + service-name = "baas" + + # pick the discovery method you'd like to use: + discovery-method = kubernetes-api + } + } + } +} From 3d5c4d4f62c65101dc468c93cc271efdc21555ed Mon Sep 17 00:00:00 2001 From: yk24na Date: Tue, 26 Nov 2019 11:12:43 +0100 Subject: [PATCH 50/86] Add yaml files for akka bootsrap via kubernetes --- examples/baas-minikube-setup/akka-cluster.yml | 71 +++++++++++++++++++ .../createMinikubeNamespace.sh | 2 +- examples/baas-minikube-setup/ingress.yml | 8 +++ examples/baas-minikube-setup/service.yml | 12 ++++ .../service_management.yml | 12 ++++ 5 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 examples/baas-minikube-setup/akka-cluster.yml create mode 100644 examples/baas-minikube-setup/ingress.yml create mode 100644 examples/baas-minikube-setup/service.yml create mode 100644 examples/baas-minikube-setup/service_management.yml diff --git a/examples/baas-minikube-setup/akka-cluster.yml b/examples/baas-minikube-setup/akka-cluster.yml new file mode 100644 index 000000000..636002720 --- /dev/null +++ b/examples/baas-minikube-setup/akka-cluster.yml @@ -0,0 +1,71 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + labels: + app: baas-akka-demo + name: baas-akka-demo +spec: + replicas: 2 + selector: + matchLabels: + app: baas-akka-demo + template: + metadata: + labels: + app: baas-akka-demo + actorSystemName: baas + spec: + containers: + - name: baas-akka-demo + image: apollo.docker.ing.net/baas-node-state-kube:latest + imagePullPolicy: Never + readinessProbe: + httpGet: + path: /api/v3 + port: 8080 + livenessProbe: + tcpSocket: + port: 8080 + ports: + # akka remoting + - name: remoting + containerPort: 2552 + protocol: TCP + # akka-management and bootstrap + - name: management + containerPort: 8558 + protocol: TCP + - name: webaccess + containerPort: 8443 + protocol: TCP + #namespace + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + #namespace + +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: pod-reader +rules: + - apiGroups: [""] # "" indicates the core API group + resources: ["pods"] + verbs: ["get", "watch", "list"] +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: read-pods +subjects: + # Note the `name` line below. The first default refers to the namespace. The second refers to the service account name. + # For instance, `name: system:serviceaccount:myns:default` would refer to the default service account in namespace `myns` + - kind: User + name: system:serviceaccount:default:default +roleRef: + kind: Role + name: pod-reader + apiGroup: rbac.authorization.k8s.io diff --git a/examples/baas-minikube-setup/createMinikubeNamespace.sh b/examples/baas-minikube-setup/createMinikubeNamespace.sh index f088cf70d..a857fb279 100755 --- a/examples/baas-minikube-setup/createMinikubeNamespace.sh +++ b/examples/baas-minikube-setup/createMinikubeNamespace.sh @@ -31,4 +31,4 @@ minikube stop minikube --vm-driver virtualbox --memory 8192 --cpus 4 start --insecure-registry=registry-all.docker.ing.net ${dockerVars} -kubectl api-resources \ No newline at end of file +kubectl apply -f akka-cluster.yml \ No newline at end of file diff --git a/examples/baas-minikube-setup/ingress.yml b/examples/baas-minikube-setup/ingress.yml new file mode 100644 index 000000000..23eb0fcb3 --- /dev/null +++ b/examples/baas-minikube-setup/ingress.yml @@ -0,0 +1,8 @@ +apiVersion: networking.k8s.io/v1beta1 +kind: Ingress +metadata: + name: baas-akka-demo-ingress +spec: + backend: + serviceName: baas-akka-demo-service + servicePort: 8443 diff --git a/examples/baas-minikube-setup/service.yml b/examples/baas-minikube-setup/service.yml new file mode 100644 index 000000000..3db5c83dd --- /dev/null +++ b/examples/baas-minikube-setup/service.yml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: baas-akka-demo-service + labels: + run: baas-akka-demo-service +spec: + ports: + - port: 8443 + protocol: TCP + selector: + app: baas-akka-demo diff --git a/examples/baas-minikube-setup/service_management.yml b/examples/baas-minikube-setup/service_management.yml new file mode 100644 index 000000000..27fd2af08 --- /dev/null +++ b/examples/baas-minikube-setup/service_management.yml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: baas-akka-demo-service-management + labels: + run: baas-akka-demo-service-management +spec: + ports: + - port: 8558 + protocol: TCP + selector: + app: baas-akka-demo \ No newline at end of file From 2141c28cc34e64d9a471173a0429ceb5e248f651 Mon Sep 17 00:00:00 2001 From: yk24na Date: Tue, 26 Nov 2019 11:18:31 +0100 Subject: [PATCH 51/86] Add yaml files for akka bootsrap via kubernetes --- examples/baas-minikube-setup/createMinikubeNamespace.sh | 2 +- examples/baas-minikube-setup/updateBAAS.sh | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/baas-minikube-setup/createMinikubeNamespace.sh b/examples/baas-minikube-setup/createMinikubeNamespace.sh index a857fb279..f088cf70d 100755 --- a/examples/baas-minikube-setup/createMinikubeNamespace.sh +++ b/examples/baas-minikube-setup/createMinikubeNamespace.sh @@ -31,4 +31,4 @@ minikube stop minikube --vm-driver virtualbox --memory 8192 --cpus 4 start --insecure-registry=registry-all.docker.ing.net ${dockerVars} -kubectl apply -f akka-cluster.yml \ No newline at end of file +kubectl api-resources \ No newline at end of file diff --git a/examples/baas-minikube-setup/updateBAAS.sh b/examples/baas-minikube-setup/updateBAAS.sh index 0003923dd..3e79ad501 100644 --- a/examples/baas-minikube-setup/updateBAAS.sh +++ b/examples/baas-minikube-setup/updateBAAS.sh @@ -62,10 +62,9 @@ sbt baas-client-example/docker:publish sbt baas-interactions-example/docker:publish sbt baas-event-listener-example/docker:publish -#TODO configmaps +cd examples/baas-minikube-setup - -#TODO namespace +kubectl apply -f akka-cluster.yml From e0a086280ad4c26fb2d471f6e5c254e4a0a861b9 Mon Sep 17 00:00:00 2001 From: yk24na Date: Tue, 26 Nov 2019 11:31:59 +0100 Subject: [PATCH 52/86] Remove docker build --- examples/baas-minikube-setup/updateBAAS.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/baas-minikube-setup/updateBAAS.sh b/examples/baas-minikube-setup/updateBAAS.sh index 3e79ad501..de8194ef0 100644 --- a/examples/baas-minikube-setup/updateBAAS.sh +++ b/examples/baas-minikube-setup/updateBAAS.sh @@ -51,8 +51,6 @@ docker rmi $app_name_lower --force || echo "Ignoring docker proxy error" log "Build new image" # make sure minikube can access registry run : minikube delete && minikube start --insecure-registry=registry-all.docker.ing.net -docker build -t $app_name_lower -f Dockerfile . - # Build baas example images # Assuming current working directory is: ../baker/examples/baas-minikube-setup From 63a2fe68260c1fa5112e6032801fb963ecd17691 Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Tue, 26 Nov 2019 13:16:27 +0100 Subject: [PATCH 53/86] worked on kubernetes setup --- examples/baas-minikube-setup/akka-cluster.yml | 6 +++--- examples/baas-minikube-setup/updateBAAS.sh | 14 ++++++++------ .../src/main/resources/kubernetes.conf | 18 +++++++++--------- 3 files changed, 20 insertions(+), 18 deletions(-) mode change 100644 => 100755 examples/baas-minikube-setup/updateBAAS.sh diff --git a/examples/baas-minikube-setup/akka-cluster.yml b/examples/baas-minikube-setup/akka-cluster.yml index 636002720..1a8e0a0c8 100644 --- a/examples/baas-minikube-setup/akka-cluster.yml +++ b/examples/baas-minikube-setup/akka-cluster.yml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: labels: @@ -17,7 +17,7 @@ spec: spec: containers: - name: baas-akka-demo - image: apollo.docker.ing.net/baas-node-state-kube:latest + image: apollo.docker.ing.net/baas-node-state-kube:3.0.2-SNAPSHOT imagePullPolicy: Never readinessProbe: httpGet: @@ -36,7 +36,7 @@ spec: containerPort: 8558 protocol: TCP - name: webaccess - containerPort: 8443 + containerPort: 8080 protocol: TCP #namespace env: diff --git a/examples/baas-minikube-setup/updateBAAS.sh b/examples/baas-minikube-setup/updateBAAS.sh old mode 100644 new mode 100755 index de8194ef0..d754ea208 --- a/examples/baas-minikube-setup/updateBAAS.sh +++ b/examples/baas-minikube-setup/updateBAAS.sh @@ -1,3 +1,5 @@ +#!/bin/bash + set -eo pipefail set -o nounset #set -o xtrace @@ -5,8 +7,8 @@ set -o nounset projectRoot=`pwd` # clean up first -app_name=baas -app_context=baas +app_name=baas-akka-demo +app_context=baas-akka-demo app_name_lower=`echo $app_name | awk '{print tolower($0)}'` image_name=apollo.docker.ing.net/${app_name_lower} namespace_name=default @@ -55,10 +57,10 @@ log "Build new image" # Build baas example images # Assuming current working directory is: ../baker/examples/baas-minikube-setup cd ../.. -sbt baas-node-state/docker:publish -sbt baas-client-example/docker:publish -sbt baas-interactions-example/docker:publish -sbt baas-event-listener-example/docker:publish +sbt baas-node-state-kube/docker:publishLocal +sbt baas-client-example/docker:publishLocal +sbt baas-interactions-example/docker:publishLocal +sbt baas-event-listener-example/docker:publishLocal cd examples/baas-minikube-setup diff --git a/examples/baas-node-state-kube/src/main/resources/kubernetes.conf b/examples/baas-node-state-kube/src/main/resources/kubernetes.conf index 35ec18186..9a9701609 100644 --- a/examples/baas-node-state-kube/src/main/resources/kubernetes.conf +++ b/examples/baas-node-state-kube/src/main/resources/kubernetes.conf @@ -20,11 +20,11 @@ baker { } } -cassandra-journal.contact-points.0 = "127.0.0.1" -cassandra-journal.contact-points.0 = ${?CASSANDRA_CONTACT_POINTS_0} +#cassandra-journal.contact-points.0 = "127.0.0.1" +#cassandra-journal.contact-points.0 = ${?CASSANDRA_CONTACT_POINTS_0} -cassandra-snapshot-store.contact-points.0 = "127.0.0.1" -cassandra-snapshot-store.contact-points.0 = ${?CASSANDRA_CONTACT_POINTS_0} +#cassandra-snapshot-store.contact-points.0 = "127.0.0.1" +#cassandra-snapshot-store.contact-points.0 = ${?CASSANDRA_CONTACT_POINTS_0} #akka.actor.allow-java-serialization = on @@ -34,18 +34,18 @@ akka { provider = "cluster" } - persistence { + #persistence { # See https://doc.akka.io/docs/akka-persistence-cassandra/current/journal.html#configuration - journal.plugin = "cassandra-journal" + #journal.plugin = "cassandra-journal" # See https://doc.akka.io/docs/akka-persistence-cassandra/current/snapshots.html#configuration - snapshot-store.plugin = "cassandra-snapshot-store" - } + #snapshot-store.plugin = "cassandra-snapshot-store" + #} management { cluster.bootstrap { contact-point-discovery { # For the kubernetes API this value is substributed into the %s in pod-label-selector - service-name = "baas" + service-name = "baas-akka-demo" # pick the discovery method you'd like to use: discovery-method = kubernetes-api From bc35331a4a1975ec0b4d1a8dd853fe30ffda5bcd Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Tue, 26 Nov 2019 14:02:41 +0100 Subject: [PATCH 54/86] work on kubernetes: --- examples/baas-minikube-setup/akka-cluster.yml | 7 ++++--- examples/baas-minikube-setup/updateBAAS.sh | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/examples/baas-minikube-setup/akka-cluster.yml b/examples/baas-minikube-setup/akka-cluster.yml index 1a8e0a0c8..5f3d6a80a 100644 --- a/examples/baas-minikube-setup/akka-cluster.yml +++ b/examples/baas-minikube-setup/akka-cluster.yml @@ -5,7 +5,7 @@ metadata: app: baas-akka-demo name: baas-akka-demo spec: - replicas: 2 + replicas: 3 selector: matchLabels: app: baas-akka-demo @@ -21,10 +21,11 @@ spec: imagePullPolicy: Never readinessProbe: httpGet: - path: /api/v3 + path: /health port: 8080 livenessProbe: - tcpSocket: + httpGet: + path: /health port: 8080 ports: # akka remoting diff --git a/examples/baas-minikube-setup/updateBAAS.sh b/examples/baas-minikube-setup/updateBAAS.sh index d754ea208..0e371df90 100755 --- a/examples/baas-minikube-setup/updateBAAS.sh +++ b/examples/baas-minikube-setup/updateBAAS.sh @@ -58,9 +58,9 @@ log "Build new image" # Assuming current working directory is: ../baker/examples/baas-minikube-setup cd ../.. sbt baas-node-state-kube/docker:publishLocal -sbt baas-client-example/docker:publishLocal -sbt baas-interactions-example/docker:publishLocal -sbt baas-event-listener-example/docker:publishLocal +#sbt baas-client-example/docker:publishLocal +#sbt baas-interactions-example/docker:publishLocal +#sbt baas-event-listener-example/docker:publishLocal cd examples/baas-minikube-setup From 1e9a97fadf09bca3a95bfdc294e15d42ebe10231 Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Tue, 26 Nov 2019 14:03:01 +0100 Subject: [PATCH 55/86] work on kube --- .../src/main/scala/com/ing/baker/baas/state/BaaSServer.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala index b0e4f5a3a..c075b81c2 100644 --- a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala +++ b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala @@ -50,7 +50,7 @@ class BaaSServer(implicit system: ActorSystem, mat: Materializer, baker: Baker, implicit private val serializersProvider: SerializersProvider = SerializersProvider(system, encryption) - def route: Route = concat(haproxyCheck, pathPrefix("api" / "v3")(concat(health, addRecipe, getRecipe, getAllRecipes, bake, + def route: Route = concat(haproxyCheck, health, pathPrefix("api" / "v3")(concat(health, addRecipe, getRecipe, getAllRecipes, bake, fireEventAndResolveWhenReceived, fireEventAndResolveWhenCompleted, fireEventAndResolveOnEvent, fireEvent, getAllRecipeInstancesMetadata, getRecipeInstanceState, getVisualState, retryInteraction, resolveInteraction, stopRetryingInteraction @@ -58,7 +58,7 @@ class BaaSServer(implicit system: ActorSystem, mat: Materializer, baker: Baker, private def haproxyCheck: Route = pathSingleSlash(get(complete(StatusCodes.OK))) - private def health: Route = get(complete("Ok")) + private def health: Route = pathPrefix("health")(get(complete(StatusCodes.OK))) private def addRecipe: Route = post(path("addRecipe") { entity(as[BaaSProtocol.AddRecipeRequest]) { request => From df62a83e392eed159a92137290d53b03e4a05145 Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 27 Nov 2019 13:27:10 +0100 Subject: [PATCH 56/86] Add service.yml --- examples/baas-minikube-setup/service.yml | 2 +- examples/baas-minikube-setup/updateBAAS.sh | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/examples/baas-minikube-setup/service.yml b/examples/baas-minikube-setup/service.yml index 3db5c83dd..b6d5d68eb 100644 --- a/examples/baas-minikube-setup/service.yml +++ b/examples/baas-minikube-setup/service.yml @@ -6,7 +6,7 @@ metadata: run: baas-akka-demo-service spec: ports: - - port: 8443 + - port: 8080 protocol: TCP selector: app: baas-akka-demo diff --git a/examples/baas-minikube-setup/updateBAAS.sh b/examples/baas-minikube-setup/updateBAAS.sh index 0e371df90..2cdb9290b 100755 --- a/examples/baas-minikube-setup/updateBAAS.sh +++ b/examples/baas-minikube-setup/updateBAAS.sh @@ -2,7 +2,7 @@ set -eo pipefail set -o nounset -#set -o xtrace +set -o xtrace projectRoot=`pwd` @@ -65,7 +65,4 @@ sbt baas-node-state-kube/docker:publishLocal cd examples/baas-minikube-setup kubectl apply -f akka-cluster.yml - - - - +kubectl apply -f service.yml \ No newline at end of file From ebf0f70b57ce80c24704ebea734feead6b9634cd Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Wed, 27 Nov 2019 17:43:15 +0100 Subject: [PATCH 57/86] Worked on the minikube example --- .../src/main/resources/application.conf | 4 + build.sbt | 96 ++++++++++--- .../{Readme.md => README.md} | 0 examples/baas-minikube-setup/akka-cluster.yml | 133 ++++++++++++++++-- .../src/main/resources/application.conf | 41 ++++++ .../webservice/ClusterHealthCheck.scala | 13 ++ .../main/scala/webshop/webservice/Main.scala | 18 +++ .../src/main/resources/application.conf | 41 ++++++ .../webservice/CheckoutFlowRecipe.scala | 62 ++++++++ .../webservice/ClusterHealthCheck.scala | 13 ++ .../main/scala/webshop/webservice/Main.scala | 27 ++++ .../webservice/MakePaymentInstance.scala | 20 +++ .../webservice/ReserveItemsInstance.scala | 19 +++ .../webservice/ShipItemsInstance.scala | 20 +++ .../src/main/resources/kubernetes.conf | 26 +++- .../webservice/ClusterHealthCheck.scala | 13 ++ examples/baas-minikube-setup/service.yml | 12 +- .../service_management.yml | 6 +- examples/baas-minikube-setup/updateBAAS.sh | 36 +---- 19 files changed, 531 insertions(+), 69 deletions(-) rename examples/baas-minikube-setup/{Readme.md => README.md} (100%) create mode 100644 examples/baas-minikube-setup/baas-minikube-event-listener/src/main/resources/application.conf create mode 100644 examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/ClusterHealthCheck.scala create mode 100644 examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/Main.scala create mode 100644 examples/baas-minikube-setup/baas-minikube-interactions/src/main/resources/application.conf create mode 100644 examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala create mode 100644 examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ClusterHealthCheck.scala create mode 100644 examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/Main.scala create mode 100644 examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/MakePaymentInstance.scala create mode 100644 examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ReserveItemsInstance.scala create mode 100644 examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ShipItemsInstance.scala rename examples/{baas-node-state-kube => baas-minikube-setup/baas-minikube-state}/src/main/resources/kubernetes.conf (67%) create mode 100644 examples/baas-minikube-setup/baas-minikube-state/src/main/scala/webshop/webservice/ClusterHealthCheck.scala diff --git a/baas-node-state/src/main/resources/application.conf b/baas-node-state/src/main/resources/application.conf index 8f4fd1531..ecd52f396 100644 --- a/baas-node-state/src/main/resources/application.conf +++ b/baas-node-state/src/main/resources/application.conf @@ -73,6 +73,10 @@ akka { # # auto-down-unreachable-after = 10s } + + management.http.routes { + cluster-management = "" + } } kamon.instrumentation.akka.filters { diff --git a/build.sbt b/build.sbt index 7abdf4b91..a05aae8a1 100644 --- a/build.sbt +++ b/build.sbt @@ -265,25 +265,6 @@ lazy val `baas-node-state` = project.in(file("baas-node-state")) ) .dependsOn(runtime, `baas-protocol-baker`, `baas-protocol-interaction-scheduling`) -lazy val `baas-node-state-kube` = project.in(file("examples/baas-node-state-kube")) - .enablePlugins(JavaAppPackaging) - .settings(commonSettings) - .settings( - moduleName := "baas-node-state-kube", - scalacOptions ++= Seq( - "-Ypartial-unification" - ), - javaOptions in Universal ++= Seq("-Dconfig.resource=kubernetes.conf"), - mainClass in Compile := Some("com.ing.baker.baas.state.Main") - ) - .settings( - maintainer in Docker := "The Apollo Squad", - packageSummary in Docker := "The core node", - packageName in Docker := "apollo.docker.ing.net/baas-node-state-kube", - dockerExposedPorts := Seq(8080) - ) - .dependsOn(`baas-node-state`) - lazy val `baas-node-interaction` = project.in(file("baas-node-interaction")) .settings(defaultModuleSettings) .settings( @@ -512,3 +493,80 @@ lazy val `baas-event-listener-example` = project dockerExposedPorts := Seq(2551) ) .dependsOn(`baas-node-event-listener`) + +lazy val `baas-minikube-state` = project.in(file("examples/baas-minikube-setup/baas-minikube-state")) + .enablePlugins(JavaAppPackaging) + .settings(commonSettings) + .settings( + moduleName := "baas-minikube-state", + scalacOptions ++= Seq( + "-Ypartial-unification" + ), + javaOptions in Universal ++= Seq("-Dconfig.resource=kubernetes.conf"), + mainClass in Compile := Some("com.ing.baker.baas.state.Main") + ) + .settings( + maintainer in Docker := "The Apollo Squad", + packageSummary in Docker := "The core node", + packageName in Docker := "apollo.docker.ing.net/baas-minikube-state", + dockerExposedPorts := Seq(8080) + ) + .dependsOn(`baas-node-state`) + +lazy val `baas-minikube-event-listener` = project.in(file("examples/baas-minikube-setup/baas-minikube-event-listener")) + .enablePlugins(JavaAppPackaging) + .settings(commonSettings) + .settings( + moduleName := "baas-minikube-event-listener", + scalacOptions ++= Seq( + "-Ypartial-unification" + ), + libraryDependencies ++= + compileDeps( + slf4jApi, + slf4jSimple, + catsEffect, + akkaManagementHttp, + akkaClusterBoostrap, + akkaDiscoveryKube + ) ++ testDeps( + scalaTest, + scalaCheck + ) + ) + .settings( + maintainer in Docker := "The Apollo Squad", + packageSummary in Docker := "The event listener node", + packageName in Docker := "apollo.docker.ing.net/baas-minikube-event-listener", + dockerExposedPorts := Seq() + ) + .dependsOn(`baas-node-event-listener`) + +lazy val `baas-minikube-interactions` = project.in(file("examples/baas-minikube-setup/baas-minikube-interactions")) + .enablePlugins(JavaAppPackaging) + .settings(commonSettings) + .settings( + moduleName := "baas-minikube-interactions", + scalacOptions ++= Seq( + "-Ypartial-unification" + ), + libraryDependencies ++= + compileDeps( + slf4jApi, + slf4jSimple, + catsEffect, + akkaManagementHttp, + akkaClusterBoostrap, + akkaDiscoveryKube + ) ++ testDeps( + scalaTest, + scalaCheck + ) + ) + .settings( + maintainer in Docker := "The Apollo Squad", + packageSummary in Docker := "The interactions node", + packageName in Docker := "apollo.docker.ing.net/baas-minikube-interactions", + dockerExposedPorts := Seq() + ) + .dependsOn(`baas-node-interaction`) diff --git a/examples/baas-minikube-setup/Readme.md b/examples/baas-minikube-setup/README.md similarity index 100% rename from examples/baas-minikube-setup/Readme.md rename to examples/baas-minikube-setup/README.md diff --git a/examples/baas-minikube-setup/akka-cluster.yml b/examples/baas-minikube-setup/akka-cluster.yml index 5f3d6a80a..4cc560783 100644 --- a/examples/baas-minikube-setup/akka-cluster.yml +++ b/examples/baas-minikube-setup/akka-cluster.yml @@ -2,31 +2,31 @@ apiVersion: apps/v1 kind: Deployment metadata: labels: - app: baas-akka-demo - name: baas-akka-demo + app: baas-state + name: baas-state spec: - replicas: 3 + replicas: 2 selector: matchLabels: - app: baas-akka-demo + app: baas-state template: metadata: labels: - app: baas-akka-demo - actorSystemName: baas + app: baas-state + actorSystemName: BaaS spec: containers: - - name: baas-akka-demo - image: apollo.docker.ing.net/baas-node-state-kube:3.0.2-SNAPSHOT + - name: baas-state + image: apollo.docker.ing.net/baas-minikube-state:3.0.2-SNAPSHOT imagePullPolicy: Never readinessProbe: httpGet: - path: /health - port: 8080 + path: /health/ready + port: 8558 livenessProbe: httpGet: - path: /health - port: 8080 + path: /health/alive + port: 8558 ports: # akka remoting - name: remoting @@ -45,9 +45,100 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: baas-interactions + name: baas-interactions +spec: + replicas: 1 + selector: + matchLabels: + app: baas-interactions + template: + metadata: + labels: + app: baas-interactions + actorSystemName: BaaS + spec: + containers: + - name: baas-interactions + image: apollo.docker.ing.net/baas-minikube-interactions:3.0.2-SNAPSHOT + imagePullPolicy: Never + readinessProbe: + httpGet: + path: /health/ready + port: 8558 + livenessProbe: + httpGet: + path: /health/alive + port: 8558 + ports: + # akka remoting + - name: remoting + containerPort: 2552 + protocol: TCP + # akka-management and bootstrap + - name: management + containerPort: 8558 + protocol: TCP #namespace + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: baas-event-listener + name: baas-event-listener +spec: + replicas: 1 + selector: + matchLabels: + app: baas-event-listener + template: + metadata: + labels: + app: baas-event-listener + actorSystemName: BaaS + spec: + containers: + - name: baas-event-listener + image: apollo.docker.ing.net/baas-minikube-event-listener:3.0.2-SNAPSHOT + imagePullPolicy: Never + readinessProbe: + httpGet: + path: /health/ready + port: 8558 + livenessProbe: + httpGet: + path: /health/alive + port: 8558 + ports: + # akka remoting + - name: remoting + containerPort: 2552 + protocol: TCP + # akka-management and bootstrap + - name: management + containerPort: 8558 + protocol: TCP + #namespace + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace --- + kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: @@ -70,3 +161,21 @@ roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io +--- + +apiVersion: v1 +kind: Service +metadata: + name: baas-state-service + labels: + run: baas-state-service +spec: + selector: + app: baas-state + ports: + - port: 8080 + protocol: TCP + type: LoadBalancer + +# Run this command to expose the service to minikube +# minikube service baas-state-service diff --git a/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/resources/application.conf b/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/resources/application.conf new file mode 100644 index 000000000..156c4b2dd --- /dev/null +++ b/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/resources/application.conf @@ -0,0 +1,41 @@ + +akka { + + actor { + provider = "cluster" + } + + cluster.configuration-compatibility-check.enforce-on-join = off + + discovery { + kubernetes-api { + pod-label-selector = "actorSystemName=%s" + } + } + + management { + + http.routes { + cluster-management = "" + } + + cluster.bootstrap { + contact-point-discovery { + # For the kubernetes API this value is substituted in the %s in pod-label-selector + service-name = "BaaS" + + # pick the discovery method you'd like to use: + discovery-method = kubernetes-api + } + } + + health-checks { + readiness-path = "health/ready" + liveness-path = "health/alive" + + liveness-checks { + cluster-health = "webshop.webservice.ClusterHealthCheck" + } + } + } +} diff --git a/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/ClusterHealthCheck.scala b/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/ClusterHealthCheck.scala new file mode 100644 index 000000000..a6ae41f89 --- /dev/null +++ b/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/ClusterHealthCheck.scala @@ -0,0 +1,13 @@ +package webshop.webservice + +import akka.actor.ActorSystem +import akka.cluster.{Cluster, MemberStatus} + +import scala.concurrent.Future + +class ClusterHealthCheck(system: ActorSystem) extends (() => Future[Boolean]) { + private val cluster = Cluster(system) + override def apply(): Future[Boolean] = { + Future.successful(cluster.selfMember.status == MemberStatus.Up) + } +} diff --git a/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/Main.scala b/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/Main.scala new file mode 100644 index 000000000..0da8207ce --- /dev/null +++ b/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/Main.scala @@ -0,0 +1,18 @@ +package webshop.webservice + +import akka.actor.ActorSystem +import akka.management.cluster.bootstrap.ClusterBootstrap +import akka.management.scaladsl.AkkaManagement +import com.ing.baker.baas.scaladsl.BaaSEventListener + +object Main extends App { + + val actorSystem = ActorSystem("BaaS") // This should be done by the BaaSInteractionInstance ecosystem to ease the configuration and improve the UX + AkkaManagement(actorSystem).start() + ClusterBootstrap(actorSystem).start() + val ecosystem = BaaSEventListener(actorSystem) + + ecosystem.registerEventListener("Webshop", (metadata, event) => { + println(metadata.recipeName + " [" + metadata.recipeInstanceId + "] " + event.name) + }) +} diff --git a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/resources/application.conf b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/resources/application.conf new file mode 100644 index 000000000..156c4b2dd --- /dev/null +++ b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/resources/application.conf @@ -0,0 +1,41 @@ + +akka { + + actor { + provider = "cluster" + } + + cluster.configuration-compatibility-check.enforce-on-join = off + + discovery { + kubernetes-api { + pod-label-selector = "actorSystemName=%s" + } + } + + management { + + http.routes { + cluster-management = "" + } + + cluster.bootstrap { + contact-point-discovery { + # For the kubernetes API this value is substituted in the %s in pod-label-selector + service-name = "BaaS" + + # pick the discovery method you'd like to use: + discovery-method = kubernetes-api + } + } + + health-checks { + readiness-path = "health/ready" + liveness-path = "health/alive" + + liveness-checks { + cluster-health = "webshop.webservice.ClusterHealthCheck" + } + } + } +} diff --git a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala new file mode 100644 index 000000000..c2df108fa --- /dev/null +++ b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/CheckoutFlowRecipe.scala @@ -0,0 +1,62 @@ +package webshop.webservice + +import CheckoutFlowIngredients._ +import CheckoutFlowEvents._ + +import scala.concurrent.Future + +object CheckoutFlowIngredients { + + case class OrderId(orderId: String) + + case class Item(itemId: String) + + case class ReservedItems(items: List[Item], data: Array[Byte]) + + case class ShippingAddress(address: String) + + case class PaymentInformation(info: String) + + case class ShippingOrder(items: List[Item], data: Array[Byte], address: ShippingAddress) +} + +object CheckoutFlowEvents { + + case class OrderPlaced(orderId: OrderId, items: List[Item]) + + case class PaymentInformationReceived(paymentInformation: PaymentInformation) + + case class ShippingAddressReceived(shippingAddress: ShippingAddress) + + sealed trait ReserveItemsOutput + + case class OrderHadUnavailableItems(unavailableItems: List[Item]) extends ReserveItemsOutput + + case class ItemsReserved(reservedItems: ReservedItems) extends ReserveItemsOutput + + sealed trait MakePaymentOutput + + case class PaymentSuccessful(shippingOrder: ShippingOrder) extends MakePaymentOutput + + case class PaymentFailed() extends MakePaymentOutput + + case class ShippingConfirmed() +} + +object CheckoutFlowInteractions { + + trait ReserveItems { + + def apply(orderId: OrderId, items: List[Item]): Future[ReserveItemsOutput] + } + + trait MakePayment { + + def apply(processId: String, items: ReservedItems, address: ShippingAddress, payment: PaymentInformation): Future[MakePaymentOutput] + } + + trait ShipItems { + + def apply(order: ShippingOrder): Future[ShippingConfirmed] + } +} diff --git a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ClusterHealthCheck.scala b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ClusterHealthCheck.scala new file mode 100644 index 000000000..a6ae41f89 --- /dev/null +++ b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ClusterHealthCheck.scala @@ -0,0 +1,13 @@ +package webshop.webservice + +import akka.actor.ActorSystem +import akka.cluster.{Cluster, MemberStatus} + +import scala.concurrent.Future + +class ClusterHealthCheck(system: ActorSystem) extends (() => Future[Boolean]) { + private val cluster = Cluster(system) + override def apply(): Future[Boolean] = { + Future.successful(cluster.selfMember.status == MemberStatus.Up) + } +} diff --git a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/Main.scala b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/Main.scala new file mode 100644 index 000000000..1a597bc56 --- /dev/null +++ b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/Main.scala @@ -0,0 +1,27 @@ +package webshop.webservice + +import akka.actor.ActorSystem +import akka.management.cluster.bootstrap.ClusterBootstrap +import akka.management.scaladsl.AkkaManagement +import cats.effect.IO +import com.ing.baker.baas.scaladsl.BaaSInteractionInstance +import com.ing.baker.runtime.scaladsl.InteractionInstance + +object Main extends App { + + val actorSystem = ActorSystem("BaaS") // This should be done by the BaaSInteractionInstance ecosystem to ease the configuration and improve the UX + AkkaManagement(actorSystem).start() + ClusterBootstrap(actorSystem).start() + val ecosystem = BaaSInteractionInstance(actorSystem) + val timer = IO.timer(actorSystem.dispatcher) + + import actorSystem.dispatcher + + val instances = InteractionInstance.unsafeFromList(List( + new MakePaymentInstance()(timer), + new ReserveItemsInstance()(timer), + new ShipItemsInstance()(timer) + )) + + ecosystem.load(instances: _*) +} diff --git a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/MakePaymentInstance.scala b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/MakePaymentInstance.scala new file mode 100644 index 000000000..3618100f0 --- /dev/null +++ b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/MakePaymentInstance.scala @@ -0,0 +1,20 @@ +package webshop.webservice + +import cats.effect.{IO, Timer} +import webshop.webservice.CheckoutFlowEvents.MakePaymentOutput +import webshop.webservice.CheckoutFlowIngredients.{PaymentInformation, ReservedItems, ShippingAddress, ShippingOrder} +import webshop.webservice.CheckoutFlowInteractions.MakePayment + +import scala.concurrent.Future +import scala.concurrent.duration._ + +class MakePaymentInstance(implicit timer: Timer[IO]) extends MakePayment { + + override def apply(processId: String, items: ReservedItems, address: ShippingAddress, payment: PaymentInformation): Future[MakePaymentOutput] = { + IO.sleep(5 second) + .map(_ => println(Console.GREEN + processId + Console.RESET)) + .map(_ => CheckoutFlowEvents.PaymentSuccessful(ShippingOrder(items.items, items.data, address))) + .unsafeToFuture() + } +} + diff --git a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ReserveItemsInstance.scala b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ReserveItemsInstance.scala new file mode 100644 index 000000000..552d800f6 --- /dev/null +++ b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ReserveItemsInstance.scala @@ -0,0 +1,19 @@ +package webshop.webservice + +import cats.effect.{IO, Timer} +import cats.implicits._ +import webshop.webservice.CheckoutFlowEvents.ReserveItemsOutput +import webshop.webservice.CheckoutFlowIngredients.{Item, OrderId, ReservedItems} +import webshop.webservice.CheckoutFlowInteractions.ReserveItems + +import scala.concurrent.Future +import scala.concurrent.duration._ + +class ReserveItemsInstance(implicit timer: Timer[IO]) extends ReserveItems { + + override def apply(orderId: OrderId, items: List[Item]): Future[ReserveItemsOutput] = { + IO.sleep(1 second) + .as(CheckoutFlowEvents.ItemsReserved(ReservedItems(items, Array.fill(1000)(Byte.MaxValue)))) + .unsafeToFuture() + } +} diff --git a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ShipItemsInstance.scala b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ShipItemsInstance.scala new file mode 100644 index 000000000..3756f0aee --- /dev/null +++ b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ShipItemsInstance.scala @@ -0,0 +1,20 @@ +package webshop.webservice + +import cats.effect.{IO, Timer} +import cats.implicits._ +import webshop.webservice.CheckoutFlowEvents.ShippingConfirmed +import webshop.webservice.CheckoutFlowIngredients.ShippingOrder +import webshop.webservice.CheckoutFlowInteractions.ShipItems + +import scala.concurrent.Future +import scala.concurrent.duration._ + +class ShipItemsInstance(implicit timer: Timer[IO]) extends ShipItems { + + override def apply(order: ShippingOrder): Future[ShippingConfirmed] = { + IO.sleep(500 millis) + .as(ShippingConfirmed()) + .unsafeToFuture() + } +} + diff --git a/examples/baas-node-state-kube/src/main/resources/kubernetes.conf b/examples/baas-minikube-setup/baas-minikube-state/src/main/resources/kubernetes.conf similarity index 67% rename from examples/baas-node-state-kube/src/main/resources/kubernetes.conf rename to examples/baas-minikube-setup/baas-minikube-state/src/main/resources/kubernetes.conf index 9a9701609..1ada0c121 100644 --- a/examples/baas-node-state-kube/src/main/resources/kubernetes.conf +++ b/examples/baas-minikube-setup/baas-minikube-state/src/main/resources/kubernetes.conf @@ -34,6 +34,8 @@ akka { provider = "cluster" } + cluster.configuration-compatibility-check.enforce-on-join = off + #persistence { # See https://doc.akka.io/docs/akka-persistence-cassandra/current/journal.html#configuration #journal.plugin = "cassandra-journal" @@ -41,15 +43,35 @@ akka { #snapshot-store.plugin = "cassandra-snapshot-store" #} + discovery { + kubernetes-api { + pod-label-selector = "actorSystemName=%s" + } + } + management { + + http.routes { + cluster-management = "" + } + cluster.bootstrap { contact-point-discovery { - # For the kubernetes API this value is substributed into the %s in pod-label-selector - service-name = "baas-akka-demo" + # For the kubernetes API this value is substituted into the %s in pod-label-selector + service-name = "BaaS" # pick the discovery method you'd like to use: discovery-method = kubernetes-api } } + + health-checks { + readiness-path = "health/ready" + liveness-path = "health/alive" + + liveness-checks { + cluster-health = "webshop.webservice.ClusterHealthCheck" + } + } } } diff --git a/examples/baas-minikube-setup/baas-minikube-state/src/main/scala/webshop/webservice/ClusterHealthCheck.scala b/examples/baas-minikube-setup/baas-minikube-state/src/main/scala/webshop/webservice/ClusterHealthCheck.scala new file mode 100644 index 000000000..a6ae41f89 --- /dev/null +++ b/examples/baas-minikube-setup/baas-minikube-state/src/main/scala/webshop/webservice/ClusterHealthCheck.scala @@ -0,0 +1,13 @@ +package webshop.webservice + +import akka.actor.ActorSystem +import akka.cluster.{Cluster, MemberStatus} + +import scala.concurrent.Future + +class ClusterHealthCheck(system: ActorSystem) extends (() => Future[Boolean]) { + private val cluster = Cluster(system) + override def apply(): Future[Boolean] = { + Future.successful(cluster.selfMember.status == MemberStatus.Up) + } +} diff --git a/examples/baas-minikube-setup/service.yml b/examples/baas-minikube-setup/service.yml index b6d5d68eb..6e301aa60 100644 --- a/examples/baas-minikube-setup/service.yml +++ b/examples/baas-minikube-setup/service.yml @@ -1,12 +1,16 @@ apiVersion: v1 kind: Service metadata: - name: baas-akka-demo-service + name: baas-state-service labels: - run: baas-akka-demo-service + run: baas-state-service spec: + selector: + app: baas-state ports: - port: 8080 protocol: TCP - selector: - app: baas-akka-demo + type: LoadBalancer + +# Run this command to expose the service to minikube +# minikube service baas-state-service diff --git a/examples/baas-minikube-setup/service_management.yml b/examples/baas-minikube-setup/service_management.yml index 27fd2af08..d62ffa9ed 100644 --- a/examples/baas-minikube-setup/service_management.yml +++ b/examples/baas-minikube-setup/service_management.yml @@ -1,12 +1,12 @@ apiVersion: v1 kind: Service metadata: - name: baas-akka-demo-service-management + name: baas-akka-management labels: - run: baas-akka-demo-service-management + run: baas-akka-management spec: ports: - port: 8558 protocol: TCP selector: - app: baas-akka-demo \ No newline at end of file + app: baas-state \ No newline at end of file diff --git a/examples/baas-minikube-setup/updateBAAS.sh b/examples/baas-minikube-setup/updateBAAS.sh index 2cdb9290b..39e8ed2e5 100755 --- a/examples/baas-minikube-setup/updateBAAS.sh +++ b/examples/baas-minikube-setup/updateBAAS.sh @@ -2,23 +2,9 @@ set -eo pipefail set -o nounset -set -o xtrace - -projectRoot=`pwd` # clean up first -app_name=baas-akka-demo -app_context=baas-akka-demo -app_name_lower=`echo $app_name | awk '{print tolower($0)}'` -image_name=apollo.docker.ing.net/${app_name_lower} namespace_name=default -targetDir=${projectRoot}/.target - - -if [ -d "$targetDir" ]; then rm -Rf $targetDir; fi - -mkdir "$targetDir" - function log () { echo -e "\n $1 \n" @@ -26,21 +12,18 @@ function log () { log "Delete current deployments" set +e -kubectl delete deployment $app_name_lower --namespace=$namespace_name | echo "Ignoring deletion of non existed" +kubectl delete -f akka-cluster.yml | echo "Ignoring delete resources declared on akka-cluster.yml" set -e -#TODO: build images - log "Check status of Minikube & start if stopped" mini_running=$(minikube status | grep 'host:' | awk '{print $2}') echo $mini_running -if [[ $mini_running == "Stopped" ]] - then - sh ./createMinikubeNamespace.sh - echo "Started minikube" +if [[ $mini_running == "Stopped" ]]; then + sh ./createMinikubeNamespace.sh + echo "Started minikube" fi log "Set to minikube env" @@ -48,19 +31,14 @@ log "Set to minikube env" eval $(minikube docker-env) kubectl config use-context minikube -log "Remove old image" -docker rmi $app_name_lower --force || echo "Ignoring docker proxy error" - log "Build new image" # make sure minikube can access registry run : minikube delete && minikube start --insecure-registry=registry-all.docker.ing.net -# Build baas example images # Assuming current working directory is: ../baker/examples/baas-minikube-setup cd ../.. -sbt baas-node-state-kube/docker:publishLocal -#sbt baas-client-example/docker:publishLocal -#sbt baas-interactions-example/docker:publishLocal -#sbt baas-event-listener-example/docker:publishLocal +sbt baas-minikube-state/docker:publishLocal +sbt baas-minikube-interactions/docker:publishLocal +sbt baas-minikube-event-listener/docker:publishLocal cd examples/baas-minikube-setup From 65a01d8849aefe18ecfc213a90ea9e982825a814 Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Wed, 4 Dec 2019 10:43:10 +0100 Subject: [PATCH 58/86] Added nodes roles and openshift example --- .../src/main/resources/application.conf | 1 + ...luster.yml => baas-kubernetes-example.yml} | 52 +++++ .../src/main/resources/application.conf | 7 +- .../src/main/resources/application.conf | 7 +- .../src/main/resources/kubernetes.conf | 7 +- .../baas-openshift-example.yml | 212 ++++++++++++++++++ .../build-and-publish-images.sh | 14 ++ .../build-and-publish-local-images.sh | 8 + ...espace.sh => create-minikube-namespace.sh} | 2 +- examples/baas-minikube-setup/ingress.yml | 8 - ...{updateBAAS.sh => refresh-baas-example.sh} | 14 +- examples/baas-minikube-setup/service.yml | 16 -- .../service_management.yml | 12 - .../actor/ClusterBakerActorProvider.scala | 16 +- 14 files changed, 327 insertions(+), 49 deletions(-) rename examples/baas-minikube-setup/{akka-cluster.yml => baas-kubernetes-example.yml} (81%) create mode 100644 examples/baas-minikube-setup/baas-openshift-example.yml create mode 100755 examples/baas-minikube-setup/build-and-publish-images.sh create mode 100755 examples/baas-minikube-setup/build-and-publish-local-images.sh rename examples/baas-minikube-setup/{createMinikubeNamespace.sh => create-minikube-namespace.sh} (96%) delete mode 100644 examples/baas-minikube-setup/ingress.yml rename examples/baas-minikube-setup/{updateBAAS.sh => refresh-baas-example.sh} (65%) delete mode 100644 examples/baas-minikube-setup/service.yml delete mode 100644 examples/baas-minikube-setup/service_management.yml diff --git a/examples/baas-client-example/src/main/resources/application.conf b/examples/baas-client-example/src/main/resources/application.conf index 4f6dc7192..64b47302c 100644 --- a/examples/baas-client-example/src/main/resources/application.conf +++ b/examples/baas-client-example/src/main/resources/application.conf @@ -2,3 +2,4 @@ baas.hostname = "http://baker-haproxy:8080" baas.hostname = ${?BAAS_HOSTNAME} service.httpServerPort = 8080 +service.httpServerPort = ${?HTTP_PORT} \ No newline at end of file diff --git a/examples/baas-minikube-setup/akka-cluster.yml b/examples/baas-minikube-setup/baas-kubernetes-example.yml similarity index 81% rename from examples/baas-minikube-setup/akka-cluster.yml rename to examples/baas-minikube-setup/baas-kubernetes-example.yml index 4cc560783..5a31d88a8 100644 --- a/examples/baas-minikube-setup/akka-cluster.yml +++ b/examples/baas-minikube-setup/baas-kubernetes-example.yml @@ -139,6 +139,43 @@ spec: fieldPath: metadata.namespace --- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: client-app + name: client-app +spec: + replicas: 1 + selector: + matchLabels: + app: client-app + template: + metadata: + labels: + app: client-app + spec: + containers: + - name: client-app + image: apollo.docker.ing.net/baas-client-example:3.0.2-SNAPSHOT + imagePullPolicy: Never + readinessProbe: + httpGet: + path: /api + port: 8080 + livenessProbe: + httpGet: + path: /api + port: 8080 + ports: + - name: http + containerPort: 8080 + protocol: TCP + env: + - name: BAAS_HOSTNAME + value: http://baas-state-service:8080/ +--- + kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: @@ -176,6 +213,21 @@ spec: - port: 8080 protocol: TCP type: LoadBalancer +--- + +apiVersion: v1 +kind: Service +metadata: + name: client-app-service + labels: + run: client-app-service +spec: + selector: + app: client-app + ports: + - port: 8080 + protocol: TCP + type: LoadBalancer # Run this command to expose the service to minikube # minikube service baas-state-service diff --git a/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/resources/application.conf b/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/resources/application.conf index 156c4b2dd..d8fa215b6 100644 --- a/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/resources/application.conf +++ b/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/resources/application.conf @@ -5,7 +5,12 @@ akka { provider = "cluster" } - cluster.configuration-compatibility-check.enforce-on-join = off + cluster { + + roles = ["event-listener-node"] + + configuration-compatibility-check.enforce-on-join = off + } discovery { kubernetes-api { diff --git a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/resources/application.conf b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/resources/application.conf index 156c4b2dd..ffe992895 100644 --- a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/resources/application.conf +++ b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/resources/application.conf @@ -5,7 +5,12 @@ akka { provider = "cluster" } - cluster.configuration-compatibility-check.enforce-on-join = off + cluster { + + roles = ["interactions-node"] + + configuration-compatibility-check.enforce-on-join = off + } discovery { kubernetes-api { diff --git a/examples/baas-minikube-setup/baas-minikube-state/src/main/resources/kubernetes.conf b/examples/baas-minikube-setup/baas-minikube-state/src/main/resources/kubernetes.conf index 1ada0c121..acf0cdcc1 100644 --- a/examples/baas-minikube-setup/baas-minikube-state/src/main/resources/kubernetes.conf +++ b/examples/baas-minikube-setup/baas-minikube-state/src/main/resources/kubernetes.conf @@ -34,7 +34,12 @@ akka { provider = "cluster" } - cluster.configuration-compatibility-check.enforce-on-join = off + cluster { + + roles = ["state-node"] + + configuration-compatibility-check.enforce-on-join = off + } #persistence { # See https://doc.akka.io/docs/akka-persistence-cassandra/current/journal.html#configuration diff --git a/examples/baas-minikube-setup/baas-openshift-example.yml b/examples/baas-minikube-setup/baas-openshift-example.yml new file mode 100644 index 000000000..e1395de0f --- /dev/null +++ b/examples/baas-minikube-setup/baas-openshift-example.yml @@ -0,0 +1,212 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: baas-state + name: baas-state +spec: + replicas: 2 + selector: + matchLabels: + app: baas-state + template: + metadata: + labels: + app: baas-state + actorSystemName: BaaS + spec: + serviceAccountName: hyperloop + containers: + - name: baas-state + image: apollo.docker.ing.net/baas-minikube-state:3.0.2-SNAPSHOT + imagePullPolicy: Always + readinessProbe: + httpGet: + path: /health/ready + port: 8558 + livenessProbe: + httpGet: + path: /health/alive + port: 8558 + ports: + # akka remoting + - name: remoting + containerPort: 2552 + protocol: TCP + # akka-management and bootstrap + - name: management + containerPort: 8558 + protocol: TCP + - name: webaccess + containerPort: 8080 + protocol: TCP + imagePullSecrets: + - name: apollo + #namespace + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: baas-interactions + name: baas-interactions +spec: + replicas: 1 + selector: + matchLabels: + app: baas-interactions + template: + metadata: + labels: + app: baas-interactions + actorSystemName: BaaS + spec: + serviceAccountName: hyperloop + containers: + - name: baas-interactions + image: apollo.docker.ing.net/baas-minikube-interactions:3.0.2-SNAPSHOT + imagePullPolicy: Always + readinessProbe: + httpGet: + path: /health/ready + port: 8558 + livenessProbe: + httpGet: + path: /health/alive + port: 8558 + ports: + # akka remoting + - name: remoting + containerPort: 2552 + protocol: TCP + # akka-management and bootstrap + - name: management + containerPort: 8558 + protocol: TCP + #namespace + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: baas-event-listener + name: baas-event-listener +spec: + replicas: 1 + selector: + matchLabels: + app: baas-event-listener + template: + metadata: + labels: + app: baas-event-listener + actorSystemName: BaaS + spec: + serviceAccountName: hyperloop + containers: + - name: baas-event-listener + image: apollo.docker.ing.net/baas-minikube-event-listener:3.0.2-SNAPSHOT + imagePullPolicy: Always + readinessProbe: + httpGet: + path: /health/ready + port: 8558 + livenessProbe: + httpGet: + path: /health/alive + port: 8558 + ports: + # akka remoting + - name: remoting + containerPort: 2552 + protocol: TCP + # akka-management and bootstrap + - name: management + containerPort: 8558 + protocol: TCP + #namespace + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: client-app + name: client-app +spec: + replicas: 1 + selector: + matchLabels: + app: client-app + template: + metadata: + labels: + app: client-app + spec: + serviceAccountName: hyperloop + containers: + - name: client-app + image: apollo.docker.ing.net/baas-client-example:3.0.2-SNAPSHOT + imagePullPolicy: Never + readinessProbe: + httpGet: + path: /api + port: 8080 + livenessProbe: + httpGet: + path: /api + port: 8080 + ports: + - name: http + containerPort: 8080 + protocol: TCP + env: + - name: BAAS_HOSTNAME + value: http://baas-state-service:8080/ +--- + +apiVersion: v1 +kind: Service +metadata: + name: baas-state-service + labels: + run: baas-state-service +spec: + selector: + app: baas-state + ports: + - port: 8080 + protocol: TCP + type: LoadBalancer +--- + +apiVersion: v1 +kind: Service +metadata: + name: client-app-service + labels: + run: client-app-service +spec: + selector: + app: client-app + ports: + - port: 8080 + protocol: TCP + type: LoadBalancer diff --git a/examples/baas-minikube-setup/build-and-publish-images.sh b/examples/baas-minikube-setup/build-and-publish-images.sh new file mode 100755 index 000000000..55b859b65 --- /dev/null +++ b/examples/baas-minikube-setup/build-and-publish-images.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +echo "Run this command from the baker root" + +sbt baas-minikube-state/docker:publish +sbt baas-minikube-interactions/docker:publish +sbt baas-minikube-event-listener/docker:publish +sbt baas-client-example/docker:publish + +#docker push apollo.docker.ing.net/baas-minikube-state:3.0.2 +#docker push apollo.docker.ing.net/baas-minikube-interactions:3.0.2 +#docker push apollo.docker.ing.net/baas-minikube-event-listener:3.0.2 +#docker push apollo.docker.ing.net/baas-client-example:3.0.2 + diff --git a/examples/baas-minikube-setup/build-and-publish-local-images.sh b/examples/baas-minikube-setup/build-and-publish-local-images.sh new file mode 100755 index 000000000..03f78fe79 --- /dev/null +++ b/examples/baas-minikube-setup/build-and-publish-local-images.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +echo "Run this command from the baker root" + +sbt baas-minikube-state/docker:publishLocal +sbt baas-minikube-interactions/docker:publishLocal +sbt baas-minikube-event-listener/docker:publishLocal +sbt baas-client-example/docker:publishLocal diff --git a/examples/baas-minikube-setup/createMinikubeNamespace.sh b/examples/baas-minikube-setup/create-minikube-namespace.sh similarity index 96% rename from examples/baas-minikube-setup/createMinikubeNamespace.sh rename to examples/baas-minikube-setup/create-minikube-namespace.sh index f088cf70d..1caa09bbc 100755 --- a/examples/baas-minikube-setup/createMinikubeNamespace.sh +++ b/examples/baas-minikube-setup/create-minikube-namespace.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash ########################################################################### -#Script Name : createMinikubeNamespace.sh +#Script Name : create-minikube-example.sh #Description : Creates and runs new minikube instance using preproxy #Args : Not supported #Bash Version : GNU bash, version 3.x.XX diff --git a/examples/baas-minikube-setup/ingress.yml b/examples/baas-minikube-setup/ingress.yml deleted file mode 100644 index 23eb0fcb3..000000000 --- a/examples/baas-minikube-setup/ingress.yml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: networking.k8s.io/v1beta1 -kind: Ingress -metadata: - name: baas-akka-demo-ingress -spec: - backend: - serviceName: baas-akka-demo-service - servicePort: 8443 diff --git a/examples/baas-minikube-setup/updateBAAS.sh b/examples/baas-minikube-setup/refresh-baas-example.sh similarity index 65% rename from examples/baas-minikube-setup/updateBAAS.sh rename to examples/baas-minikube-setup/refresh-baas-example.sh index 39e8ed2e5..ab1b29b00 100755 --- a/examples/baas-minikube-setup/updateBAAS.sh +++ b/examples/baas-minikube-setup/refresh-baas-example.sh @@ -12,7 +12,7 @@ function log () { log "Delete current deployments" set +e -kubectl delete -f akka-cluster.yml | echo "Ignoring delete resources declared on akka-cluster.yml" +#kubectl delete -f baas-kubernetes-example.yml | echo "Ignoring delete resources declared on baas-kubernetes-example.yml" set -e log "Check status of Minikube & start if stopped" @@ -22,7 +22,7 @@ mini_running=$(minikube status | grep 'host:' | awk '{print $2}') echo $mini_running if [[ $mini_running == "Stopped" ]]; then - sh ./createMinikubeNamespace.sh + sh ./create-minikube-namespace.sh echo "Started minikube" fi @@ -36,11 +36,11 @@ log "Build new image" # Assuming current working directory is: ../baker/examples/baas-minikube-setup cd ../.. -sbt baas-minikube-state/docker:publishLocal -sbt baas-minikube-interactions/docker:publishLocal -sbt baas-minikube-event-listener/docker:publishLocal +#sbt baas-minikube-state/docker:publishLocal +#sbt baas-minikube-interactions/docker:publishLocal +#sbt baas-minikube-event-listener/docker:publishLocal +#sbt baas-client-example/docker:publishLocal cd examples/baas-minikube-setup -kubectl apply -f akka-cluster.yml -kubectl apply -f service.yml \ No newline at end of file +#kubectl apply -f baas-kubernetes-example.yml diff --git a/examples/baas-minikube-setup/service.yml b/examples/baas-minikube-setup/service.yml deleted file mode 100644 index 6e301aa60..000000000 --- a/examples/baas-minikube-setup/service.yml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: baas-state-service - labels: - run: baas-state-service -spec: - selector: - app: baas-state - ports: - - port: 8080 - protocol: TCP - type: LoadBalancer - -# Run this command to expose the service to minikube -# minikube service baas-state-service diff --git a/examples/baas-minikube-setup/service_management.yml b/examples/baas-minikube-setup/service_management.yml deleted file mode 100644 index d62ffa9ed..000000000 --- a/examples/baas-minikube-setup/service_management.yml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: baas-akka-management - labels: - run: baas-akka-management -spec: - ports: - - port: 8558 - protocol: TCP - selector: - app: baas-state \ No newline at end of file diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/ClusterBakerActorProvider.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/ClusterBakerActorProvider.scala index fb1c97b01..5de4f55cb 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/ClusterBakerActorProvider.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/ClusterBakerActorProvider.scala @@ -94,10 +94,16 @@ class ClusterBakerActorProvider( override def createProcessIndexActor(interactionManager: InteractionManager, recipeManager: ActorRef)(implicit actorSystem: ActorSystem): ActorRef = { + val roles = Cluster(actorSystem).selfRoles ClusterSharding(actorSystem).start( typeName = "ProcessIndexActor", entityProps = ProcessIndex.props(actorIdleTimeout, Some(retentionCheckInterval), configuredEncryption, interactionManager, recipeManager, ingredientsFilter), - settings = ClusterShardingSettings.create(actorSystem), + settings = { + if(roles.contains("state-node")) + ClusterShardingSettings(actorSystem).withRole("state-node") + else + ClusterShardingSettings(actorSystem) + }, extractEntityId = ClusterBakerActorProvider.entityIdExtractor(nrOfShards), extractShardId = ClusterBakerActorProvider.shardIdExtractor(nrOfShards) ) @@ -111,12 +117,18 @@ class ClusterBakerActorProvider( RecipeManager.props(), terminationMessage = PoisonPill, settings = ClusterSingletonManagerSettings(actorSystem)) + val roles = Cluster(actorSystem).selfRoles actorSystem.actorOf(props = singletonManagerProps, name = recipeManagerName) val singletonProxyProps = ClusterSingletonProxy.props( singletonManagerPath = s"/user/$recipeManagerName", - settings = ClusterSingletonProxySettings(actorSystem)) + settings = { + if (roles.contains("state-node")) + ClusterSingletonProxySettings(actorSystem).withRole("state-node") + else + ClusterSingletonProxySettings(actorSystem) + }) actorSystem.actorOf(props = singletonProxyProps, name = "RecipeManagerProxy") } From b0eba5771ed2ddf53e24cd8fea2d965675458dba Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 4 Dec 2019 10:55:34 +0100 Subject: [PATCH 59/86] Fix syntax in yaml file --- .../baas-openshift-example.yml | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/examples/baas-minikube-setup/baas-openshift-example.yml b/examples/baas-minikube-setup/baas-openshift-example.yml index e1395de0f..ed3050ad9 100644 --- a/examples/baas-minikube-setup/baas-openshift-example.yml +++ b/examples/baas-minikube-setup/baas-openshift-example.yml @@ -87,7 +87,7 @@ spec: protocol: TCP # akka-management and bootstrap - name: management - containerPort: 8558 + containerPort: 8558 protocol: TCP #namespace env: @@ -182,31 +182,31 @@ spec: value: http://baas-state-service:8080/ --- -apiVersion: v1 -kind: Service -metadata: - name: baas-state-service - labels: - run: baas-state-service -spec: - selector: - app: baas-state - ports: - - port: 8080 - protocol: TCP - type: LoadBalancer ---- +#apiVersion: v1 +#kind: Service +#metadata: +# name: baas-state-service +# labels: +# run: baas-state-service +#spec: +# selector: +# app: baas-state +# ports: +# - port: 8080 +# protocol: TCP +# type: LoadBalancer +#--- -apiVersion: v1 -kind: Service -metadata: - name: client-app-service - labels: - run: client-app-service -spec: - selector: - app: client-app - ports: - - port: 8080 - protocol: TCP - type: LoadBalancer +#apiVersion: v1 +#kind: Service +#metadata: +# name: client-app-service +# labels: +# run: client-app-service +#spec: +# selector: +# app: client-app +# ports: +# - port: 8080 +# protocol: TCP +# type: LoadBalancer From 9c0bee7cd77d1f4fc29a069b329e006c87110681 Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 4 Dec 2019 10:59:39 +0100 Subject: [PATCH 60/86] Fix syntax in yaml file --- examples/baas-minikube-setup/baas-openshift-example.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/baas-minikube-setup/baas-openshift-example.yml b/examples/baas-minikube-setup/baas-openshift-example.yml index ed3050ad9..317bb3da1 100644 --- a/examples/baas-minikube-setup/baas-openshift-example.yml +++ b/examples/baas-minikube-setup/baas-openshift-example.yml @@ -40,14 +40,14 @@ spec: - name: webaccess containerPort: 8080 protocol: TCP - imagePullSecrets: - - name: apollo - #namespace env: - name: NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace + imagePullSecrets: + - name: apollo + #namespace --- apiVersion: apps/v1 From 255c779ac1576b97d5cc9d87ebcb49f40d3e5286 Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 4 Dec 2019 11:20:42 +0100 Subject: [PATCH 61/86] Increase timeouts into 2 minutes --- examples/baas-minikube-setup/baas-openshift-example.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/baas-minikube-setup/baas-openshift-example.yml b/examples/baas-minikube-setup/baas-openshift-example.yml index 317bb3da1..08958ca6c 100644 --- a/examples/baas-minikube-setup/baas-openshift-example.yml +++ b/examples/baas-minikube-setup/baas-openshift-example.yml @@ -24,10 +24,12 @@ spec: httpGet: path: /health/ready port: 8558 + periodSeconds: 120 livenessProbe: httpGet: path: /health/alive port: 8558 + periodSeconds: 120 ports: # akka remoting - name: remoting @@ -76,10 +78,12 @@ spec: httpGet: path: /health/ready port: 8558 + periodSeconds: 120 livenessProbe: httpGet: path: /health/alive port: 8558 + periodSeconds: 120 ports: # akka remoting - name: remoting @@ -123,10 +127,12 @@ spec: httpGet: path: /health/ready port: 8558 + periodSeconds: 120 livenessProbe: httpGet: path: /health/alive port: 8558 + periodSeconds: 120 ports: # akka remoting - name: remoting @@ -169,10 +175,12 @@ spec: httpGet: path: /api port: 8080 + periodSeconds: 120 livenessProbe: httpGet: path: /api port: 8080 + periodSeconds: 120 ports: - name: http containerPort: 8080 From 1b158734118d710b9c1e259ac07dd963b809f75e Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Wed, 4 Dec 2019 11:34:13 +0100 Subject: [PATCH 62/86] image pull --- .../baas-minikube-setup/baas-openshift-example.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/baas-minikube-setup/baas-openshift-example.yml b/examples/baas-minikube-setup/baas-openshift-example.yml index 317bb3da1..141583bd4 100644 --- a/examples/baas-minikube-setup/baas-openshift-example.yml +++ b/examples/baas-minikube-setup/baas-openshift-example.yml @@ -20,6 +20,8 @@ spec: - name: baas-state image: apollo.docker.ing.net/baas-minikube-state:3.0.2-SNAPSHOT imagePullPolicy: Always + imagePullSecrets: + - name: apollo readinessProbe: httpGet: path: /health/ready @@ -45,8 +47,6 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - imagePullSecrets: - - name: apollo #namespace --- @@ -72,6 +72,8 @@ spec: - name: baas-interactions image: apollo.docker.ing.net/baas-minikube-interactions:3.0.2-SNAPSHOT imagePullPolicy: Always + imagePullSecrets: + - name: apollo readinessProbe: httpGet: path: /health/ready @@ -119,6 +121,8 @@ spec: - name: baas-event-listener image: apollo.docker.ing.net/baas-minikube-event-listener:3.0.2-SNAPSHOT imagePullPolicy: Always + imagePullSecrets: + - name: apollo readinessProbe: httpGet: path: /health/ready @@ -164,7 +168,9 @@ spec: containers: - name: client-app image: apollo.docker.ing.net/baas-client-example:3.0.2-SNAPSHOT - imagePullPolicy: Never + imagePullPolicy: Always + imagePullSecrets: + - name: apollo readinessProbe: httpGet: path: /api From 15114b3e954b19520ba82e0cf12c9995c2fb675d Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 4 Dec 2019 11:37:40 +0100 Subject: [PATCH 63/86] Increase timeout to 10 minutes --- .../baas-openshift-example.yml | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/baas-minikube-setup/baas-openshift-example.yml b/examples/baas-minikube-setup/baas-openshift-example.yml index 4dc462496..a30e7e52a 100644 --- a/examples/baas-minikube-setup/baas-openshift-example.yml +++ b/examples/baas-minikube-setup/baas-openshift-example.yml @@ -16,22 +16,22 @@ spec: actorSystemName: BaaS spec: serviceAccountName: hyperloop + imagePullSecrets: + - name: apollo containers: - name: baas-state image: apollo.docker.ing.net/baas-minikube-state:3.0.2-SNAPSHOT imagePullPolicy: Always - imagePullSecrets: - - name: apollo readinessProbe: httpGet: path: /health/ready port: 8558 - periodSeconds: 120 + periodSeconds: 600 livenessProbe: httpGet: path: /health/alive port: 8558 - periodSeconds: 120 + periodSeconds: 600 ports: # akka remoting - name: remoting @@ -70,22 +70,22 @@ spec: actorSystemName: BaaS spec: serviceAccountName: hyperloop + imagePullSecrets: + - name: apollo containers: - name: baas-interactions image: apollo.docker.ing.net/baas-minikube-interactions:3.0.2-SNAPSHOT imagePullPolicy: Always - imagePullSecrets: - - name: apollo readinessProbe: httpGet: path: /health/ready port: 8558 - periodSeconds: 120 + periodSeconds: 600 livenessProbe: httpGet: path: /health/alive port: 8558 - periodSeconds: 120 + periodSeconds: 600 ports: # akka remoting - name: remoting @@ -121,22 +121,22 @@ spec: actorSystemName: BaaS spec: serviceAccountName: hyperloop + imagePullSecrets: + - name: apollo containers: - name: baas-event-listener image: apollo.docker.ing.net/baas-minikube-event-listener:3.0.2-SNAPSHOT imagePullPolicy: Always - imagePullSecrets: - - name: apollo readinessProbe: httpGet: path: /health/ready port: 8558 - periodSeconds: 120 + periodSeconds: 600 livenessProbe: httpGet: path: /health/alive port: 8558 - periodSeconds: 120 + periodSeconds: 600 ports: # akka remoting - name: remoting @@ -171,22 +171,22 @@ spec: app: client-app spec: serviceAccountName: hyperloop + imagePullSecrets: + - name: apollo containers: - name: client-app image: apollo.docker.ing.net/baas-client-example:3.0.2-SNAPSHOT imagePullPolicy: Always - imagePullSecrets: - - name: apollo readinessProbe: httpGet: path: /api port: 8080 - periodSeconds: 120 + periodSeconds: 600 livenessProbe: httpGet: path: /api port: 8080 - periodSeconds: 120 + periodSeconds: 600 ports: - name: http containerPort: 8080 From f99da597e98241d0fd60282d55604e84e1a7d934 Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Wed, 4 Dec 2019 14:12:34 +0100 Subject: [PATCH 64/86] fixed tests --- .../com/ing/baker/runtime/akka/BakerExecutionSpec.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala index dc2395586..14747ab45 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala @@ -72,7 +72,7 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { for { exception <- Future.successful { intercept[IllegalArgumentException] { - Baker.akka(config, setupActorSystem) + AkkaBaker(config, setupActorSystem) } } _ <- setupActorSystem.terminate() @@ -94,7 +94,7 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { val setupActorSystem = ActorSystem("setup-actor-system", config) for { exception <- Future.successful { - intercept[MalformedURLException](Baker.akka(config, setupActorSystem)) + intercept[MalformedURLException](AkkaBaker(config, setupActorSystem)) } _ <- setupActorSystem.terminate() } yield assert(exception.getMessage contains "wrong-address") @@ -113,7 +113,7 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { val setupActorSystem = ActorSystem("setup-actor-system", config) for { exception <- Future.successful { - intercept[IllegalArgumentException](Baker.akka(config, setupActorSystem)) + intercept[IllegalArgumentException](AkkaBaker(config, setupActorSystem)) } _ <- setupActorSystem.terminate() } yield assert(exception.getMessage contains "No default service discovery implementation configured in `akka.discovery.method`") From c23474578f35579a315b315892e8dd59f6b3c997 Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 4 Dec 2019 12:57:52 +0100 Subject: [PATCH 65/86] Delete OpenShift specific configuration --- .../baas-openshift-example.yml | 226 ------------------ 1 file changed, 226 deletions(-) delete mode 100644 examples/baas-minikube-setup/baas-openshift-example.yml diff --git a/examples/baas-minikube-setup/baas-openshift-example.yml b/examples/baas-minikube-setup/baas-openshift-example.yml deleted file mode 100644 index a30e7e52a..000000000 --- a/examples/baas-minikube-setup/baas-openshift-example.yml +++ /dev/null @@ -1,226 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: baas-state - name: baas-state -spec: - replicas: 2 - selector: - matchLabels: - app: baas-state - template: - metadata: - labels: - app: baas-state - actorSystemName: BaaS - spec: - serviceAccountName: hyperloop - imagePullSecrets: - - name: apollo - containers: - - name: baas-state - image: apollo.docker.ing.net/baas-minikube-state:3.0.2-SNAPSHOT - imagePullPolicy: Always - readinessProbe: - httpGet: - path: /health/ready - port: 8558 - periodSeconds: 600 - livenessProbe: - httpGet: - path: /health/alive - port: 8558 - periodSeconds: 600 - ports: - # akka remoting - - name: remoting - containerPort: 2552 - protocol: TCP - # akka-management and bootstrap - - name: management - containerPort: 8558 - protocol: TCP - - name: webaccess - containerPort: 8080 - protocol: TCP - env: - - name: NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - #namespace ---- - -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: baas-interactions - name: baas-interactions -spec: - replicas: 1 - selector: - matchLabels: - app: baas-interactions - template: - metadata: - labels: - app: baas-interactions - actorSystemName: BaaS - spec: - serviceAccountName: hyperloop - imagePullSecrets: - - name: apollo - containers: - - name: baas-interactions - image: apollo.docker.ing.net/baas-minikube-interactions:3.0.2-SNAPSHOT - imagePullPolicy: Always - readinessProbe: - httpGet: - path: /health/ready - port: 8558 - periodSeconds: 600 - livenessProbe: - httpGet: - path: /health/alive - port: 8558 - periodSeconds: 600 - ports: - # akka remoting - - name: remoting - containerPort: 2552 - protocol: TCP - # akka-management and bootstrap - - name: management - containerPort: 8558 - protocol: TCP - #namespace - env: - - name: NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace ---- - -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: baas-event-listener - name: baas-event-listener -spec: - replicas: 1 - selector: - matchLabels: - app: baas-event-listener - template: - metadata: - labels: - app: baas-event-listener - actorSystemName: BaaS - spec: - serviceAccountName: hyperloop - imagePullSecrets: - - name: apollo - containers: - - name: baas-event-listener - image: apollo.docker.ing.net/baas-minikube-event-listener:3.0.2-SNAPSHOT - imagePullPolicy: Always - readinessProbe: - httpGet: - path: /health/ready - port: 8558 - periodSeconds: 600 - livenessProbe: - httpGet: - path: /health/alive - port: 8558 - periodSeconds: 600 - ports: - # akka remoting - - name: remoting - containerPort: 2552 - protocol: TCP - # akka-management and bootstrap - - name: management - containerPort: 8558 - protocol: TCP - #namespace - env: - - name: NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace ---- - -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app: client-app - name: client-app -spec: - replicas: 1 - selector: - matchLabels: - app: client-app - template: - metadata: - labels: - app: client-app - spec: - serviceAccountName: hyperloop - imagePullSecrets: - - name: apollo - containers: - - name: client-app - image: apollo.docker.ing.net/baas-client-example:3.0.2-SNAPSHOT - imagePullPolicy: Always - readinessProbe: - httpGet: - path: /api - port: 8080 - periodSeconds: 600 - livenessProbe: - httpGet: - path: /api - port: 8080 - periodSeconds: 600 - ports: - - name: http - containerPort: 8080 - protocol: TCP - env: - - name: BAAS_HOSTNAME - value: http://baas-state-service:8080/ ---- - -#apiVersion: v1 -#kind: Service -#metadata: -# name: baas-state-service -# labels: -# run: baas-state-service -#spec: -# selector: -# app: baas-state -# ports: -# - port: 8080 -# protocol: TCP -# type: LoadBalancer -#--- - -#apiVersion: v1 -#kind: Service -#metadata: -# name: client-app-service -# labels: -# run: client-app-service -#spec: -# selector: -# app: client-app -# ports: -# - port: 8080 -# protocol: TCP -# type: LoadBalancer From 52def85d32c75974093738d96ad75b70fc33fe5c Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 4 Dec 2019 15:07:42 +0100 Subject: [PATCH 66/86] Update manual with latest steps to run minikube cluster with example pods. --- examples/baas-minikube-setup/README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/examples/baas-minikube-setup/README.md b/examples/baas-minikube-setup/README.md index cbee36017..0e4e20b90 100644 --- a/examples/baas-minikube-setup/README.md +++ b/examples/baas-minikube-setup/README.md @@ -12,8 +12,11 @@ https://kubernetes.io/docs/tasks/tools/install-minikube/ ##Create and start minikube cluster via VirtualBox Execute `/baas-openshift-scripts/minikube/createMinikubeNamespace.sh` -##Deploy POD to minikube -Execute `/baas-openshift-scripts/minikube/refresh_minikube.sh` +##[Optional] Run minikube dashboard +Execute `minikube dashboard` -##Run minikube dashboard -Execute `minikube dashboard` \ No newline at end of file +## Build example Docker images +`/examples/baas-minikube-setup/build-and-publish-images.sh` + +##Deploy PODs to minikube +`kubectl apply -f /examples/baas-minikube-setup/baas-kubernetes-example.yml` \ No newline at end of file From a0a54533c320aa6698896e6b181e8368c1c82c01 Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 4 Dec 2019 15:09:00 +0100 Subject: [PATCH 67/86] Remove corporate proxy specific steps from namespace creation. --- .../create-minikube-namespace.sh | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/examples/baas-minikube-setup/create-minikube-namespace.sh b/examples/baas-minikube-setup/create-minikube-namespace.sh index 1caa09bbc..57403d082 100755 --- a/examples/baas-minikube-setup/create-minikube-namespace.sh +++ b/examples/baas-minikube-setup/create-minikube-namespace.sh @@ -18,17 +18,6 @@ NC='\033[0m' # No Color echo -e "Creating minikube cluster locally ${RED}(takes up to 10 minutes)${NC}" minikube delete || echo "Ignoring delete for non existed minikube cluster" -minikube --vm-driver virtualbox --memory 8192 --cpus 4 start --insecure-registry=registry-all.docker.ing.net - -hostIp=$(minikube ssh "route -n | grep ^0.0.0.0 | awk '{ print \$2 }'") - -#Removes last \r symbol -hostIp=${hostIp%?} - -dockerVars="--insecure-registry=registry-all.docker.ing.net --docker-env http_proxy=${hostIp}:3128 --docker-env https_proxy=${hostIp}:3128" - -minikube stop - -minikube --vm-driver virtualbox --memory 8192 --cpus 4 start --insecure-registry=registry-all.docker.ing.net ${dockerVars} +minikube --vm-driver virtualbox --memory 8192 --cpus 4 start kubectl api-resources \ No newline at end of file From a88e2d2e20d175649d2f9c70ab5e5d21d5412a80 Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 4 Dec 2019 15:10:06 +0100 Subject: [PATCH 68/86] Remove dependency to private images hub. --- build.sbt | 16 ++++++++-------- .../baas-kubernetes-example.yml | 8 ++++---- .../build-and-publish-images.sh | 6 ------ .../com/ing/baker/playground/commands/BaaS.scala | 10 +++++----- 4 files changed, 17 insertions(+), 23 deletions(-) diff --git a/build.sbt b/build.sbt index a05aae8a1..47869ba02 100644 --- a/build.sbt +++ b/build.sbt @@ -260,7 +260,7 @@ lazy val `baas-node-state` = project.in(file("baas-node-state")) .settings( maintainer in Docker := "The Apollo Squad", packageSummary in Docker := "The core node", - packageName in Docker := "apollo.docker.ing.net/baas-node-state", + packageName in Docker := "baas-node-state", dockerExposedPorts := Seq(8080) ) .dependsOn(runtime, `baas-protocol-baker`, `baas-protocol-interaction-scheduling`) @@ -400,7 +400,7 @@ lazy val `baker-example` = project .settings( maintainer in Docker := "The Apollo Squad", packageSummary in Docker := "A web-shop checkout service example running baker", - packageName in Docker := "apollo.docker.ing.net/baker-example-app", + packageName in Docker := "baker-example-app", dockerExposedPorts := Seq(8080) ) .dependsOn(bakertypes, runtime, recipeCompiler, recipeDsl, intermediateLanguage) @@ -433,7 +433,7 @@ lazy val `baas-client-example` = project .settings( maintainer in Docker := "The Apollo Squad", packageSummary in Docker := "A web-shop checkout service example running on baas", - packageName in Docker := "apollo.docker.ing.net/baas-client-example", + packageName in Docker := "baas-client-example", dockerExposedPorts := Seq(8080) ) .dependsOn(bakertypes, `baas-node-client`, recipeCompiler, recipeDsl) @@ -461,7 +461,7 @@ lazy val `baas-interactions-example` = project .settings( maintainer in Docker := "The Apollo Squad", packageSummary in Docker := "A web-shop checkout service interaction instances example running on baas", - packageName in Docker := "apollo.docker.ing.net/baas-interactions-example", + packageName in Docker := "baas-interactions-example", dockerExposedPorts := Seq(2551) ) .dependsOn(`baas-node-interaction`) @@ -489,7 +489,7 @@ lazy val `baas-event-listener-example` = project .settings( maintainer in Docker := "The Apollo Squad", packageSummary in Docker := "A web-shop checkout service interaction instances example running on baas", - packageName in Docker := "apollo.docker.ing.net/baas-event-listener-example", + packageName in Docker := "baas-event-listener-example", dockerExposedPorts := Seq(2551) ) .dependsOn(`baas-node-event-listener`) @@ -508,7 +508,7 @@ lazy val `baas-minikube-state` = project.in(file("examples/baas-minikube-setup/b .settings( maintainer in Docker := "The Apollo Squad", packageSummary in Docker := "The core node", - packageName in Docker := "apollo.docker.ing.net/baas-minikube-state", + packageName in Docker := "baas-minikube-state", dockerExposedPorts := Seq(8080) ) .dependsOn(`baas-node-state`) @@ -537,7 +537,7 @@ lazy val `baas-minikube-event-listener` = project.in(file("examples/baas-minikub .settings( maintainer in Docker := "The Apollo Squad", packageSummary in Docker := "The event listener node", - packageName in Docker := "apollo.docker.ing.net/baas-minikube-event-listener", + packageName in Docker := "baas-minikube-event-listener", dockerExposedPorts := Seq() ) .dependsOn(`baas-node-event-listener`) @@ -566,7 +566,7 @@ lazy val `baas-minikube-interactions` = project.in(file("examples/baas-minikube- .settings( maintainer in Docker := "The Apollo Squad", packageSummary in Docker := "The interactions node", - packageName in Docker := "apollo.docker.ing.net/baas-minikube-interactions", + packageName in Docker := "baas-minikube-interactions", dockerExposedPorts := Seq() ) .dependsOn(`baas-node-interaction`) diff --git a/examples/baas-minikube-setup/baas-kubernetes-example.yml b/examples/baas-minikube-setup/baas-kubernetes-example.yml index 5a31d88a8..6f1388dc7 100644 --- a/examples/baas-minikube-setup/baas-kubernetes-example.yml +++ b/examples/baas-minikube-setup/baas-kubernetes-example.yml @@ -17,7 +17,7 @@ spec: spec: containers: - name: baas-state - image: apollo.docker.ing.net/baas-minikube-state:3.0.2-SNAPSHOT + image: baas-minikube-state:3.0.2-SNAPSHOT imagePullPolicy: Never readinessProbe: httpGet: @@ -66,7 +66,7 @@ spec: spec: containers: - name: baas-interactions - image: apollo.docker.ing.net/baas-minikube-interactions:3.0.2-SNAPSHOT + image: baas-minikube-interactions:3.0.2-SNAPSHOT imagePullPolicy: Never readinessProbe: httpGet: @@ -112,7 +112,7 @@ spec: spec: containers: - name: baas-event-listener - image: apollo.docker.ing.net/baas-minikube-event-listener:3.0.2-SNAPSHOT + image: baas-minikube-event-listener:3.0.2-SNAPSHOT imagePullPolicy: Never readinessProbe: httpGet: @@ -157,7 +157,7 @@ spec: spec: containers: - name: client-app - image: apollo.docker.ing.net/baas-client-example:3.0.2-SNAPSHOT + image: baas-client-example:3.0.2-SNAPSHOT imagePullPolicy: Never readinessProbe: httpGet: diff --git a/examples/baas-minikube-setup/build-and-publish-images.sh b/examples/baas-minikube-setup/build-and-publish-images.sh index 55b859b65..66ea56a82 100755 --- a/examples/baas-minikube-setup/build-and-publish-images.sh +++ b/examples/baas-minikube-setup/build-and-publish-images.sh @@ -6,9 +6,3 @@ sbt baas-minikube-state/docker:publish sbt baas-minikube-interactions/docker:publish sbt baas-minikube-event-listener/docker:publish sbt baas-client-example/docker:publish - -#docker push apollo.docker.ing.net/baas-minikube-state:3.0.2 -#docker push apollo.docker.ing.net/baas-minikube-interactions:3.0.2 -#docker push apollo.docker.ing.net/baas-minikube-event-listener:3.0.2 -#docker push apollo.docker.ing.net/baas-client-example:3.0.2 - diff --git a/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala b/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala index 519294000..7e27f4293 100644 --- a/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala +++ b/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala @@ -8,7 +8,7 @@ object BaaS { val baasVersion = "3.0.2-SNAPSHOT" - val haproxyStateNodesImage = "apollo.docker.ing.net/playground-haproxy-state-nodes:latest" + val haproxyStateNodesImage = "playground-haproxy-state-nodes:latest" def startBaaS: App[Unit] = for { @@ -33,7 +33,7 @@ object BaaS { ) .map { case (env, value) => s"-e $env=$value"} .mkString(" ") - val cmd = s"docker run --name $containerName --network $networkName $envVars apollo.docker.ing.net/baas-node-state:$version" + val cmd = s"docker run --name $containerName --network $networkName $envVars baas-node-state:$version" for { _ <- Terminal.execAndWait( command = cmd, @@ -54,7 +54,7 @@ object BaaS { ) .map { case (env, value) => s"-e $env=$value"} .mkString(" ") - val cmd = s"docker run --name $containerName --network $networkName $envVars apollo.docker.ing.net/baas-interactions-example:$version" + val cmd = s"docker run --name $containerName --network $networkName $envVars baas-interactions-example:$version" for { _ <- Terminal.execAndWait( command = cmd, @@ -74,7 +74,7 @@ object BaaS { ) .map { case (env, value) => s"-e $env=$value"} .mkString(" ") - val cmd = s"docker run --name $containerName --network $networkName $envVars apollo.docker.ing.net/baas-event-listener-example:$version" + val cmd = s"docker run --name $containerName --network $networkName $envVars baas-event-listener-example:$version" for { _ <- Terminal.execAndWait( command = cmd, @@ -92,7 +92,7 @@ object BaaS { ) .map { case (env, value) => s"-e $env=$value"} .mkString(" ") - val cmd = s"docker run --name $containerName --network $networkName $envVars -p 8080:8080 apollo.docker.ing.net/baas-client-example:$version" + val cmd = s"docker run --name $containerName --network $networkName $envVars -p 8080:8080 baas-client-example:$version" for { _ <- Terminal.execAndWait( command = cmd, From b7d3299e358c5d862b74cf4cb0ef76917bc52ce1 Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 4 Dec 2019 15:16:50 +0100 Subject: [PATCH 69/86] Remove unused executable. --- .../refresh-baas-example.sh | 46 ------------------- 1 file changed, 46 deletions(-) delete mode 100755 examples/baas-minikube-setup/refresh-baas-example.sh diff --git a/examples/baas-minikube-setup/refresh-baas-example.sh b/examples/baas-minikube-setup/refresh-baas-example.sh deleted file mode 100755 index ab1b29b00..000000000 --- a/examples/baas-minikube-setup/refresh-baas-example.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash - -set -eo pipefail -set -o nounset - -# clean up first -namespace_name=default - -function log () { - echo -e "\n $1 \n" -} - -log "Delete current deployments" -set +e -#kubectl delete -f baas-kubernetes-example.yml | echo "Ignoring delete resources declared on baas-kubernetes-example.yml" -set -e - -log "Check status of Minikube & start if stopped" - -mini_running=$(minikube status | grep 'host:' | awk '{print $2}') - -echo $mini_running - -if [[ $mini_running == "Stopped" ]]; then - sh ./create-minikube-namespace.sh - echo "Started minikube" -fi - -log "Set to minikube env" - -eval $(minikube docker-env) -kubectl config use-context minikube - -log "Build new image" -# make sure minikube can access registry run : minikube delete && minikube start --insecure-registry=registry-all.docker.ing.net - -# Assuming current working directory is: ../baker/examples/baas-minikube-setup -cd ../.. -#sbt baas-minikube-state/docker:publishLocal -#sbt baas-minikube-interactions/docker:publishLocal -#sbt baas-minikube-event-listener/docker:publishLocal -#sbt baas-client-example/docker:publishLocal - -cd examples/baas-minikube-setup - -#kubectl apply -f baas-kubernetes-example.yml From dbd7ffa741f1c8eae151c4dcbedfdd829a0c5c26 Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Thu, 5 Dec 2019 13:02:04 +0100 Subject: [PATCH 70/86] solved some PR comments --- .../main/scala/com/ing/baker/baas/state/BaaSServer.scala | 4 +--- .../com/ing/baker/baas/recipe/MakePaymentInstance.scala | 2 +- .../com/ing/baker/baas/recipe/ReserveItemsInstance.scala | 2 +- .../com/ing/baker/baas/recipe/ShipItemsInstance.scala | 2 +- .../scala/webshop/webservice/MakePaymentInstance.scala | 2 +- .../scala/webshop/webservice/ReserveItemsInstance.scala | 2 +- .../main/scala/webshop/webservice/ShipItemsInstance.scala | 2 +- .../src/main/scala/webshop/webservice/Main.scala | 5 ++++- .../scala/webshop/webservice/MakePaymentInstance.scala | 2 +- .../scala/webshop/webservice/ReserveItemsInstance.scala | 2 +- .../main/scala/webshop/webservice/ShipItemsInstance.scala | 2 +- .../scala/webshop/webservice/MakePaymentInstance.scala | 2 +- .../scala/webshop/webservice/ReserveItemsInstance.scala | 2 +- .../main/scala/webshop/webservice/ShipItemsInstance.scala | 2 +- .../recipe/common/InteractionFailureStrategySpec.scala | 6 +++--- .../scala/com/ing/baker/runtime/akka/actor/UtilSpec.scala | 2 +- .../akka/actor/process_index/ProcessIndexSpec.scala | 8 ++++---- .../actor/downing/SplitBrainResolverHickUpNodeSpec.scala | 8 ++++---- .../actor/downing/SplitBrainResolverNodeCrashSpec.scala | 4 ++-- .../downing/SplitBrainResolverWithNetworkSplitSpec.scala | 8 ++++---- 20 files changed, 35 insertions(+), 34 deletions(-) diff --git a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala index c075b81c2..b7bc99868 100644 --- a/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala +++ b/baas-node-state/src/main/scala/com/ing/baker/baas/state/BaaSServer.scala @@ -50,14 +50,12 @@ class BaaSServer(implicit system: ActorSystem, mat: Materializer, baker: Baker, implicit private val serializersProvider: SerializersProvider = SerializersProvider(system, encryption) - def route: Route = concat(haproxyCheck, health, pathPrefix("api" / "v3")(concat(health, addRecipe, getRecipe, getAllRecipes, bake, + def route: Route = concat(pathPrefix("api" / "v3")(concat(health, addRecipe, getRecipe, getAllRecipes, bake, fireEventAndResolveWhenReceived, fireEventAndResolveWhenCompleted, fireEventAndResolveOnEvent, fireEvent, getAllRecipeInstancesMetadata, getRecipeInstanceState, getVisualState, retryInteraction, resolveInteraction, stopRetryingInteraction ))) - private def haproxyCheck: Route = pathSingleSlash(get(complete(StatusCodes.OK))) - private def health: Route = pathPrefix("health")(get(complete(StatusCodes.OK))) private def addRecipe: Route = post(path("addRecipe") { diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/MakePaymentInstance.scala b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/MakePaymentInstance.scala index 805174db1..470b1fa8b 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/MakePaymentInstance.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/MakePaymentInstance.scala @@ -11,7 +11,7 @@ import scala.concurrent.duration._ class MakePaymentInstance(implicit timer: Timer[IO]) extends MakePayment { override def apply(items: ReservedItems, address: ShippingAddress, payment: PaymentInformation): Future[MakePaymentOutput] = { - IO.sleep(5 second) + IO.sleep(5.second) .map(_ => CheckoutFlowEvents.PaymentSuccessful(ShippingOrder(items.items, items.data, address))) .unsafeToFuture() } diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ReserveItemsInstance.scala b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ReserveItemsInstance.scala index 1bc2d123e..7d1b0f715 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ReserveItemsInstance.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ReserveItemsInstance.scala @@ -12,7 +12,7 @@ import scala.concurrent.duration._ class ReserveItemsInstance(implicit timer: Timer[IO]) extends ReserveItems { override def apply(orderId: OrderId, items: List[Item]): Future[ReserveItemsOutput] = { - IO.sleep(1 second) + IO.sleep(1.second) .as(CheckoutFlowEvents.ItemsReserved(ReservedItems(items, Array.fill(1000)(Byte.MaxValue)))) .unsafeToFuture() } diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ShipItemsInstance.scala b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ShipItemsInstance.scala index afa5a5e47..723eeaaf9 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ShipItemsInstance.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/ShipItemsInstance.scala @@ -12,7 +12,7 @@ import scala.concurrent.duration._ class ShipItemsInstance(implicit timer: Timer[IO]) extends ShipItems { override def apply(order: ShippingOrder): Future[ShippingConfirmed] = { - IO.sleep(500 millis) + IO.sleep(500.millis) .as(ShippingConfirmed()) .unsafeToFuture() } diff --git a/examples/baas-interactions-example/src/main/scala/webshop/webservice/MakePaymentInstance.scala b/examples/baas-interactions-example/src/main/scala/webshop/webservice/MakePaymentInstance.scala index 3618100f0..a78c49088 100644 --- a/examples/baas-interactions-example/src/main/scala/webshop/webservice/MakePaymentInstance.scala +++ b/examples/baas-interactions-example/src/main/scala/webshop/webservice/MakePaymentInstance.scala @@ -11,7 +11,7 @@ import scala.concurrent.duration._ class MakePaymentInstance(implicit timer: Timer[IO]) extends MakePayment { override def apply(processId: String, items: ReservedItems, address: ShippingAddress, payment: PaymentInformation): Future[MakePaymentOutput] = { - IO.sleep(5 second) + IO.sleep(5.second) .map(_ => println(Console.GREEN + processId + Console.RESET)) .map(_ => CheckoutFlowEvents.PaymentSuccessful(ShippingOrder(items.items, items.data, address))) .unsafeToFuture() diff --git a/examples/baas-interactions-example/src/main/scala/webshop/webservice/ReserveItemsInstance.scala b/examples/baas-interactions-example/src/main/scala/webshop/webservice/ReserveItemsInstance.scala index 552d800f6..b6d1634ac 100644 --- a/examples/baas-interactions-example/src/main/scala/webshop/webservice/ReserveItemsInstance.scala +++ b/examples/baas-interactions-example/src/main/scala/webshop/webservice/ReserveItemsInstance.scala @@ -12,7 +12,7 @@ import scala.concurrent.duration._ class ReserveItemsInstance(implicit timer: Timer[IO]) extends ReserveItems { override def apply(orderId: OrderId, items: List[Item]): Future[ReserveItemsOutput] = { - IO.sleep(1 second) + IO.sleep(1.second) .as(CheckoutFlowEvents.ItemsReserved(ReservedItems(items, Array.fill(1000)(Byte.MaxValue)))) .unsafeToFuture() } diff --git a/examples/baas-interactions-example/src/main/scala/webshop/webservice/ShipItemsInstance.scala b/examples/baas-interactions-example/src/main/scala/webshop/webservice/ShipItemsInstance.scala index 3756f0aee..c9424a151 100644 --- a/examples/baas-interactions-example/src/main/scala/webshop/webservice/ShipItemsInstance.scala +++ b/examples/baas-interactions-example/src/main/scala/webshop/webservice/ShipItemsInstance.scala @@ -12,7 +12,7 @@ import scala.concurrent.duration._ class ShipItemsInstance(implicit timer: Timer[IO]) extends ShipItems { override def apply(order: ShippingOrder): Future[ShippingConfirmed] = { - IO.sleep(500 millis) + IO.sleep(500.millis) .as(ShippingConfirmed()) .unsafeToFuture() } diff --git a/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/Main.scala b/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/Main.scala index 0da8207ce..557703a50 100644 --- a/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/Main.scala +++ b/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/Main.scala @@ -4,15 +4,18 @@ import akka.actor.ActorSystem import akka.management.cluster.bootstrap.ClusterBootstrap import akka.management.scaladsl.AkkaManagement import com.ing.baker.baas.scaladsl.BaaSEventListener +import org.slf4j.LoggerFactory object Main extends App { + val log = LoggerFactory.getLogger("EventListener") + val actorSystem = ActorSystem("BaaS") // This should be done by the BaaSInteractionInstance ecosystem to ease the configuration and improve the UX AkkaManagement(actorSystem).start() ClusterBootstrap(actorSystem).start() val ecosystem = BaaSEventListener(actorSystem) ecosystem.registerEventListener("Webshop", (metadata, event) => { - println(metadata.recipeName + " [" + metadata.recipeInstanceId + "] " + event.name) + log.info(metadata.recipeName + " [" + metadata.recipeInstanceId + "] " + event.name) }) } diff --git a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/MakePaymentInstance.scala b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/MakePaymentInstance.scala index 3618100f0..a78c49088 100644 --- a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/MakePaymentInstance.scala +++ b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/MakePaymentInstance.scala @@ -11,7 +11,7 @@ import scala.concurrent.duration._ class MakePaymentInstance(implicit timer: Timer[IO]) extends MakePayment { override def apply(processId: String, items: ReservedItems, address: ShippingAddress, payment: PaymentInformation): Future[MakePaymentOutput] = { - IO.sleep(5 second) + IO.sleep(5.second) .map(_ => println(Console.GREEN + processId + Console.RESET)) .map(_ => CheckoutFlowEvents.PaymentSuccessful(ShippingOrder(items.items, items.data, address))) .unsafeToFuture() diff --git a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ReserveItemsInstance.scala b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ReserveItemsInstance.scala index 552d800f6..b6d1634ac 100644 --- a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ReserveItemsInstance.scala +++ b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ReserveItemsInstance.scala @@ -12,7 +12,7 @@ import scala.concurrent.duration._ class ReserveItemsInstance(implicit timer: Timer[IO]) extends ReserveItems { override def apply(orderId: OrderId, items: List[Item]): Future[ReserveItemsOutput] = { - IO.sleep(1 second) + IO.sleep(1.second) .as(CheckoutFlowEvents.ItemsReserved(ReservedItems(items, Array.fill(1000)(Byte.MaxValue)))) .unsafeToFuture() } diff --git a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ShipItemsInstance.scala b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ShipItemsInstance.scala index 3756f0aee..c9424a151 100644 --- a/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ShipItemsInstance.scala +++ b/examples/baas-minikube-setup/baas-minikube-interactions/src/main/scala/webshop/webservice/ShipItemsInstance.scala @@ -12,7 +12,7 @@ import scala.concurrent.duration._ class ShipItemsInstance(implicit timer: Timer[IO]) extends ShipItems { override def apply(order: ShippingOrder): Future[ShippingConfirmed] = { - IO.sleep(500 millis) + IO.sleep(500.millis) .as(ShippingConfirmed()) .unsafeToFuture() } diff --git a/examples/baker-example/src/main/scala/webshop/webservice/MakePaymentInstance.scala b/examples/baker-example/src/main/scala/webshop/webservice/MakePaymentInstance.scala index 81ca19cb8..9206f9280 100644 --- a/examples/baker-example/src/main/scala/webshop/webservice/MakePaymentInstance.scala +++ b/examples/baker-example/src/main/scala/webshop/webservice/MakePaymentInstance.scala @@ -11,7 +11,7 @@ import scala.concurrent.duration._ class MakePaymentInstance(implicit timer: Timer[IO]) extends MakePayment { override def apply(processId: String, items: ReservedItems, address: ShippingAddress, payment: PaymentInformation): Future[MakePaymentOutput] = { - IO.sleep(5 second) + IO.sleep(5.second) .map(_ => println(Console.GREEN + processId + Console.RESET)) .map(_ => CheckoutFlowEvents.PaymentSuccessful(ShippingOrder(items.items, items.data, address))) .unsafeToFuture() diff --git a/examples/baker-example/src/main/scala/webshop/webservice/ReserveItemsInstance.scala b/examples/baker-example/src/main/scala/webshop/webservice/ReserveItemsInstance.scala index 140f6e003..84001a0b4 100644 --- a/examples/baker-example/src/main/scala/webshop/webservice/ReserveItemsInstance.scala +++ b/examples/baker-example/src/main/scala/webshop/webservice/ReserveItemsInstance.scala @@ -12,7 +12,7 @@ import scala.concurrent.duration._ class ReserveItemsInstance(implicit timer: Timer[IO]) extends ReserveItems { override def apply(orderId: OrderId, items: List[Item]): Future[ReserveItemsOutput] = { - IO.sleep(1 second) + IO.sleep(1.second) .as(CheckoutFlowEvents.ItemsReserved(ReservedItems(items, Array.fill(1000)(Byte.MaxValue)))) .unsafeToFuture() } diff --git a/examples/baker-example/src/main/scala/webshop/webservice/ShipItemsInstance.scala b/examples/baker-example/src/main/scala/webshop/webservice/ShipItemsInstance.scala index 3dea936ad..d4951eaed 100644 --- a/examples/baker-example/src/main/scala/webshop/webservice/ShipItemsInstance.scala +++ b/examples/baker-example/src/main/scala/webshop/webservice/ShipItemsInstance.scala @@ -12,7 +12,7 @@ import scala.concurrent.duration._ class ShipItemsInstance(implicit timer: Timer[IO]) extends ShipItems { override def apply(order: ShippingOrder): Future[ShippingConfirmed] = { - IO.sleep(500 millis) + IO.sleep(500.millis) .as(ShippingConfirmed()) .unsafeToFuture() } diff --git a/recipe-dsl/src/test/scala/com/ing/baker/recipe/common/InteractionFailureStrategySpec.scala b/recipe-dsl/src/test/scala/com/ing/baker/recipe/common/InteractionFailureStrategySpec.scala index 43939c3e5..d87e89ad0 100644 --- a/recipe-dsl/src/test/scala/com/ing/baker/recipe/common/InteractionFailureStrategySpec.scala +++ b/recipe-dsl/src/test/scala/com/ing/baker/recipe/common/InteractionFailureStrategySpec.scala @@ -34,7 +34,7 @@ class InteractionFailureStrategySpec extends WordSpecLike with Matchers { "derive the correct parameters when deadline is specified2" in { val deadline = 16 seconds - val initialDelay = 1 seconds + val initialDelay = 1.seconds val backoffFactor: Double = 2.0 val actual = RetryWithIncrementalBackoff.builder() @@ -55,7 +55,7 @@ class InteractionFailureStrategySpec extends WordSpecLike with Matchers { "derive the correct parameters when deadline is specified and max time between retries set" in { val deadline = 22 seconds - val initialDelay = 1 seconds + val initialDelay = 1.seconds val backoffFactor: Double = 2.0 val maxDurationBetweenRetries = 4 seconds @@ -78,7 +78,7 @@ class InteractionFailureStrategySpec extends WordSpecLike with Matchers { "verify that deadline is greater than initial delay" in { - val deadline = 1 seconds + val deadline = 1.seconds val initialDelay = 2 seconds intercept[IllegalArgumentException] { diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/UtilSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/UtilSpec.scala index c25d890e7..314380ad3 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/UtilSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/UtilSpec.scala @@ -18,7 +18,7 @@ class UtilSpec extends AkkaTestBase("UtilSpec") { val futures = fastFutures :+ slowFuture - val collected = Util.collectFuturesWithin(futures, 1 second, system.scheduler) + val collected = Util.collectFuturesWithin(futures, 1.second, system.scheduler) val expectedResult = List.fill(5)(true) diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexSpec.scala index c8c63eb54..c9c13328b 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_index/ProcessIndexSpec.scala @@ -102,7 +102,7 @@ class ProcessIndexSpec extends TestKit(ActorSystem("ProcessIndexSpec", ProcessIn } "delete a process if a retention period is defined, stop command is received" in { - val recipeRetentionPeriod = 500 milliseconds + val recipeRetentionPeriod = 500.milliseconds val processProbe = TestProbe() val recipeManagerProbe = TestProbe() val actorIndex = createActorIndex(processProbe.ref, recipeManagerProbe.ref) @@ -118,7 +118,7 @@ class ProcessIndexSpec extends TestKit(ActorSystem("ProcessIndexSpec", ProcessIn Thread.sleep(recipeRetentionPeriod.toMillis) // inform the index to check for processes to be cleaned up actorIndex ! CheckForProcessesToBeDeleted - processProbe.expectMsg(15 seconds, Stop(delete = true)) + processProbe.expectMsg(15.seconds, Stop(delete = true)) } "Forward the FireTransition command when a valid HandleEvent is sent" in { @@ -177,7 +177,7 @@ class ProcessIndexSpec extends TestKit(ActorSystem("ProcessIndexSpec", ProcessIn "reply with an InvalidEvent rejection message when attempting to fire an event that is now know in the compiledRecipe" in { - val receivePeriodTimeout = 500 milliseconds + val receivePeriodTimeout = 500.milliseconds val petriNetActorProbe = TestProbe("petrinet-probe") val recipeManagerProbe = TestProbe("recipe-manager-probe") @@ -206,7 +206,7 @@ class ProcessIndexSpec extends TestKit(ActorSystem("ProcessIndexSpec", ProcessIn "reply with an InvalidEvent rejection message when attempting to fire an event that does not comply to the recipe" in { - val receivePeriodTimeout = 500 milliseconds + val receivePeriodTimeout = 500.milliseconds val petriNetActorProbe = TestProbe("petrinet-probe") val recipeManagerProbe = TestProbe("recipe-manager-probe") diff --git a/split-brain-resolver/src/multi-jvm/scala/com/ing/baker/runtime/akka/actor/downing/SplitBrainResolverHickUpNodeSpec.scala b/split-brain-resolver/src/multi-jvm/scala/com/ing/baker/runtime/akka/actor/downing/SplitBrainResolverHickUpNodeSpec.scala index f47642b21..0a08ae254 100644 --- a/split-brain-resolver/src/multi-jvm/scala/com/ing/baker/runtime/akka/actor/downing/SplitBrainResolverHickUpNodeSpec.scala +++ b/split-brain-resolver/src/multi-jvm/scala/com/ing/baker/runtime/akka/actor/downing/SplitBrainResolverHickUpNodeSpec.scala @@ -45,8 +45,8 @@ abstract class SplitBrainResolverHickUpNodeSpec(splitBrainResolverConfig: SplitB enterBarrier("cluster-is-up") runOn(nodeA) { - scheduleReachable = Some(system.scheduler.schedule(0 seconds, 2 second, () => statusNodeE(reachable = true))) - scheduleUnreachable = Some(system.scheduler.schedule(1 seconds, 2 second, () => statusNodeE(reachable = false))) + scheduleReachable = Some(system.scheduler.schedule(0.seconds, 2 second, () => statusNodeE(reachable = true))) + scheduleUnreachable = Some(system.scheduler.schedule(1.seconds, 2 second, () => statusNodeE(reachable = false))) } Thread.sleep(10 * 1000) @@ -66,8 +66,8 @@ abstract class SplitBrainResolverHickUpNodeSpec(splitBrainResolverConfig: SplitB runOn(nodeD) { awaitAssert( clusterView.isTerminated should be(true), - 20 seconds, - 1 second + 20.seconds, + 1.second ) enterBarrier("fourth-node-down") } diff --git a/split-brain-resolver/src/multi-jvm/scala/com/ing/baker/runtime/akka/actor/downing/SplitBrainResolverNodeCrashSpec.scala b/split-brain-resolver/src/multi-jvm/scala/com/ing/baker/runtime/akka/actor/downing/SplitBrainResolverNodeCrashSpec.scala index 27112790f..668f8c23a 100644 --- a/split-brain-resolver/src/multi-jvm/scala/com/ing/baker/runtime/akka/actor/downing/SplitBrainResolverNodeCrashSpec.scala +++ b/split-brain-resolver/src/multi-jvm/scala/com/ing/baker/runtime/akka/actor/downing/SplitBrainResolverNodeCrashSpec.scala @@ -102,7 +102,7 @@ abstract class SplitBrainResolverNodeCrashSpec(splitBrainResolverConfig: SplitBr awaitAssert( clusterView.isTerminated should be(true), 20 seconds, - 1 second + 1.second ) } @@ -112,7 +112,7 @@ abstract class SplitBrainResolverNodeCrashSpec(splitBrainResolverConfig: SplitBr awaitAssert( clusterView.isTerminated should be(true), 20 seconds, - 1 second + 1.second ) } diff --git a/split-brain-resolver/src/multi-jvm/scala/com/ing/baker/runtime/akka/actor/downing/SplitBrainResolverWithNetworkSplitSpec.scala b/split-brain-resolver/src/multi-jvm/scala/com/ing/baker/runtime/akka/actor/downing/SplitBrainResolverWithNetworkSplitSpec.scala index b2aadca42..e4e0cbf00 100644 --- a/split-brain-resolver/src/multi-jvm/scala/com/ing/baker/runtime/akka/actor/downing/SplitBrainResolverWithNetworkSplitSpec.scala +++ b/split-brain-resolver/src/multi-jvm/scala/com/ing/baker/runtime/akka/actor/downing/SplitBrainResolverWithNetworkSplitSpec.scala @@ -49,7 +49,7 @@ abstract class SplitBrainResolverWithNetworkSplitSpec(splitBrainResolverConfig: awaitAssert( clusterView.isTerminated should be(true), 20 seconds, - 1 second + 1.second ) } @@ -85,7 +85,7 @@ abstract class SplitBrainResolverWithNetworkSplitSpec(splitBrainResolverConfig: awaitAssert( clusterView.isTerminated should be(true), 20 seconds, - 1 second + 1.second ) } @@ -124,7 +124,7 @@ abstract class SplitBrainResolverWithNetworkSplitSpec(splitBrainResolverConfig: awaitAssert( clusterView.isTerminated should be(true), 20 seconds, - 1 second + 1.second ) enterBarrier("unreachable-fourth-node") } @@ -158,7 +158,7 @@ abstract class SplitBrainResolverWithNetworkSplitSpec(splitBrainResolverConfig: awaitAssert( clusterView.isTerminated should be(true), 20 seconds, - 1 second + 1.second ) enterBarrier("split-between-remaining-nodes") } From 0982719597d0629d0907fe31281c34ed97a65771 Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Tue, 10 Dec 2019 11:54:31 +0100 Subject: [PATCH 71/86] Ignoring interface and generated protobuf code for correct code coverage reports --- build.sbt | 1 + 1 file changed, 1 insertion(+) diff --git a/build.sbt b/build.sbt index ed8788b3b..e71c5f143 100644 --- a/build.sbt +++ b/build.sbt @@ -23,6 +23,7 @@ val commonSettings = Defaults.coreDefaultSettings ++ Seq( s"-target:jvm-$jvmV", "-Xfatal-warnings" ), + coverageExcludedPackages := ";.*.javadsl;.*.scaladsl;.*.common;.*.protobuf", packageOptions in (Compile, packageBin) += Package.ManifestAttributes( "Build-Time" -> new java.util.Date().toString, From 3e2b0de6d036efe8433f80400f2c6566ac1c768d Mon Sep 17 00:00:00 2001 From: yk24na Date: Tue, 10 Dec 2019 13:28:46 +0100 Subject: [PATCH 72/86] Minor improvements to spec --- .../ProcessInstanceEventSourcingSpec.scala | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcingSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcingSpec.scala index a9cd24e2f..20a83a3b8 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcingSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcingSpec.scala @@ -24,12 +24,12 @@ import scala.concurrent.duration._ class ProcessInstanceEventSourcingSpec extends AkkaTestBase("ProcessQuerySpec") with BeforeAndAfterEach { - implicit val akkaTimout = Timeout(2 seconds) - val timeOut: Duration = akkaTimout.duration + private implicit val akkaTimout: Timeout = Timeout(2 seconds) + private val timeOut: Duration = akkaTimout.duration - implicit def materializer = ActorMaterializer() + private implicit val materializer: ActorMaterializer = ActorMaterializer() - implicit def ec: ExecutionContext = system.dispatcher + private implicit val ec: ExecutionContext = system.dispatcher override protected def beforeEach(): Unit = { // Clean the journal before each test @@ -59,16 +59,16 @@ class ProcessInstanceEventSourcingSpec extends AkkaTestBase("ProcessQuerySpec") instance ! Initialize(p1.markWithN(1), ()) expectMsg(Initialized(p1.markWithN(1), ())) - expectMsgPF(timeOut) {case TransitionFired(_, 1, _, _, _, _, _) ⇒} - expectMsgPF(timeOut) {case TransitionFired(_, 2, _, _, _, _, _) ⇒} + expectMsgPF(timeOut) { case TransitionFired(_, 1, _, _, _, _, _) ⇒ } + expectMsgPF(timeOut) { case TransitionFired(_, 2, _, _, _, _, _) ⇒ } ProcessInstanceEventSourcing.eventsForInstance[Place, Transition, Unit, Unit]( - "test", - recipeInstanceId, - petriNet, - NoEncryption, - readJournal, - t ⇒ eventSourceFunction) + processTypeName = "test", + recipeInstanceId = recipeInstanceId, + topology = petriNet, + encryption = NoEncryption, + readJournal = readJournal, + eventSourceFn = t ⇒ eventSourceFunction) .map(_._2) // Get the event from the tuple .runWith(TestSink.probe) .request(3) @@ -82,7 +82,6 @@ class ProcessInstanceEventSourcingSpec extends AkkaTestBase("ProcessQuerySpec") consumed shouldBe p2.markWithN(1).marshall produced shouldBe p3.markWithN(1).marshall } - } } } From 9e43014143b0e18fa1b130214dd068da3fe31abd Mon Sep 17 00:00:00 2001 From: yk24na Date: Tue, 10 Dec 2019 13:41:32 +0100 Subject: [PATCH 73/86] Remove unused code. --- .../ing/baker/baas/akka/InteractionAgent.scala | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/InteractionAgent.scala b/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/InteractionAgent.scala index 4fa75c811..41bc1cb05 100644 --- a/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/InteractionAgent.scala +++ b/baas-node-interaction/src/main/scala/com/ing/baker/baas/akka/InteractionAgent.scala @@ -66,13 +66,15 @@ class InteractionAgent(interaction: InteractionInstance) extends Actor { subscribePush() pull() + private val timeout: FiniteDuration = 10.seconds + def receive: Receive = { case ProtocolPushPullMatching.Push(mandated, uuid) => // start Quest commit protocol log.info(s"${interaction.name}:$uuid: Considering quest from $mandated") mandated ! ProtocolQuestCommit.Considering(self) unsubscribePush() - context.system.scheduler.scheduleOnce(10 seconds, self, CommitTimeout)(context.dispatcher, self) + context.system.scheduler.scheduleOnce(timeout, self, CommitTimeout)(context.dispatcher, self) context.become(considering(uuid)) case ProtocolPushPullMatching.AvailableQuest(mandated, uuid) => @@ -80,7 +82,7 @@ class InteractionAgent(interaction: InteractionInstance) extends Actor { log.info(s"${interaction.name}:$uuid: Considering quest from $mandated") mandated ! ProtocolQuestCommit.Considering(self) unsubscribePush() - context.system.scheduler.scheduleOnce(10 seconds, self, CommitTimeout)(context.dispatcher, self) + context.system.scheduler.scheduleOnce(timeout, self, CommitTimeout)(context.dispatcher, self) context.become(considering(uuid)) } @@ -92,7 +94,6 @@ class InteractionAgent(interaction: InteractionInstance) extends Actor { subscribePush() pull() context.become(receive) - // context.become(committed(mandated, uuid)) case ProtocolQuestCommit.QuestTaken => log.info(s"${interaction.name}:$uuid: Quest taken, starting the protocol again") @@ -108,15 +109,4 @@ class InteractionAgent(interaction: InteractionInstance) extends Actor { context.become(receive) } - -// def committed(mandated: ActorRef, uuid: UUID): Receive = { -// case message: ProtocolInteractionExecution => -// log.info(s"${interaction.name}:$uuid: Considering quest from $mandated") -// // Forward the result -// mandated ! message -// // Start all over again -// subscribePush() -// pull() -// context.become(receive) -// } } From ba0b34dc252f294bd998279cc4a34ed81e5af9b1 Mon Sep 17 00:00:00 2001 From: yk24na Date: Tue, 10 Dec 2019 13:45:36 +0100 Subject: [PATCH 74/86] Extract timeouts into variable --- .../src/main/scala/com/ing/baker/baas/state/Main.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/baas-node-state/src/main/scala/com/ing/baker/baas/state/Main.scala b/baas-node-state/src/main/scala/com/ing/baker/baas/state/Main.scala index ec2dce78f..7a85b7aca 100644 --- a/baas-node-state/src/main/scala/com/ing/baker/baas/state/Main.scala +++ b/baas-node-state/src/main/scala/com/ing/baker/baas/state/Main.scala @@ -5,10 +5,11 @@ import akka.stream.ActorMaterializer import com.ing.baker.runtime.akka.AkkaBaker import com.typesafe.config.ConfigFactory -import scala.concurrent.duration._ import scala.concurrent.Await +import scala.concurrent.duration._ object Main extends App { + private val timeout: FiniteDuration = 20.seconds println(Console.YELLOW + "Starting State Node..." + Console.RESET) @@ -24,6 +25,6 @@ object Main extends App { Await.result(BaaSServer.run(stateNodeBaker, "0.0.0.0", httpServerPort)(stateNodeSystem, materializer).map { hook => println(Console.GREEN + "State Node started..." + Console.RESET) println(hook.localAddress) - sys.addShutdownHook(Await.result(hook.unbind(), 20.seconds)) - }, 20.seconds) + sys.addShutdownHook(Await.result(hook.unbind(), timeout)) + }, timeout) } From a30b17282289f53a2efd17d136d41fed32d12893 Mon Sep 17 00:00:00 2001 From: yk24na Date: Tue, 10 Dec 2019 13:58:14 +0100 Subject: [PATCH 75/86] Remove unused code --- .../baker/baas/protocol/BaaSProtocol.scala | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/baas-protocol-baker/src/main/scala/com/ing/baker/baas/protocol/BaaSProtocol.scala b/baas-protocol-baker/src/main/scala/com/ing/baker/baas/protocol/BaaSProtocol.scala index d4c5a8731..296913f59 100644 --- a/baas-protocol-baker/src/main/scala/com/ing/baker/baas/protocol/BaaSProtocol.scala +++ b/baas-protocol-baker/src/main/scala/com/ing/baker/baas/protocol/BaaSProtocol.scala @@ -16,14 +16,10 @@ object BaaSProtocol { case class GetRecipeResponse(recipeInformation: RecipeInformation) - //case class GetAllRecipesRequest() - case class GetAllRecipesResponse(map: Map[String, RecipeInformation]) case class BakeRequest(recipeId: String, recipeInstanceId: String) - //case class BakeResponse() - case class FireEventAndResolveWhenReceivedRequest(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]) case class FireEventAndResolveWhenReceivedResponse(sensoryEventStatus: SensoryEventStatus) @@ -39,9 +35,6 @@ object BaaSProtocol { case class FireEventRequest(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]) // case class FireEventResponse() TODO figure out how to deal with this one - //def fireEvent(recipeInstanceId: String, event: EventInstance, correlationId: Option[String]): EventResolutions = ??? - - //case class GetAllRecipeInstancesMetadataRequest() case class GetAllRecipeInstancesMetadataResponse(set: Set[RecipeInstanceMetadata]) @@ -49,25 +42,13 @@ object BaaSProtocol { case class GetRecipeInstanceStateResponse(recipeInstanceState: RecipeInstanceState) - //case class GetIngredientsRequest(recipeInstanceId: String) - //case class GetIngredientsResponse(map: Map[String, Value]) - //case class GetEventsRequest(re) - //def getEvents(recipeInstanceId: String): Future[Seq[EventMoment]] = ??? - //def getEventNames(recipeInstanceId: String): Future[Seq[String]] = ??? - case class GetVisualStateRequest(recipeInstanceId: String) case class GetVisualStateResponse(state: String) case class RetryInteractionRequest(recipeInstanceId: String, interactionName: String) - //case class RetryInteractionResponse() - case class ResolveInteractionRequest(recipeInstanceId: String, interactionName: String, event: EventInstance) - // case class ResolveInteractionResponse() - case class StopRetryingInteractionRequest(recipeInstanceId: String, interactionName: String) - - // response } From 01eac0fec7c830faab4604f5e20020cd3e462cae Mon Sep 17 00:00:00 2001 From: yk24na Date: Tue, 10 Dec 2019 16:14:09 +0100 Subject: [PATCH 76/86] Minor reformat the code. --- .../ing/baker/baas/recipe/CheckoutFlowRecipe.scala | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/CheckoutFlowRecipe.scala b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/CheckoutFlowRecipe.scala index e3fe5e117..bbc41cc27 100644 --- a/baas-tests/src/test/scala/com/ing/baker/baas/recipe/CheckoutFlowRecipe.scala +++ b/baas-tests/src/test/scala/com/ing/baker/baas/recipe/CheckoutFlowRecipe.scala @@ -23,6 +23,7 @@ object CheckoutFlowIngredients { case class PaymentInformation(info: String) case class ShippingOrder(items: List[Item], data: Array[Byte], address: ShippingAddress) + } object CheckoutFlowEvents { @@ -46,6 +47,7 @@ object CheckoutFlowEvents { case class PaymentFailed() extends MakePaymentOutput case class ShippingConfirmed() + } object CheckoutFlowInteractions { @@ -55,7 +57,7 @@ object CheckoutFlowInteractions { def apply(orderId: OrderId, items: List[Item]): Future[ReserveItemsOutput] } - def ReserveItemsInteraction = Interaction( + def ReserveItemsInteraction: Interaction = Interaction( name = "ReserveItems", inputIngredients = Seq( Ingredient[OrderId]("orderId"), @@ -72,7 +74,7 @@ object CheckoutFlowInteractions { def apply(items: ReservedItems, address: ShippingAddress, payment: PaymentInformation): Future[MakePaymentOutput] } - def MakePaymentInteraction = Interaction( + def MakePaymentInteraction: Interaction = Interaction( name = "MakePayment", inputIngredients = Seq( Ingredient[ReservedItems]("reservedItems"), @@ -90,7 +92,7 @@ object CheckoutFlowInteractions { def apply(order: ShippingOrder): Future[ShippingConfirmed] } - def ShipItemsInteraction = Interaction( + def ShipItemsInteraction: Interaction = Interaction( name = "ShipItems", inputIngredients = Seq( Ingredient[ShippingOrder]("shippingOrder") @@ -117,9 +119,9 @@ object CheckoutFlowRecipe { recipeBase.withDefaultFailureStrategy( RetryWithIncrementalBackoff .builder() - .withInitialDelay(100 milliseconds) - .withUntil(Some(UntilDeadline(24 hours))) - .withMaxTimeBetweenRetries(Some(10 minutes)) + .withInitialDelay(100.milliseconds) + .withUntil(Some(UntilDeadline(24.hours))) + .withMaxTimeBetweenRetries(Some(10.minutes)) .build()) def recipeWithBlockingStrategy: Recipe = From 0278c9262d234e6e1961fed4efc18a8bc4efa92f Mon Sep 17 00:00:00 2001 From: yk24na Date: Tue, 10 Dec 2019 16:35:13 +0100 Subject: [PATCH 77/86] Remove duplicates. --- .../webshop/webservice/WebShopBaker.scala | 55 ++++++++----------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopBaker.scala b/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopBaker.scala index 092e19b8c..48acb8f2e 100644 --- a/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopBaker.scala +++ b/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopBaker.scala @@ -5,15 +5,13 @@ import java.util.UUID import cats.effect.{IO, Timer} import com.ing.baker.compiler.RecipeCompiler import com.ing.baker.il.CompiledRecipe -import com.ing.baker.runtime.scaladsl.{Baker, EventInstance, InteractionInstance} -import org.log4s.{Logger, getLogger} +import com.ing.baker.runtime.scaladsl.{Baker, EventInstance} +import com.typesafe.scalalogging.LazyLogging import webshop.webservice.CheckoutFlowIngredients.{Item, OrderId, PaymentInformation, ShippingAddress} -import scala.concurrent.ExecutionContext +import scala.concurrent.{ExecutionContext, Future} -object WebShopBaker { - - val logger: Logger = getLogger("webshop.webservice") +object WebShopBaker extends LazyLogging { val checkoutFlowCompiledRecipe: CompiledRecipe = RecipeCompiler.compileRecipe(CheckoutFlowRecipe.recipe) @@ -44,47 +42,38 @@ class WebShopBaker(baker: Baker, checkoutRecipeId: String)(implicit ec: Executio override def addCheckoutAddressInfo(orderId: String, address: String): IO[Option[String]] = IO.fromFuture(IO { - val event = EventInstance.unsafeFrom( - CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress(address))) - for { - status <- baker.fireEventAndResolveWhenReceived(orderId, event) - _ = logger.info(s"${event.name}[$orderId]: $status") - } yield None + fireAndInformEvent(orderId, EventInstance.unsafeFrom( + CheckoutFlowEvents.ShippingAddressReceived(ShippingAddress(address)))) }) override def addCheckoutPaymentInfo(orderId: String, paymentInfo: String): IO[Option[String]] = IO.fromFuture(IO { - val event = EventInstance.unsafeFrom( - CheckoutFlowEvents.PaymentInformationReceived(PaymentInformation(paymentInfo))) - for { - status <- baker.fireEventAndResolveWhenReceived(orderId, event) - _ = logger.info(s"${event.name}[$orderId]: $status") - } yield None + fireAndInformEvent(orderId, EventInstance.unsafeFrom( + CheckoutFlowEvents.PaymentInformationReceived(PaymentInformation(paymentInfo)))) }) + private def fireAndInformEvent(orderId: String, event: EventInstance): Future[Option[String]] = { + for { + status <- baker.fireEventAndResolveWhenReceived(orderId, event) + _ = logger.info(s"${event.name}[$orderId]: $status") + } yield None + } + override def pollOrderStatus(orderId: String): IO[OrderStatus] = IO.fromFuture(IO { for { state <- baker.getRecipeInstanceState(orderId) - /* - _ = println - _ = println("EVENTS") - _ = state.events.foreach(println) - _ = println - _ = println("INGREDIENTS") - _ = state.ingredients.foreach(println) - */ eventNames = state.events.map(_.name) status = { - if(eventNames.contains("ShippingConfirmed")) + if (eventNames.contains("ShippingConfirmed")) OrderStatus.Complete - else if(eventNames.contains("PaymentFailed")) + else if (eventNames.contains("PaymentFailed")) OrderStatus.PaymentFailed - else if(eventNames.contains("OrderHadUnavailableItems")) + else if (eventNames.contains("OrderHadUnavailableItems")) OrderStatus.UnavailableItems(state.ingredients("unavailableItems").as[List[Item]].map(_.itemId)) - else if(eventNames.containsSlice(List("ShippingAddressReceived", "PaymentInformationReceived"))) + else if (eventNames.containsSlice(List("ShippingAddressReceived", "PaymentInformationReceived"))) OrderStatus.ProcessingPayment - else if(eventNames.contains("PaymentSuccessful")) + else if (eventNames.contains("PaymentSuccessful")) OrderStatus.ShippingItems else OrderStatus.InfoPending(List("ShippingAddressReceived", "PaymentInformationReceived") @@ -95,5 +84,7 @@ class WebShopBaker(baker: Baker, checkoutRecipeId: String)(implicit ec: Executio }) override def gracefulShutdown: IO[Unit] = - IO { baker.gracefulShutdown() } + IO { + baker.gracefulShutdown() + } } From c15f6ae91c7c9a6615e09c69d25ebda4a8f6417d Mon Sep 17 00:00:00 2001 From: yk24na Date: Tue, 10 Dec 2019 16:39:00 +0100 Subject: [PATCH 78/86] Remove println statements. --- .../webshop/webservice/WebShopService.scala | 107 ++++++++---------- 1 file changed, 47 insertions(+), 60 deletions(-) diff --git a/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopService.scala b/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopService.scala index 639ee8313..6e03544f5 100644 --- a/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopService.scala +++ b/examples/baas-client-example/src/main/scala/webshop/webservice/WebShopService.scala @@ -4,6 +4,7 @@ import java.io.File import java.util.concurrent.Executors import cats.data.Kleisli +import cats.effect.concurrent.Ref import cats.effect.{ContextShift, IO, Timer} import cats.implicits._ import io.circe.generic.auto._ @@ -13,22 +14,21 @@ import org.http4s.circe._ import org.http4s.dsl.io._ import org.http4s.implicits._ import org.http4s.server.Router -import fs2.io.file -import java.util.UUID - -import cats.effect.concurrent.{MVar, Ref} import scala.concurrent.ExecutionContext object WebShopService { case class PlaceOrderRequest(items: List[String]) + case class PlaceOrderResponse(orderId: String) case class AddAddressRequest(address: String) + case class AddPaymentRequest(payment: String) case class PollPaymentStatusResponse(status: String) + } class WebShopService(webshop: WebShop)(implicit timer: Timer[IO], cs: ContextShift[IO]) { @@ -56,65 +56,52 @@ class WebShopService(webshop: WebShop)(implicit timer: Timer[IO], cs: ContextShi } }) <+> - Router("/admin" -> HttpRoutes.of[IO] { - - case GET -> Root / "shutdown" => - println(Console.GREEN + "SHUTTING DOWN" + Console.RESET) - println(Console.GREEN + "====================" + Console.RESET) - for { - _ <- shuttingDown.modify(_ => (true, ())) - _ <- webshop.gracefulShutdown - response <- Ok("down") - } yield response - - /* - case GET -> Root / "memdump.hprof" => - val path = memoryDumpPath + "-" + UUID.randomUUID().toString + ".hprof" - dumpHeap(path, live = true).as( - Response[IO]( - Status.Ok, - body = file.readAll[IO](java.nio.file.Paths.get(path), blockingEc, chunkSize = 4096), - headers = Headers(headers.`Content-Type`(MediaType.application.`octet-stream`, Charset.`UTF-8`).pure[List])) - ) - */ + Router("/admin" -> HttpRoutes.of[IO] { + + case GET -> Root / "shutdown" => + for { + _ <- shuttingDown.modify(_ => (true, ())) + _ <- webshop.gracefulShutdown + response <- Ok("down") + } yield response + }) <+> + Router("/api" -> HttpRoutes.of[IO] { + + case GET -> Root => + Ok("Ok") + + case req@POST -> Root / "order" => + for { + request <- req.as[PlaceOrderRequest] + orderId <- webshop.createCheckoutOrder(request.items) + response <- Ok(PlaceOrderResponse(orderId).asJson) + } yield response + + case req@PUT -> Root / "order" / orderId / "address" => + for { + request <- req.as[AddAddressRequest] + _ <- webshop.addCheckoutAddressInfo(orderId, request.address) + response <- Ok() + } yield response + + case req@PUT -> Root / "order" / orderId / "payment" => + for { + request <- req.as[AddPaymentRequest] + _ <- webshop.addCheckoutPaymentInfo(orderId, request.payment) + response <- Ok() + } yield response + + case GET -> Root / "order" / orderId => + for { + status <- webshop.pollOrderStatus(orderId) + response <- Ok(PollPaymentStatusResponse(status.toString).asJson) + } yield response + + })).orNotFound - }) <+> - Router("/api" -> HttpRoutes.of[IO] { - - case GET -> Root => - Ok("Ok") - - case req@POST -> Root / "order" => - for { - request <- req.as[PlaceOrderRequest] - orderId <- webshop.createCheckoutOrder(request.items) - response <- Ok(PlaceOrderResponse(orderId).asJson) - } yield response - - case req@PUT -> Root / "order" / orderId / "address" => - for { - request <- req.as[AddAddressRequest] - _ <- webshop.addCheckoutAddressInfo(orderId, request.address) - response <- Ok() - } yield response - - case req@PUT -> Root / "order" / orderId / "payment" => - for { - request <- req.as[AddPaymentRequest] - _ <- webshop.addCheckoutPaymentInfo(orderId, request.payment) - response <- Ok() - } yield response - - case GET -> Root / "order" / orderId => - for { - status <- webshop.pollOrderStatus(orderId) - response <- Ok(PollPaymentStatusResponse(status.toString).asJson) - } yield response - - })).orNotFound + import java.lang.management.ManagementFactory import com.sun.management.HotSpotDiagnosticMXBean - import java.lang.management.ManagementFactory def dumpHeap(filePath: String, live: Boolean): IO[Unit] = IO { val file = new File(filePath) From ddefe5385aaa1986191041ef5527719edf24c9d8 Mon Sep 17 00:00:00 2001 From: yk24na Date: Tue, 10 Dec 2019 16:43:14 +0100 Subject: [PATCH 79/86] Remove println statement. --- .../src/main/scala/webshop/webservice/Main.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/baas-event-listener-example/src/main/scala/webshop/webservice/Main.scala b/examples/baas-event-listener-example/src/main/scala/webshop/webservice/Main.scala index e162dd14e..ae3815f3c 100644 --- a/examples/baas-event-listener-example/src/main/scala/webshop/webservice/Main.scala +++ b/examples/baas-event-listener-example/src/main/scala/webshop/webservice/Main.scala @@ -2,13 +2,14 @@ package webshop.webservice import akka.actor.ActorSystem import com.ing.baker.baas.scaladsl.BaaSEventListener +import com.typesafe.scalalogging.LazyLogging -object Main extends App { +object Main extends App with LazyLogging { - val actorSystem = ActorSystem("BaaS") // This should be done by the BaaSInteractionInstance ecosystem to ease the configuration and improve the UX + val actorSystem = ActorSystem("BaaS") // TODO: This should be done by the BaaSInteractionInstance ecosystem to ease the configuration and improve the UX val ecosystem = BaaSEventListener(actorSystem) ecosystem.registerEventListener("Webshop", (metadata, event) => { - println(metadata.recipeName + " [" + metadata.recipeInstanceId + "] " + event.name) + logger.info("%s [%s] %s", metadata.recipeName, metadata.recipeInstanceId, event.name) }) } From 5a3371e119db0f972426bdac2849f610a270d6e1 Mon Sep 17 00:00:00 2001 From: yk24na Date: Tue, 10 Dec 2019 16:47:28 +0100 Subject: [PATCH 80/86] Remove println statement. --- .../src/main/scala/webshop/webservice/Main.scala | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/Main.scala b/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/Main.scala index 557703a50..b70b4a782 100644 --- a/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/Main.scala +++ b/examples/baas-minikube-setup/baas-minikube-event-listener/src/main/scala/webshop/webservice/Main.scala @@ -4,11 +4,9 @@ import akka.actor.ActorSystem import akka.management.cluster.bootstrap.ClusterBootstrap import akka.management.scaladsl.AkkaManagement import com.ing.baker.baas.scaladsl.BaaSEventListener -import org.slf4j.LoggerFactory +import com.typesafe.scalalogging.LazyLogging -object Main extends App { - - val log = LoggerFactory.getLogger("EventListener") +object Main extends App with LazyLogging { val actorSystem = ActorSystem("BaaS") // This should be done by the BaaSInteractionInstance ecosystem to ease the configuration and improve the UX AkkaManagement(actorSystem).start() @@ -16,6 +14,6 @@ object Main extends App { val ecosystem = BaaSEventListener(actorSystem) ecosystem.registerEventListener("Webshop", (metadata, event) => { - log.info(metadata.recipeName + " [" + metadata.recipeInstanceId + "] " + event.name) + logger.info(metadata.recipeName + " [" + metadata.recipeInstanceId + "] " + event.name) }) } From 02cecb1ee4e8a5f7db0069cef716c14f169f05b3 Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 11 Dec 2019 10:24:17 +0100 Subject: [PATCH 81/86] Optimise Dependencies --- build.sbt | 12 ++++++------ .../main/scala/com/ing/baker/playground/Main.scala | 7 ++++--- .../com/ing/baker/playground/commands/BaaS.scala | 2 -- project/Dependencies.scala | 3 +++ 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/build.sbt b/build.sbt index e71c5f143..04c907135 100644 --- a/build.sbt +++ b/build.sbt @@ -32,11 +32,10 @@ val commonSettings = Defaults.coreDefaultSettings ++ Seq( ) val dependencyOverrideSettings = Seq( - // note that this does NOT add the dependencies, just forces the version dependencyOverrides ++= Seq( catsCore, akkaActor, - "com.github.jnr" % "jnr-constants" % "0.9.9" + jnrConstants ) ) @@ -343,10 +342,11 @@ lazy val playground = project organization := "com.ing.baker", scalaVersion := "2.12.4", libraryDependencies ++= Seq( - "org.typelevel" %% "cats-effect" % "2.0.0", - "dev.profunktor" %% "console4cats" % "0.8.0", - "org.scalatest" %% "scalatest" % "3.0.8" % "test", - "org.scalacheck" %% "scalacheck" % "1.14.1" % "test" + catsEffect, + console4Cats, + scalaTest, + scalaCheck, + scalaLogging ), scalacOptions := Seq( "-unchecked", diff --git a/playground/src/main/scala/com/ing/baker/playground/Main.scala b/playground/src/main/scala/com/ing/baker/playground/Main.scala index 0273e7219..1244091a2 100644 --- a/playground/src/main/scala/com/ing/baker/playground/Main.scala +++ b/playground/src/main/scala/com/ing/baker/playground/Main.scala @@ -1,15 +1,16 @@ package com.ing.baker.playground import cats.effect.{ExitCode, IO, IOApp} +import com.typesafe.scalalogging.LazyLogging -object Main extends IOApp { +object Main extends IOApp with LazyLogging { override def run(args: List[String]): IO[ExitCode] = { PlaygroundApp.loop .run(AppUtils.Environment.empty) .map { case (finalState, _) => - println(s"Finishing with final state $finalState") - ExitCode.Success + logger.info(s"Finishing with final state $finalState") + ExitCode.Success } } } diff --git a/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala b/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala index 7e27f4293..6a8d14426 100644 --- a/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala +++ b/playground/src/main/scala/com/ing/baker/playground/commands/BaaS.scala @@ -15,8 +15,6 @@ object BaaS { _ <- createDockerNetwork _ <- EnvSystems.runCassandra node1 <- runStateNode(baasVersion, 1, "self") - //_ <- runStateNode(baasVersion, 2, node1) - //_ <- runStateNode(baasVersion, 3, node1) _ <- EnvSystems.runHaproxy _ <- runInteractionNode(baasVersion, 1, node1) _ <- runEventListenerNode(baasVersion, 1, node1) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 1060459fd..8d5111cc2 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -65,6 +65,9 @@ object Dependencies { val catsEffect = "org.typelevel" %% "cats-effect" % "2.0.0" val catsCore = "org.typelevel" %% "cats-core" % "2.0.0" + val console4Cats = "dev.profunktor" %% "console4cats" % "0.8.0" + + val jnrConstants = "com.github.jnr" % "jnr-constants" % "0.9.9" def scalaReflect(scalaV: String): ModuleID = "org.scala-lang"% "scala-reflect" % scalaV val javaxInject = "javax.inject" % "javax.inject" % "1" From 874e237c5323f07c2cc0064bda61bfac56fba966 Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 11 Dec 2019 10:36:48 +0100 Subject: [PATCH 82/86] Remove unused lines. --- project/plugins.sbt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index b1803c22e..9ccb8769c 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -14,7 +14,4 @@ addSbtPlugin("com.typesafe.sbt" % "sbt-multi-jvm" % "0.4.0") addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.5.1") -libraryDependencies += "org.slf4j" % "slf4j-nop" % "1.7.29" - -// For the example application -//addSbtPlugin("io.kamon" % "sbt-kanela-runner" % "2.0.1") +libraryDependencies += "org.slf4j" % "slf4j-nop" % "1.7.29" \ No newline at end of file From b10edd13fff4300d05deb49d7a150efc2657cc7c Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 11 Dec 2019 10:43:40 +0100 Subject: [PATCH 83/86] Reformat the code. --- .../scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala index a9721b106..4d991a93d 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala @@ -108,7 +108,9 @@ object AkkaBakerConfig { } }, interactionManager = config.as[Option[String]]("baker.interaction-manager") match { - case Some("remote") => new InteractionManagerDis(actorSystem, 10 seconds, 600 seconds) //TODO read timeout from config //TODO 2 remore computation timeout + case Some("remote") => new InteractionManagerDis(actorSystem, 10.seconds, 600.seconds) + // TODO read timeout from config + // TODO 2 remove computation timeout case _ => new InteractionManagerLocal() }, readJournal = PersistenceQuery(actorSystem) From f6c5d2b36a3661e4a1d1a4f56dba03f8f9d91021 Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 11 Dec 2019 10:54:49 +0100 Subject: [PATCH 84/86] Reformat the code. --- .../process_instance/ProcessInstanceEventSourcing.scala | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala index 62860441c..4fa383530 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/actor/process_instance/ProcessInstanceEventSourcing.scala @@ -98,6 +98,7 @@ object ProcessInstanceEventSourcing { val src = readJournal.currentEventsByPersistenceId(persistentId, 0, Long.MaxValue) val eventSource = ProcessInstanceEventSourcing.apply[P, T, S, E](eventSourceFn) + // TODO: remove null value src.scan[(Instance[P, T, S], Event)]((Instance.uninitialized[P, T, S](topology), null.asInstanceOf[Event])) { case ((instance, _), e) ⇒ val serializedEvent = e.event.asInstanceOf[AnyRef] @@ -113,9 +114,10 @@ abstract class ProcessInstanceEventSourcing[P : Identifiable, T : Identifiable, encryption: Encryption, eventSourceFn: T => (S => E => S)) extends PersistentActor { - implicit val system = context.system + protected implicit val system: ActorSystem = context.system - val eventSource = ProcessInstanceEventSourcing.apply[P, T, S, E](eventSourceFn) + protected val eventSource: Instance[P, T, S] => Event => Instance[P, T, S] = + ProcessInstanceEventSourcing.apply[P, T, S, E](eventSourceFn) private val serializer = new ProcessInstanceSerialization[P, T, S, E](SerializersProvider(system, encryption)) @@ -128,7 +130,7 @@ abstract class ProcessInstanceEventSourcing[P : Identifiable, T : Identifiable, private var recoveringState: Instance[P, T, S] = Instance.uninitialized[P, T, S](petriNet) - private def applyToRecoveringState(e: AnyRef) = { + private def applyToRecoveringState(e: AnyRef): Unit = { val deserializedEvent = serializer.deserializeEvent(e)(recoveringState) recoveringState = eventSource(recoveringState)(deserializedEvent) } From 157e27281da9bfa8ce6e8cda9e155c0da51e5fee Mon Sep 17 00:00:00 2001 From: yk24na Date: Wed, 11 Dec 2019 10:59:24 +0100 Subject: [PATCH 85/86] Remove Thread sleep --- .../com/ing/baker/runtime/akka/BakerExecutionSpec.scala | 9 --------- 1 file changed, 9 deletions(-) diff --git a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala index 7900e24f4..9f0b33271 100644 --- a/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala +++ b/runtime/src/test/scala/com/ing/baker/runtime/akka/BakerExecutionSpec.scala @@ -968,9 +968,6 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { _ <- baker.bake(recipeId, recipeInstanceId) //Handle first event _ <- baker.fireEventAndResolveWhenCompleted(recipeInstanceId, EventInstance.unsafeFrom(InitialEvent(initialIngredientValue))) - _ <- Future { - Thread.sleep(50) - } state <- baker.getRecipeInstanceState(recipeInstanceId) } yield state.eventNames should contain(interactionOne.retryExhaustedEventName) } @@ -989,9 +986,6 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { _ <- baker.bake(recipeId, recipeInstanceId) //Handle first event _ <- baker.fireEventAndResolveWhenCompleted(recipeInstanceId, EventInstance.unsafeFrom(InitialEvent(initialIngredientValue))) - _ <- Future { - Thread.sleep(50) - } //Since the defaultEventExhaustedName is set the retryExhaustedEventName of interactionOne will be picked. state <- baker.getRecipeInstanceState(recipeInstanceId) } yield state.eventNames should not contain interactionOne.retryExhaustedEventName @@ -1016,9 +1010,6 @@ class BakerExecutionSpec extends BakerRuntimeTestBase { //Handle first event _ <- baker.fireEventAndResolveWhenCompleted(recipeInstanceId, EventInstance.unsafeFrom(InitialEvent(initialIngredientValue))) - _ <- Future { - Thread.sleep(50) - } _ = verify(listenerMock).apply(mockitoEq(RecipeEventMetadata(recipeId, recipe.name, recipeInstanceId.toString)), argThat(new RuntimeEventMatcher(EventInstance.unsafeFrom(InitialEvent(initialIngredientValue))))) _ = verify(listenerMock).apply(mockitoEq(RecipeEventMetadata(recipeId, recipe.name, recipeInstanceId.toString)), argThat(new RuntimeEventMatcher(EventInstance(interactionOne.retryExhaustedEventName, Map.empty)))) From 813e96ee197db6b70d96ee49b077aa08c41a6ce2 Mon Sep 17 00:00:00 2001 From: "Francisco M. Aramburo Torres" Date: Fri, 13 Dec 2019 11:13:12 +0100 Subject: [PATCH 86/86] Adressed a TODO, reading config from config file --- runtime/src/main/resources/reference.conf | 9 +++++++++ .../com/ing/baker/runtime/akka/AkkaBakerConfig.scala | 10 ++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/runtime/src/main/resources/reference.conf b/runtime/src/main/resources/reference.conf index 12db14010..a51a4dcf2 100644 --- a/runtime/src/main/resources/reference.conf +++ b/runtime/src/main/resources/reference.conf @@ -55,6 +55,15 @@ baker { # use "local" unless you are configuring a BaaS environment, then you will need "remote" interaction-manager = "local" + + remote-interaction-manager { + + # amount of time to wait before failing an interaction when the remote interaction manager can't find an interaction node to run on + post-timeout = 10 seconds + + # amount of time to wait before failing an interaction when the interaction node is not responding with the computation result + computation-timeout = 60 seconds + } } akka { diff --git a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala index 4d991a93d..e2dd6e562 100644 --- a/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala +++ b/runtime/src/main/scala/com/ing/baker/runtime/akka/AkkaBakerConfig.scala @@ -108,10 +108,12 @@ object AkkaBakerConfig { } }, interactionManager = config.as[Option[String]]("baker.interaction-manager") match { - case Some("remote") => new InteractionManagerDis(actorSystem, 10.seconds, 600.seconds) - // TODO read timeout from config - // TODO 2 remove computation timeout - case _ => new InteractionManagerLocal() + case Some("remote") => + val postTimeout = config.as[FiniteDuration]("baker.remote-interaction-manager.post-timeout") + val computationTimeout = config.as[FiniteDuration]("baker.remote-interaction-manager.computation-timeout") + new InteractionManagerDis(actorSystem, postTimeout, computationTimeout) + case _ => + new InteractionManagerLocal() }, readJournal = PersistenceQuery(actorSystem) .readJournalFor[BakerPersistenceQuery](config.as[String]("baker.actor.read-journal-plugin"))