factor 0.1.09 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+
3
+ module Factor
4
+ module Channel
5
+ class Listener
6
+ attr_accessor :workflow_id, :event
7
+
8
+ def start(params,&code)
9
+ end
10
+
11
+ def stop()
12
+ end
13
+
14
+ def initialize(workflow_id,event)
15
+ @workflow_id=workflow_id
16
+ @event=event
17
+ end
18
+ end
19
+ end
20
+ end
@@ -11,11 +11,26 @@ module Factor
11
11
  puts "starting workflow #{workflow_name} with options #{options.parameters.to_s}"
12
12
 
13
13
  engine = Factor::Runtime::Engine.new(get_config[:email],get_config[:token])
14
- id = engine.launch(workflow_name,options.parameters)
14
+ id = engine.send_start_workflow(workflow_name,options.parameters)
15
15
 
16
16
  puts "workflow executed with id #{id}"
17
17
  end
18
18
 
19
+ desc "listen WORKFLOW","start listener for workflow"
20
+ def listen(workflow_name)
21
+ puts "starting listener #{workflow_name}"
22
+
23
+ engine = Factor::Runtime::Engine.new(get_config[:email],get_config[:token])
24
+ engine.send_start_listener(workflow_name)
25
+ end
26
+
27
+ desc "stop WORKFLOW","stop listener for workflow"
28
+ def stop(workflow_name)
29
+ puts "starting listener #{workflow_name}"
30
+
31
+ engine = Factor::Runtime::Engine.new(get_config[:email],get_config[:token])
32
+ engine.send_stop_listener(workflow_name)
33
+ end
19
34
 
20
35
 
21
36
  desc "list", "list all the workflows"
@@ -7,16 +7,17 @@ require 'mustache'
7
7
  module Factor
8
8
  module Runtime
9
9
  class Engine
10
- attr_accessor :channel_modules, :workflows, :message_bus
10
+ attr_accessor :channel_modules, :workflows, :message_bus, :listeners
11
11
 
12
12
  # Engine needs modules that contain the code, workflows to run, and message bus for communication
13
13
  def initialize(username,token)
14
- @channel_modules=Hash.new
15
- @channel_definitions=Array.new
16
- @workflows = Hash.new
14
+ @channel_modules={}
15
+ @channel_definitions=[]
16
+ @workflows = {}
17
17
  @message_bus = MessageBus.new(username,token)
18
- @credentials = Hash.new
19
- @tags = Hash.new
18
+ @credentials = {}
19
+ @tags = {}
20
+ @listeners={}
20
21
  end
21
22
 
22
23
  def tag(key,value)
@@ -38,7 +39,14 @@ module Factor
38
39
  end
39
40
 
40
41
  def load_credentials credentials,secret=nil
41
- @credentials["credentials"] = credentials
42
+ credentials.each do |service_name,services|
43
+ @credentials[service_name] = {} if !@credentials.include?(service_name)
44
+ services.each do |credential_name,credential|
45
+ @credentials[service_name][credential_name] = credential["value"]
46
+ end
47
+ end
48
+
49
+ # @credentials["credentials"] = credentials
42
50
  end
43
51
 
44
52
  # adds the workflow to the workflows list
@@ -55,11 +63,11 @@ module Factor
55
63
  end
56
64
  end
57
65
 
58
- def launch workflow, params, keep_open=false
66
+ def send_start_workflow workflow, params, keep_open=false
59
67
  instance_id=SecureRandom.hex
60
68
 
61
69
  @message_bus.start do
62
- message = Message.new
70
+ message = WorkflowStepMessage.new
63
71
  message.position << "start"
64
72
  message.workflow=workflow
65
73
  message.add_values params
@@ -68,51 +76,116 @@ module Factor
68
76
  end
69
77
  instance_id
70
78
  end
79
+
80
+ def send_start_listener workflow_name, keep_open=false
81
+ @message_bus.start do
82
+ message = ListenerMessage.new("start",workflow_name)
83
+ @message_bus.send message, !keep_open
84
+ end
85
+ end
86
+
87
+ def send_stop_listener workflow_name, keep_open=false
88
+ @message_bus.start do
89
+ message = ListenerMessage.new("stop",workflow_name)
90
+ @message_bus.send message, !keep_open
91
+ end
92
+ end
71
93
 
72
94
  # start your engines. vroom vrooooom!
