capistrano_sentinel 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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