blue_green_process 0.1.3 → 0.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 89de1bb6ab2d7f30cf4063f1f04411da882e1061550603ee8ca866839a62f9d0
4
- data.tar.gz: dc64126db9c11c6e03dfa80be32aed24e0a7142f463efd04915729f335233c68
3
+ metadata.gz: c8905db7b63e35a80a3fa1272553fa4f84002e06747501b5749110a6edfed79e
4
+ data.tar.gz: 467fbb4d348d6fae9cfc70a013f88a560cc69a97690451d0b53908585d312e20
5
5
  SHA512:
6
- metadata.gz: '00874bdfeba757a3e8cc5bba6cebdf8a8bfa63d2ab8ff4779f26a9ce5bd8a5afd9ac933e4833b8a0042ce55cefda62d69f70077396d8f6df9bb64961d2e12f70'
7
- data.tar.gz: c5de3504ad7ec738260fcf4969ea9cb1cba38539f582ad122c159f543e05666ac1cc3dc7d8f1111134a5d8ad8ae4392006db8d7c4893f4d1214ae9bcea98361f
6
+ metadata.gz: f042564e95f91038d87faaae43d891d798204784a27f0b2fb1a038df195717c58755c7a65531216d97f4477296dee1775119ba1c01560c7fb067a336c1b613aa
7
+ data.tar.gz: 28d937c6280847b821ef49f4c247649549a13bf4a5c0f62d444cb6d5c391d88c491ac2d2fcca38a56947e4eb66b5583200885b4cc4e4f40c63cd61c2a8ac5bc1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## [0.1.4] - 2022-12-
2
+ * BlueGreenProcess.terminate_workers_immediately を呼び出すことで、シグナル経由で終了できるようになりました
3
+
1
4
  ## [0.1.3] - 2022-9-5
2
5
  * 単一プロセスでの実行を延長するとGC.startを実行しなくなりました
3
6
  * 長時間にわたって延長する時は呼び出し側でGC.startを実行してください
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- blue_green_process (0.1.3)
4
+ blue_green_process (0.1.4)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  A library that solves GC bottlenecks with multi-process.
4
4
 
5
+ ```mermaid
6
+ sequenceDiagram
7
+ autonumber
8
+ loop
9
+ Master->>+Blue: be active
10
+ Blue->>-Master: response
11
+ Master->>+Blue: work
12
+ Blue->>-Master: response
13
+ Master->>+Blue: be inactive
14
+ Blue->>-Master: response
15
+ Blue-->>Blue: GC.start
16
+ Master->>+Green: be active
17
+ Green->>-Master: response
18
+ Master->>+Green: work
19
+ Green->>-Master: response
20
+ Master->>+Green: be inactive
21
+ Green->>-Master: response
22
+ Green->>Green: GC.start
23
+ end
24
+
25
+ ```
26
+
27
+
5
28
  ## Installation
6
29
 
7
30
  Install the gem and add to the application's Gemfile by executing:
@@ -31,6 +54,7 @@ end
31
54
  sleep(1)
32
55
 
33
56
  process.shutdown
57
+ # or BlueGreenProcess.terminate_workers_immediately
34
58
  Process.waitall
