glider 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4aa4101f0537f562aa326ba31408d9ff2035b08a
4
+ data.tar.gz: 9cf46b6473470aa0029b7b599c8b98763c228abb
5
+ SHA512:
6
+ metadata.gz: 14458f9f29b9c9f1ab8032d73ae189811c1cfe6448a7e5b712545df7764783ca301ba722defe2076950d6e32f0109b602162e7b697b25293a5b068ac3f39879f
7
+ data.tar.gz: 72306154571324a022b22c3e09ddee1778602b4362e8cf985dee25e8e9a74f7a71803aa6fe2f3d600938b4c6447121bad60025ad5990b026ba27730efe6601f4
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'pry'
4
+ gem 'aws-sdk'
5
+ gem 'colorize'
6
+ gem 'activesupport', '~> 4.0.1', require: 'active_support/inflector'
data/Gemfile.lock ADDED
@@ -0,0 +1,40 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ activesupport (4.0.1)
5
+ i18n (~> 0.6, >= 0.6.4)
6
+ minitest (~> 4.2)
7
+ multi_json (~> 1.3)
8
+ thread_safe (~> 0.1)
9
+ tzinfo (~> 0.3.37)
10
+ atomic (1.1.14)
11
+ aws-sdk (1.26.0)
12
+ json (~> 1.4)
13
+ nokogiri (>= 1.4.4, < 1.6.0)
14
+ uuidtools (~> 2.1)
15
+ coderay (1.0.9)
16
+ colorize (0.6.0)
17
+ i18n (0.6.5)
18
+ json (1.8.1)
19
+ method_source (0.8.2)
20
+ minitest (4.7.5)
21
+ multi_json (1.8.2)
22
+ nokogiri (1.5.10)
23
+ pry (0.9.12.2)
24
+ coderay (~> 1.0.5)
25
+ method_source (~> 0.8)
26
+ slop (~> 3.4)
27
+ slop (3.4.6)
28
+ thread_safe (0.1.3)
29
+ atomic
30
+ tzinfo (0.3.38)
31
+ uuidtools (2.1.4)
32
+
33
+ PLATFORMS
34
+ ruby
35
+
36
+ DEPENDENCIES
37
+ activesupport (~> 4.0.1)
38
+ aws-sdk
39
+ colorize
40
+ pry
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ Useful documentation links:
2
+
3
+ http://docs.aws.amazon.com/amazonswf/latest/apireference/API_RespondDecisionTaskCompleted.html
4
+
5
+ http://docs.aws.amazon.com/amazonswf/latest/apireference/API_HistoryEvent.html
6
+
7
+ http://docs.aws.amazon.com/amazonswf/latest/developerguide/swf-dev-workflow-exec-lifecycle.html
8
+
9
+ USEFUL TO DECIDE WHAT TO PASS TO THE METHOD
10
+
11
+ INFO 15:16:05 Starting workers for ["hello_world-1.0"] and ["say_hi-1.0"]
12
+ INFO 15:16:05 Startig worker for say_hi (class: MySWF)
13
+ INFO 15:16:42 Processing decision task workflow_id=bb235559-9ee6-4a80-96c5-9eed168046d5
14
+ INFO 15:16:42 say_hi event=workflow_execution_started data=ALOHA
15
+ WARN 15:16:42 No result for decision_task_scheduled, attributes: {:task_list=>"say_hi", :start_to_close_timeout=>5}
16
+ WARN 15:16:42 say_hi event=decision_task_scheduled data=
17
+ WARN 15:16:42 No result for decision_task_started, attributes: {:identity=>"dmb.local:49424", :scheduled_event_id=>2}
18
+ WARN 15:16:42 say_hi event=decision_task_started data=
19
+ WARN 15:16:42 No result for decision_task_timed_out, attributes: {:timeout_type=>"START_TO_CLOSE", :scheduled_event_id=>2, :started_event_id=>3}
20
+ WARN 15:16:42 say_hi event=decision_task_timed_out data=
21
+ WARN 15:16:42 No result for decision_task_scheduled, attributes: {:task_list=>"say_hi", :start_to_close_timeout=>5}
22
+ WARN 15:16:42 say_hi event=decision_task_scheduled data=
23
+ WARN 15:16:42 No result for decision_task_started, attributes: {:identity=>"dmb.local:49461", :scheduled_event_id=>5}
24
+ WARN 15:16:42 say_hi event=decision_task_started data=
25
+ DEBUG 15:16:42 [{:decision_type=>"CompleteWorkflowExecution", :complete_workflow_execution_decision_attributes=>{}}]
26
+
27
+ terminations dont trigger decisions
28
+
29
+
30
+ TODO:
31
+
32
+ Proces monitoring
33
+ activity task signaling
34
+
35
+ Exec scoped logger
36
+ instance methods
@@ -0,0 +1,129 @@
1
+
2
+ taken from docs.aws.amazon.com/amazonswf/latest/apireference/API_HistoryEvent.html
3
+
4
+
5
+ WorkflowExecutionStarted:
6
+ The workflow execution was started.
7
+
8
+ WorkflowExecutionCompleted:
9
+ The workflow execution was closed due to successful completion.
10
+
11
+ WorkflowExecutionFailed:
12
+ The workflow execution closed due to a failure.
13
+
14
+ WorkflowExecutionTimedOut:
15
+ The workflow execution was closed because a time out was exceeded.
16
+
17
+ WorkflowExecutionCanceled:
18
+ The workflow execution was successfully canceled and closed.
19
+
20
+ WorkflowExecutionTerminated:
21
+ The workflow execution was terminated.
22
+
23
+ WorkflowExecutionContinuedAsNew:
24
+ The workflow execution was closed and a new execution of the same type was created with the same workflowId.
25
+
26
+ WorkflowExecutionCancelRequested:
27
+ A request to cancel this workflow execution was made.
28
+
29
+ DecisionTaskScheduled:
30
+ A decision task was scheduled for the workflow execution.
31
+
32
+ DecisionTaskStarted:
33
+ The decision task was dispatched to a decider.
34
+
35
+ DecisionTaskCompleted:
36
+ The decider successfully completed a decision task by calling RespondDecisionTaskCompleted.
37
+
38
+ DecisionTaskTimedOut:
39
+ The decision task timed out.
40
+
41
+ ActivityTaskScheduled:
42
+ An activity task was scheduled for execution.
43
+
44
+ ScheduleActivityTaskFailed:
45
+ Failed to process ScheduleActivityTask decision. This happens when the decision is not configured properly, for example the activity type specified is not registered.
46
+
47
+ ActivityTaskStarted:
48
+ The scheduled activity task was dispatched to a worker.
49
+
50
+ ActivityTaskCompleted:
51
+ An activity worker successfully completed an activity task by calling RespondActivityTaskCompleted.
52
+
53
+ ActivityTaskFailed:
54
+ An activity worker failed an activity task by calling RespondActivityTaskFailed.
55
+
56
+ ActivityTaskTimedOut:
57
+ The activity task timed out.
58
+
59
+ ActivityTaskCanceled:
60
+ The activity task was successfully canceled.
61
+
62
+ ActivityTaskCancelRequested:
63
+ A RequestCancelActivityTask decision was received by the system.
64
+
65
+ RequestCancelActivityTaskFailed:
66
+ Failed to process RequestCancelActivityTask decision. This happens when the decision is not configured properly.
67
+
68
+ WorkflowExecutionSignaled:
69
+ An external signal was received for the workflow execution.
70
+
71
+ MarkerRecorded:
72
+ A marker was recorded in the workflow history as the result of a RecordMarker decision.
73
+
74
+ TimerStarted:
75
+ A timer was started for the workflow execution due to a StartTimer decision.
76
+
77
+ StartTimerFailed:
78
+ Failed to process StartTimer decision. This happens when the decision is not configured properly, for example a timer already exists with the specified timer Id.
79
+
80
+ TimerFired:
81
+ A timer, previously started for this workflow execution, fired.
82
+
83
+ TimerCanceled:
84
+ A timer, previously started for this workflow execution, was successfully canceled.
85
+
86
+ CancelTimerFailed:
87
+ Failed to process CancelTimer decision. This happens when the decision is not configured properly, for example no timer exists with the specified timer Id.
88
+
89
+ StartChildWorkflowExecutionInitiated:
90
+ A request was made to start a child workflow execution.
91
+
92
+ StartChildWorkflowExecutionFailed:
93
+ Failed to process StartChildWorkflowExecution decision. This happens when the decision is not configured properly, for example the workflow type specified is not registered.
94
+
95
+ ChildWorkflowExecutionStarted:
96
+ A child workflow execution was successfully started.
97
+
98
+ ChildWorkflowExecutionCompleted:
99
+ A child workflow execution, started by this workflow execution, completed successfully and was closed.
100
+
101
+ ChildWorkflowExecutionFailed:
102
+ A child workflow execution, started by this workflow execution, failed to complete successfully and was closed.
103
+
104
+ ChildWorkflowExecutionTimedOut:
105
+ A child workflow execution, started by this workflow execution, timed out and was closed.
106
+
107
+ ChildWorkflowExecutionCanceled:
108
+ A child workflow execution, started by this workflow execution, was canceled and closed.
109
+
110
+ ChildWorkflowExecutionTerminated:
111
+ A child workflow execution, started by this workflow execution, was terminated.
112
+
113
+ SignalExternalWorkflowExecutionInitiated:
114
+ A request to signal an external workflow was made.
115
+
116
+ ExternalWorkflowExecutionSignaled:
117
+ A signal, requested by this workflow execution, was successfully delivered to the target external workflow execution.
118
+
119
+ SignalExternalWorkflowExecutionFailed:
120
+ The request to signal an external workflow execution failed.
121
+
122
+ RequestCancelExternalWorkflowExecutionInitiated:
123
+ A request was made to request the cancellation of an external workflow execution.
124
+
125
+ ExternalWorkflowExecutionCancelRequested:
126
+ Request to cancel an external workflow execution was successfully delivered to the target execution.
127
+
128
+ RequestCancelExternalWorkflowExecutionFailed:
129
+ Request to cancel an external workflow execution failed.
data/lib/glider.rb ADDED
@@ -0,0 +1,11 @@
1
+ $LOAD_PATH << File.dirname(__FILE__)
2
+
3
+ require 'pry'
4
+
5
+ require 'glider/utils'
6
+
7
+ require 'glider/component'
8
+ require 'glider/process_manager'
9
+
10
+ require 'glider/workflows'
11
+ require 'glider/activities'
@@ -0,0 +1,69 @@
1
+ # isolates the common needed tasks of other elemtns
2
+
3
+ module Glider
4
+
5
+ class Component
6
+ class << self
7
+
8
+ def activities
9
+ @activities ||= []
10
+ end
11
+
12
+ def register_activity(name, version, options={})
13
+ default_options = {
14
+ :default_task_list => name.to_s,
15
+ :default_task_schedule_to_start_timeout => :none,
16
+ :default_task_start_to_close_timeout => 60,
17
+ :default_task_schedule_to_close_timeout => :none,
18
+ :default_task_heartbeat_timeout => :none
19
+
20
+ }
21
+
22
+ options = default_options.merge options
23
+
24
+ begin
25
+ activity_type = domain.activity_types.create name.to_s, version, options
26
+ rescue AWS::SimpleWorkflow::Errors::TypeAlreadyExistsFault
27
+ # already registered
28
+ activity_type = domain.activity_types[name.to_s, version]
29
+ end
30
+ workers.times do
31
+ ProcessManager.register_worker loop_block_for_activity(activity_type)
32
+ end
33
+ end
34
+
35
+
36
+
37
+ def loop_block_for_activity(activity_type)
38
+ Proc.new do
39
+ $0 = "ruby #{activity_type.name}-#{activity_type.version}"
40
+ signal_handling
41
+ Glider.logger.info "Startig worker for #{activity_type.name} activity (pid #{Process.pid})"
42
+ begin
43
+ domain.activity_tasks.poll activity_type.name do |activity_task|
44
+ task_lock! do
45
+ begin
46
+ workflow_id = activity_task.workflow_execution.workflow_id
47
+ Glider.logger.info "Executing activity=#{activity_type.name} workflow_id=#{workflow_id}"
48
+ target_instance = self.new activity_task
49
+ activity_result = target_instance.send activity_type.name, activity_task.input
50
+ activity_task.complete! result: activity_result.to_s
51
+ rescue AWS::SimpleWorkflow::ActivityTask::CancelRequestedError
52
+ # cleanup after ourselves
53
+ activity_task.cancel!
54
+ end
55
+ end
56
+ end
57
+ rescue AWS::SimpleWorkflow::Errors::UnknownResourceFault
58
+ $logger.error "An action relating to an expired workflow was sent. Probably the activity took longer than the execution timeout span. Killing activity process."
59
+ exit 1
60
+ end
61
+ end
62
+ end
63
+
64
+
65
+ end
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,67 @@
1
+ # isolates the common needed tasks of other elemtns
2
+
3
+ module Glider
4
+
5
+ class Component
6
+
7
+ attr_reader :task, :event
8
+
9
+ def initialize(task, event=nil)
10
+ @task = task
11
+ @event = event
12
+ end
13
+
14
+
15
+ class << self
16
+
17
+ def task_lock!
18
+ @in_task = true
19
+ yield
20
+ ensure
21
+ @in_task = false
22
+ Process.exit! 0 if @time_to_exit # in case an exit signal was received during task processing
23
+ end
24
+
25
+ def graceful_exit
26
+ if @in_task
27
+ @time_to_exit = true
28
+ else
29
+ Process.exit! 0
30
+ end
31
+ end
32
+
33
+ def signal_handling
34
+ Signal.trap('USR1') do
35
+ graceful_exit
36
+ end
37
+ end
38
+
39
+ def swf
40
+ @swf ||= AWS::SimpleWorkflow.new
41
+ end
42
+
43
+ # both setter and getter
44
+ def workers(workers_count=nil)
45
+ workers_count ? @workers = workers_count : @workers ||= 1
46
+ end
47
+
48
+ # both setter and getter
49
+ def domain(domain_name=nil, retention_period: 10)
50
+ if domain_name
51
+ begin
52
+ @domain = swf.domains[domain_name.to_s]
53
+ @domain.status
54
+ rescue AWS::SimpleWorkflow::Errors::UnknownResourceFault => e
55
+ # create it if necessary
56
+ @domain = swf.domains.create(domain_name.to_s, retention_period)
57
+ end
58
+ else
59
+ @domain
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,19 @@
1
+ module Glider
2
+
3
+ def Glider.logger
4
+ $logger ||= Logger.new STDOUT
5
+ end
6
+
7
+ def Glider.execute(domain_name, workflow_name, version, input)
8
+ swf = AWS::SimpleWorkflow.new
9
+ domain = swf.domains[domain_name.to_s]
10
+ domain.workflow_types[workflow_name.to_s, version].start_execution input: input, task_start_to_close_timeout: 5
11
+ end
12
+
13
+ def Glider.signal(domain_name, workflow_id, signal_name, options={})
14
+ swf = AWS::SimpleWorkflow.new
15
+ domain = swf.domains[domain_name.to_s]
16
+ workflow_execution = domain.workflow_executions.with_workflow_id(workflow_id).with_status(:open).first
17
+ workflow_execution.signal signal_name.to_s, options
18
+ end
19
+ end
@@ -0,0 +1,146 @@
1
+ # isolates the common needed tasks of other elemtns
2
+
3
+ module Glider
4
+
5
+ class Component
6
+
7
+
8
+
9
+ class << self
10
+ def workflows
11
+ @workflows ||= []
12
+ end
13
+
14
+ def register_workflow(name, version, options={})
15
+
16
+ default_options = {
17
+ :default_task_list => name.to_s,
18
+ :default_child_policy => :request_cancel,
19
+ :default_task_start_to_close_timeout => 10, # decider timeout
20
+ :default_execution_start_to_close_timeout => 120
21
+ }
22
+ options = default_options.merge options
23
+ begin
24
+ workflow_type = domain.workflow_types.create name.to_s, version, options
25
+ rescue AWS::SimpleWorkflow::Errors::TypeAlreadyExistsFault
26
+ # already registered
27
+ workflow_type = domain.workflow_types[name.to_s, version]
28
+ end
29
+ workers.times do
30
+ ProcessManager.register_worker loop_block_for_workflow(workflow_type)
31
+ end
32
+ end
33
+
34
+ # let's us determine if :decised_task_started should be called :workflow_execution_started
35
+ def has_previous_decisions?(workflow_execution)
36
+ workflow_execution.history_events.each do |event|
37
+ event_type = ActiveSupport::Inflector.underscore(event.event_type).to_sym
38
+ return true if event_type == :decision_task_completed
39
+ end
40
+ return false
41
+ end
42
+
43
+ def should_call_workflow_target?(event_name, workflow_execution)
44
+ case event_name
45
+ when :activity_task_scheduled,
46
+ :activity_task_started,
47
+ :decision_task_scheduled,
48
+ :decision_task_started,
49
+ :decision_task_completed,
50
+ :marker_recorded,
51
+ :timer_started,
52
+ :start_child_workflow_execution_initiated,
53
+ :start_child_workflow_execution_started,
54
+ :signal_external_workflow_execution_initiated,
55
+ :request_cancel_external_workflow_execution_initiated
56
+
57
+ Glider.logger.debug "Skipping decider call event=#{event_name} workflow_id=#{workflow_execution.workflow_id}"
58
+ return false
59
+ else
60
+ return true
61
+ end
62
+ end
63
+
64
+ def workflow_data_for(event_name, event)
65
+ case event_name
66
+ when :workflow_execution_started #:decision_task_scheduled
67
+ event.attributes.input
68
+ when :workflow_execution_signaled
69
+ begin event.attributes.input rescue nil end
70
+ when :activity_task_completed
71
+ begin event.attributes.result rescue nil end
72
+ else
73
+ begin
74
+ event.attributes.result
75
+ rescue
76
+ Glider.logger.debug "no input or result in event, data will be nil event=#{event_name} attributes=#{event.attributes.to_h}"
77
+ nil
78
+ end
79
+ end
80
+ end
81
+
82
+ # used for timeouts and activity task completed
83
+ def activity_name_for(task, event)
84
+ # taken from SimplerWorkflow
85
+ completed_event = task.workflow_execution.events.reverse_order.find do |e|
86
+ e.id == event.attributes.scheduled_event_id
87
+ end
88
+ activity_name = completed_event.attributes.activity_type.name
89
+ inflected_name = ActiveSupport::Inflector.underscore activity_name
90
+ end
91
+
92
+ def process_decision_task(workflow_type, task)
93
+ workflow_id = task.workflow_execution.workflow_id
94
+ Glider.logger.info "Deciding workflow=#{workflow_type.name} workflow_id=#{workflow_id}"
95
+ task.new_events.each do |event|
96
+ event_name = ActiveSupport::Inflector.underscore(event.event_type).to_sym
97
+ if should_call_workflow_target? event_name, task.workflow_execution
98
+ target_instance = self.new task, event
99
+ data = workflow_data_for(event_name, event)
100
+ # convert signals to event names!
101
+ case event_name
102
+ when :workflow_execution_signaled
103
+ event_name = "#{event.attributes.signal_name}_signal".to_sym
104
+ when :activity_task_completed
105
+ event_name = "#{activity_name_for(task, event)}_activity_completed".to_sym
106
+ when :activity_task_timed_out
107
+ event_name = "#{activity_name_for(task, event)}_activity_timed_out".to_sym
108
+ end
109
+
110
+ target_instance.send workflow_type.name, event_name, event, data
111
+
112
+
113
+ # ensure proper response was given (aka a decision taken)
114
+ decisions = task.instance_eval {@decisions}
115
+ Glider.logger.debug decisions
116
+ if decisions.length == 0 && !task.responded?
117
+ # the decider didn't add any decision
118
+ Glider.logger.warn "No decision made workflow=#{workflow_type.name} workflow_id=#{task.workflow_execution.workflow_id}"
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ def loop_block_for_workflow(workflow_type)
125
+ Proc.new do
126
+ $0 = "ruby #{workflow_type.name}-#{workflow_type.version}"
127
+ signal_handling
128
+ Glider.logger.info "Startig worker for #{workflow_type.name} (pid #{Process.pid})"
129
+ begin
130
+ domain.decision_tasks.poll workflow_type.name do |decision_task|
131
+ task_lock! do
132
+ process_decision_task workflow_type, decision_task
133
+ end
134
+ end
135
+ rescue AWS::SimpleWorkflow::Errors::UnknownResourceFault
136
+ $logger.error "An action relating to an expired decision was sent. Probably the decider took longer than the decision timeout span. Killing decider process."
137
+ exit 1
138
+ end
139
+ end
140
+ end
141
+
142
+ end
143
+
144
+ end
145
+
146
+ end
data/readme.md ADDED
@@ -0,0 +1,36 @@
1
+ Useful documentation links:
2
+
3
+ http://docs.aws.amazon.com/amazonswf/latest/apireference/API_RespondDecisionTaskCompleted.html
4
+
5
+ http://docs.aws.amazon.com/amazonswf/latest/apireference/API_HistoryEvent.html
6
+
7
+ http://docs.aws.amazon.com/amazonswf/latest/developerguide/swf-dev-workflow-exec-lifecycle.html
8
+
9
+ USEFUL TO DECIDE WHAT TO PASS TO THE METHOD
10
+
11
+ INFO 15:16:05 Starting workers for ["hello_world-1.0"] and ["say_hi-1.0"]
12
+ INFO 15:16:05 Startig worker for say_hi (class: MySWF)
13
+ INFO 15:16:42 Processing decision task workflow_id=bb235559-9ee6-4a80-96c5-9eed168046d5
14
+ INFO 15:16:42 say_hi event=workflow_execution_started data=ALOHA
15
+ WARN 15:16:42 No result for decision_task_scheduled, attributes: {:task_list=>"say_hi", :start_to_close_timeout=>5}
16
+ WARN 15:16:42 say_hi event=decision_task_scheduled data=
17
+ WARN 15:16:42 No result for decision_task_started, attributes: {:identity=>"dmb.local:49424", :scheduled_event_id=>2}
18
+ WARN 15:16:42 say_hi event=decision_task_started data=
19
+ WARN 15:16:42 No result for decision_task_timed_out, attributes: {:timeout_type=>"START_TO_CLOSE", :scheduled_event_id=>2, :started_event_id=>3}
20
+ WARN 15:16:42 say_hi event=decision_task_timed_out data=
21
+ WARN 15:16:42 No result for decision_task_scheduled, attributes: {:task_list=>"say_hi", :start_to_close_timeout=>5}
22
+ WARN 15:16:42 say_hi event=decision_task_scheduled data=
23
+ WARN 15:16:42 No result for decision_task_started, attributes: {:identity=>"dmb.local:49461", :scheduled_event_id=>5}
24
+ WARN 15:16:42 say_hi event=decision_task_started data=
25
+ DEBUG 15:16:42 [{:decision_type=>"CompleteWorkflowExecution", :complete_workflow_execution_decision_attributes=>{}}]
26
+
27
+ terminations dont trigger decisions
28
+
29
+
30
+ TODO:
31
+
32
+ Proces monitoring
33
+ activity task signaling
34
+
35
+ Exec scoped logger
36
+ instance methods
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: glider
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - David Pelaez
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aws-sdk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 4.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 4.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: jeweler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.8.7
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 1.8.7
69
+ description: Minimal opinionated wrapper around SimpleWorkflow
70
+ email: david@vlipco.co
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files:
74
+ - README.md
75
+ files:
76
+ - Gemfile
77
+ - Gemfile.lock
78
+ - docs/event_names.md
79
+ - lib/glider.rb
80
+ - lib/glider/activities.rb
81
+ - lib/glider/component.rb
82
+ - lib/glider/utils.rb
83
+ - lib/glider/workflows.rb
84
+ - readme.md
85
+ - README.md
86
+ homepage: http://github.com/vlipco/glider
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.1.9
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: Minimal opinionated wrapper around SimpleWorkflow
110
+ test_files: []