procon_bypass_man 0.1.12 → 0.1.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +33 -0
  3. data/CHANGELOG.md +13 -0
  4. data/Gemfile +1 -1
  5. data/Gemfile.lock +35 -15
  6. data/README.md +19 -8
  7. data/lib/ext/em_pure_ruby.rb +25 -0
  8. data/lib/procon_bypass_man/background/job_runner.rb +6 -5
  9. data/lib/procon_bypass_man/background/jobs/base_job.rb +1 -6
  10. data/lib/procon_bypass_man/background/jobs/concerns/has_external_api_setting.rb +5 -0
  11. data/lib/procon_bypass_man/background/jobs/concerns/has_internal_api_setting.rb +5 -0
  12. data/lib/procon_bypass_man/background/{job_runnable.rb → jobs/concerns/job_runnable.rb} +0 -0
  13. data/lib/procon_bypass_man/background/jobs/report_boot_job.rb +5 -3
  14. data/lib/procon_bypass_man/background/jobs/report_error_job.rb +6 -5
  15. data/lib/procon_bypass_man/background/jobs/report_event_base_job.rb +5 -0
  16. data/lib/procon_bypass_man/background/jobs/report_load_config_job.rb +11 -0
  17. data/lib/procon_bypass_man/background/jobs/report_pressed_buttons_job.rb +7 -10
  18. data/lib/procon_bypass_man/background/jobs/report_reload_config_job.rb +5 -4
  19. data/lib/procon_bypass_man/background/jobs/sync_device_stats_job.rb +16 -0
  20. data/lib/procon_bypass_man/background.rb +7 -4
  21. data/lib/procon_bypass_man/buttons_setting_configuration/layer.rb +36 -35
  22. data/lib/procon_bypass_man/buttons_setting_configuration.rb +2 -2
  23. data/lib/procon_bypass_man/bypass/usb_hid_logger.rb +8 -6
  24. data/lib/procon_bypass_man/bypass.rb +13 -6
  25. data/lib/procon_bypass_man/commands/bypass_command.rb +86 -0
  26. data/lib/procon_bypass_man/commands/connect_device_command.rb +7 -2
  27. data/lib/procon_bypass_man/commands/print_boot_message_command.rb +51 -2
  28. data/lib/procon_bypass_man/commands/print_message_command.rb +8 -0
  29. data/lib/procon_bypass_man/commands/run_remote_pbm_action_dispatch_command.rb +21 -0
  30. data/lib/procon_bypass_man/commands/send_error_command.rb +2 -1
  31. data/lib/procon_bypass_man/commands/send_reload_config_event_command.rb +2 -2
  32. data/lib/procon_bypass_man/commands/write_device_id_command.rb +1 -0
  33. data/lib/procon_bypass_man/commands/write_session_id_command.rb +1 -7
  34. data/lib/procon_bypass_man/commands.rb +3 -0
  35. data/lib/procon_bypass_man/configuration.rb +51 -5
  36. data/lib/procon_bypass_man/device_connector.rb +32 -24
  37. data/lib/procon_bypass_man/device_status.rb +44 -0
  38. data/lib/procon_bypass_man/domains/binary/base.rb +11 -0
  39. data/lib/procon_bypass_man/domains/binary/has_immutable_binary.rb +5 -0
  40. data/lib/procon_bypass_man/domains/binary/has_mutable_binary.rb +5 -0
  41. data/lib/procon_bypass_man/domains/binary/inbound_procon_binary.rb +23 -0
  42. data/lib/procon_bypass_man/domains/binary/processing_procon_binary.rb +80 -0
  43. data/lib/procon_bypass_man/domains.rb +11 -0
  44. data/lib/procon_bypass_man/plugin/splatoon2/macro/fast_return.rb +17 -0
  45. data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_left_key.rb +17 -0
  46. data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_right_key.rb +17 -0
  47. data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_up_key.rb +17 -0
  48. data/lib/procon_bypass_man/plugin/splatoon2/mode/guruguru.rb +59 -0
  49. data/lib/procon_bypass_man/plugin/splatoon2/version.rb +9 -0
  50. data/lib/procon_bypass_man/plugins.rb +11 -0
  51. data/lib/procon_bypass_man/processor.rb +4 -5
  52. data/lib/procon_bypass_man/procon/analog_stick_cap.rb +1 -1
  53. data/lib/procon_bypass_man/procon/button.rb +11 -0
  54. data/lib/procon_bypass_man/procon/button_collection.rb +2 -12
  55. data/lib/procon_bypass_man/procon/layer_changer.rb +3 -2
  56. data/lib/procon_bypass_man/procon/press_button_aware.rb +5 -4
  57. data/lib/procon_bypass_man/procon/user_operation.rb +46 -63
  58. data/lib/procon_bypass_man/procon/{analog_stick.rb → value_objects/analog_stick.rb} +3 -4
  59. data/lib/procon_bypass_man/procon/value_objects/procon_reader.rb +34 -0
  60. data/lib/procon_bypass_man/procon.rb +16 -14
  61. data/lib/procon_bypass_man/remote_pbm_action/base_action.rb +53 -0
  62. data/lib/procon_bypass_man/remote_pbm_action/change_pbm_version_action.rb +25 -0
  63. data/lib/procon_bypass_man/remote_pbm_action/commands/update_remote_pbm_action_status_command.rb +24 -0
  64. data/lib/procon_bypass_man/remote_pbm_action/reboot_os_action.rb +21 -0
  65. data/lib/procon_bypass_man/remote_pbm_action/restore_pbm_setting.rb +28 -0
  66. data/lib/procon_bypass_man/remote_pbm_action/stop_pbm_action.rb +21 -0
  67. data/lib/procon_bypass_man/remote_pbm_action/value_objects/remote_pbm_action_object.rb +38 -0
  68. data/lib/procon_bypass_man/remote_pbm_action.rb +32 -0
  69. data/lib/procon_bypass_man/runner.rb +8 -97
  70. data/lib/procon_bypass_man/scheduler.rb +85 -0
  71. data/lib/procon_bypass_man/{callbacks.rb → support/callbacks.rb} +0 -0
  72. data/lib/procon_bypass_man/support/compress_array.rb +56 -0
  73. data/lib/procon_bypass_man/support/http_client.rb +102 -0
  74. data/lib/procon_bypass_man/{on_memory_cache.rb → support/on_memory_cache.rb} +0 -0
  75. data/lib/procon_bypass_man/support/report_http_client.rb +19 -0
  76. data/lib/procon_bypass_man/{timer.rb → support/safe_timeout.rb} +1 -1
  77. data/lib/procon_bypass_man/support/send_device_stats_http_client.rb +9 -0
  78. data/lib/procon_bypass_man/{background/has_server_pool.rb → support/server_pool.rb} +3 -15
  79. data/lib/procon_bypass_man/support/signal_handler.rb +11 -0
  80. data/lib/procon_bypass_man/support/update_remote_pbm_action_status_http_client.rb +9 -0
  81. data/lib/procon_bypass_man/{uptime.rb → support/uptime.rb} +0 -0
  82. data/lib/procon_bypass_man/version.rb +1 -1
  83. data/lib/procon_bypass_man/websocket/pbm_job_client.rb +79 -0
  84. data/lib/procon_bypass_man.rb +68 -34
  85. data/procon_bypass_man.gemspec +5 -3
  86. data/project_template/README.md +18 -11
  87. data/project_template/app.rb +1 -2
  88. data/project_template/setting.yml +8 -8
  89. data/sig/{README.rb → README.md} +0 -0
  90. data/sig/main.rbs +16 -1
  91. metadata +102 -21
  92. data/lib/procon_bypass_man/background/http_client.rb +0 -70
  93. data/lib/procon_bypass_man/background/jobs/report_heartbeat_job.rb +0 -10
  94. data/lib/procon_bypass_man/boot_message.rb +0 -42
  95. data/lib/procon_bypass_man/procon_reader.rb +0 -31