73
95
  def start
74
96
  begin
75
97
  @message_bus.start do
76
- @message_bus.listen do |message|
77
- if @workflows.include? message.workflow
78
- workflow = @workflows[message.workflow]
79
- activity = workflow.get_activity(message.position)
98
+ @message_bus.listen("listener") do |payload|
99
+ message = ListenerMessage.new
100
+ message.from_queue(payload)
101
+
102
+ listener=@workflows[message.workflow].definition["listener"]
103
+ params = render_template(listener["params"],@credentials)
104
+
105
+ if message.command=="start"
106
+ start_listening(listener["channel"],listener["name"],listener["event"],message.workflow,params)
107
+ else
108
+ stop_listening(listener["channel"],listener["name"],listener["event"],message.workflow)
109
+ end
110
+ end
111
+
112
+ @message_bus.listen("workflow") do |payload|
113
+ step = WorkflowStepMessage.new
114
+ step.from_queue(payload)
115
+ if @workflows.include? step.workflow
116
+ workflow = @workflows[step.workflow]
117
+ activity = workflow.get_activity(step.position)
80
118
  if !activity.nil?
81
119
  action = activity["action"]
82
120
  channel = activity["channel"]
83
121
  target = activity["target"]
84
122
  params_template = activity["params"]
85
-
86
- # if match(target)
87
- values = message.body.merge(@credentials)
123
+
124
+ # if match(target)
125
+ values = step.body.merge(@credentials)
126
+ # puts "Values: #{values.inspect}"
88
127
 
89
- # this maps the input values passed in with the templated defined in the workflow
90
- params = render_template(params_template,values)
91
- event = call_channel_method(channel,action,params)
92
- response_message = message.respond(event.params,event.class.name.split("::").last)
128
+ # this maps the input values passed in with the templated defined in the workflow
129
+ params = render_template(params_template,values)
130
+ puts "content: #{params}"
131
+ event = call_channel_method(channel,action,params)
132
+ response_message = step.respond(event.params,event.class.name.split("::").last)
93
133
 
94
- @message_bus.send response_message
134
+ @message_bus.send response_message
95
135
  # end
136
+ else
137
+ puts "[error] no activity found for position '#{step.position}'"
96
138
  end
97
139
  else
98
140
  # workflow doesn't exist
141
+ puts "[warning] '#{step.workflow}' workflow wasn't found"
99
142
  end
100
143
  end
101
144
  end
102
145
  rescue SystemExit, Interrupt
103
- "done"
146
+ puts "done"
104
147
  rescue Exception => ex
105
- ex
148
+ puts ex
106
149
  end
107
150
  end
108
151
 
109
152
  def call_channel_method(channel_name,action_name,params)
110
153
  channel_module_name = get_channel_module(channel_name)
111
154
  channel_module = @channel_modules[channel_module_name]
112
- action_class = get_action_class(channel_name,action_name)
113
- command = channel_module.const_get(action_class)
155
+ action_class_name = get_class_name("actions",channel_name,action_name)
156
+ command = channel_module.const_get(action_class_name)
114
157
  command.new.do_work(params)
115
158
  end
159
+
160
+ def start_listening(channel_name,listener_name,event,workflow_name,params)
161
+ channel_module_name = get_channel_module(channel_name)
162
+ channel_module = @channel_modules[channel_module_name]
163
+ listener_class_name = get_class_name("listeners",channel_name,listener_name)
164
+ command = channel_module.const_get(listener_class_name)
165
+ job_info = {:channel_name=>channel_name,:listener_name=>listener_name,:workflow_name=>workflow_name,:event=>event}.to_json
166
+
167
+ @job = Thread.new do
168
+ puts "Creating listener #{channel_name}::#{listener_name} on event '#{event}' => #{workflow_name}"
169
+ listener=command.new(workflow_name,event)
170
+
171
+ puts "Starting listener thread #{params}"
172
+ listener.start params do |event_params|
173
+ send_start_workflow workflow_name, event_params
174
+ end
175
+ end
176
+ @listeners[job_info]=@job
177
+ end
178
+
179
+ def stop_listening(channel_name,listener_name,event,workflow_name)
180
+ # channel_module_name = get_channel_module(channel_name)
181
+ # channel_module = @channel_modules[channel_module_name]
182
+ # listener_class = get_class_name("listeners",channel_name,listener_name)
183
+ # command = channel_module.const_get(listener_name)
184
+ job_info = {:channel_name=>channel_name,:listener_name=>listener_name,:workflow_name=>workflow_name,:event=>event}.to_json
185
+
186
+ @listeners[job_info].kill if @listeners.include?(job_info)
187
+
188
+ end
116
189
 
