acpc_table_manager 1.0.9 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c92fc6d2b98a660e84a1c35388a611ea823e1aff
4
- data.tar.gz: ca8cf252e3be0b58f38eae14b5473e7fc03eb717
3
+ metadata.gz: e5d135a405ab862b042bc72b5bc5f9171e3bd0ed
4
+ data.tar.gz: 0ee34a84a44f500946fdab2e8b08945b0ce09366
5
5
  SHA512:
6
- metadata.gz: 19bb3dcdffa38b0569a6f3634a3e7010783f9022867bbf589c778ea89d17f427b0b3a3f877295bd914437b884af637791dc741da51832ed6e6106589f10f6c5c
7
- data.tar.gz: 39be21a03b63c06f4124df18bb2e009557d7208e3fb53d234fae85800ca0fba148c357f2b17c897306e3a63f86daf9587cbcb42a7fdcb40733e322ff0ede65e7
6
+ metadata.gz: 8c0d1bee251f1d5bc040c6feb568cc278ef5fcbef42f020199ab5dea64ebb89c0a92ed7e440ffa6a67a210da187d1e4810ac7fb849e063803b5bc1bd40877d8d
7
+ data.tar.gz: a13cab8ef8c26b889577d05094bed698b00ceca9f02bba5b34c137f8fe73dd2534ffdefd2dd0d8e4e4c835905753a975d00862c9d3db36733aff9bf1b1fb2812
@@ -44,8 +44,12 @@ unless match.running? && !match.finished?
44
44
  raise OptionParser::ArgumentError.new("Match \"#{options[:match_id]}\" is not running or has already finished.")
45
45
  end
46
46
 
47
+ Signal.trap("INT") { exit }
48
+ Signal.trap("TERM") { exit }
49
+
47
50
  begin
48
51
  proxy = AcpcTableManager::Proxy.start match
52
+ proxy.log __method__, options
49
53
  loop do
50
54
  message = AcpcTableManager.redis.blpop(
51
55
  "#{AcpcTableManager.config.player_action_channel_prefix}#{options[:match_id]}",
@@ -78,5 +82,5 @@ rescue => e
78
82
  },
79
83
  Logger::Severity::ERROR
80
84
  )
81
- Rusen.notify e # Send an email notification
85
+ AcpcTableManager.notify e # Send an email notification
82
86
  end
@@ -30,6 +30,10 @@ CONFIG_FILE = options[:table_manager_config]
30
30
 
31
31
  AcpcTableManager.load! CONFIG_FILE
32
32
  table_manager = AcpcTableManager::Maintainer.new
33
+
34
+ Signal.trap("INT") { exit }
35
+ Signal.trap("TERM") { exit }
36
+
33
37
  loop do
34
38
  begin
35
39
  message = AcpcTableManager.redis.blpop("table-manager", :timeout => AcpcTableManager.config.maintenance_interval_s)
@@ -64,6 +68,6 @@ loop do
64
68
  },
65
69
  Logger::Severity::ERROR
66
70
  )
67
- Rusen.notify e # Send an email notification
71
+ AcpcTableManager.notify e
68
72
  end
69
73
  end
@@ -1,6 +1,7 @@
1
1
  require 'socket'
2
2
  require 'json'
3
3
  require 'mongoid'
4
+ require 'moped'
4
5
  require 'rusen'
5
6
  require 'contextual_exceptions'
6
7
  require 'acpc_dealer'
@@ -18,9 +19,9 @@ module AcpcTableManager
18
19
  THIS_MACHINE = Socket.gethostname
19
20
  DEALER_HOST = THIS_MACHINE
20
21
 
21
- attr_reader :file, :log_directory, :my_log_directory, :match_log_directory
22
+ attr_reader :file, :log_directory, :my_log_directory, :match_log_directory, :proxy_pids_file
22
23
 
23
- def initialize(file_path, log_directory_, match_log_directory_, interpolation_hash)
24
+ def initialize(file_path, log_directory_, match_log_directory_, proxy_pids_file_, interpolation_hash)
24
25
  @file = file_path
25
26
  JSON.parse(File.read(file_path)).each do |constant, val|
26
27
  define_singleton_method(constant.to_sym) do
@@ -30,6 +31,7 @@ module AcpcTableManager
30
31
  @log_directory = log_directory_
31
32
  @match_log_directory = match_log_directory_
