acpc_table_manager 1.0.9 → 2.0.0
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/exe/acpc_proxy +5 -1
- data/exe/acpc_table_manager +5 -1
- data/lib/acpc_table_manager/config.rb +16 -4
- data/lib/acpc_table_manager/maintainer.rb +81 -8
- data/lib/acpc_table_manager/simple_logging.rb +1 -1
- data/lib/acpc_table_manager/table_queue.rb +19 -14
- data/lib/acpc_table_manager/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e5d135a405ab862b042bc72b5bc5f9171e3bd0ed
|
|
4
|
+
data.tar.gz: 0ee34a84a44f500946fdab2e8b08945b0ce09366
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8c0d1bee251f1d5bc040c6feb568cc278ef5fcbef42f020199ab5dea64ebb89c0a92ed7e440ffa6a67a210da187d1e4810ac7fb849e063803b5bc1bd40877d8d
|
|
7
|
+
data.tar.gz: a13cab8ef8c26b889577d05094bed698b00ceca9f02bba5b34c137f8fe73dd2534ffdefd2dd0d8e4e4c835905753a975d00862c9d3db36733aff9bf1b1fb2812
|
data/exe/acpc_proxy
CHANGED
|
@@ -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
|
-
|
|
85
|
+
AcpcTableManager.notify e # Send an email notification
|
|
82
86
|
end
|
data/exe/acpc_table_manager
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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!
|
|
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
|
|
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
|
-
|
|
40
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
-
#
|
|
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
|
|
361
|
+
return nil if @matches_to_start.empty?
|
|
359
362
|
else
|
|
360
363
|
break
|
|
361
364
|
end
|
|
362
365
|
end
|
|
363
|
-
return
|
|
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
|
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:
|
|
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:
|
|
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.
|
|
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
|