@@ -20,8 +20,11 @@ class ProconBypassMan::Procon
20
20
  end
21
21
  reset!
22
22
 
23
+ # @param [string] binary
23
24
  def initialize(binary)
24
- self.user_operation = ProconBypassMan::Procon::UserOperation.new(binary.dup)
25
+ self.user_operation = ProconBypassMan::Procon::UserOperation.new(
26
+ binary.dup
27
+ )
25
28
  end
26
29
 
27
30
  def status; @@status[:buttons]; end
@@ -43,7 +46,7 @@ class ProconBypassMan::Procon
43
46
 
44
47
  if ongoing_macro.finished?
45
48
  current_layer.macros.each do |macro_name, options|
46
- if options[:if_pressed].all? { |b| user_operation.pressed_button?(b) }
49
+ if user_operation.pressing_all_buttons?(options[:if_pressed])
47
50
  @@status[:ongoing_macro] = MacroRegistry.load(macro_name)
48
51
  end
49
52
  end
@@ -60,7 +63,7 @@ class ProconBypassMan::Procon
60
63
  next
61
64
  end
62
65
 
63
- if options[:if_pressed] && options[:if_pressed].all? { |b| user_operation.pressed_button?(b) }
66
+ if options[:if_pressed] && user_operation.pressing_all_buttons?(options[:if_pressed])
64
67
  FlipCache.fetch(key: button, expires_in: options[:flip_interval]) do