35
59
  ```
36
60
 
@@ -148,6 +172,3 @@ The gem is available as open source under the terms of the [MIT License](https:/
148
172
 
149
173
  ## TODO
150
174
  * shutdownしないでプロセスを停止したときにSIGINTを受け取りたい
151
- * runしている間にsignalをもらったらすぐにdieを送りたい
152
- * inactiveからactiveへの切り替えになる時間を測定したい
153
- * GCが長引いてactiveプロセスが処理開始に時間がかかるので
@@ -24,10 +24,18 @@ module BlueGreenProcess
24
24
  @max_work = max_work
25
25
  end
26
26
 
27
+ # @return [Array<Integer>]
28
+ # 削除予定
27
29
  def pids
28
30
  @processes.map(&:pid)
29
31
  end
30
32
 
33
+ # @return [Array<Integer>]
34
+ def worker_pids
35
+ @processes.map(&:pid)
36
+ end
37
+
38
+ # @return [BlueGreenProcess::WorkerProcess]
31
39
  def fork_process(label:, worker_instance:)
32
40
  child_read, parent_write = IO.pipe
33
41
  parent_read, child_write = IO.pipe
@@ -39,10 +47,12 @@ module BlueGreenProcess
39
47
  parent_write.close
40
48
  parent_read.close
41
49
  process_status = :inactive
50
+ handle_signal(pipes: [child_read, child_write])
42
51
 
43
52
  loop do
44
- data = child_read.gets&.strip
45
- json = JSON.parse(data)
53
+ next unless (data = child_read.gets)
54
+
55
+ json = JSON.parse(data.strip)
46
56
  command = json["c"]
47
57
  case command
48
58
  when BlueGreenProcess::PROCESS_COMMAND_DIE, nil, ""
@@ -76,6 +86,8 @@ module BlueGreenProcess
76
86
  puts "unknown. from #{label}(#{$PROCESS_ID})"
77
87
  exit 1
78
88
  end
89
+ rescue IOError # NOTE: シグナル経由でpipeが破棄された時にこれが発生する
90
+ exit 127
79
91
  end
80
92
 
81
93
  exit 0
@@ -87,6 +99,7 @@ module BlueGreenProcess
87
99
  BlueGreenProcess::WorkerProcess.new(pid, label, parent_read, parent_write)
88
100
  end
89
101
 
102
+ # @return [void]
90
103
  def work
91
104
  active_process do |process|
92
105
  @max_work.times do
@@ -99,6 +112,7 @@ module BlueGreenProcess
99
112
  raise eval(e.error_class), e.message
100
113
  end
101
114
 
115
+ # @return [void]
102
116
  def shutdown
103
117
  @processes.each(&:shutdown)
104
118
  Process.waitall
@@ -106,6 +120,7 @@ module BlueGreenProcess
106
120
 
107
121
  private
108
122
 
123
+ # @return [void]
109
124
  def active_process
110
125
  active_process = nil
111
126
  @stage[!@stage_state].be_inactive
@@ -126,5 +141,32 @@ module BlueGreenProcess
126
141
 
127
142
  true
128
143
  end
144
+
145
+ # @return [void]
146
+ # シグナルを受け取ってpipeをcloseする
147
+ def handle_signal(pipes:)
148
+ Thread.new do
149
+ self_read, self_write = IO.pipe
150
+ %w[INT TERM].each do |sig|
151
+ trap sig do
152
+ self_write.puts(sig)
153
+ end
154
+ rescue ArgumentError
155
+ warn("Signal #{sig} not supported")
156
+ end
157
+
158
+ begin
159
+ while (readable_io = IO.select([self_read]))
160
+ signal = readable_io.first[0].gets.strip
161
+ case signal
162
+ when "INT", "TERM"
163
+ raise Interrupt
164
+ end
165
+ end
166
+ rescue Interrupt
167
+ pipes.each(&:close)
168
+ end
169
+ end
170
+ end
129
171
  end
130
172
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BlueGreenProcess
4
- VERSION = "0.1.3"
4
+ VERSION = "0.1.4"
5
5
  end
@@ -47,7 +47,9 @@ module BlueGreenProcess
47
47
  end
48
48
 
49
49
  def wait_response
50
- response = JSON.parse(read)
50
+ return unless (text = read)
51
+
52
+ response = JSON.parse(text.strip)
51
53
  BlueGreenProcess::SharedVariable.instance.restore(response["data"])
52
54
  case response["c"]
53
55
  when BlueGreenProcess::RESPONSE_OK
@@ -60,11 +62,15 @@ module BlueGreenProcess
60
62
  end
61
63
 
62
64
  def read
63
- rpipe.gets.strip
65
+ rpipe.gets
66
+ rescue IOError
67
+ # NOTE: シグナル経由でpipeが破棄された時にこれが発生する
64
68
  end
65
69
 
66
70
  def write(token, args = {})
67
71
  wpipe.puts({ c: token }.merge!(args).to_json)
72
+ rescue Errno::EPIPE
73
+ # NOTE: シグナル経由でpipeが破棄された時にこれが発生する
68
74
  end
69
75
 
70
76
  def enforce_to_be_active
@@ -13,6 +13,8 @@ require "json"
13
13
  require "singleton"
14
14
 
15
15
  module BlueGreenProcess
16
+ PID_PATH = "/tmp/pbm_blue_green_process_pids"
17
+
16
18
  PROCESS_STATUS_ACTIVE = :active
17
19
  PROCESS_STATUS_INACTIVE = :inactive
18
20
 
@@ -25,7 +27,9 @@ module BlueGreenProcess
25
27
  RESPONSE_ERROR = "ERR"
26
28
 
27
29
  def self.new(worker_instance:, max_work:)
28
- BlueGreenProcess::MasterProcess.new(worker_instance: worker_instance, max_work: max_work)
30
+ master_process = BlueGreenProcess::MasterProcess.new(worker_instance: worker_instance, max_work: max_work)
31
+ File.write(PID_PATH, master_process.worker_pids.join(","))
32
+ master_process
29
33
  end
30
34
 
31
35
  def self.configure
@@ -50,4 +54,21 @@ module BlueGreenProcess
50
54
  @config = Config.new
51
55
  @performance = Performance.new
52
56
  end
57
+
58
+ # @return [void]
59
+ def self.terminate_workers_immediately
60
+ worker_pids = nil
61
+ begin
62
+ worker_pids = File.read(PID_PATH).split(",").map(&:to_i)
63
+ rescue Errno::ENOENT
64
+ warn("#{PID_PATH}にファイルがありませんでした")
65
+ return
66
+ end
67
+
68
+ worker_pids.each do |worker_pid|
69
+ Process.kill "TERM", worker_pid
70
+ rescue Errno::ESRCH => e
71
+ warn("BlueGreenProcess workerプロセス(#{worker_pid})の終了に失敗しました。", e.message)
72
+ end
73
+ end
53
74
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blue_green_process
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - jiikko
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-05 00:00:00.000000000 Z
11
+ date: 2022-12-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A library that solves GC bottlenecks with multi-process.
14
14
  email: