GithubHelp home page GithubHelp logo

ing-bank / baker Goto Github PK

View Code? Open in Web Editor NEW
320.0 21.0 84.0 170.87 MB

Orchestrate microservice-based process flows

Home Page: https://ing-bank.github.io/baker/

License: MIT License

Scala 87.25% Java 4.33% Shell 0.75% JavaScript 0.12% TypeScript 3.42% CSS 0.17% HTML 0.77% SCSS 0.24% Kotlin 2.93%
petri-net microservices serverless functions-as-a-service orchestration scala hacktoberfest

baker's People

Contributors

adilakhter avatar anubhav0712 avatar basdgrt avatar bekiroguz avatar jacum avatar jdin avatar jlengrand avatar jordymoos avatar kevinvandervlist avatar krisvandebroek avatar merlijn avatar nightscape avatar nikolakasev avatar p3trur0 avatar pausa avatar sander avatar sander-cb avatar scala-steward avatar stasimus avatar tim-linschoten avatar vledicfranco avatar wilmveel avatar winitzki avatar wwbakker avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

baker's Issues

More boilerplate needed when creating a Scala baker instance than for Java

To stick with the documentation when creating my first recipe I have been using the JBaker object.
However today I refactored the code to be full Scala.

Using JBaker

val baker = new JBaker(
      recipe,
      ImmutableList.<Interaction>of(
                ...
        );
    )

while using Baker directly requires more boilerplate

  implicit val timeout: FiniteDuration = new FiniteDuration(10, java.util.concurrent.TimeUnit.SECONDS)
    val baker = new Baker(
      recipe,
      implementations = Map(
        classOf[InteractionExample] -> (() => new InteractionExample()),
        ....
      ),
      actorSystem = ActorSystem.apply("BakerActorSystem", JBaker.defaultConfig)
    )

It would be nice to have a SBaker object, just like for Java, that avoids having to consider things like actorSystems and timeout.

Especially since those items are currently not part of the available documentation 👼

BakerResponse should support waiting until an event to happen

At the moment when an event is handled by baker, a BakerResponse object is returned, and it has 2 methods: confirmReceived and confirmCompleted.
In many cases, what we do is calling confirmCompleted, and in the next line looking for an event (eventually consistent) or an ingredient (consistent) to be available, and return a different http response accordingly.

And also the eventual consistency behaviour of the baker.events() is not easily guessed from the name, and not well known by many developers. This sometimes causes bugs due to misassumptions.

It would be nicer to add the possibility to wait until some event or some ingredient available when we call confirmReceived or confirmCompleted methods. Or maybe make a new method for that.

And the confirmation of the ingredient or event should be done synchronously (eventual consistency is not a good pattern here).

give better error message when null ingredient is produced

If SOMEEVENT produces an ingredient with null value, baker fails with the following message which is confusing:

Transition 'INTERACTIONNAME' failed with: com.ing.baker.runtime.petrinet.FatalInteractionException: Output: $$SOMEEVENT$$ fired by interaction INTERACTIONNAME but could not link it to any known event for the
 interaction\n      at com.ing.baker.runtime.petrinet.ReflectedInteractionTask$$anonfun$interactionTask$1.createRuntimeEvent$1(ReflectedInteractionTask.scala:109)\n        at com.ing.baker.
runtime.petrinet.ReflectedInteractionTask$$anonfun$interactionTask$1.apply(ReflectedInteractionTask.scala:125)\n       at com.ing.baker.runtime.petrinet.ReflectedInteractionTask$$anonfun$in
teractionTask$1.apply(ReflectedInteractionTask.scala:77)\n        at com.ing.baker.runtime.petrinet.TaskProvider$$anonfun$interactionTransitionTask$1$$anonfun$apply$2$$anonfun$apply$3.apply
(TaskProvider.scala:59)\n    at com.ing.baker.runtime.petrinet.TaskProvider$$anonfun$interactionTransitionTask$1$$anonfun$apply$2$$anonfun$apply$3.apply(TaskProvider.scala:59)\n    at fs2.T
ask$$anonfun$delay$1.apply(Task.scala:191)\n    at fs2.Task$$anonfun$delay$1.apply(Task.scala:191)\n    at fs2.Task$$anonfun$suspend$1$$anonfun$2.apply(Task.scala:199)\n       at fs2.Task$$
anonfun$suspend$1$$anonfun$2.apply(Task.scala:199)\n       at fs2.util.Attempt$.apply(Attempt.scala:12)\n  at fs2.Task$$anonfun$suspend$1.apply(Task.scala:199)\n  at fs2.Task$$anonfun$suspe
nd$1.apply(Task.scala:199)\n  at fs2.internal.Future.step(Future.scala:54)\n  at fs2.internal.Future.listen(Future.scala:30)\n        at fs2.internal.Future.runAsync(Future.scala:69)\n
      at fs2.Task.unsafeRunAsync(Task.scala:100)\n    at fs2.Task$Ref$$anonfun$set$1$$anonfun$apply$mcV$sp$1.apply$mcV$sp(Task.scala:343)\n   at fs2.Strategy$$anon$5$$anon$6.run(Strategy.sc
ala:60)\n        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\n    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\n
    at java.lang.Thread.run(Thread.java:748)\n 