65
68
  status[button] = !status[button]
66
69
  end
@@ -75,7 +78,7 @@ class ProconBypassMan::Procon
75
78
  @@status[:ongoing_mode] = ProconBypassMan::Procon::ModeRegistry.load(current_layer.mode)
76
79
  end
77
80
  if(binary = ongoing_mode.next_binary)
78
- self.user_operation.merge(target_binary: binary)
81
+ self.user_operation.merge([binary].pack("H*"))
79
82
  end
80
83
  return
81
84
  end
@@ -83,24 +86,24 @@ class ProconBypassMan::Procon
83
86
  status
84
87
  end
85
88
 
86
- # @return [String<binary>]
89
+ # @return [ProconBypassMan::Domains::ProcessingProconBinary]
87
90
  def to_binary
88
91
  if ongoing_mode.name != :manual
89
- return user_operation.binary
92
+ return user_operation.binary.raw
90
93
  end
91
94
 
92
95
  if ongoing_macro.ongoing?
93
- step = ongoing_macro.next_step or return(user_operation.binary)
96
+ step = ongoing_macro.next_step or return(user_operation.binary.raw)
94
97
  user_operation.press_button_only(step)
95
- return user_operation.binary
98
+ return user_operation.binary.raw
96
99
  end
97
100
 
98
101
  current_layer.disables.each do |button|
99
102
  user_operation.unpress_button(button)
100
103
  end
101
104
 
102
- current_layer.left_analog_stick_caps.each do |button, options|
103
- if button.nil? || button.all? { |b| user_operation.pressed_button?(b) }
105
+ current_layer.left_analog_stick_caps.each do |buttons, options|
106
+ if buttons.nil? || user_operation.pressing_all_buttons?(buttons)
104
107
  options[:force_neutral]&.each do |force_neutral_button|
105
108
  user_operation.unpress_button(force_neutral_button)
106
109
  end
@@ -116,7 +119,7 @@ class ProconBypassMan::Procon
116
119
  end
117
120
 
118
121
  # 押している時だけ連打
119
- if options[:if_pressed] && options[:if_pressed].all? { |b| user_operation.pressed_button?(b) }
122
+ if options[:if_pressed] && user_operation.pressing_all_buttons?(options[:if_pressed])
120
123
  if !status[button]