117
190
  private
118
191
 
@@ -120,11 +193,31 @@ module Factor
120
193
  @channel_definitions.select { |channel_definition| channel_definition['name']==channel_name }.first['module_name']
121
194
  end
122
195
 
123
- def get_action_class(channel_name,action_name)
196
+ # def get_action_class(channel_name,action_name)
197
+ # @channel_definitions.each do |channel_definition|
198
+ # if channel_definition['name']==channel_name
199
+ # channel_definition['actions'].each do |action|
200
+ # return action["class_name"] if action['name']==action_name
201
+ # end
202
+ # end
203
+ # end
204
+ # end
205
+
206
+ # def get_listener_class(channel_name,listener_name)
207
+ # @channel_definitions.each do |channel_definition|
208
+ # if channel_definition['name']==channel_name
209
+ # channel_definition['listeners'].each do |listener|
210
+ # return listener["class_name"] if listener['name']==listener_name
211
+ # end
212
+ # end
213
+ # end
214
+ # end
215
+
216
+ def get_class_name(type,channel_name,class_name)
124
217
  @channel_definitions.each do |channel_definition|
125
218
  if channel_definition['name']==channel_name
126
- channel_definition['actions'].each do |action|
127
- return action["class_name"] if action['name']==action_name
219
+ channel_definition[type].each do |definition|
220
+ return definition["class_name"] if definition['name']==class_name
128
221
  end
129
222
  end
130
223
  end
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+ require 'json/ext'
3
+
4
+ module Factor
5
+ module Runtime
6
+ class ListenerMessage
7
+ attr_accessor :command,:workflow
8
+ def initialize(command=nil,workflow=nil)
9
+ @command=command
10
+ @workflow=workflow
11
+ end
12
+
13
+
14
+ def route
15
+ # "#{workflow}.#{position.join('.')}"
16
+ "listener"
17
+ end
18
+
19
+ def payload
20
+ JSON.generator = JSON::Ext::Generator
21
+ obj = {"command"=>@command, "workflow"=>@workflow}
22
+ JSON.generate(obj)
23
+ end
24
+
25
+ def from_queue payload
26
+ message=JSON.parse(payload)
27
+ @command=message["command"]
28
+ @workflow=message["workflow"]
29
+ end
30
+ # def from_queue payload
31
+ #
32
+ # @workflow = message["workflow"]
33
+ # @position=message["position"]
34
+ # @body=message["body"]
35
+ # @workflow_instance_id=message["workflow_instance_id"]
36
+ # @step_id=message["step_id"]
37
+ # @last_step_id=message["last_step_id"]
38
+ # end
39
+
40
+ end
41
+ end
42
+ end
@@ -18,7 +18,7 @@ module Factor
18
18
  # Creates the connection and creates a topic exchange
19
19
  # An exchange references a place to send messages to
20
20
  # the exchange routes it to the queues based on the route_key
21
- def start(topic="workflow",&code)
21
+ def start(topic="factor",&code)
22
22
  EventMachine.run do
23
23
  #connection_settings={:host=>@host,:user=>@username,:password=>@token,:vhost=>@vhost}
24
24
  connection_settings={:host=>@host}
@@ -36,15 +36,14 @@ module Factor
36
36
  @queue.bind(@exchange, :routing_key=>routing_key) # bind queue to the Exchange
37
37
 
38
38
  @queue.subscribe do |headers,payload|
39
- message = Message.new
40
- message.from_queue headers.routing_key, payload
41
- puts "[Received Message (#{message.route})] #{message.body.inspect}"
42
- code.call(message)
39
+ # code.call(headers.routing_key,payload)
40
+ puts "[Received Message (#{headers.routing_key})] #{payload.inspect}"
41
+ code.call(payload)
43
42
  end
44
43
  end
45
44
 
46
45
  def send(message,close=false)
47
- puts "[Sending Message (#{message.route})] #{message.body.inspect}"
46
+ puts "[Sending Message (#{message.route})] #{message.payload.inspect}"
48
47
  @exchange.publish(message.payload,:routing_key => message.route)