32
33
  @my_log_directory = File.join(@log_directory, 'acpc_table_manager')
34
+ @proxy_pids_file = proxy_pids_file_
33
35
  @logger = Logger.from_file_name(File.join(@my_log_directory, 'config.log'))
34
36
  end
35
37
 
@@ -124,6 +126,9 @@ module AcpcTableManager
124
126
  @@config_file = nil
125
127
  def self.config_file() @@config_file end
126
128
 
129
+ @@notifier = nil
130
+ def self.notifier() @@notifier end
131
+
127
132
  def self.load_config!(config_data, yaml_directory = File.pwd)
128
133
  interpolation_hash = {
129
134
  pwd: yaml_directory,
@@ -137,6 +142,7 @@ module AcpcTableManager
137
142
  config['table_manager_constants'],
138
143
  config['log_directory'],
139
144
  config['match_log_directory'],
145
+ config['proxy_pids_file'],
140
146
  interpolation_hash
141
147
  )
142
148
  @@exhibition_config = ExhibitionConfig.new(
@@ -145,7 +151,11 @@ module AcpcTableManager
145
151
  Logger.from_file_name(File.join(@@config.my_log_directory, 'exhibition_config.log'))
146
152
  )
147
153
 
148
- Mongoid.logger = Logger.from_file_name(File.join(@@config.log_directory, 'mongoid.log'))
154
+ # Moped.logger = Logger.from_file_name(File.join(@@config.log_directory, 'moped.log'))
155
+ # Mongoid.logger = Logger.from_file_name(File.join(@@config.log_directory, 'mongoid.log'))
156
+ # TODO: These should be set in configuration files
157
+ Moped.logger.level = ::Logger::FATAL
158
+ Mongoid.logger.level = ::Logger::FATAL
149
159
  Mongoid.load!(config['mongoid_config'], config['mongoid_env'].to_sym)
150
160
 
151
161
  if config['error_report']
@@ -156,6 +166,8 @@ module AcpcTableManager
156
166
  Rusen.settings.sections = config['error_report']['sections'] || [:backtrace]
157
167
  Rusen.settings.email_prefix = config['error_report']['email_prefix'] || '[ERROR] '
158
168
  Rusen.settings.smtp_settings = config['error_report']['smtp']
169
+
170
+ @@notifier = Rusen
159
171
  else
160
172
  @@config.log(__method__, {warning: "Email reporting disabled. Please set email configuration to enable this feature."}, Logger::Severity::WARN)
161
173
  end
@@ -182,7 +194,7 @@ module AcpcTableManager
182
194
  end
183
195
 
184
196
  def self.notify(exception)
185
- Rusen.notify exception
197
+ @@notifier.notify(exception) if @@notifier
186
198
  end
187
199
 
188
200
  def self.initialized?
@@ -1,3 +1,4 @@
1
+ require 'yaml'
1
2
  require_relative 'dealer'
2
3
  require_relative 'match'
3
4
 
@@ -8,36 +9,103 @@ module AcpcTableManager
8
9
  class Maintainer
9
10
  include SimpleLogging
10
11
 
12
+ def self.proxy_pids(pids_file)
13
+ if !File.exists?(pids_file)
14
+ File.open(pids_file, 'w') do |pids_file|
15
+ yield pids_file, {} if block_given?
16
+ end
17
+ else
18
+ File.open(pids_file, 'r+') do |pids_file|
19
+ pids = YAML.safe_load(pids_file) || {}
20
+ pids_file.seek(0, IO::SEEK_SET)
21
+ pids_file.truncate(0)
22
+ yield pids_file, pids if block_given?
23
+ end
24
+ end
25
+ end
26
+
27
+ def self.kill_orphan_proxies(pids, pids_file)
28
+ new_pids = []
29
+ pids.each do |pid_pair|
30
+ if AcpcDealer::process_exists?(pid_pair['proxy']) && !AcpcDealer::process_exists?(pid_pair['dealer'])
31
+ AcpcDealer::kill_process pid_pair['proxy']
32
+ sleep 1 # Give the process a chance to exit
33
+
34
+ if AcpcDealer::process_exists?(pid_pair['proxy'])
35
+ AcpcDealer::force_kill_process pid_pair['proxy']
36
+ sleep 1 # Give the process a chance to exit
37
+
38
+ if AcpcDealer::process_exists?(pid_pair['proxy'])
39
+ raise(
40
+ StandardError.new(
41
+ "Proxy process #{pid_pair['proxy']} couldn't be killed!"
42
+ )
43
+ )
44
+ end
45
+ end
46
+ else
47
+ new_pids << pid_pair
48
+ end
49
+ end
50
+ new_pids
51
+ end
52
+
53
+ def self.update_pids(pids)
54
+ pids, pids_file = proxy_pids proxy_pids_file do |pids_file, pids|
55
+ pids = kill_orphan_proxies pids, pids_file
56
+
57
+ matches_started = yield if block_given?
58
+
59
+ matches_started.each do |info|
60
+ if info
61
+ pids << {'dealer' => info[:dealer][:pid], 'proxy' => info[:proxy]}
62
+ end
63
+ end
64
+ pids_file.write(YAML.dump(pids)) unless pids.empty?
65
+ end
66
+ end
67
+
68
+ def self.proxy_pids_file() ::AcpcTableManager.config.proxy_pids_file end
69
+
11
70
  def initialize(logger_ = AcpcTableManager.new_log('table_manager.log'))