121
124
  user_operation.unpress_button(button)
122
125
  end
@@ -128,16 +131,15 @@ class ProconBypassMan::Procon
128
131
  end
129
132
 
130
133
  current_layer.remaps.each do |from_button, to_buttons|
131
- if user_operation.pressed_button?(from_button)
134
+ if user_operation.pressing_button?(from_button)
132
135
  user_operation.unpress_button(from_button)
133
- # TODO 2重でpressしないようにしたい
134
136
  to_buttons[:to].each do |to_button|
135
137
  user_operation.press_button(to_button)
136
138
  end
137
139
  end
138
140
  end
139
141
 
140
- user_operation.binary
142
+ user_operation.binary.raw
141
143
  end
142
144
 
143
145
  private
@@ -0,0 +1,53 @@
1
+ module ProconBypassMan
2
+ module RemotePbmAction
3
+ class ActionUnexpectedError < StandardError; end
4
+ class NeedPbmVersionError < ActionUnexpectedError; end
5
+
6
+ class BaseAction
7
+ attr_accessor :pbm_job_uuid
8
+
9
+ # @param [String] pbm_job_uuid
10
+ def initialize(pbm_job_uuid: )
11
+ self.pbm_job_uuid = pbm_job_uuid
12
+ end
13
+
14
+ # @return [void]
15
+ def action_content(_args)
16
+ raise NotImplementedError, nil
17
+ end
18
+
19
+ # @param [Hash] args
20
+ # @return [void]
21
+ def run!(job_args: )
22
+ before_action_callback
23
+ action_content(args: job_args)
24
+ after_action_callback
25
+ rescue => e
26
+ be_failed
27
+ ProconBypassMan::SendErrorCommand.execute(error: e)
28
+ end
29
+
30
+ private
31
+
32
+ # @return [void]
33
+ def before_action_callback; end
34
+ # @return [void]
35
+ def after_action_callback; end
36
+
37
+ # @return [void]
38
+ def be_failed
39
+ ProconBypassMan::UpdateRemotePbmActionStatusCommand.new(pbm_job_uuid: pbm_job_uuid).execute(to_status: :failed)
40
+ end
41
+
42
+ # @return [void]
43
+ def be_in_progress
44
+ ProconBypassMan::UpdateRemotePbmActionStatusCommand.new(pbm_job_uuid: pbm_job_uuid).execute(to_status: :in_progress)
45
+ end
46
+
47
+ # @return [void]
48
+ def be_processed
49
+ ProconBypassMan::UpdateRemotePbmActionStatusCommand.new(pbm_job_uuid: pbm_job_uuid).execute(to_status: :processed)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,25 @@
1
+ module ProconBypassMan
2
+ module RemotePbmAction
3
+ class ChangePbmVersionAction < BaseAction
4
+
5
+ def action_content(args: )
6
+ require "pbmenv"
7
+ ProconBypassMan.logger.info "execute ChangePbmVersionAction!"
8
+ pbm_version = args["pbm_version"] or raise(ProconBypassMan::RemotePbmAction::NeedPbmVersionError, "pbm_versionが必要です, #{args.inspect}")
9
+ Pbmenv.install(pbm_version)
10
+ Pbmenv.use(pbm_version)
11
+ `reboot` # symlinkの参照先が変わるのでrebootする必要がある
12
+ end
13
+
14
+ private
15
+
16
+ def before_action_callback
17
+ be_processed
18
+ end
19
+
20
+ def after_action_callback
21
+ # no-op
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ module ProconBypassMan
2
+ class UpdateRemotePbmActionStatusCommand
3
+ # @param [String] pbm_job_uuid
4
+ def initialize(pbm_job_uuid: )
5
+ @pbm_job_uuid = pbm_job_uuid
6
+ end
7
+
8
+ # @param [String] to_status
9
+ # @return [void]
10
+ def execute(to_status: )
11
+ ProconBypassMan::UpdateRemotePbmActionStatusHttpClient.new(
12
+ path: path,
13
+ server_pool: ProconBypassMan.config.server_pool,
14
+ ).put(to_status: to_status)
15
+ end
16
+
17
+ private
18
+
19
+ # @return [String]
20
+ def path
21
+ "/api/devices/#{ProconBypassMan.device_id}/pbm_jobs/#{@pbm_job_uuid}"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ module ProconBypassMan
2
+ module RemotePbmAction
3
+ class RebootOsAction < BaseAction
4
+
5
+ def action_content(_args)
6
+ ProconBypassMan.logger.info "execute RebootOsAction!"
7
+ `reboot`
8
+ end
9
+
10
+ private
11
+
12
+ def before_action_callback
13
+ be_processed
14
+ end
15
+
16
+ def after_action_callback
17
+ # no-op
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ module ProconBypassMan
2
+ module RemotePbmAction
3
+ class RestorePbmSettingAction < BaseAction
4
+
5
+ def action_content(args: )
6
+ require "pbmenv"
7
+ ProconBypassMan.logger.info "execute RestorePbmSettingAction!"
8
+ setting = args.dig("setting") or raise(ProconBypassMan::RemotePbmAction::NeedPbmVersionError, "settingが必要です, #{args.inspect}")
9
+ File.write(
10
+ ProconBypassMan::ButtonsSettingConfiguration.instance.setting_path,
11
+ setting.to_yaml,
12
+ )
13
+ ProconBypassMan.hot_reload!
14
+ end
15
+
16
+ private
17
+
18
+ def before_action_callback
19
+ be_in_progress
20
+ end
21
+
22
+ def after_action_callback
23
+ be_processed
24
+ end
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,21 @@
1
+ module ProconBypassMan
2
+ module RemotePbmAction
3
+ class StopPbmAction < BaseAction
4
+
5
+ def action_content(_args)
6
+ ProconBypassMan.logger.info "execute StopPbmAction!"
7
+ Process.kill("TERM", ProconBypassMan.pid)
8
+ end
9
+
10
+ private
11
+
12
+ def before_action_callback
13
+ be_processed
14
+ end
15
+
16
+ def after_action_callback
17
+ # no-op
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ module ProconBypassMan
2
+ class RemotePbmActionObject
3
+ # valueobjectがvalidatorの責務も持っている. 今度分離する
4
+ class ValidationError < StandardError; end
5
+ class MustBeNotNilError < ValidationError; end
6
+ class NonSupportAction < ValidationError; end
7
+
8
+ attr_accessor :action, :status, :uuid, :created_at, :job_args
9
+
10
+ # @param [String] action
11
+ # @param [String] status
12
+ # @param [String] #uuid
13
+ # @param [Time] created_at
14
+ # @return [Hash] job_args
15
+ def initialize(action: , status:, uuid:, created_at:, job_args: )
16
+ self.action = action
17
+ self.status = status
18
+ self.uuid = uuid
19
+ self.created_at = created_at
20
+ self.job_args = job_args
21
+
22
+ freeze
23
+ end
24
+
25
+ # @raise [MustBeNotNilError]
26
+ # @raise [NonSupportAction]
27
+ # @return [void]
28
+ def validate!
29
+ self.action or raise MustBeNotNilError, "actionは値が必須です"
30
+ self.status or raise MustBeNotNilError, "statusは値が必須です"
31
+ self.uuid or raise MustBeNotNilError, "uuidは値が必須です"
32
+
33
+ unless ProconBypassMan::RemotePbmAction::ACTIONS.include?(action)
34
+ raise NonSupportAction, "知らないアクションです"
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,32 @@
1
+ module ProconBypassMan
2
+ module RemotePbmAction
3
+ require "procon_bypass_man/remote_pbm_action/base_action"
4
+ require "procon_bypass_man/remote_pbm_action/change_pbm_version_action"
5
+ require "procon_bypass_man/remote_pbm_action/reboot_os_action"
6
+ require "procon_bypass_man/remote_pbm_action/stop_pbm_action"
7
+ require "procon_bypass_man/remote_pbm_action/restore_pbm_setting.rb"
8
+ require "procon_bypass_man/remote_pbm_action/commands/update_remote_pbm_action_status_command"
9
+
10
+ ACTION_CHANGE_PBM_VERSION = "change_pbm_version"
11
+ ACTION_REBOOT_OS = "reboot_os"
12
+ ACTION_STOP_PBM = "stop_pbm"
13
+ ACTION_RESTORE_SETTING = "restore_pbm_setting"
14
+
15
+ ACTIONS = [
16
+ ACTION_CHANGE_PBM_VERSION,
17
+ ACTION_REBOOT_OS,
18
+ ACTION_STOP_PBM,
19
+ ACTION_RESTORE_SETTING,
20
+ ]
21
+
22
+ STATUS_FAILED = :failed
23
+ STATUS_IN_PROGRESS = :in_progress
24
+ STATUS_PROCESSED = :processed
25
+
26
+ ACTION_STATUSES = [
27
+ STATUS_FAILED,
28
+ STATUS_IN_PROGRESS,
29
+ STATUS_PROCESSED,
30
+ ]
31
+ end
32
+ end
@@ -1,17 +1,15 @@
1
1
  require_relative "io_monitor"