ddata replication is extremely slow/intensive on node startup

Scenario:

  1. A new baker/akka node joins the cluster and is given some shards.
  2. The ProcessIndex actors for those shards are replayed.
  3. After replay, for every ProcessMetadata in the index an update is send to to ddata replicator.

This process is extremely slow/intensive and has been seen to even crash the node.

  • In case of shard is handover the index information is already know and should not have to be updated.
  • In case of cold boot, we need a method to add all ProcessMetadata in one Update to the replicator.

Baker should not add static field as Ingredients

Example :

public static final String REQUIRED_SIGNATURES = "requiredSignatures";
private final SignatureList requiredSignatures;

Constant is reused to lookup Ingredients in API (possibly not consistent with baker philosophy :), but since the result returned by the API varies with different events being present, there is already a dependency)

Change place/transition identifier types from Long to String

Places and Transitions in the petri net are currently identified by a Long number. This identifier is used in a number of commands and messages send to/from the ProcessInstance actor.

In hindsight this choice proved to be mistake because it is not easily used in the DSL or understandable by humans.

Also there is a potential hash collision problem since the id is not explicitly specified but computed from other properties.

In a Recipe interactions are given a "label" which is converted to a number using a hashcode function. Even tough a 64 bit SHA256 hashcode is used there can still be collisions.

The proposition is to re-use the "label" given to an interaction as it's transition identifier. The same goes for places.

Invalid V8 thread access

Hi Baker team!

I have just tried the latest release of Baker (1.1.14) and have noticed one issue with CompiledRecipe::getVisualRecipeAsSVG method. It looks like that because of graphviz-java this method can only be called from a single thread otherwise an exception is thrown:

java.lang.Error: Invalid V8 thread access
                at com.eclipsesource.v8.V8Locker.checkThread(V8Locker.java:56)
                at com.eclipsesource.v8.V8.checkThread(V8.java:676)
                at com.eclipsesource.v8.V8.executeStringScript(V8.java:499)
                at com.eclipsesource.v8.V8.executeStringScript(V8.java:483)
...

For now the workaround is to use smth like singlethreadexecutor and always call this method using it. But of course it would be nicer if you can handle it.

Kind regards,
Sergey

PS: Here you can find some more information about this exception.

provide sensible actor idle-timeout value in baker.conf

This is needed because enabling this feature could be easily forgotten by the API's which might lead to memory leaks because of growing number of actors in memory.

a suggestion could be using 5 minutes as a sensible default.

baker.actor.idle-timeout = 5 minutes

Duplicate place identifiers

Duplicate place identifiers are generated during compilation of a huge recipe. Can be reproduced by property based test suite.

