flogo-lib icon indicating copy to clipboard operation
flogo-lib copied to clipboard

activities.Factory

Open Adirio opened this issue 7 years ago • 5 comments

¿Why do the triggers follow the Factory pattern and the activities instead just use a constructor method?

Adirio avatar Oct 05 '17 08:10 Adirio

Currently there can be multiple instances of a trigger so we chose a factory pattern. There is only one instance of an activity and at the moment we do not need to inject anything into Activity so there was no need to impose a factory. For consistency we could look into enforcing a factory pattern.

fm-tibco avatar Oct 05 '17 15:10 fm-tibco

I don't get what you mean by single instance of activities. You could have as much as you want, can't you? For example 2 different CoAP activities sending messages to different servers.

As for the inject part, are you refering to the metadata? Because you are also injecting metadata to the activities through the constructor for the activities and through the factory for the triggers case.

I'm not trying to question your design, jsut trying to understand it.

Adirio avatar Oct 05 '17 19:10 Adirio

An activity object is only instantiated once in the engine, it is basically a singleton. All of the necessary data to execute it (which is described in the metadata) is sent along in the activity.Context when the Eval is executed. So essentially it is sort of like a function call.

We could enhance the interface in the future so that the fact that it behaves like a function call might be more clear... lets say for example:

Eval(context, inputs) (outputs, done, err)

The engine doesn't inject the metadata into an Activity, the activity provides it as a description of what are required inputs and subsequent outputs when it is called. Technically the activity implementation just has to implement activity.Activity and register itself. The CLI generates code to facilitate that registration if you adhere to providing a factory method "func NewActivity(metadata *activity.Metadata) activity.Activity" in your code, so we are kind of doing a factory by convention and not interface.

fm-tibco avatar Oct 05 '17 19:10 fm-tibco

NewActivity(metadata *activity.Metadata) activity.Activity is used by code auto-generated from the CLI to register the activity so that it can then be instantiated. I managed to find this in flogo-cli's code some time ago, as I wasn't finding where that method was being called. I must say that this approach is a bit unclear as it is not docummented.

This is one of the reasons I asked for a glossary. I'm gonna try to make a formal definition, correct whatever is not right or whatever is missing.

  • An application is a set of trigger instances and action instances, the mappings relating both and the activity instances that will execute the tasks that form an action instance.
  1. App = {ti, ai, m, AI} where ti is the set of all trigger instances, ai is the set of all action instances, m the set of all mappings and AI the set of all activity instances..
  • Triggers:
  1. ti implements t where t is the set of all trigger types.
  2. size(t) = N where N is the ammount of trigger types.
  3. t = {t_1, t_2, ..., t_i, ..., t_N} where t_i is the trigger type i.
  4. size(ti) = M = sum(i=(1=>N), M_i) where M is the ammount of trigger instances of any type and M_i the ammount of instances of type i.
  5. ti = {ti_(1,1), ..., ti_(i,j), ..., ti_(N,M_N)} where ti_(i,j) is the trigger instance j of t_i.
  • Actions:
  1. ai implemts a where a is the set of all action types.
  2. size(a) = O where O is the ammount of action types.
  3. a = {a_1, a_2, ..., a_k, ..., a_O} where a_i is the action type k.
  4. size(ai) = P = sum(k=(1=>O),P_k) where P is the ammount of action instances of any type and P_k the ammount of instances of type k.
  5. ai = {ai_(1,1), ..., ai_(k,l), ..., ai_(O,P_O)} where ai_(k,l) is the action instance l of a_k.
  • Each trigger instance starts any ammount of action instances. This may not be actual components of the application right now from a code perspective but are references in the config and will become more tangible components with future releases as explained in the first Flogo Happy Hour.
  1. size(m) = M
  2. m = {m_(1,1), ..., m_(i,j), ..., m_(N,M_N)} where m_(i,j) is the set of relations of trigger instance ti_(i,j).
  3. m_(i,j) = {ti_(i,j), [ai]} where [ai] is a vector containing each of the actions that the trigger ti_(i,j) starts.
  • Activities:
  1. AI implements A where A is the set of all activity types.
  2. size(A) = Q where Q is the ammount of activity types.
  3. A = {A_1, A_2, ..., A_m, ..., A_Q} where A_m is the activity type m.
  4. size(AI) = Q
  5. AI = {AI_1, AI_2, ..., AI_m, ..., AI_Q} where AI_m is the activity instance of A_m.
  • Each action instance is made up of tasks that are executed by the (method activity.Eval(metada *activity.Metadata) activity.Activity of the) activities instances AI:
  1. ai_(k,l) = [T_(k,l,1,m), T_(k,l,2,m), ..., T_(k,l,n,m), ..., T_(k,l,R_(1,k),m)] where T_(k,l,n,m) is the task n executed by AI_m belonging to ai_(k,l) and R_(k,l) is the ammount of tasks of ai_(k,l).

Equations 8-11 and 20 can be simplified due to the fact that there's only 1 action type, but being located in flogo-contrib suggests that there may be more action types in the future, thats why I sticked to the more general version. The simplified version would be:

  • 8-11
  1. size(a) = 1
  2. a = {a_1}
  3. size(ai) = P = P_1
  4. ai = {ai_1, ..., ai_l, ..., ai_,P}
  • 20
  1. ai_l = [T_(l,1,m), T_(l,2,m), ..., T_(l,n,m), ..., T_(l,R_(1,k),m)]

Adirio avatar Oct 06 '17 09:10 Adirio

Answering to #111 I was not sure if the single activity instance was per App or per Flow/Action.

Adirio avatar Oct 06 '17 10:10 Adirio