2
- require_relative "uptime"
3
- require_relative "boot_message"
4
- require_relative "background/job_runner"
5
2
 
6
3
  class ProconBypassMan::Runner
7
4
  class InterruptForRestart < StandardError; end
8
5
 
6
+ include ProconBypassMan::SignalHandler
7
+
9
8
  def initialize(gadget: , procon: )
10
9
  @gadget = gadget
11
10
  @procon = procon
12
11
 
13
12
  ProconBypassMan::PrintBootMessageCommand.execute
14
- ProconBypassMan::Background::JobRunner.start!
15
13
  end
16
14
 
17
15
  def run
@@ -28,9 +26,11 @@ class ProconBypassMan::Runner
28
26
 
29
27
  loop do
30
28
  $will_terminate_token = false
31
- main_loop_pid = fork { main_loop }
29
+ # NOTE メインプロセスではThreadをいくつか起動しているので念のためパフォーマンスを優先するためにforkしていく
30
+ main_loop_pid = Kernel.fork { ProconBypassMan::BypassCommand.new(gadget: @gadget, procon: @procon).execute }
32
31
 
33
32
  begin
33
+ # TODO 小プロセスが消滅した時に、メインプロセスは生き続けてしまい、何もできなくなる問題がある
34
34
  while(readable_io = IO.select([self_read]))
