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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ae4fbf6d36f0f5d968cc7c54909698a162beab9b
4
- data.tar.gz: ab4447f63da11d537944cc16d0b86c40da872139
3
+ metadata.gz: b4e0fbeda8f0f050a57fbf5d42806d6da5570a67
4
+ data.tar.gz: a2736fd639a962b9eada95a86e5e92bbe4e2f347
5
5
  SHA512:
6
- metadata.gz: 108ec4ded055368856ceb64720d600ba48fd1ad27f4d1ec9f436ea134846120ea6c0944a54475a076756849dabcc79dcc88eec698c38be79afbbc54ab08a5742
7
- data.tar.gz: 3cf8b04a4187e248b44386f7473c4a49365274e11584fd72f018461788a7407e78c160b42371306fbf780ddc98c5bcbcb373ab8a9999572d4fe4e80cfe8483ca
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
@@ -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::TableManager.new
32
+ table_manager = AcpcTableManager::Maintainer.new
51
33
  loop do
52
- message = redis.blpop("backend", :timeout => AcpcTableManager.config.maintenance_interval_s)
53
- if message
54
- data = JSON.parse message[1]
55
- if data['request'] == 'reload'
56
- AcpcTableManager.load! CONFIG_FILE
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.perform! data['request'], data['params']
56
+ table_manager.maintain!
59
57
  end
60
- else
61
- table_manager.maintain!
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
@@ -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/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 ||= Match.find(@match_id)
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
- log(__method__, msg: "Starting proxy for #{match.id.to_s}")
65
- @running_matches[match.id.to_s][:proxy] = Proxy.start(match)
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
@@ -1,3 +1,3 @@
1
1
  module AcpcTableManager
2
- VERSION = "0.0.1"
2
+ VERSION = "1.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: 0.0.1
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-09 00:00:00.000000000 Z
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