Module: Inform::Daemons
- Included in:
- Object, System::Object
- Defined in:
- lib/runtime/daemon.rb
Overview
The Inform::Daemons module
Defined Under Namespace
Classes: Entheogen
Constant Summary collapse
- DaemonScanElapsedMessage =
"Scanned %<daemons>s daemons in %<elapsed>0.2f milliseconds".freeze
- DaemonExecutionElapsedMessage =
"\e[1m\e[33mExecuted daemons in %<elapsed>0.2f milliseconds\e[39m\e[22m".freeze
- RecordNotFoundPattern =
%r{Record not found}.freeze
Class Method Summary collapse
- .daemons ⇒ Object
- .ensure_inform_library(obj) ⇒ Object
- .execute(obj) ⇒ Object
-
.execute_daemon(obj) ⇒ Object
TODO: Potentially go ahead and print any string results from the daemon invocation.
- .execute_each_turn(obj) ⇒ Object
- .refresh_or_remove(obj) ⇒ Object
- .scan_objects ⇒ Object
-
.start ⇒ Object
rubocop: disable Metrics/AbcSize.
-
.stop ⇒ Object
rubocop: enable Metrics/AbcSize.
Instance Method Summary collapse
- #before_destroy ⇒ Object
- #daemonic? ⇒ Boolean
- #daemonize(event) ⇒ Object
- #ghost ⇒ Object
- #heart ⇒ Object
- #init_heart ⇒ Object
-
#occasionally(time = nil, &block) ⇒ Object
rubocop: disable Metrics/AbcSize.
- #on? ⇒ Boolean
- #rescan ⇒ Object
- #schedules ⇒ Object
- #spawn ⇒ Object
- #StartDaemon(obj) ⇒ Object
- #StartTimer(obj, interval) ⇒ Object
- #StopDaemon(obj) ⇒ Object
- #StopTimer(obj) ⇒ Object
Class Method Details
.daemons ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/runtime/daemon.rb', line 161 def self.daemons start = Time.ms Inform::Daemons.spawn.each do |daemon| # In realtime games, each_turn is a synonym for daemon next unless daemon.respond_to?(:daemon) || daemon.respond_to?(:each_turn) Inform::Daemons.execute daemon end ensure finish = Time.ms elapsed = finish - start log.debug format(DaemonExecutionElapsedMessage, elapsed: elapsed) if finish % 300_000 == 0 end |
.ensure_inform_library(obj) ⇒ Object
183 184 185 186 187 188 189 |
# File 'lib/runtime/daemon.rb', line 183 def self.ensure_inform_library(obj) return unless obj.inflib.nil? # TODO: Use a pool of InformLibraries until # comprehensive event contexts can be implemented log.warn "Using singleton Ghost InformLibrary for #{obj} daemon" obj.inflib = Inform::Runtime.libraries[Inform::Daemons.ghost] end |
.execute(obj) ⇒ Object
207 208 209 210 211 212 213 214 215 216 |
# File 'lib/runtime/daemon.rb', line 207 def self.execute(obj) return if obj.nil? if obj.respond_to? :daemon execute_daemon(obj) elsif obj.respond_to? :each_turn execute_each_turn(obj) end rescue StandardError => e log.error "Error executing daemon for #{obj}", e end |
.execute_daemon(obj) ⇒ Object
TODO: Potentially go ahead and print any string results from the daemon invocation. For example:
obj.println obj.daemon
195 196 197 198 199 |
# File 'lib/runtime/daemon.rb', line 195 def self.execute_daemon(obj) refresh_or_remove(obj) ensure_inform_library(obj) obj.daemon end |
.execute_each_turn(obj) ⇒ Object
201 202 203 204 205 |
# File 'lib/runtime/daemon.rb', line 201 def self.execute_each_turn(obj) refresh_or_remove(obj) ensure_inform_library(obj) obj.each_turn end |
.refresh_or_remove(obj) ⇒ Object
176 177 178 179 180 181 |
# File 'lib/runtime/daemon.rb', line 176 def self.refresh_or_remove(obj) return if obj.nil? obj.refresh rescue StandardError => e Spawn.remove obj if RecordNotFoundPattern.match?(e.) end |
.scan_objects ⇒ Object
128 129 130 131 132 133 134 135 136 137 |
# File 'lib/runtime/daemon.rb', line 128 def self.scan_objects start = Time.now Inform::Object.all.each do |obj| Spawn.add obj if obj.respond_to?(:daemon) || obj.respond_to?(:each_turn) end rescue StandardError => e log.error "Error executing daemon method: #{e.}", e ensure log.debug format(DaemonScanElapsedMessage, daemons: Spawn.length, elapsed: Time.now - start) end |
.start ⇒ Object
rubocop: disable Metrics/AbcSize
140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/runtime/daemon.rb', line 140 def self.start initial_delay = Inform::Game.config[:daemon_initial_delay] period = Inform::Game.config[:daemons_period] unit = defined?(Java) ? java.util.concurrent.TimeUnit::MILLISECONDS : 'milliseconds' Thread.new do Inform::Daemons.rescan log.debug "Starting daemons..." daemons = Inform::Daemons.method(:daemons).to_proc Inform::Daemons.ghost.heartbeat = Inform::Daemons.heart.scheduleAtFixedRate( daemons, initial_delay, period, unit) end end |
Instance Method Details
#before_destroy ⇒ Object
245 246 247 248 249 |
# File 'lib/runtime/daemon.rb', line 245 def before_destroy log.debug "#{self}: before_destroy stopping daemon" StopDaemon(self) if daemonic? super end |
#daemonic? ⇒ Boolean
241 242 243 |
# File 'lib/runtime/daemon.rb', line 241 def daemonic? Inform::Daemons.schedules.include? self end |
#daemonize(event) ⇒ Object
237 238 239 |
# File 'lib/runtime/daemon.rb', line 237 def daemonize(event) Inform::Daemons.schedules[self] = event end |
#ghost ⇒ Object
108 109 110 |
# File 'lib/runtime/daemon.rb', line 108 def ghost @ghost ||= Entheogen.new end |
#heart ⇒ Object
91 92 93 |
# File 'lib/runtime/daemon.rb', line 91 def heart @heart ||= init_heart end |
#init_heart ⇒ Object
95 96 97 98 99 |
# File 'lib/runtime/daemon.rb', line 95 def init_heart # TODO: Figure out ruby-concurrency Executors? return unless defined?(Java) java.util.concurrent.Executors.newSingleThreadScheduledExecutor() end |
#occasionally(time = nil, &block) ⇒ Object
rubocop: disable Metrics/AbcSize
252 253 254 255 256 257 258 259 260 261 |
# File 'lib/runtime/daemon.rb', line 252 def occasionally(time = nil, &block) time = Inform::Game.config[:daemons_frequency_default] if time.nil? return if active? || daemonic? frequency = ((self.&:frequency) || time).to_i occasion = rand(frequency) + 1 log.trace "Scheduling occasional daemonic event for #{self} in #{occasion} seconds" (Inform::Daemons.schedules[self] = delay(occasion, &block)).finally do Inform::Daemons.schedules.delete self end end |
#on? ⇒ Boolean
116 117 118 119 |
# File 'lib/runtime/daemon.rb', line 116 def on? return false if Inform::Daemons.ghost.heartbeat.nil? Inform::Daemons.ghost.heartbeat.isCancelled() == false end |
#rescan ⇒ Object
121 122 123 124 |
# File 'lib/runtime/daemon.rb', line 121 def rescan Inform::Daemons.spawn.clear Inform::Daemons.scan_objects end |
#schedules ⇒ Object
112 113 114 |
# File 'lib/runtime/daemon.rb', line 112 def schedules @schedules ||= defined?(Java) ? java.util.concurrent.ConcurrentHashMap.new : {} end |
#spawn ⇒ Object
87 88 89 |
# File 'lib/runtime/daemon.rb', line 87 def spawn @spawn ||= defined?(Java) ? java.util.concurrent.ConcurrentSkipListSet.new : Set.new end |
#StartDaemon(obj) ⇒ Object
218 219 220 |
# File 'lib/runtime/daemon.rb', line 218 def StartDaemon(obj) Inform::Daemons.spawn.add obj if obj.respond_to?(:daemon) || obj.respond_to?(:each_turn) end |
#StartTimer(obj, interval) ⇒ Object
229 230 231 |
# File 'lib/runtime/daemon.rb', line 229 def StartTimer(obj, interval) # TODO: Implement end |
#StopDaemon(obj) ⇒ Object
222 223 224 225 226 227 |
# File 'lib/runtime/daemon.rb', line 222 def StopDaemon(obj) return if obj.nil? log.warn "Stopping daemon: #{obj}" obj.undef_method(:daemon) # TODO: Maybe don't do this Inform::Daemons.spawn.remove obj end |
#StopTimer(obj) ⇒ Object
233 234 235 |
# File 'lib/runtime/daemon.rb', line 233 def StopTimer(obj) # TODO: Implement end |