35
35
  signal = readable_io.first[0].gets.strip
36
36
  handle_signal(signal)
@@ -39,14 +39,14 @@ class ProconBypassMan::Runner
39
39
  $will_terminate_token = true
40
40
  Process.kill("TERM", main_loop_pid)
41
41
  Process.wait
42
- ProconBypassMan.logger.info("Reloading config file")
42
+ ProconBypassMan::PrintMessageCommand.execute(text: "Reloading config file")
43
43
  begin
44
44
  ProconBypassMan::ButtonsSettingConfiguration::Loader.reload_setting
45
+ ProconBypassMan::SendReloadConfigEventCommand.execute
45
46
  rescue ProconBypassMan::CouldNotLoadConfigError
46
47
  ProconBypassMan::SendErrorCommand.execute(error: "設定ファイルが不正です。再読み込みができませんでした")
47
48
  end
48
- ProconBypassMan::SendReloadConfigEventCommand.execute
49
- ProconBypassMan.logger.info("バイパス処理を再開します")
49
+ ProconBypassMan::PrintMessageCommand.execute(text: "バイパス処理を再開します")
50
50
  rescue Interrupt
51
51
  $will_terminate_token = true
52
52
  Process.kill("TERM", main_loop_pid)
@@ -59,93 +59,4 @@ class ProconBypassMan::Runner
59
59
  end