Generated recipe ::: name: recipe-c1c8d3c2-db8f-4829-9db4-7ece702a2053 nrOfSensoryEvents: 31 nrOfInteractions: 55
Compiled recipe ::: name: recipe-c1c8d3c2-db8f-4829-9db4-7ece702a2053 nrOfAllIngredients: 14645 nrOfSensoryEvents: 31 nrOfInteractionEvents: 500 nrOfInteractions: 55
Validation errors: List(Duplicate identifier for: Place(-21729854,ingredient-26e86f42-09b5-49d2-a911-2afee69e3a6c,IngredientPlace) and Place(-21729854,interaction-004429de-6082-4979-b33c-6aad207ad5f9-ingredient-5044ed52-23c5-4a94-bb65-68c338bd5a0a,MultiTransitionPlace), Duplicate identifier for: Place(-21729854,interaction-004429de-6082-4979-b33c-6aad207ad5f9-ingredient-5044ed52-23c5-4a94-bb65-68c338bd5a0a,MultiTransitionPlace) and Place(-21729854,ingredient-26e86f42-09b5-49d2-a911-2afee69e3a6c,IngredientPlace), Duplicate identifier for: Place(1196063734,interaction-a77bf31c-bff8-4482-89b2-27a451c0f02a-ingredient-c496018d-892f-4bb8-9f01-9ded2a4beceb,MultiTransitionPlace) and Place(1196063734,interaction-26f6d826-d293-4096-9dea-ff4481a95a93-ingredient-bd7cb3ee-c5e8-488f-bdbd-b1eec5d6ba37,MultiTransitionPlace), Duplicate identifier for: Place(1196063734,interaction-26f6d826-d293-4096-9dea-ff4481a95a93-ingredient-bd7cb3ee-c5e8-488f-bdbd-b1eec5d6ba37,MultiTransitionPlace) and Place(1196063734,interaction-a77bf31c-bff8-4482-89b2-27a451c0f02a-ingredient-c496018d-892f-4bb8-9f01-9ded2a4beceb,MultiTransitionPlace))
Dumping the visual recipe ...

NullPointer in JBaker constructor when passing implementations

This affects the latest 1.3.3 and before.

When you attempt to construct a JBaker instance and pass the implementations directly like:

val implementations = ...
val jbaker = new JBaker(actorSystem, implementations)

You will get a NullPointerException, this is because the baker proxy is initialised too late in the constructor.

fix the unhandled messages in event listener subscriber actor

Whenever baker event handler subscriber actor receives the following event, it is considered as unhandled and published to the akka event bus as an error case. This event should be handled properly and maybe ignored just to prevent these debug messages.

Inside Baker.registerEventListener function:

ProcessInstanceEvent(processType, processId, event: InitializedEvent[,,_])

Unclear that events from multiple interactions work with AND condition.

If and event can be fired from multiple interactions it is only fired into the decision model (petri-net) if all interactions have provided this event.
In the event list the event is still found even if the event will not be fired for the petri-net.

This is unclear for the users of Baker. They expect this to be a OR condition.
We should make this as the user expect by doing one the following:

  1. Make it a OR condition
  2. Disallow having multiple interactions fire the same event in the compiler.

Improve readability of duration of scheduled retry log entries

In ProcessInstance we log when we schedule a transition for retry.

Currently you will see these kind of log entries:

Scheduling a retry of transition 'SomeInteraction' in 6400 milliseconds
Scheduling a retry of transition 'SomeInteraction' in 12800 milliseconds
Scheduling a retry of transition 'SomeInteraction' in 25600 milliseconds

The format is not really human readable, it only uses milliseconds.

It would be nice to convert it to seconds, minutes, hours etc.. to be better understandable.

Provide an example of the DSL in your README

Hi

I followed a link to this project from a newsletter and was surprised to realize that the README mentions recipes only as images but never actually shows the DSL to reproduce those recipes. I tried to find an example in the test code but couldn't figure it out within 5 minutes.

I think it would really help people evaluating your library if you have a coupe of code examples in the README.

Baker should add fields in event superclass as Ingredients

This works :

`
public class SignatureEnrolled {

@Data
public static class NeedMoreSignature extends SignatureEnrolled {
    //should ensure that type and name is the same in both subclasses, but Baker does not seem
    // to find fields in super class
    private final SignatureList enrolledSignatures;
}

@Data
public static class AllRequiredSignatureObtained extends SignatureEnrolled {
    private final SignatureList enrolledSignatures;
}

}
`

That doesnt

`
@DaTa
public class SignatureEnrolled {
private final SignatureList enrolledSignatures;

public class NeedMoreSignature extends SignatureEnrolled {
    public NeedMoreSignature(SignatureList enrolledSignatures) {
        super(enrolledSignatures);
    }
}

public class AllRequiredSignatureObtained extends SignatureEnrolled {
    public AllRequiredSignatureObtained(SignatureList enrolledSignatures) {
        super(enrolledSignatures);
    }
}

}
`

Baker metrics

