acpc_table_manager 0.0.1 → 1.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 +83 -0
- data/exe/acpc_table_manager +33 -27
- data/lib/acpc_table_manager.rb +1 -2
- data/lib/acpc_table_manager/config.rb +25 -1
- data/lib/acpc_table_manager/maintainer.rb +131 -0
- data/lib/acpc_table_manager/proxy.rb +6 -2
- data/lib/acpc_table_manager/simple_logging.rb +3 -3
- data/lib/acpc_table_manager/table_queue.rb +66 -5
- data/lib/acpc_table_manager/version.rb +1 -1
- metadata +5 -4
- data/lib/acpc_table_manager/param_retrieval.rb +0 -32
- data/lib/acpc_table_manager/table_manager.rb +0 -260
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4e0fbeda8f0f050a57fbf5d42806d6da5570a67
|
4
|
+
data.tar.gz: a2736fd639a962b9eada95a86e5e92bbe4e2f347
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c15bd647dc2f70b11b5fd2a27bca7f11d1b7d24e88bd2de4f55cd93e99c1781799f4c0361f755f274efadaee95eb1ef81f9dc541fcc309299903e4a202283b8
|
7
|
+
data.tar.gz: eeb9c3573365c3e11c4fe260150ee0c16578318b7ae26c00c0a2050c96f573d5afe469699f0b388192f858b5daa803863148a567448dbeff6001fb624421e441
|
data/exe/acpc_proxy
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'acpc_table_manager'
|
4
|
+
require 'redis'
|
5
|
+
require 'json'
|
6
|
+
require 'optparse'
|
7
|
+
require 'mongoid'
|
8
|
+
|
9
|
+
ARGV << '-h' if ARGV.empty?
|
10
|
+
|
11
|
+
options = {}
|
12
|
+
OptionParser.new do |opts|
|
13
|
+
opts.banner = "Usage: #{$0} [options]"
|
14
|
+
|
15
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
16
|
+
puts opts
|
17
|
+
exit
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on("-m", "--match_id MATCH ID", "The ID of the match to join.") do |c|
|
21
|
+
options[:match_id] = c.strip
|
22
|
+
end
|
23
|
+
opts.on("-t", "--config TABLE MANAGER CONFIG", "Table manager configuration file.") do |c|
|
24
|
+
options[:table_manager_config] = File.expand_path c, Dir.pwd
|
25
|
+
end
|
26
|
+
end.parse!
|
27
|
+
|
28
|
+
raise OptionParser::MissingArgument.new('MATCH ID') unless options[:match_id]
|
29
|
+
raise OptionParser::MissingArgument.new('TABLE MANAGER CONFIG') unless options[:table_manager_config]
|
30
|
+
|
31
|
+
raise OptionParser::ArgumentError.new("#{options[:table_manager_config]} doesn't exist.") unless File.exist?(options[:table_manager_config])
|
32
|
+
|
33
|
+
CONFIG_FILE = options[:table_manager_config]
|
34
|
+
|
35
|
+
AcpcTableManager.load! CONFIG_FILE
|
36
|
+
|
37
|
+
match = begin
|
38
|
+
AcpcTableManager::Match.find options[:match_id]
|
39
|
+
rescue Mongoid::Errors::DocumentNotFound
|
40
|
+
raise OptionParser::ArgumentError.new("Match \"#{options[:match_id]}\" doesn't exist.")
|
41
|
+
end
|
42
|
+
|
43
|
+
unless match.running? && !match.finished?
|
44
|
+
raise OptionParser::ArgumentError.new("Match \"#{options[:match_id]}\" is not running or has already finished.")
|
45
|
+
end
|
46
|
+
|
47
|
+
proxy = AcpcTableManager::Proxy.start match
|
48
|
+
|
49
|
+
loop do
|
50
|
+
begin
|
51
|
+
message = AcpcTableManager.redis.blpop(
|
52
|
+
"play-action-in-#{options[:match_id]}",
|
53
|
+
:timeout => AcpcTableManager.config.maintenance_interval_s
|
54
|
+
)
|
55
|
+
if message
|
56
|
+
data = JSON.parse message[1]
|
57
|
+
proxy.play! data[AcpcTableManager.config.action_key]
|
58
|
+
end
|
59
|
+
if proxy.match_ended?
|
60
|
+
AcpcTableManager.redis.rpush(
|
61
|
+
'table-manager',
|
62
|
+
{
|
63
|
+
'request' => AcpcTableManager.config.kill_match,
|
64
|
+
'params' => {
|
65
|
+
AcpcTableManager.config.match_id_key => options[:match_id]
|
66
|
+
}
|
67
|
+
}.to_json
|
68
|
+
)
|
69
|
+
exit
|
70
|
+
end
|
71
|
+
rescue => e
|
72
|
+
proxy.log(
|
73
|
+
__method__,
|
74
|
+
{
|
75
|
+
match_id: options[:match_id],
|
76
|
+
message: e.message,
|
77
|
+
backtrace: e.backtrace
|
78
|
+
},
|
79
|
+
Logger::Severity::ERROR
|
80
|
+
)
|
81
|
+
Rusen.notify e # Send an email notification
|
82
|
+
end
|
83
|
+
end
|
data/exe/acpc_table_manager
CHANGED
@@ -20,44 +20,50 @@ OptionParser.new do |opts|
|
|
20
20
|
opts.on("-t", "--table_manager TABLE MANAGER CONFIG", "Table manager configuration file.") do |c|
|
21
21
|
options[:table_manager_config] = File.expand_path c, Dir.pwd
|
22
22
|
end
|
23
|
-
opts.on("-r", "--redis REDIS CONFIG", "Redis configuration file.") do |c|
|
24
|
-
options[:redis_config] = File.expand_path c, Dir.pwd
|
25
|
-
end
|
26
|
-
opts.on("-e", "--env [ENVIRONMENT MODE]", "The environment mode to run in, such as 'development' or 'production'.") do |e|
|
27
|
-
options[:environment_mode] = e if e && !e.empty?
|
28
|
-
end
|
29
23
|
end.parse!
|
30
24
|
|
31
25
|
raise OptionParser::MissingArgument.new('TABLE MANAGER CONFIG') unless options[:table_manager_config]
|
32
|
-
raise OptionParser::MissingArgument.new('REDIS CONFIG') unless options[:redis_config]
|
33
26
|
|
34
27
|
raise OptionParser::ArgumentError.new("#{options[:table_manager_config]} doesn't exist.") unless File.exist?(options[:table_manager_config])
|
35
|
-
raise OptionParser::ArgumentError.new("#{options[:redis_config]} doesn't exist.") unless File.exist?(options[:redis_config])
|
36
|
-
|
37
|
-
REDIS_CONFIG = YAML.load_file(options[:redis_config]).symbolize_keys
|
38
|
-
DFLT = REDIS_CONFIG[:default].symbolize_keys
|
39
|
-
redis = Redis.new(
|
40
|
-
if options[:environment_mode] && REDIS_CONFIG[options[:environment_mode].to_sym]
|
41
|
-
DFLT.merge(REDIS_CONFIG[options[:environment_mode].to_sym].symbolize_keys)
|
42
|
-
else
|
43
|
-
DFLT
|
44
|
-
end
|
45
|
-
)
|
46
28
|
|
47
29
|
CONFIG_FILE = options[:table_manager_config]
|
48
30
|
|
49
31
|
AcpcTableManager.load! CONFIG_FILE
|
50
|
-
table_manager = AcpcTableManager::
|
32
|
+
table_manager = AcpcTableManager::Maintainer.new
|
51
33
|
loop do
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
34
|
+
begin
|
35
|
+
message = AcpcTableManager.redis.blpop("table-manager", :timeout => AcpcTableManager.config.maintenance_interval_s)
|
36
|
+
if message
|
37
|
+
data = JSON.parse message[1]
|
38
|
+
case data['request']
|
39
|
+
when AcpcTableManager.config.start_match_request_code
|
40
|
+
table_manager.enqueue_match!(
|
41
|
+
data['params'][AcpcTableManager.config.match_id_key],
|
42
|
+
data['params'][AcpcTableManager.config.options_key]
|
43
|
+
)
|
44
|
+
when AcpcTableManager.config.kill_match
|
45
|
+
table_manager.kill_match! match_id
|
46
|
+
when 'reload'
|
47
|
+
AcpcTableManager.load! CONFIG_FILE
|
48
|
+
when AcpcTableManager.config.check_match
|
49
|
+
table_manager.check_match data['params'][AcpcTableManager.config.match_id_key]
|
50
|
+
when AcpcTableManager.config.delete_irrelevant_matches_request_code
|
51
|
+
table_manager.clean_up_matches!
|
52
|
+
else
|
53
|
+
raise StandardError.new("Unrecognized request: #{data['request']}")
|
54
|
+
end
|
57
55
|
else
|
58
|
-
table_manager.
|
56
|
+
table_manager.maintain!
|
59
57
|
end
|
60
|
-
|
61
|
-
table_manager.
|
58
|
+
rescue => e
|
59
|
+
table_manager.log(
|
60
|
+
__method__,
|
61
|
+
{
|
62
|
+
message: e.message,
|
63
|
+
backtrace: e.backtrace
|
64
|
+
},
|
65
|
+
Logger::Severity::ERROR
|
66
|
+
)
|
67
|
+
Rusen.notify e # Send an email notification
|
62
68
|
end
|
63
69
|
end
|
data/lib/acpc_table_manager.rb
CHANGED
@@ -6,10 +6,9 @@ require_relative "acpc_table_manager/match_view"
|
|
6
6
|
require_relative "acpc_table_manager/monkey_patches"
|
7
7
|
require_relative "acpc_table_manager/opponents"
|
8
8
|
require_relative "acpc_table_manager/dealer"
|
9
|
-
require_relative "acpc_table_manager/param_retrieval"
|
10
9
|
require_relative "acpc_table_manager/proxy"
|
11
10
|
require_relative "acpc_table_manager/simple_logging"
|
12
|
-
require_relative "acpc_table_manager/
|
11
|
+
require_relative "acpc_table_manager/maintainer"
|
13
12
|
require_relative "acpc_table_manager/table_queue"
|
14
13
|
require_relative "acpc_table_manager/utils"
|
15
14
|
|
@@ -4,9 +4,10 @@ require 'mongoid'
|
|
4
4
|
require 'rusen'
|
5
5
|
require 'contextual_exceptions'
|
6
6
|
require 'acpc_dealer'
|
7
|
+
require 'redis'
|
7
8
|
|
8
9
|
require_relative 'simple_logging'
|
9
|
-
using SimpleLogging::MessageFormatting
|
10
|
+
using AcpcTableManager::SimpleLogging::MessageFormatting
|
10
11
|
|
11
12
|
require_relative 'utils'
|
12
13
|
|
@@ -114,6 +115,15 @@ module AcpcTableManager
|
|
114
115
|
|
115
116
|
@@is_initialized = false
|
116
117
|
|
118
|
+
@@redis_config_file = nil
|
119
|
+
def self.redis_config_file() @@redis_config_file end
|
120
|
+
|
121
|
+
@@redis = nil
|
122
|
+
def self.redis() @@redis end
|
123
|
+
|
124
|
+
@@config_file = nil
|
125
|
+
def self.config_file() @@config_file end
|
126
|
+
|
117
127
|
def self.load_config!(config_data, yaml_directory = File.pwd)
|
118
128
|
interpolation_hash = {
|
119
129
|
pwd: yaml_directory,
|
@@ -150,10 +160,24 @@ module AcpcTableManager
|
|
150
160
|
@@config.log(__method__, {warning: "Email reporting disabled. Please set email configuration to enable this feature."}, Logger::Severity::WARN)
|
151
161
|
end
|
152
162
|
|
163
|
+
if config['redis_config_file']
|
164
|
+
@@redis_config_file = config['redis_config_file']
|
165
|
+
redis_config = YAML.load_file(@@redis_config_file).symbolize_keys
|
166
|
+
dflt = redis_config[:default].symbolize_keys
|
167
|
+
@@redis = Redis.new(
|
168
|
+
if config['redis_environment_mode'] && redis_config[config['redis_environment_mode'].to_sym]
|
169
|
+
dflt.merge(redis_config[config['redis_environment_mode'].to_sym].symbolize_keys)
|
170
|
+
else
|
171
|
+
dflt
|
172
|
+
end
|
173
|
+
)
|
174
|
+
end
|
175
|
+
|
153
176
|
@@is_initialized = true
|
154
177
|
end
|
155
178
|
|
156
179
|
def self.load!(config_file_path)
|
180
|
+
@@config_file = config_file_path
|
157
181
|
load_config! YAML.load_file(config_file_path), File.dirname(config_file_path)
|
158
182
|
end
|
159
183
|
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require_relative 'dealer'
|
2
|
+
require_relative 'match'
|
3
|
+
|
4
|
+
require_relative 'simple_logging'
|
5
|
+
using AcpcTableManager::SimpleLogging::MessageFormatting
|
6
|
+
|
7
|
+
module AcpcTableManager
|
8
|
+
class Maintainer
|
9
|
+
include SimpleLogging
|
10
|
+
|
11
|
+
def initialize(logger_ = AcpcTableManager.new_log('table_manager.log'))
|
12
|
+
@logger = logger_
|
13
|
+
|
14
|
+
@table_queues = {}
|
15
|
+
enqueue_waiting_matches
|
16
|
+
|
17
|
+
log(__method__)
|
18
|
+
end
|
19
|
+
|
20
|
+
def enqueue_waiting_matches(game_definition_key=nil)
|
21
|
+
if game_definition_key
|
22
|
+
@table_queues[game_definition_key] ||= ::AcpcTableManager::TableQueue.new(game_definition_key)
|
23
|
+
@table_queues[game_definition_key].my_matches.not_running.and.not_started.each do |m|
|
24
|
+
@table_queues[game_definition_key].enqueue! m.id.to_s, m.dealer_options
|
25
|
+
end
|
26
|
+
else
|
27
|
+
::AcpcTableManager.exhibition_config.games.keys.each do |game_definition_key|
|
28
|
+
enqueue_waiting_matches game_definition_key
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def maintain!
|
34
|
+
log __method__, msg: "Starting maintenance"
|
35
|
+
|
36
|
+
enqueue_waiting_matches
|
37
|
+
@table_queues.each { |key, queue| queue.check_queue! }
|
38
|
+
clean_up_matches!
|
39
|
+
|
40
|
+
log __method__, msg: "Finished maintenance"
|
41
|
+
end
|
42
|
+
|
43
|
+
def kill_match!(match_id)
|
44
|
+
log(__method__, match_id: match_id)
|
45
|
+
|
46
|
+
@table_queues.each do |key, queue|
|
47
|
+
queue.kill_match!(match_id)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def clean_up_matches!
|
52
|
+
::AcpcTableManager::Match.delete_matches_older_than! 1.day
|
53
|
+
end
|
54
|
+
|
55
|
+
def enqueue_match!(match_id, options)
|
56
|
+
begin
|
57
|
+
m = ::AcpcTableManager::Match.find match_id
|
58
|
+
rescue Mongoid::Errors::DocumentNotFound
|
59
|
+
return kill_match!(match_id)
|
60
|
+
else
|
61
|
+
@table_queues[m.game_definition_key.to_s].enqueue! match_id, options
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def start_proxy!(match_id)
|
66
|
+
begin
|
67
|
+
match = ::AcpcTableManager::Match.find match_id
|
68
|
+
rescue Mongoid::Errors::DocumentNotFound
|
69
|
+
return kill_match!(match_id)
|
70
|
+
else
|
71
|
+
@table_queues[match.game_definition_key.to_s].start_proxy match
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def check_match(match_id)
|
76
|
+
log(__method__, { match_id: match_id })
|
77
|
+
begin
|
78
|
+
match = ::AcpcTableManager::Match.find match_id
|
79
|
+
rescue Mongoid::Errors::DocumentNotFound
|
80
|
+
log(
|
81
|
+
__method__,
|
82
|
+
{
|
83
|
+
msg: "Match \"#{match_id}\" doesn't exist! Killing match.",
|
84
|
+
match_id: match_id
|
85
|
+
},
|
86
|
+
Logger::Severity::ERROR
|
87
|
+
)
|
88
|
+
return kill_match!(match_id)
|
89
|
+
end
|
90
|
+
unless @table_queues[match.game_definition_key.to_s].running_matches[match_id]
|
91
|
+
log(
|
92
|
+
__method__,
|
93
|
+
{
|
94
|
+
msg: "Match \"#{match_id}\" in seat #{match.seat} doesn't have a proxy! Killing match.",
|
95
|
+
match_id: match_id,
|
96
|
+
match_name: match.name,
|
97
|
+
last_updated_at: match.updated_at,
|
98
|
+
running?: match.running?,
|
99
|
+
last_slice_viewed: match.last_slice_viewed,
|
100
|
+
last_slice_present: match.slices.length - 1
|
101
|
+
},
|
102
|
+
Logger::Severity::ERROR
|
103
|
+
)
|
104
|
+
return kill_match!(match_id)
|
105
|
+
end
|
106
|
+
proxy_pid = @table_queues[match.game_definition_key.to_s].running_matches[match_id][:proxy]
|
107
|
+
|
108
|
+
log __method__, {
|
109
|
+
match_id: match_id,
|
110
|
+
running?: proxy_pid && AcpcDealer::process_exists?(proxy_pid)
|
111
|
+
}
|
112
|
+
|
113
|
+
unless proxy_pid && AcpcDealer::process_exists?(proxy_pid)
|
114
|
+
log(
|
115
|
+
__method__,
|
116
|
+
{
|
117
|
+
msg: "The proxy for match \"#{match_id}\" in seat #{match.seat} isn't running! Killing match.",
|
118
|
+
match_id: match_id,
|
119
|
+
match_name: match.name,
|
120
|
+
last_updated_at: match.updated_at,
|
121
|
+
running?: match.running?,
|
122
|
+
last_slice_viewed: match.last_slice_viewed,
|
123
|
+
last_slice_present: match.slices.length - 1
|
124
|
+
},
|
125
|
+
Logger::Severity::ERROR
|
126
|
+
)
|
127
|
+
kill_match!(match_id)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -6,7 +6,7 @@ require 'acpc_poker_player_proxy'
|
|
6
6
|
require 'acpc_poker_types'
|
7
7
|
|
8
8
|
require_relative 'simple_logging'
|
9
|
-
using SimpleLogging::MessageFormatting
|
9
|
+
using AcpcTableManager::SimpleLogging::MessageFormatting
|
10
10
|
|
11
11
|
require 'contextual_exceptions'
|
12
12
|
using ContextualExceptions::ClassRefinement
|
@@ -109,7 +109,11 @@ class Proxy
|
|
109
109
|
def match_ended?
|
110
110
|
return false if @player_proxy.nil?
|
111
111
|
|
112
|
-
@match ||=
|
112
|
+
@match ||= begin
|
113
|
+
Match.find(@match_id)
|
114
|
+
rescue Mongoid::Errors::DocumentNotFound
|
115
|
+
return true
|
116
|
+
end
|
113
117
|
|
114
118
|
@player_proxy.match_ended? ||
|
115
119
|
(
|
@@ -2,8 +2,6 @@ require 'awesome_print'
|
|
2
2
|
require 'logger'
|
3
3
|
require 'fileutils'
|
4
4
|
|
5
|
-
# @todo Move to its own gem the next time I find I need easier logging faculties
|
6
|
-
|
7
5
|
class Logger
|
8
6
|
# Defaults correspond to Logger#new defaults
|
9
7
|
def self.from_file_name(file_name, shift_age = 0, shift_size = 1048576)
|
@@ -20,6 +18,7 @@ class Logger
|
|
20
18
|
end
|
21
19
|
end
|
22
20
|
|
21
|
+
module AcpcTableManager
|
23
22
|
module SimpleLogging
|
24
23
|
module MessageFormatting
|
25
24
|
refine Logger do
|
@@ -51,4 +50,5 @@ module SimpleLogging
|
|
51
50
|
def log(method, variables = nil, msg_type = Logger::Severity::INFO)
|
52
51
|
log_with(logger, method, variables, msg_type)
|
53
52
|
end
|
54
|
-
end
|
53
|
+
end
|
54
|
+
end
|
@@ -2,15 +2,13 @@ require 'acpc_poker_types'
|
|
2
2
|
require 'acpc_dealer'
|
3
3
|
require 'timeout'
|
4
4
|
|
5
|
-
require_relative 'proxy'
|
6
|
-
|
7
5
|
require_relative 'dealer'
|
8
6
|
require_relative 'opponents'
|
9
7
|
require_relative 'config'
|
10
8
|
require_relative 'match'
|
11
9
|
|
12
10
|
require_relative 'simple_logging'
|
13
|
-
using SimpleLogging::MessageFormatting
|
11
|
+
using AcpcTableManager::SimpleLogging::MessageFormatting
|
14
12
|
|
15
13
|
require 'contextual_exceptions'
|
16
14
|
using ContextualExceptions::ClassRefinement
|
@@ -61,8 +59,28 @@ module AcpcTableManager
|
|
61
59
|
end
|
62
60
|
|
63
61
|
def start_proxy(match)
|
64
|
-
|
65
|
-
|
62
|
+
command = "acpc_proxy -t #{AcpcTableManager.config_file} -m #{match.id.to_s}"
|
63
|
+
log(
|
64
|
+
__method__,
|
65
|
+
{
|
66
|
+
msg: "Starting proxy for #{match.id.to_s}",
|
67
|
+
command: command
|
68
|
+
}
|
69
|
+
)
|
70
|
+
|
71
|
+
@running_matches[match.id.to_s][:proxy] = Timeout::timeout(3) do
|
72
|
+
pid = Process.spawn(command)
|
73
|
+
Process.detach(pid)
|
74
|
+
pid
|
75
|
+
end
|
76
|
+
|
77
|
+
log(
|
78
|
+
__method__,
|
79
|
+
{
|
80
|
+
msg: "Started proxy for #{match.id.to_s}",
|
81
|
+
pid: pid
|
82
|
+
}
|
83
|
+
)
|
66
84
|
end
|
67
85
|
|
68
86
|
def my_matches
|
@@ -164,6 +182,7 @@ module AcpcTableManager
|
|
164
182
|
@matches_to_start.delete_if { |m| m[:match_id] == match_id }
|
165
183
|
|
166
184
|
kill_dealer!(match_info[:dealer]) if match_info && match_info[:dealer]
|
185
|
+
kill_proxy!(match_info[:proxy]) if match_info && match_info[:proxy]
|
167
186
|
|
168
187
|
log __method__, match_id: match_id, msg: 'Match successfully killed'
|
169
188
|
end
|
@@ -219,6 +238,48 @@ module AcpcTableManager
|
|
219
238
|
end
|
220
239
|
end
|
221
240
|
|
241
|
+
def kill_proxy!(proxy_pid)
|
242
|
+
log(
|
243
|
+
__method__,
|
244
|
+
pid: proxy_pid,
|
245
|
+
was_running?: true,
|
246
|
+
proxy_running?: AcpcDealer::process_exists?(proxy_pid)
|
247
|
+
)
|
248
|
+
|
249
|
+
if proxy_pid && AcpcDealer::process_exists?(proxy_pid)
|
250
|
+
AcpcDealer.kill_process proxy_pid
|
251
|
+
|
252
|
+
sleep 1 # Give the proxy a chance to exit
|
253
|
+
|
254
|
+
log(
|
255
|
+
__method__,
|
256
|
+
pid: proxy_pid,
|
257
|
+
msg: 'After TERM signal',
|
258
|
+
proxy_still_running?: AcpcDealer::process_exists?(proxy_pid)
|
259
|
+
)
|
260
|
+
|
261
|
+
if AcpcDealer::process_exists?(proxy_pid)
|
262
|
+
AcpcDealer.force_kill_process proxy_pid
|
263
|
+
sleep 1
|
264
|
+
|
265
|
+
log(
|
266
|
+
__method__,
|
267
|
+
pid: proxy_pid,
|
268
|
+
msg: 'After KILL signal',
|
269
|
+
proxy_still_running?: AcpcDealer::process_exists?(proxy_pid)
|
270
|
+
)
|
271
|
+
|
272
|
+
if AcpcDealer::process_exists?(proxy_pid)
|
273
|
+
raise(
|
274
|
+
StandardError.new(
|
275
|
+
"Proxy process #{proxy_pid} couldn't be killed!"
|
276
|
+
)
|
277
|
+
)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
222
283
|
def kill_matches!
|
223
284
|
log __method__
|
224
285
|
running_matches_array = @running_matches.to_a
|
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: 0.0
|
4
|
+
version: 1.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
|
+
date: 2015-12-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pony
|
@@ -254,6 +254,7 @@ description: Backend components to the ACPC Poker GUI Client. Includes a player
|
|
254
254
|
email:
|
255
255
|
- dmorrill10@gmail.com
|
256
256
|
executables:
|
257
|
+
- acpc_proxy
|
257
258
|
- acpc_table_manager
|
258
259
|
extensions: []
|
259
260
|
extra_rdoc_files: []
|
@@ -267,19 +268,19 @@ files:
|
|
267
268
|
- acpc_table_manager.gemspec
|
268
269
|
- bin/console
|
269
270
|
- bin/setup
|
271
|
+
- exe/acpc_proxy
|
270
272
|
- exe/acpc_table_manager
|
271
273
|
- lib/acpc_table_manager.rb
|
272
274
|
- lib/acpc_table_manager/config.rb
|
273
275
|
- lib/acpc_table_manager/dealer.rb
|
276
|
+
- lib/acpc_table_manager/maintainer.rb
|
274
277
|
- lib/acpc_table_manager/match.rb
|
275
278
|
- lib/acpc_table_manager/match_slice.rb
|
276
279
|
- lib/acpc_table_manager/match_view.rb
|
277
280
|
- lib/acpc_table_manager/monkey_patches.rb
|
278
281
|
- lib/acpc_table_manager/opponents.rb
|
279
|
-
- lib/acpc_table_manager/param_retrieval.rb
|
280
282
|
- lib/acpc_table_manager/proxy.rb
|
281
283
|
- lib/acpc_table_manager/simple_logging.rb
|
282
|
-
- lib/acpc_table_manager/table_manager.rb
|
283
284
|
- lib/acpc_table_manager/table_queue.rb
|
284
285
|
- lib/acpc_table_manager/utils.rb
|
285
286
|
- lib/acpc_table_manager/version.rb
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require_relative 'monkey_patches'
|
2
|
-
using AcpcTableManager::MonkeyPatches::StringToEnglishExtension
|
3
|
-
|
4
|
-
require_relative 'config'
|
5
|
-
|
6
|
-
module AcpcTableManager
|
7
|
-
module ParamRetrieval
|
8
|
-
protected
|
9
|
-
|
10
|
-
# @param [Hash<String, Object>] params Parameter hash
|
11
|
-
# @param parameter_key The key of the parameter to be retrieved.
|
12
|
-
# @raise
|
13
|
-
def retrieve_parameter_or_raise_exception(
|
14
|
-
params,
|
15
|
-
parameter_key
|
16
|
-
)
|
17
|
-
raise StandardError.new("nil params hash given") unless params
|
18
|
-
retrieved_param = params[parameter_key]
|
19
|
-
unless retrieved_param
|
20
|
-
raise StandardError.new("No #{parameter_key.to_english} provided")
|
21
|
-
end
|
22
|
-
retrieved_param
|
23
|
-
end
|
24
|
-
|
25
|
-
# @param [Hash<String, Object>] params Parameter hash
|
26
|
-
# @raise (see #param)
|
27
|
-
def retrieve_match_id_or_raise_exception(params)
|
28
|
-
AcpcTableManager.raise_if_uninitialized
|
29
|
-
retrieve_parameter_or_raise_exception params, AcpcTableManager.config.match_id_key
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,260 +0,0 @@
|
|
1
|
-
require_relative 'dealer'
|
2
|
-
require_relative 'match'
|
3
|
-
|
4
|
-
require_relative 'simple_logging'
|
5
|
-
using SimpleLogging::MessageFormatting
|
6
|
-
|
7
|
-
module AcpcTableManager
|
8
|
-
class Null
|
9
|
-
def method_missing(*args, &block) self end
|
10
|
-
end
|
11
|
-
module HandleException
|
12
|
-
protected
|
13
|
-
|
14
|
-
# @param [String] match_id The ID of the match in which the exception occurred.
|
15
|
-
# @param [Exception] e The exception to log.
|
16
|
-
def handle_exception(match_id, e)
|
17
|
-
log(
|
18
|
-
__method__,
|
19
|
-
{
|
20
|
-
match_id: match_id,
|
21
|
-
message: e.message,
|
22
|
-
backtrace: e.backtrace
|
23
|
-
},
|
24
|
-
Logger::Severity::ERROR
|
25
|
-
)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
class Maintainer
|
30
|
-
include ParamRetrieval
|
31
|
-
include SimpleLogging
|
32
|
-
include HandleException
|
33
|
-
|
34
|
-
def initialize(logger_)
|
35
|
-
@logger = logger_
|
36
|
-
|
37
|
-
@table_queues = {}
|
38
|
-
enqueue_waiting_matches
|
39
|
-
|
40
|
-
log(__method__)
|
41
|
-
end
|
42
|
-
|
43
|
-
def enqueue_waiting_matches(game_definition_key=nil)
|
44
|
-
if game_definition_key
|
45
|
-
@table_queues[game_definition_key] ||= ::AcpcTableManager::TableQueue.new(game_definition_key)
|
46
|
-
@table_queues[game_definition_key].my_matches.not_running.and.not_started.each do |m|
|
47
|
-
@table_queues[game_definition_key].enqueue! m.id.to_s, m.dealer_options
|
48
|
-
end
|
49
|
-
else
|
50
|
-
::AcpcTableManager.exhibition_config.games.keys.each do |game_definition_key|
|
51
|
-
enqueue_waiting_matches game_definition_key
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def maintain!
|
57
|
-
log __method__, msg: "Starting maintenance"
|
58
|
-
|
59
|
-
begin
|
60
|
-
enqueue_waiting_matches
|
61
|
-
@table_queues.each { |key, queue| queue.check_queue! }
|
62
|
-
clean_up_matches!
|
63
|
-
rescue => e
|
64
|
-
handle_exception nil, e
|
65
|
-
Rusen.notify e # Send an email notification
|
66
|
-
end
|
67
|
-
log __method__, msg: "Finished maintenance"
|
68
|
-
end
|
69
|
-
|
70
|
-
def kill_match!(match_id)
|
71
|
-
log(__method__, match_id: match_id)
|
72
|
-
|
73
|
-
@table_queues.each do |key, queue|
|
74
|
-
queue.kill_match!(match_id)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def clean_up_matches!
|
79
|
-
::AcpcTableManager::Match.delete_matches_older_than! 1.day
|
80
|
-
end
|
81
|
-
|
82
|
-
def enqueue_match!(match_id, options)
|
83
|
-
begin
|
84
|
-
m = ::AcpcTableManager::Match.find match_id
|
85
|
-
rescue Mongoid::Errors::DocumentNotFound
|
86
|
-
return kill_match!(match_id)
|
87
|
-
else
|
88
|
-
@table_queues[m.game_definition_key.to_s].enqueue! match_id, options
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def start_proxy!(match_id)
|
93
|
-
begin
|
94
|
-
match = ::AcpcTableManager::Match.find match_id
|
95
|
-
rescue Mongoid::Errors::DocumentNotFound
|
96
|
-
return kill_match!(match_id)
|
97
|
-
else
|
98
|
-
@table_queues[match.game_definition_key.to_s].start_proxy match
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def play_action!(match_id, action)
|
103
|
-
log __method__, {
|
104
|
-
match_id: match_id,
|
105
|
-
action: action
|
106
|
-
}
|
107
|
-
begin
|
108
|
-
match = ::AcpcTableManager::Match.find match_id
|
109
|
-
rescue Mongoid::Errors::DocumentNotFound
|
110
|
-
log(
|
111
|
-
__method__,
|
112
|
-
{
|
113
|
-
msg: "Request to play in match #{match_id} when no such proxy exists! Killed match.",
|
114
|
-
match_id: match_id,
|
115
|
-
action: action
|
116
|
-
},
|
117
|
-
Logger::Severity::ERROR
|
118
|
-
)
|
119
|
-
return kill_match!(match_id)
|
120
|
-
end
|
121
|
-
unless @table_queues[match.game_definition_key.to_s].running_matches[match_id]
|
122
|
-
log(
|
123
|
-
__method__,
|
124
|
-
{
|
125
|
-
msg: "Request to play in match #{match_id} in seat #{match.seat} when no such proxy exists! Killed match.",
|
126
|
-
match_id: match_id,
|
127
|
-
match_name: match.name,
|
128
|
-
last_updated_at: match.updated_at,
|
129
|
-
running?: match.running?,
|
130
|
-
last_slice_viewed: match.last_slice_viewed,
|
131
|
-
last_slice_present: match.slices.length - 1,
|
132
|
-
action: action
|
133
|
-
},
|
134
|
-
Logger::Severity::ERROR
|
135
|
-
)
|
136
|
-
return kill_match!(match_id)
|
137
|
-
end
|
138
|
-
log __method__, {
|
139
|
-
match_id: match_id,
|
140
|
-
action: action,
|
141
|
-
running?: !@table_queues[match.game_definition_key.to_s].running_matches[match_id].nil?
|
142
|
-
}
|
143
|
-
proxy = @table_queues[match.game_definition_key.to_s].running_matches[match_id][:proxy]
|
144
|
-
if proxy
|
145
|
-
proxy.play! action
|
146
|
-
else
|
147
|
-
log(
|
148
|
-
__method__,
|
149
|
-
{
|
150
|
-
msg: "Request to play in match #{match_id} in seat #{match.seat} when no such proxy exists! Killed match.",
|
151
|
-
match_id: match_id,
|
152
|
-
match_name: match.name,
|
153
|
-
last_updated_at: match.updated_at,
|
154
|
-
running?: match.running?,
|
155
|
-
last_slice_viewed: match.last_slice_viewed,
|
156
|
-
last_slice_present: match.slices.length - 1,
|
157
|
-
action: action
|
158
|
-
},
|
159
|
-
Logger::Severity::ERROR
|
160
|
-
)
|
161
|
-
end
|
162
|
-
kill_match!(match_id) if proxy.nil? || proxy.match_ended?
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
class TableManager
|
167
|
-
include ParamRetrieval
|
168
|
-
include SimpleLogging
|
169
|
-
include HandleException
|
170
|
-
|
171
|
-
attr_accessor :maintainer
|
172
|
-
|
173
|
-
def initialize
|
174
|
-
@logger = AcpcTableManager.new_log 'table_manager.log'
|
175
|
-
log __method__, "Starting new #{self.class()}"
|
176
|
-
@maintainer = Maintainer.new @logger
|
177
|
-
end
|
178
|
-
|
179
|
-
def maintain!
|
180
|
-
begin
|
181
|
-
@maintainer.maintain!
|
182
|
-
rescue => e
|
183
|
-
log(
|
184
|
-
__method__,
|
185
|
-
{
|
186
|
-
message: e.message,
|
187
|
-
backtrace: e.backtrace
|
188
|
-
},
|
189
|
-
Logger::Severity::ERROR
|
190
|
-
)
|
191
|
-
Rusen.notify e # Send an email notification
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def perform!(request, params=nil)
|
196
|
-
match_id = nil
|
197
|
-
begin
|
198
|
-
log(__method__, {request: request, params: params})
|
199
|
-
|
200
|
-
case request
|
201
|
-
# when START_MATCH_REQUEST_CODE
|
202
|
-
# @todo Put bots in erb yaml and have them reread here
|
203
|
-
when ::AcpcTableManager.config.delete_irrelevant_matches_request_code
|
204
|
-
return @maintainer.clean_up_matches!
|
205
|
-
end
|
206
|
-
|
207
|
-
match_id = retrieve_match_id_or_raise_exception params
|
208
|
-
|
209
|
-
log(__method__, {request: request, match_id: match_id})
|
210
|
-
|
211
|
-
do_request!(request, match_id, params)
|
212
|
-
rescue => e
|
213
|
-
handle_exception match_id, e
|
214
|
-
Rusen.notify e # Send an email notification
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
protected
|
219
|
-
|
220
|
-
def do_request!(request, match_id, params)
|
221
|
-
case request
|
222
|
-
when ::AcpcTableManager.config.start_match_request_code
|
223
|
-
log(__method__, {request: request, match_id: match_id, msg: 'Enqueueing match'})
|
224
|
-
|
225
|
-
@maintainer.enqueue_match!(
|
226
|
-
match_id,
|
227
|
-
retrieve_parameter_or_raise_exception(params, ::AcpcTableManager.config.options_key)
|
228
|
-
)
|
229
|
-
when ::AcpcTableManager.config.start_proxy_request_code
|
230
|
-
log(
|
231
|
-
__method__,
|
232
|
-
request: request,
|
233
|
-
match_id: match_id,
|
234
|
-
msg: 'Starting proxy'
|
235
|
-
)
|
236
|
-
|
237
|
-
@maintainer.start_proxy! match_id
|
238
|
-
when ::AcpcTableManager.config.play_action_request_code
|
239
|
-
log(
|
240
|
-
__method__,
|
241
|
-
request: request,
|
242
|
-
match_id: match_id,
|
243
|
-
msg: 'Taking action'
|
244
|
-
)
|
245
|
-
|
246
|
-
@maintainer.play_action! match_id, retrieve_parameter_or_raise_exception(params, ::AcpcTableManager.config.action_key)
|
247
|
-
when ::AcpcTableManager.config.kill_match
|
248
|
-
log(
|
249
|
-
__method__,
|
250
|
-
request: request,
|
251
|
-
match_id: match_id,
|
252
|
-
msg: "Killing match #{match_id}"
|
253
|
-
)
|
254
|
-
@maintainer.kill_match! match_id
|
255
|
-
else
|
256
|
-
raise StandardError.new("Unrecognized request: #{request}")
|
257
|
-
end
|
258
|
-
end
|
259
|
-
end
|
260
|
-
end
|