60
60
  end
61
61
  end
62
-
63
- private
64
-
65
- def main_loop
66
- ProconBypassMan::IOMonitor.start!
67
- ProconBypassMan::Background::JobRunner.start!
68
-
69
- # gadget => procon
70
- # 遅くていい
71
- monitor1 = ProconBypassMan::IOMonitor.new(label: "switch -> procon")
72
- monitor2 = ProconBypassMan::IOMonitor.new(label: "procon -> switch")
73
- ProconBypassMan.logger.info "Thread1を起動します"
74
- t1 = Thread.new do
75
- timer = ProconBypassMan::Timer.new(timeout: Time.now + 10)
76
- bypass = ProconBypassMan::Bypass.new(gadget: @gadget, procon: @procon, monitor: monitor1)
77
- loop do
78
- break if $will_terminate_token
79
- timer.throw_if_timeout!
80
- bypass.send_gadget_to_procon!
81
- sleep(0.005)
82
- rescue ProconBypassMan::Timer::Timeout
83
- ProconBypassMan.logger.info "10秒経過したのでThread1を終了します"
84
- monitor1.shutdown
85
- puts "10秒経過したのでThread1を終了します"
86
- break
87
- rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError => e
88
- ProconBypassMan::SendErrorCommand.execute(error: "Switchとの切断されました.終了処理を開始します. #{e.full_message}")
89
- Process.kill "TERM", Process.ppid
90
- rescue Errno::ETIMEDOUT => e
91
- # TODO まれにこれが発生する. 再接続したい
92
- ProconBypassMan::SendErrorCommand.execute(error: "Switchと意図せず切断されました.終了処理を開始します. #{e.full_message}")
93
- Process.kill "TERM", Process.ppid
94
- end
95
- ProconBypassMan.logger.info "Thread1を終了します"
96
- end
97
-
98
- # procon => gadget
99
- # シビア
100
- ProconBypassMan.logger.info "Thread2を起動します"
101
- t2 = Thread.new do
102
- bypass = ProconBypassMan::Bypass.new(gadget: @gadget, procon: @procon, monitor: monitor2)
103
- loop do
104
- break if $will_terminate_token
105
- bypass.send_procon_to_gadget!
106
- rescue EOFError => e
107
- ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します. #{e.full_message}")
108
- Process.kill "TERM", Process.ppid
109
- rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError => e
110
- ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します2. #{e.full_message}")
111
- Process.kill "TERM", Process.ppid
112
- end
113
- ProconBypassMan.logger.info "Thread2を終了します"
114
- end
115
-
116
- self_read, self_write = IO.pipe
117
- %w(TERM INT).each do |sig|
118
- begin
119
- trap sig do
120
- self_write.puts(sig)
121
- end
122
- rescue ArgumentError
123
- puts "プロセスでSignal #{sig} not supported"
124
- end
125
- end
126
-
127
- ProconBypassMan.logger.info "子プロセスでgraceful shutdownの準備ができました"
128
- begin
129
- while(readable_io = IO.select([self_read]))
130
- signal = readable_io.first[0].gets.strip
131
- handle_signal(signal)
132
- end
133
- rescue Interrupt
134
- $will_terminate_token = true
135
- [t1, t2].each(&:join)
136
- @gadget&.close
137
- @procon&.close
138
- exit 1
139
- end
140
- end
141
-
142
- def handle_signal(sig)
143
- ProconBypassMan.logger.info "#{$$}で#{sig}を受け取りました"
144
- case sig
145
- when 'USR2'
146
- raise InterruptForRestart
147
- when 'INT', 'TERM'
148
- raise Interrupt
149
- end
150
- end
151
62
  end