12
71
  @logger = logger_
13
-
14
72
  @table_queues = {}
15
- enqueue_waiting_matches
73
+
74
+ maintain!
16
75
 
17
76
  log(__method__)
18
77
  end
19
78
 
20
79
  def enqueue_waiting_matches(game_definition_key=nil)
80
+ queues_touched = []
21
81
  if game_definition_key
22
82
  @table_queues[game_definition_key] ||= ::AcpcTableManager::TableQueue.new(game_definition_key)
23
83
  matches_to_check = @table_queues[game_definition_key].my_matches.not_running.and.not_started.to_a
24
84
  matches_to_check.each do |m|
25
85
  unless @table_queues[game_definition_key].running_matches[m.id.to_s]
26
- @table_queues[game_definition_key].enqueue! m.id.to_s, m.dealer_options
86
+ queues_touched << @table_queues[game_definition_key].enqueue!(m.id.to_s, m.dealer_options)
27
87
  end
28
88
  end
29
89
  else
30
90
  ::AcpcTableManager.exhibition_config.games.keys.each do |game_definition_key|
31
- enqueue_waiting_matches game_definition_key
91
+ queues_touched += enqueue_waiting_matches(game_definition_key)
32
92
  end
33
93
  end
94
+ queues_touched
34
95
  end
35
96
 
36
97
  def maintain!
37
98
  log __method__, msg: "Starting maintenance"
38
99
 
39
- enqueue_waiting_matches
40
- @table_queues.each { |key, queue| queue.check_queue! }
100
+ self.class().update_pids self.class().proxy_pids_file do
101
+ queues_touched = enqueue_waiting_matches
102
+ matches_started = []
103
+ queues_touched.each do |_, queue|
104
+ matches_started << queue.check_queue!
105
+ end
106
+ matches_started
107
+ end
108
+
41
109
  clean_up_matches!
42
110
 
43
111
  log __method__, msg: "Finished maintenance"
@@ -61,7 +129,10 @@ module AcpcTableManager
61
129
  rescue Mongoid::Errors::DocumentNotFound
62
130
  return kill_match!(match_id)
63
131
  else
64
- @table_queues[m.game_definition_key.to_s].enqueue! match_id, options
132
+ self.class().update_pids self.class().proxy_pids_file do
133
+ @table_queues[m.game_definition_key.to_s].enqueue! match_id, options
134
+ @table_queues[m.game_definition_key.to_s].check_queue!
135
+ end
65
136
  end
66
137
  end
67
138
 
@@ -71,7 +142,9 @@ module AcpcTableManager
71
142
  rescue Mongoid::Errors::DocumentNotFound
72
143
  return kill_match!(match_id)
73
144
  else
74
- @table_queues[match.game_definition_key.to_s].start_proxy match
145
+ self.class().update_pids self.class().proxy_pids_file do
146
+ [@table_queues[match.game_definition_key.to_s].start_proxy(match)]
147
+ end
75
148
  end
76
149
  end
77
150
 
@@ -5,7 +5,7 @@ require 'fileutils'
5
5
  class Logger
6
6
  # Defaults correspond to Logger#new defaults
7
7
  def self.from_file_name(file_name, shift_age = 0, shift_size = 1048576)
