TIBCOSoftware / flogo-lib

Project Flogo Library
http://flogo.io
BSD 3-Clause "New" or "Revised" License
49 stars 33 forks source link

Activity.Init() #111

Open Adirio opened 6 years ago

Adirio commented 6 years ago

In this line it gets asked if activities should have an activity.Init() method.

I would love to re-raise this question as I consider it necessary. The same way a trigger usually holds the client inside one of its attributes and its shared accross multiple trigger.Start() calls, activities that send messages such as for example the MQTT activity that is missing from flogo-contrib should be able to share a client thus not requiring to stablish a connection every time it runs. Client initialization and connection creation should be done in the activity.Init() method.

fm-tibco commented 6 years ago

There is only one instance of a particular activity. The intent of an activity is to work as a stateless function. One of the reasons this was done was in the case of building a server, it would discourage classic server models and encourage cloud friendly servers. The less state in these objects the better. With activities designed in this way flows can be more easily shared. This approach would also make it easier to implement an arbitrary flow processing service in the cloud for example.

We do recognize that there is a need there and are looking to address it. It is good to have in a resource limited environment and even a server one where you want to avoid the constant creation of clients. One way to address your issue would be to have the notation of a "shared resource" that can be at the app or flow level. This could be a separate contribution that different types activities can share, for example an mqtt client . Another approach would be to possibly confine it to a particular activity type and the engine provides a means to pass this along to those activities when they are executed in a particular flow or app. We have created an github issue #113 to explore possible solutions to this problem without introducing the complexity of commercial products.

vijaynalawade commented 6 years ago

@Adirio A simple alternative solution would be a runtime connection cache that can be part of MQTT implementation. Based on connection info(may be URL), you can create a connection once and keep it in the cache and reuse it for every execution. This is a much cleaner approach(and you have better control as well) than an engine maintaining state of some sort for each activity type.

Adirio commented 6 years ago

Let's use as an example a CoAP to MQTT routing app assuming a shared resource cappability. A CoAP trigger would route different paths to different MQTT servers for example, so we would have multiple flows with an MQTT publish activity each. Let's imagine we are doing the following routing:

CoAP URI and method --> MQTT broker and topic

We would use 2 different MQTT clients for each of the MQTT brokers and 2 different flows for each of the CoAP methods. The flows will check if the clients are in the shared resources and if they aren't they would create them so that the flow that is instantiated after will see the clients are already created and won't need to do it itself.

This functionality could be placed in the activity.Eval() method but that would mean that they are checking it every time an activity of that type gets triggered, while doing it in a activity.Init() method has more sense as it will only have to do it once and then you can assume that they are ready for activity.Eval().

Summing up: Only being able to act over the shared resources and keeping the activities stateless seems reasonable but I still see room for an activity.Init() method.

As an additional note, the state of an activity will actually be some kind of shared resource among all the tasks executed by that activity, if there is an interest in giving an equivalent to scopes for the shared resources, there could be a app scope, a flow scope and a activity scope.