49
48
  EM.add_timer(1, Proc.new { close}) if close
50
49
  end
@@ -3,20 +3,20 @@ require 'json/ext'
3
3
 
4
4
  module Factor
5
5
  module Runtime
6
- class Message
7
- attr_accessor :body, :workflow, :workflow_instance_id, :activity_instance_id, :last_activity_instance_id, :position
6
+ class WorkflowStepMessage
7
+ attr_accessor :body, :workflow, :workflow_instance_id, :step_id, :last_step_id, :position
8
8
  def initialize
9
- @activity_instance_id=SecureRandom.hex
10
- @workflow = workflow
9
+ @step_id=SecureRandom.hex
10
+ # @workflow = workflow
11
11
  @body = Hash.new
12
12
  @position = Array.new
13
13
  end
14
14
 
15
15
  def respond(params, event)
16
- m = Message.new
16
+ m = WorkflowStepMessage.new
17
17
  m.body = @body
18
18
  m.workflow_instance_id=@workflow_instance_id
19
- m.last_activity_instance_id = @activity_instance_id
19
+ m.last_step_id = @step_id
20
20
  m.workflow = @workflow
21
21
  m.position = @position
22
22
  m.position << "on"
@@ -25,11 +25,9 @@ module Factor
25
25
  m
26
26
  end
27
27
 
28
-
29
28
  def add_values(values)
30
29
  current=@body
31
30
  position.each do |key|
32
- #puts "[add value] #{key} (#{key.class.name})"
33
31
  current[key]={} if !current.include?(key)
34
32
  current=current[key]
35
33
  end
@@ -40,25 +38,24 @@ module Factor
40
38
  end
41
39
 
42
40
  def route
43
- "#{workflow}.#{position.join('.')}"
41
+ # "#{workflow}.#{position.join('.')}"
42
+ "workflow"
44
43
  end
45
44
 
46
45
  def payload
47
46
  JSON.generator = JSON::Ext::Generator
48
- obj = {"body"=>@body, "workflow_instance_id"=>@workflow_instance_id, "activity_instance_id"=>@activity_instance_id, "last_activity_instance_id"=>@last_activity_instance_id}
47
+ obj = {"body"=>@body, "workflow_instance_id"=>@workflow_instance_id, "step_id"=>@step_id, "last_step_id"=>@last_step_id, "workflow"=>@workflow,"position"=>@position}
49
48
  JSON.generate(obj)
50
49
  end
51
50
 
52
- def from_queue routing_key, payload
53
- routing_array=routing_key.split('.')
54
- @workflow=routing_array.first #first
55
- @position=routing_array.drop(1) # everything after first
56
-
51
+ def from_queue payload
57
52
  message=JSON.parse(payload)
53
+ @workflow = message["workflow"]
54
+ @position=message["position"]
58
55
  @body=message["body"]
59
56
  @workflow_instance_id=message["workflow_instance_id"]
60
- @activity_instance_id=message["activity_instance_id"]
61
- @last_activity_instance_id=message["last_activity_instance_id"]
57
+ @step_id=message["step_id"]
58
+ @last_step_id=message["last_step_id"]
62
59
  end
63
60
 
64
61
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: factor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.09
4
+ version: 0.1.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-21 00:00:00.000000000 Z
12
+ date: 2013-02-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -133,6 +133,7 @@ files:
133
133
  - lib/channel/activity.rb
134
134
  - lib/channel/channel.rb
135
135
  - lib/channel/event.rb
136
+ - lib/channel/listener.rb
136
137
  - lib/channel/trigger.rb
137
138
  - lib/cli/channel_task.rb
138
139
  - lib/cli/command.rb
@@ -144,10 +145,11 @@ files:
144
145
  - lib/factor.rb
145
146
  - lib/runtime/attributes.rb
146
147
  - lib/runtime/engine.rb
147
- - lib/runtime/message.rb
148
+ - lib/runtime/listener_message.rb
148
149
  - lib/runtime/message_bus.rb
149
150
  - lib/runtime/workflow.rb
150
151
  - lib/runtime/workflow_instance.rb
152
+ - lib/runtime/workflow_step_messsage.rb
151
153
  - bin/factor
152
154
  homepage: http://rubygems.org/gems/factor
153
155
  licenses: []