activities.Factory
¿Why do the triggers follow the Factory pattern and the activities instead just use a constructor method?
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.
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.
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.
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.
-
App = {ti, ai, m, AI}wheretiis the set of all trigger instances,aiis the set of all action instances,mthe set of all mappings andAIthe set of all activity instances..
- Triggers:
-
ti implements twheretis the set of all trigger types. -
size(t) = NwhereNis the ammount of trigger types. -
t = {t_1, t_2, ..., t_i, ..., t_N}wheret_iis the trigger typei. -
size(ti) = M = sum(i=(1=>N), M_i)whereMis the ammount of trigger instances of any type andM_ithe ammount of instances of typei. -
ti = {ti_(1,1), ..., ti_(i,j), ..., ti_(N,M_N)}whereti_(i,j)is the trigger instancejoft_i.
- Actions:
-
ai implemts awhereais the set of all action types. -
size(a) = OwhereOis the ammount of action types. -
a = {a_1, a_2, ..., a_k, ..., a_O}wherea_iis the action typek. -
size(ai) = P = sum(k=(1=>O),P_k)wherePis the ammount of action instances of any type andP_kthe ammount of instances of typek. -
ai = {ai_(1,1), ..., ai_(k,l), ..., ai_(O,P_O)}whereai_(k,l)is the action instancelofa_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.
-
size(m) = M -
m = {m_(1,1), ..., m_(i,j), ..., m_(N,M_N)}wherem_(i,j)is the set of relations of trigger instanceti_(i,j). -
m_(i,j) = {ti_(i,j), [ai]}where[ai]is a vector containing each of the actions that the triggerti_(i,j)starts.
- Activities:
-
AI implements AwhereAis the set of all activity types. -
size(A) = QwhereQis the ammount of activity types. -
A = {A_1, A_2, ..., A_m, ..., A_Q}whereA_mis the activity typem. -
size(AI) = Q -
AI = {AI_1, AI_2, ..., AI_m, ..., AI_Q}whereAI_mis the activity instance ofA_m.
- Each action instance is made up of tasks that are executed by the (method
activity.Eval(metada *activity.Metadata) activity.Activityof the) activities instancesAI:
-
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)]whereT_(k,l,n,m)is the tasknexecuted byAI_mbelonging toai_(k,l)andR_(k,l)is the ammount of tasks ofai_(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
-
size(a) = 1 -
a = {a_1} -
size(ai) = P = P_1 -
ai = {ai_1, ..., ai_l, ..., ai_,P}
- 20
-
ai_l = [T_(l,1,m), T_(l,2,m), ..., T_(l,n,m), ..., T_(l,R_(1,k),m)]
Answering to #111 I was not sure if the single activity instance was per App or per Flow/Action.