We should report metrics that users of Baker could be interested in.

To decide:

  • Which framework, codahale metrics?
  • Which metrics, for example: interaction execution time.

primitive ingredient types are not supported

When an event provides an ingredient of type primitive 'boolean' and this event is fired, baker throws a FatalInteractionException with this message:
ERROR c.i.b.runtime.petrinet.TaskProvider - Output: fired by interaction but could not link it to any known event for the interaction

This is not nice to have at runtime. We should either do not support primitive data types and fail during recipe compilation or support it and fix this problem.

Allow custom converters to/from baker type system

The existing supported types should also be refactored to this system.

Since this conversion code is statically referenced the converters must be added statically as well.

We can do this by registering extensions in a reference.conf:

baker.types {
  "com.example.MyClass" = "com.example.MyCustomConverter"
}

with com.example.MyCustomConverter something along the lines of:

public class MyCustomConverter extends TypeConverter[MyClass] {
  def typeOf(clazz: Class[MyClass]): Type = ???
  def to(value: Value): MyClass = ???
  def from(value: MyClass): Value = ???
}

Join akka cluster after persistence warmup actor succeeds to start

In case there's no connection to any local cassandra nodes, this warmup actor times out but baker already started the actor system and joined the akka cluster which means, started already receiving actor messages, sharding region handover messages, etc... And these will all fail because there's no connection to local cassandra nodes in local data center.

Joining to cluster should be done after successfully connecting to cassandra, which could be done by hooking into the warmup actor status...

When configuring retry with exhausted event on Recipe level the exhausted event is not added to the possible outcomes of the interactions

When configuring retry with exhausted event on Recipe level the exhausted event is not added to the possible outcomes of the interactions.

We should not allow setting retry with exhausted events on recipe level because the exhausted event is then shared between interactions.
Or we should have a standarized event name for each interactions failure event so they do not overlap.

upgrade akka-persistence-cassandra 0.54 => 0.58

This is needed because of unhandled Request(16) messages coming from the akka eventsByPersistenceId query module which depends on akka streams. The new version of the library does not use these messages, so an upgrade might fix these annoying debug log lines:

