capistrano_sentinel 0.0.1

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.
@@ -0,0 +1,52 @@
1
+ require_relative './application_helper'
2
+ module CapistranoSentinel
3
+ module AsyncActor
4
+ include CapistranoSentinel::ApplicationHelper
5
+
6
+ Context = Struct.new(:method, :args, :block)
7
+
8
+ Async = Struct.new(:instance, :mailbox) do
9
+ extend Forwardable
10
+ def_delegator :instance, :respond_to?
11
+
12
+ private :instance
13
+ private :mailbox
14
+
15
+ def initialize(instance, mailbox)
16
+ super(instance, mailbox)
17
+ run!
18
+ end
19
+
20
+ def method_missing(method, *args, &block)
21
+ mailbox << CapistranoSentinel::AsyncActor::Context.new(method, args, block)
22
+ nil
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def run!
29
+ Thread.new do
30
+ loop do
31
+ break if mailbox.empty?
32
+ begin
33
+ mailbox.synchronize do
34
+ ctx = mailbox.pop
35
+ instance.public_send(ctx.method, *ctx.args, &ctx.block)
36
+ end
37
+ rescue => e
38
+ log_to_file("crashed with #{e.inspect} #{e.backtrace}")
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def async_queue
45
+ @async_queue ||= Queue.new.extend(MonitorMixin)
46
+ end
47
+
48
+ def async
49
+ @async ||= CapistranoSentinel::AsyncActor::Async.new(self, async_queue)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,47 @@
1
+ require_relative './logging'
2
+ module CapistranoSentinel
3
+ # class that holds the options that are configurable for this gem
4
+ module ApplicationHelper
5
+ include CapistranoSentinel::Logging
6
+ module_function
7
+
8
+ # Method that is used to parse a string as JSON , if it fails will return nil
9
+ # @see JSON#parse
10
+ # @param [string] res The string that will be parsed as JSON
11
+ # @return [Hash, nil] Returns Hash object if the json parse succeeds or nil otherwise
12
+ def parse_json(res)
13
+ return if res.blank?
14
+ JSON.parse(res)
15
+ rescue JSON::ParserError
16
+ nil
17
+ end
18
+
19
+ def show_warning(message)
20
+ warn message
21
+ end
22
+
23
+
24
+ def msg_for_stdin?(message)
25
+ message['action'] == 'stdin'
26
+ end
27
+
28
+ def message_is_for_stdout?(message)
29
+ message.present? && message.is_a?(Hash) && message['action'].present? && message['job_id'].present? && message['action'] == 'stdout'
30
+ end
31
+
32
+ def message_is_about_a_task?(message)
33
+ message.present? && message.is_a?(Hash) && message['action'].present? && message['job_id'].present? && message['task'].present? && message['action'] == 'invoke'
34
+ end
35
+
36
+ def message_from_bundler?(message)
37
+ message.present? && message.is_a?(Hash) && message['action'].present? && message['job_id'].present? && message['task'].present? && message['action'] == 'bundle_install'
38
+ end
39
+
40
+ def get_question_details(data)
41
+ matches = /(.*)\?*\s*\:*\s*(\([^)]*\))*/m.match(data).captures
42
+ [matches[0], matches[1]]
43
+ end
44
+
45
+
46
+ end
47
+ end
@@ -0,0 +1,79 @@
1
+ module CapistranoSentinel
2
+ # class that holds the options that are configurable for this gem
3
+ module Logging
4
+ module_function
5
+
6
+ def logger
7
+ @logger ||= ::Logger.new('/home/raul/workspace/ecommerce/ecommerce-livechat/log/multi_cap.log')
8
+ end
9
+
10
+ def error_filtered?(error)
11
+ [SystemExit].find { |class_name| error.is_a?(class_name) }.present?
12
+ end
13
+
14
+ def log_error(error, options = {})
15
+ message = format_error(error)
16
+ log_output_error(error, options.fetch(:output, nil), message)
17
+ log_to_file(message, options.merge(log_method: 'fatal'))
18
+ end
19
+
20
+ def log_output_error(error, output, message)
21
+ return if message.blank? || error_filtered?(error)
22
+ puts message if output.present?
23
+ terminal_actor.errors.push(message) if terminal_errors?
24
+ end
25
+
26
+ def format_error(exception)
27
+ message = "\n#{exception.class} (#{exception.respond_to?(:message) ? exception.message : exception.inspect}):\n"
28
+ message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
29
+ message << ' ' << exception.backtrace.join("\n ") if exception.respond_to?(:backtrace)
30
+ message
31
+ end
32
+
33
+ def log_to_file(message, options = {})
34
+ worker_log = options.fetch(:job_id, '').present? ? find_worker_log(options[:job_id]) : logger
35
+ print_to_log_file(worker_log, options.merge(message: message)) if worker_log.present?
36
+ end
37
+
38
+ def print_to_log_file(worker_log, options = {})
39
+ worker_log.send(options.fetch(:log_method, 'debug'), "#{options.fetch(:message, '')}\n")
40
+ end
41
+
42
+ def find_worker_log(job_id)
43
+ return if job_id.blank?
44
+ FileUtils.mkdir_p(log_directory) unless File.directory?(log_directory)
45
+ filename = File.join(log_directory, "worker_#{job_id}.log")
46
+ setup_filename_logger(filename)
47
+ end
48
+
49
+ def setup_filename_logger(filename)
50
+ worker_log = ::Logger.new(filename)
51
+ worker_log.level = ::Logger::Severity::DEBUG
52
+ setup_logger_formatter(worker_log)
53
+ worker_log
54
+ end
55
+
56
+ def setup_logger_formatter(logger)
57
+ logger.formatter = proc do |severity, datetime, progname, msg|
58
+ date_format = datetime.strftime('%Y-%m-%d %H:%M:%S')
59
+ "[#{date_format}] #{severity} (#{progname}): #{msg}\n"
60
+ end
61
+ end
62
+
63
+ def execute_with_rescue(output = nil)
64
+ yield if block_given?
65
+ rescue Interrupt
66
+ rescue_interrupt
67
+ rescue => error
68
+ rescue_error(error, output)
69
+ end
70
+
71
+ def rescue_error(error, output = nil)
72
+ log_error(error, output: output)
73
+ exit(1)
74
+ end
75
+
76
+
77
+
78
+ end
79
+ end
@@ -0,0 +1,143 @@
1
+ class Object
2
+ # An object is blank if it's false, empty, or a whitespace string.
3
+ # For example, +false+, '', ' ', +nil+, [], and {} are all blank.
4
+ #
5
+ # This simplifies
6
+ #
7
+ # !address || address.empty?
8
+ #
9
+ # to
10
+ #
11
+ # address.blank?
12
+ #
13
+ # @return [true, false]
14
+ def blank?
15
+ respond_to?(:empty?) ? !!empty? : !self
16
+ end
17
+
18
+ # An object is present if it's not blank.
19
+ #
20
+ # @return [true, false]
21
+ def present?
22
+ !blank?
23
+ end
24
+
25
+ # Returns the receiver if it's present otherwise returns +nil+.
26
+ # <tt>object.presence</tt> is equivalent to
27
+ #
28
+ # object.present? ? object : nil
29
+ #
30
+ # For example, something like
31
+ #
32
+ # state = params[:state] if params[:state].present?
33
+ # country = params[:country] if params[:country].present?
34
+ # region = state || country || 'US'
35
+ #
36
+ # becomes
37
+ #
38
+ # region = params[:state].presence || params[:country].presence || 'US'
39
+ #
40
+ # @return [Object]
41
+ def presence
42
+ self if present?
43
+ end
44
+ end
45
+
46
+ class NilClass
47
+ # +nil+ is blank:
48
+ #
49
+ # nil.blank? # => true
50
+ #
51
+ # @return [true]
52
+ def blank?
53
+ true
54
+ end
55
+ end
56
+
57
+ class FalseClass
58
+ # +false+ is blank:
59
+ #
60
+ # false.blank? # => true
61
+ #
62
+ # @return [true]
63
+ def blank?
64
+ true
65
+ end
66
+ end
67
+
68
+ class TrueClass
69
+ # +true+ is not blank:
70
+ #
71
+ # true.blank? # => false
72
+ #
73
+ # @return [false]
74
+ def blank?
75
+ false
76
+ end
77
+ end
78
+
79
+ class Array
80
+ # An array is blank if it's empty:
81
+ #
82
+ # [].blank? # => true
83
+ # [1,2,3].blank? # => false
84
+ #
85
+ # @return [true, false]
86
+ alias_method :blank?, :empty?
87
+ end
88
+
89
+ class Hash
90
+ # A hash is blank if it's empty:
91
+ #
92
+ # {}.blank? # => true
93
+ # { key: 'value' }.blank? # => false
94
+ #
95
+ # @return [true, false]
96
+ alias_method :blank?, :empty?
97
+ end
98
+
99
+ class String
100
+ BLANK_RE2 = /\A[[:space:]]*\z/
101
+
102
+ # A string is blank if it's empty or contains whitespaces only:
103
+ #
104
+ # ''.blank? # => true
105
+ # ' '.blank? # => true
106
+ # "\t\n\r".blank? # => true
107
+ # ' blah '.blank? # => false
108
+ #
109
+ # Unicode whitespace is supported:
110
+ #
111
+ # "\u00a0".blank? # => true
112
+ #
113
+ # @return [true, false]
114
+ def blank?
115
+ # The regexp that matches blank strings is expensive. For the case of empty
116
+ # strings we can speed up this method (~3.5x) with an empty? call. The
117
+ # penalty for the rest of strings is marginal.
118
+ empty? || BLANK_RE2 === self
119
+ end
120
+ end
121
+
122
+ class Numeric #:nodoc:
123
+ # No number is blank:
124
+ #
125
+ # 1.blank? # => false
126
+ # 0.blank? # => false
127
+ #
128
+ # @return [false]
129
+ def blank?
130
+ false
131
+ end
132
+ end
133
+
134
+ class Time #:nodoc:
135
+ # No Time is blank:
136
+ #
137
+ # Time.now.blank? # => false
138
+ #
139
+ # @return [false]
140
+ def blank?
141
+ false
142
+ end
143
+ end
@@ -0,0 +1,172 @@
1
+ class Hash
2
+
3
+ # Returns a new hash with all keys converted using the +block+ operation.
4
+ #
5
+ # hash = { name: 'Rob', age: '28' }
6
+ #
7
+ # hash.transform_keys { |key| key.to_s.upcase } # => {"NAME"=>"Rob", "AGE"=>"28"}
8
+ #
9
+ # If you do not provide a +block+, it will return an Enumerator
10
+ # for chaining with other methods:
11
+ #
12
+ # hash.transform_keys.with_index { |k, i| [k, i].join } # => {"name0"=>"Rob", "age1"=>"28"}
13
+ def transform_keys
14
+ return enum_for(:transform_keys) { size } unless block_given?
15
+ result = {}
16
+ each_key do |key|
17
+ result[yield(key)] = self[key]
18
+ end
19
+ result
20
+ end
21
+
22
+ # Destructively converts all keys using the +block+ operations.
23
+ # Same as +transform_keys+ but modifies +self+.
24
+ def transform_keys!
25
+ return enum_for(:transform_keys!) { size } unless block_given?
26
+ keys.each do |key|
27
+ self[yield(key)] = delete(key)
28
+ end
29
+ self
30
+ end
31
+
32
+ # Returns a new hash with all keys converted to strings.
33
+ #
34
+ # hash = { name: 'Rob', age: '28' }
35
+ #
36
+ # hash.stringify_keys
37
+ # # => {"name"=>"Rob", "age"=>"28"}
38
+ def stringify_keys
39
+ transform_keys(&:to_s)
40
+ end
41
+
42
+ # Destructively converts all keys to strings. Same as
43
+ # +stringify_keys+, but modifies +self+.
44
+ def stringify_keys!
45
+ transform_keys!(&:to_s)
46
+ end
47
+
48
+ # Returns a new hash with all keys converted to symbols, as long as
49
+ # they respond to +to_sym+.
50
+ #
51
+ # hash = { 'name' => 'Rob', 'age' => '28' }
52
+ #
53
+ # hash.symbolize_keys
54
+ # # => {:name=>"Rob", :age=>"28"}
55
+ def symbolize_keys
56
+ transform_keys{ |key| key.to_sym rescue key }
57
+ end
58
+ alias_method :to_options, :symbolize_keys
59
+
60
+ # Destructively converts all keys to symbols, as long as they respond
61
+ # to +to_sym+. Same as +symbolize_keys+, but modifies +self+.
62
+ def symbolize_keys!
63
+ transform_keys!{ |key| key.to_sym rescue key }
64
+ end
65
+ alias_method :to_options!, :symbolize_keys!
66
+
67
+ # Validates all keys in a hash match <tt>*valid_keys</tt>, raising
68
+ # +ArgumentError+ on a mismatch.
69
+ #
70
+ # Note that keys are treated differently than HashWithIndifferentAccess,
71
+ # meaning that string and symbol keys will not match.
72
+ #
73
+ # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
74
+ # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
75
+ # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
76
+ def assert_valid_keys(*valid_keys)
77
+ valid_keys.flatten!
78
+ each_key do |k|
79
+ unless valid_keys.include?(k)
80
+ raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
81
+ end
82
+ end
83
+ end
84
+
85
+ # Returns a new hash with all keys converted by the block operation.
86
+ # This includes the keys from the root hash and from all
87
+ # nested hashes and arrays.
88
+ #
89
+ # hash = { person: { name: 'Rob', age: '28' } }
90
+ #
91
+ # hash.deep_transform_keys{ |key| key.to_s.upcase }
92
+ # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
93
+ def deep_transform_keys(&block)
94
+ _deep_transform_keys_in_object(self, &block)
95
+ end
96
+
97
+ # Destructively converts all keys by using the block operation.
98
+ # This includes the keys from the root hash and from all
99
+ # nested hashes and arrays.
100
+ def deep_transform_keys!(&block)
101
+ _deep_transform_keys_in_object!(self, &block)
102
+ end
103
+
104
+ # Returns a new hash with all keys converted to strings.
105
+ # This includes the keys from the root hash and from all
106
+ # nested hashes and arrays.
107
+ #
108
+ # hash = { person: { name: 'Rob', age: '28' } }
109
+ #
110
+ # hash.deep_stringify_keys
111
+ # # => {"person"=>{"name"=>"Rob", "age"=>"28"}}
112
+ def deep_stringify_keys
113
+ deep_transform_keys(&:to_s)
114
+ end
115
+
116
+ # Destructively converts all keys to strings.
117
+ # This includes the keys from the root hash and from all
118
+ # nested hashes and arrays.
119
+ def deep_stringify_keys!
120
+ deep_transform_keys!(&:to_s)
121
+ end
122
+
123
+ # Returns a new hash with all keys converted to symbols, as long as
124
+ # they respond to +to_sym+. This includes the keys from the root hash
125
+ # and from all nested hashes and arrays.
126
+ #
127
+ # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
128
+ #
129
+ # hash.deep_symbolize_keys
130
+ # # => {:person=>{:name=>"Rob", :age=>"28"}}
131
+ def deep_symbolize_keys
132
+ deep_transform_keys{ |key| key.to_sym rescue key }
133
+ end
134
+
135
+ # Destructively converts all keys to symbols, as long as they respond
136
+ # to +to_sym+. This includes the keys from the root hash and from all
137
+ # nested hashes and arrays.
138
+ def deep_symbolize_keys!
139
+ deep_transform_keys!{ |key| key.to_sym rescue key }
140
+ end
141
+
142
+ private
143
+ # support methods for deep transforming nested hashes and arrays
144
+ def _deep_transform_keys_in_object(object, &block)
145
+ case object
146
+ when Hash
147
+ object.each_with_object({}) do |(key, value), result|
148
+ result[yield(key)] = _deep_transform_keys_in_object(value, &block)
149
+ end
150
+ when Array
151
+ object.map {|e| _deep_transform_keys_in_object(e, &block) }
152
+ else
153
+ object
154
+ end
155
+ end
156
+
157
+ def _deep_transform_keys_in_object!(object, &block)
158
+ case object
159
+ when Hash
160
+ object.keys.each do |key|
161
+ value = object.delete(key)
162
+ object[yield(key)] = _deep_transform_keys_in_object!(value, &block)
163
+ end
164
+ object
165
+ when Array
166
+ object.map! {|e| _deep_transform_keys_in_object!(e, &block)}
167
+ else
168
+ object
169
+ end
170
+ end
171
+
172
+ end