@@ -0,0 +1,85 @@
1
+ module ProconBypassMan
2
+ class Scheduler
3
+ class Schedule
4
+ attr_accessor :klass, :args, :interval, :next_enqueue_at
5
+
6
+ # @param [any] klass
7
+ # @param [Array] args
8
+ # @param [Integer] interval
9
+ def initialize(klass: , args: , interval: )
10
+ self.klass = klass
11
+ self.args = args
12
+ self.interval = interval
13
+ self.next_enqueue_at = Time.now
14
+ end
15
+
16
+ # @return [void]
17
+ def enqueue
18
+ klass.perform_async(*unwrap_args(args))
19
+ set_next_enqueue_at!
20
+ end
21
+
22
+ # @return [boolean]
23
+ def past_interval?
24
+ next_enqueue_at < Time.now
25
+ end
26
+
27
+ private
28
+
29
+ # @return [void]
30
+ def set_next_enqueue_at!
31
+ self.next_enqueue_at = Time.now + interval
32
+ end
33
+
34
+ # @param [Array] args
35
+ # @return [void]
36
+ def unwrap_args(args)
37
+ args.map do |arg|
38
+ case arg
39
+ when Proc
40
+ arg.call
41
+ else
42
+ arg
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ # @return [Hash]
49
+ def self.schedules
50
+ @@schedules
51
+ end
52
+
53
+ @@schedules = {}
54
+
55
+ def self.start!
56
+ register_schedules
57
+
58
+ @@thread = Thread.start do
59
+ loop do
60
+ schedules.each do |_key, schedule|
61
+ if schedule.past_interval?
62
+ schedule.enqueue
63
+ end
64
+ end
65
+ sleep 10
66
+ end
67
+ end
68
+ end
69
+
70
+ def self.register_schedules
71
+ register(
72
+ schedule: Schedule.new(
73
+ klass: ProconBypassMan::SyncDeviceStatsJob,
74
+ args: [->{ ProconBypassMan::DeviceStatus.current }],
75
+ interval: 60,
76
+ )
77
+ )
78
+ end
79
+
80
+ # @param [Schedule] schedule
81
+ def self.register(schedule: )
82
+ schedules[schedule.klass] = schedule
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,56 @@
1
+ module ProconBypassMan
2
+ class CompressArray
3
+ class CompressibleValue
4
+ # @params [String] prev
5
+ # @params [String] current
6
+ def initialize(prev, current)
7
+ @prev = prev
8
+ @current = current
9
+ end
10
+
11
+ # @return [Boolean]
12
+ def compress?
13
+ @prev.include?(@current)
14
+ end
15
+
16
+ # @return [String]
17
+ def to_s_with_mark
18
+ if /^(.+) \* (\d+)/ =~ @prev
19
+ value = $1
20
+ count = $2
21
+ return "#{value} * #{count.to_i + 1}"
22
+ end
23
+ if /^(.+)/ =~ @prev
24
+ value = $1
25
+ return "#{value} * 1"
26
+ end
27
+ end
28
+ end
29
+
30
+ def initialize(array)
31
+ @array = array
32
+ end
33
+
34
+ # @return [Array<String>]
35
+ def compress
36
+ previous_value = nil
37
+ @array.reduce([]) do |acc, item|
38
+ if previous_value.nil?
39
+ acc << item
40
+ previous_value = item
41
+ next acc
42
+ end
43
+
44
+ if CompressibleValue.new(previous_value, item).compress?
45
+ registered_value = acc.pop
46
+ acc << CompressibleValue.new(registered_value, item).to_s_with_mark
47
+ else
48
+ acc << item
49
+ end
50
+
51
+ previous_value = item
52
+ next acc
53
+ end
54
+ end
55
+ end
56
+ end