DEBUG akka.actor.RepointableActorRef - unhandled message from Actor[akka://actorsystem/deadLetters]: Request(16)

problem with the sensory events with maxFireLimit config

When baker fires a sensory event 2nd time with a maxFireLimit set, getEvents call fails with the following stack trace:

2017-09-22 11:49:27,213 [DOCA-akka.actor.default-dispatcher-3] [] INFO  akka.actor.RepointableActorRef - Message [akka.persistence.cassandra.query.QueryActorPublisher$Finished] from Actor[akka://DOCA/user/StreamSupervisor-3/flow-903-1-currentEventsByPersistenceId-process-DigitalOnboarding-c65c77b3-513a-4a32-b24c-bcd6985c8830#400218330] to Actor[akka://DOCA/user/StreamSupervisor-3/flow-903-1-currentEventsByPersistenceId-process-DigitalOnboarding-c65c77b3-513a-4a32-b24c-bcd6985c8830#400218330] was not delivered. [6] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
2017-09-22 11:50:11,993 [tomcat-http--22] [c65c77b3-513a-4a32-b24c-bcd6985c8830] ERROR n.i.r.p.r.p.e.RuntimeExceptionHandlingMapper - Caught RuntimeException from application with exception:
java.lang.IllegalStateException: No element found with id: 651199937733138216
        at com.ing.baker.petrinet.api.package$IdentifiableOps$$anonfun$getById$1.apply(package.scala:38)
        at com.ing.baker.petrinet.api.package$IdentifiableOps$$anonfun$getById$1.apply(package.scala:38)
        at scala.Option.getOrElse(Option.scala:121)
        at com.ing.baker.petrinet.api.package$IdentifiableOps.getById(package.scala:38)
        at com.ing.baker.runtime.actor.serialization.ProtobufSerialization$$anonfun$com$ing$baker$runtime$actor$serialization$ProtobufSerialization$$deserializeConsumedMarking$1.apply(ProtobufSerialization.scala:116)
        at com.ing.baker.runtime.actor.serialization.ProtobufSerialization$$anonfun$com$ing$baker$runtime$actor$serialization$ProtobufSerialization$$deserializeConsumedMarking$1.apply(ProtobufSerialization.scala:114)
        at scala.collection.TraversableOnce$$anonfun$foldLeft$1.apply(TraversableOnce.scala:157)
        at scala.collection.TraversableOnce$$anonfun$foldLeft$1.apply(TraversableOnce.scala:157)
        at scala.collection.Iterator$class.foreach(Iterator.scala:891)
        at scala.collection.AbstractIterator.foreach(Iterator.scala:1334)
        at scala.collection.IterableLike$class.foreach(IterableLike.scala:72)
        at scala.collection.AbstractIterable.foreach(Iterable.scala:54)
        at scala.collection.TraversableOnce$class.foldLeft(TraversableOnce.scala:157)
        at scala.collection.AbstractTraversable.foldLeft(Traversable.scala:104)
        at com.ing.baker.runtime.actor.serialization.ProtobufSerialization.com$ing$baker$runtime$actor$serialization$ProtobufSerialization$$deserializeConsumedMarking(ProtobufSerialization.scala:114)
        at com.ing.baker.runtime.actor.serialization.ProtobufSerialization$$anonfun$deserializeTransitionFired$1.apply(ProtobufSerialization.scala:197)
        at com.ing.baker.runtime.actor.serialization.ProtobufSerialization$$anonfun$deserializeTransitionFired$1.apply(ProtobufSerialization.scala:195)
        at com.ing.baker.runtime.actor.ProcessQuery$$anonfun$eventsForInstance$1.apply(ProcessQuery.scala:33)
        at com.ing.baker.runtime.actor.ProcessQuery$$anonfun$eventsForInstance$1.apply(ProcessQuery.scala:30)
        at akka.stream.impl.fusing.Scan$$anon$14.onPush(Ops.scala:393)
        at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:499)
        at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:401)
        at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:571)
        at akka.stream.impl.fusing.GraphInterpreterShell$AsyncInput.execute(ActorGraphInterpreter.scala:457)
        at akka.stream.impl.fusing.GraphInterpreterShell.processEvent(ActorGraphInterpreter.scala:546)
        at akka.stream.impl.fusing.ActorGraphInterpreter.akka$stream$impl$fusing$ActorGraphInterpreter$$processEvent(ActorGraphInterpreter.scala:725)
        at akka.stream.impl.fusing.ActorGraphInterpreter.akka$stream$impl$fusing$ActorGraphInterpreter$$shortCircuitBatch(ActorGraphInterpreter.scala:715)
        at akka.stream.impl.fusing.ActorGraphInterpreter$$anonfun$receive$1.applyOrElse(ActorGraphInterpreter.scala:741)
        at akka.actor.Actor$class.aroundReceive(Actor.scala:514)
        at akka.stream.impl.fusing.ActorGraphInterpreter.aroundReceive(ActorGraphInterpreter.scala:650)
        at akka.actor.ActorCell.receiveMessage(ActorCell.scala:527)
        at akka.actor.ActorCell.invoke(ActorCell.scala:496)
        at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257)
        at akka.dispatch.Mailbox.run(Mailbox.scala:224)
        at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
        at akka.dispatch.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
        at akka.dispatch.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
        at akka.dispatch.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
        at akka.dispatch.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
2017-09-22 11:50:12,009 [DOCA-akka.actor.default-dispatcher-4] [] INFO  akka.actor.RepointableActorRef - Message [akka.persistence.cassandra.query.QueryActorPublisher$Finished] from Actor[akka://DOCA/user/StreamSupervisor-3/flow-905-1-currentEventsByPersistenceId-process-DigitalOnboarding-c65c77b3-513a-4a32-b24c-bcd6985c8830#391973354] to Actor[akka://DOCA/user/StreamSupervisor-3/flow-905-1-currentEventsByPersistenceId-process-DigitalOnboarding-c65c77b3-513a-4a32-b24c-bcd6985c8830#391973354] was not delivered. [7] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.

baker compilation should fail if there are non-reachable interactions

During PBT of the recipe runtime, it is found that some generated recipes have interactions that can never be executed because their input ingredients are coming from separate events which are mutual exclusively fired. So, only one of them can fire at a time, therefore the interaction requirements never satisfy. These kinds of recipes should be already caught during compilation.
See this example: Interaction 'kcrt6yzk' is unreachable.

screen shot 2017-07-24 at 16 36 45

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.