deploy_pin 1.3.0 → 1.3.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.
- checksums.yaml +4 -4
- data/lib/deploy_pin/collector.rb +26 -15
- data/lib/deploy_pin/database.rb +8 -13
- data/lib/deploy_pin/parallel_wrapper.rb +95 -0
- data/lib/deploy_pin/task.rb +25 -8
- data/lib/deploy_pin/version.rb +1 -1
- data/lib/deploy_pin.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3006ccc3913b4cc7ee0b5d68b316ffb70ecef2bbfeae27c7efec65422246cdb
|
4
|
+
data.tar.gz: d055a8554b590bc039915d3a2866f23aa8541db9ffe8c2c933294f54c2013785
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 70d4054142995c62609666711a87d4d4e42783bf4631e61f3a43e3407a9cd68654de65b0925655ca416fb65e41bccd3a2246125e446f5f4d8a9cb48f70e7ffd4
|
7
|
+
data.tar.gz: 654cbb997e23bf9a2cc9d8579e71646f68fd669dfd92235da2a1d15b8b3d9775b01db714ce99e79e23e6389282a907c2f9ae5b573c348bd4b0d3f43105989903
|
data/lib/deploy_pin/collector.rb
CHANGED
@@ -19,7 +19,11 @@ module DeployPin
|
|
19
19
|
yield(index, _tasks.count, task, executable)
|
20
20
|
|
21
21
|
# run if executable
|
22
|
-
|
22
|
+
if executable
|
23
|
+
run_with_timeout(!task.explicit_timeout? && !task.parallel?) do
|
24
|
+
task.run
|
25
|
+
end
|
26
|
+
end
|
23
27
|
|
24
28
|
# mark each task as done
|
25
29
|
task.mark unless task.done?
|
@@ -46,23 +50,30 @@ module DeployPin
|
|
46
50
|
end
|
47
51
|
|
48
52
|
private
|
53
|
+
# :reek:UtilityFunction
|
54
|
+
def files
|
55
|
+
Dir["#{DeployPin.tasks_path}/*.rb"]
|
56
|
+
end
|
49
57
|
|
50
|
-
|
51
|
-
|
52
|
-
|
58
|
+
def tasks
|
59
|
+
files.map do |file|
|
60
|
+
task = DeployPin::Task.new(file)
|
61
|
+
task.parse_file
|
53
62
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
63
|
+
# check if task is suitable
|
64
|
+
task if task_criteria.suitable?(task)
|
65
|
+
end.compact.sort # sort by group position in config
|
66
|
+
end
|
58
67
|
|
59
|
-
|
60
|
-
|
61
|
-
end
|
62
|
-
end
|
68
|
+
def task_criteria
|
69
|
+
@task_criteria ||= DeployPin::TaskCriteria.new(identifiers: identifiers)
|
70
|
+
end
|
63
71
|
|
64
|
-
|
65
|
-
|
66
|
-
|
72
|
+
# :reek:UtilityFunction and :reek:ControlParameter
|
73
|
+
def run_with_timeout(under_timeout, &block)
|
74
|
+
return yield unless under_timeout
|
75
|
+
|
76
|
+
DeployPin::Database.execute_with_timeout(DeployPin.statement_timeout, **{}, &block)
|
77
|
+
end
|
67
78
|
end
|
68
79
|
end
|
data/lib/deploy_pin/database.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
module DeployPin
|
4
4
|
module Database
|
5
|
+
PG_TIMEOUT_STATEMENT = 'SET statement_timeout TO %s'
|
6
|
+
MYSQL_TIMEOUT_STATEMENT = 'SET max_execution_time = %s'
|
7
|
+
|
5
8
|
extend self
|
6
9
|
|
7
10
|
# Run a block under a sql maximum timeout.
|
@@ -46,7 +49,7 @@ module DeployPin
|
|
46
49
|
|
47
50
|
return call_block_under_timeout(timeout, &blk) unless params.key? :connected_to
|
48
51
|
|
49
|
-
klass = params[:connected_to].key?
|
52
|
+
klass = params[:connected_to].key?(:database) ? ActiveRecord::Base : ::ApplicationRecord
|
50
53
|
klass.connected_to(**params[:connected_to]) do
|
51
54
|
call_block_under_timeout(timeout, &blk)
|
52
55
|
end
|
@@ -65,32 +68,24 @@ module DeployPin
|
|
65
68
|
|
66
69
|
timeout_statement =
|
67
70
|
if postgresql?
|
68
|
-
|
71
|
+
PG_TIMEOUT_STATEMENT
|
69
72
|
elsif mysql?
|
70
|
-
|
73
|
+
MYSQL_TIMEOUT_STATEMENT
|
71
74
|
end
|
72
75
|
|
73
|
-
connection.
|
76
|
+
connection.execute timeout_statement % connection.quote(timeout_in_milliseconds)
|
74
77
|
end
|
75
78
|
|
76
79
|
def postgresql?
|
77
80
|
connection.adapter_name =~ /postg/i
|
78
81
|
end
|
79
82
|
|
80
|
-
def postgresql_timeout_statement
|
81
|
-
"SET statement_timeout TO"
|
82
|
-
end
|
83
|
-
|
84
83
|
def mysql?
|
85
84
|
connection.adapter_name =~ /mysql/i
|
86
85
|
end
|
87
86
|
|
88
|
-
def mysql_timeout_statement
|
89
|
-
"SET max_execution_time ="
|
90
|
-
end
|
91
|
-
|
92
87
|
def connection
|
93
88
|
ActiveRecord::Base.connection
|
94
89
|
end
|
95
90
|
end
|
96
|
-
end
|
91
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DeployPin
|
4
|
+
# Parallel wrapper to run parallel tasks using database statement timeout.
|
5
|
+
# This wrapper keeps parallel interface, but running the processes under db statement timeout.
|
6
|
+
#
|
7
|
+
# In order to use this wrapper, just use call parallel methods with `parallel_`. Ex.:
|
8
|
+
# parallel_each(1..2, in_processes: 2, timeout: 0.3.seconds) do |i|
|
9
|
+
# puts "Item: #{i}, Worker: #{Parallel.worker_number}"
|
10
|
+
# ActiveRecord::Base.connection.execute("<some db query>")
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# In order to pass more `timeout` options, it requires to pass an array, like:
|
14
|
+
# parallel_each(1..2, in_processes: 2, timeout: [0.3.seconds, { connected_to: { role: :reading } }]) do |i|
|
15
|
+
# puts "Item: #{i}, Worker: #{Parallel.worker_number}"
|
16
|
+
# ActiveRecord::Base.connection.execute("<some db query>")
|
17
|
+
# end
|
18
|
+
module ParallelWrapper
|
19
|
+
PARALLEL_PREFIX = 'parallel_'
|
20
|
+
|
21
|
+
# :reek:TooManyInstanceVariables
|
22
|
+
class ParallelRunner
|
23
|
+
def initialize(method_name, *args, &db_block)
|
24
|
+
@method_name = method_name
|
25
|
+
@db_block = db_block
|
26
|
+
|
27
|
+
if args.last.is_a?(Hash) && args.last.key?(:timeout)
|
28
|
+
@timeout_args = args.pop
|
29
|
+
prepare_timeout_args
|
30
|
+
end
|
31
|
+
|
32
|
+
@parallel_args = args
|
33
|
+
end
|
34
|
+
|
35
|
+
def run
|
36
|
+
raise 'You must provide at least one argument for parallel methods' if parallel_args.empty?
|
37
|
+
|
38
|
+
Parallel.send(parallel_method_name, *parallel_args) do |*block_args|
|
39
|
+
ActiveRecord::Base.connection_pool.with_connection do
|
40
|
+
DeployPin::Database.execute_with_timeout(timeout, **timeout_params) do
|
41
|
+
db_block.call(*block_args)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
attr_accessor :method_name, :parallel_args, :db_block
|
50
|
+
|
51
|
+
def prepare_timeout_args
|
52
|
+
timeout = @timeout_args[:timeout]
|
53
|
+
if timeout.is_a?(Array)
|
54
|
+
@timeout = timeout.shift
|
55
|
+
@timeout_params = timeout.first
|
56
|
+
else
|
57
|
+
@timeout = timeout
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def timeout
|
62
|
+
@timeout ||= DeployPin.statement_timeout
|
63
|
+
end
|
64
|
+
|
65
|
+
def timeout_params
|
66
|
+
@timeout_params ||= {}
|
67
|
+
end
|
68
|
+
|
69
|
+
def parallel_method_name
|
70
|
+
@parallel_method_name ||= method_name.to_s.gsub(PARALLEL_PREFIX, '').to_sym
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def method_missing(name, *args, &block)
|
75
|
+
return super unless respond_to_missing?(name)
|
76
|
+
|
77
|
+
ParallelRunner.new(name, *args, &block).run
|
78
|
+
end
|
79
|
+
|
80
|
+
# :reek:ManualDispatch and :reek:BooleanParameter
|
81
|
+
def respond_to_missing?(method_name, include_private = false)
|
82
|
+
return super unless parallel_prefix_pattern.match? method_name
|
83
|
+
|
84
|
+
parallel_method_name = method_name.to_s.gsub(PARALLEL_PREFIX, '').to_sym
|
85
|
+
|
86
|
+
Parallel.respond_to?(parallel_method_name) || super
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def parallel_prefix_pattern
|
92
|
+
@parallel_prefix_pattern ||= /\A#{PARALLEL_PREFIX}/
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/lib/deploy_pin/task.rb
CHANGED
@@ -3,11 +3,15 @@
|
|
3
3
|
# Task wrapper
|
4
4
|
module DeployPin
|
5
5
|
class Task
|
6
|
+
extend ::DeployPin::ParallelWrapper
|
7
|
+
include ::DeployPin::ParallelWrapper
|
8
|
+
|
6
9
|
attr_reader :file,
|
7
10
|
:uuid,
|
8
11
|
:group,
|
9
12
|
:title,
|
10
|
-
:script
|
13
|
+
:script,
|
14
|
+
:explicit_timeout
|
11
15
|
|
12
16
|
def initialize(file)
|
13
17
|
@file = file
|
@@ -15,6 +19,8 @@ module DeployPin
|
|
15
19
|
@group = nil
|
16
20
|
@title = ''
|
17
21
|
@script = ''
|
22
|
+
@explicit_timeout = false
|
23
|
+
@parallel = false
|
18
24
|
end
|
19
25
|
|
20
26
|
def run
|
@@ -31,6 +37,14 @@ module DeployPin
|
|
31
37
|
DeployPin::Record.where(uuid: uuid).exists?
|
32
38
|
end
|
33
39
|
|
40
|
+
def explicit_timeout?
|
41
|
+
@explicit_timeout
|
42
|
+
end
|
43
|
+
|
44
|
+
def parallel?
|
45
|
+
@parallel
|
46
|
+
end
|
47
|
+
|
34
48
|
def parse_file
|
35
49
|
File.foreach(file) do |line|
|
36
50
|
case line.strip
|
@@ -41,6 +55,9 @@ module DeployPin
|
|
41
55
|
@title = Regexp.last_match(1).strip
|
42
56
|
when /\A[^#].*/
|
43
57
|
@script += line
|
58
|
+
|
59
|
+
@explicit_timeout = true if line =~ /Database.execute_with_timeout.*/
|
60
|
+
@parallel = true if line =~ /[Pp]arallel.*/
|
44
61
|
end
|
45
62
|
end
|
46
63
|
end
|
@@ -60,13 +77,13 @@ module DeployPin
|
|
60
77
|
|
61
78
|
protected
|
62
79
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
80
|
+
# for sorting
|
81
|
+
def <=>(other)
|
82
|
+
group_index <=> other.group_index
|
83
|
+
end
|
67
84
|
|
68
|
-
|
69
|
-
|
70
|
-
|
85
|
+
def group_index
|
86
|
+
DeployPin.groups.index(group)
|
87
|
+
end
|
71
88
|
end
|
72
89
|
end
|
data/lib/deploy_pin/version.rb
CHANGED
data/lib/deploy_pin.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deploy_pin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Viktor Sych
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-08-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -166,6 +166,7 @@ files:
|
|
166
166
|
- lib/deploy_pin/collector.rb
|
167
167
|
- lib/deploy_pin/database.rb
|
168
168
|
- lib/deploy_pin/engine.rb
|
169
|
+
- lib/deploy_pin/parallel_wrapper.rb
|
169
170
|
- lib/deploy_pin/runner.rb
|
170
171
|
- lib/deploy_pin/task.rb
|
171
172
|
- lib/deploy_pin/task_criteria.rb
|