8
- unless File.exists?(file_name)
8
+ unless File.exist?(file_name)
9
9
  FileUtils.mkdir_p File.dirname(file_name)
10
10
  FileUtils.touch file_name
11
11
  end
@@ -55,7 +55,6 @@ module AcpcTableManager
55
55
  log(__method__, msg: "Opponents started for #{match.id.to_s}")
56
56
 
57
57
  start_proxy match
58
- self
59
58
  end
60
59
 
61
60
  def start_proxy(match)
@@ -81,6 +80,7 @@ module AcpcTableManager
81
80
  pid: @running_matches[match.id.to_s][:proxy]
82
81
  }
83
82
  )
83
+ @running_matches[match.id.to_s]
84
84
  end
85
85
 
86
86
  def my_matches
@@ -114,7 +114,7 @@ module AcpcTableManager
114
114
  end
115
115
  end
116
116
 
117
- # @return (@see #dequeue!)
117
+ # @return +self+
118
118
  def enqueue!(match_id, dealer_options)
119
119
  log(
120
120
  __method__,
@@ -127,18 +127,18 @@ module AcpcTableManager
127
127
  )
128
128
 
129
129
  if @running_matches[match_id]
130
- return log(
130
+ log(
131
131
  __method__,
132
132
  msg: "Match #{match_id} already started!"
133
133
  )
134
+ return self
134
135
  end
135
136
 
136
137
  @matches_to_start << {match_id: match_id, options: dealer_options}
137
-
138
- check_queue!
138
+ self
139
139
  end
140
140
 
141
- # @return (@see #dequeue!)
141
+ # @return [Array] The list of PID information about the matches that were dequeued.
142
142
  def check_queue!
143
143
  log __method__
144
144
 
@@ -146,11 +146,14 @@ module AcpcTableManager
146
146
 
147
147
  log __method__, {num_running_matches: @running_matches.length, num_matches_to_start: @matches_to_start.length}
148
148
 
149
- if @running_matches.length < AcpcTableManager.exhibition_config.games[@game_definition_key]['max_num_matches']
150
- dequeue!
151
- else
152
- nil
149
+ matches_started = []
150
+ while !@matches_to_start.empty? && @running_matches.length < AcpcTableManager.exhibition_config.games[@game_definition_key]['max_num_matches']
151
+ matches_started << dequeue
153
152
  end
153
+
154
+ log __method__, {matches_started: matches_started, num_running_matches: @running_matches.length, num_matches_to_start: @matches_to_start.length}
155
+
156
+ matches_started
154
157
  end
155
158
 
156
159
  # @todo Shouldn't be necessary, so this method isn't called right now, but I've written it so I'll leave it for now
@@ -338,8 +341,8 @@ module AcpcTableManager
338
341
  end
339
342
 
340
343
  # @return [Object] The match that has been started or +nil+ if none could
341
- # be started.
342
- def dequeue!
344
+ # be started.
345
+ def dequeue
343
346
  log(
344
347
  __method__,
345
348
  num_matches_to_start: @matches_to_start.length
@@ -355,12 +358,12 @@ module AcpcTableManager
355
358
  begin
356
359
  match = Match.find match_id
357
360
  rescue Mongoid::Errors::DocumentNotFound
358
- return self if @matches_to_start.empty?
361
+ return nil if @matches_to_start.empty?
359
362
  else
360
363
  break
361
364
  end
362
365
  end
363
- return self unless match_id
366
+ return nil unless match_id
364
367
 
365
368
  options = match_info[:options]
366
369
 
@@ -452,6 +455,8 @@ module AcpcTableManager
452
455
  )
453
456
 
454
457
  start_players! match
458
+
459
+ @running_matches[match_id]
455
460
  end
456
461
  end
457
462
  end
@@ -1,3 +1,3 @@
1
1
  module AcpcTableManager
2
- VERSION = "1.0.9"
2
+ VERSION = "2.0.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acpc_table_manager
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dustin Morrill
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-12-11 00:00:00.000000000 Z
11
+ date: 2016-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pony
@@ -318,7 +318,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
318
318
  version: '0'
319
319
  requirements: []
320
320
  rubyforge_project:
321
- rubygems_version: 2.2.2
321
+ rubygems_version: 2.5.1
322
322
  signing_key:
323
323
  specification_version: 4
324
324
  summary: Backend components to the ACPC Poker GUI Client