Class: Zoidberg::Proxy
- Inherits:
- BasicObject
- Defined in:
- lib/zoidberg/proxy.rb,
lib/zoidberg/proxy.rb,
lib/zoidberg/proxy/confined.rb,
lib/zoidberg/proxy/liberated.rb
Overview
Instance proxy that filters requests to shelled instance
Defined Under Namespace
Constant Summary collapse
- @@__registry =
::Hash.new
Class Method Summary collapse
-
.inherited(klass) ⇒ Object
Setup proxy for proper scrubbing support.
-
.register(r_id, proxy) ⇒ Zoidberg::Proxy
Register the proxy a WeakRef is pointing to.
-
.registry ⇒ Hash
WeakRef -> Proxy mapping.
-
.scrub!(o_id) ⇒ Truthy, Falsey
Destroy the proxy referenced by the WeakRef with the provided ID.
Instance Method Summary collapse
-
#_zoidberg_available? ⇒ TrueClass, FalseClass
Currently unlocked.
-
#_zoidberg_destroy!(error = nil, &block) ⇒ TrueClass
(also: #terminate)
Destroy the real instance.
-
#_zoidberg_handle_unexpected_error(error) ⇒ TrueClass
When real instance is being supervised, unexpected exceptions will force the real instance to be terminated and replaced with a fresh instance.
- #_zoidberg_link ⇒ Object, NilClass
- #_zoidberg_link=(inst) ⇒ Object
-
#_zoidberg_locked? ⇒ TrueClass, FalseClass
Currently locked.
- #_zoidberg_object ⇒ self
-
#_zoidberg_signal(sig) ⇒ TrueClass, FalseClass
Send a signal if the optional signal instance has been set.
-
#_zoidberg_signal=(signal) ⇒ Signal
Set an optional state signal instance.
-
#_zoidberg_unexpected_error(e) ⇒ Object
Properly handle an unexpected exception when encountered.
-
#initialize(*_) ⇒ Proxy
constructor
Abstract class gets no builder.
Constructor Details
#initialize(*_) ⇒ Proxy
Abstract class gets no builder
52 53 54 |
# File 'lib/zoidberg/proxy.rb', line 52 def initialize(*_) raise NotImplementedError end |
Class Method Details
.inherited(klass) ⇒ Object
Setup proxy for proper scrubbing support
42 43 44 45 46 47 48 49 |
# File 'lib/zoidberg/proxy.rb', line 42 def self.inherited(klass) klass.class_eval do # @return [Array] arguments used to build real instance attr_accessor :_build_args # @return [Object] wrapped instance attr_reader :_raw_instance end end |
.register(r_id, proxy) ⇒ Zoidberg::Proxy
Register the proxy a WeakRef is pointing to
24 25 26 |
# File 'lib/zoidberg/proxy.rb', line 24 def register(r_id, proxy) @@__registry[r_id] = proxy end |
.registry ⇒ Hash
Returns WeakRef -> Proxy mapping.
15 16 17 |
# File 'lib/zoidberg/proxy.rb', line 15 def registry @@__registry end |
.scrub!(o_id) ⇒ Truthy, Falsey
Destroy the proxy referenced by the WeakRef with the provided ID
33 34 35 36 37 38 |
# File 'lib/zoidberg/proxy.rb', line 33 def scrub!(o_id) proxy = @@__registry.delete(o_id) if(proxy) proxy._zoidberg_destroy! end end |
Instance Method Details
#_zoidberg_available? ⇒ TrueClass, FalseClass
Returns currently unlocked.
62 63 64 |
# File 'lib/zoidberg/proxy.rb', line 62 def _zoidberg_available? !_zoidberg_locked? end |
#_zoidberg_destroy!(error = nil, &block) ⇒ TrueClass Also known as: terminate
Destroy the real instance. Will update all methods on real instance to raise exceptions noting it as terminated rendering it unusable. This is generally used with the supervise module but can be used on its own if desired.
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/zoidberg/proxy.rb', line 162 def _zoidberg_destroy!(error=nil, &block) unless(_raw_instance.respond_to?(:_zoidberg_destroyed)) if(_raw_instance.respond_to?(:terminate)) if(_raw_instance.method(:terminate).arity == 0) _raw_instance.terminate else _raw_instance.terminate(error) end end death_from_above = ::Proc.new do ::Kernel.raise ::Zoidberg::DeadException.new('Instance in terminated state!') end death_from_above_display = ::Proc.new do "#<#{self.class.name}:TERMINATED>" end block.call if block _raw_instance.instance_variables.each do |i_var| _raw_instance.remove_instance_variable(i_var) end ( _raw_instance.public_methods(false) + _raw_instance.protected_methods(false) + _raw_instance.private_methods(false) ).each do |m_name| next if m_name.to_sym == :alive? _raw_instance.send(:define_singleton_method, m_name, &death_from_above) end _raw_instance.send(:define_singleton_method, :to_s, &death_from_above_display) _raw_instance.send(:define_singleton_method, :inspect, &death_from_above_display) _raw_instance.send(:define_singleton_method, :_zoidberg_destroyed, ::Proc.new{ true }) _zoidberg_signal(:destroyed) end true end |
#_zoidberg_handle_unexpected_error(error) ⇒ TrueClass
When real instance is being supervised, unexpected exceptions will force the real instance to be terminated and replaced with a fresh instance.
If the real instance provides a #restart method that will be called instead of forcibly terminating the current real instance and rebuild a new instance.
If the real instance provides a #restarted! method, that method will be called on the newly created instance on replacement
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/zoidberg/proxy.rb', line 133 def _zoidberg_handle_unexpected_error(error) if(_raw_instance.respond_to?(:restart)) begin _raw_instance.restart(error) return # short circuit rescue => e end end _zoidberg_destroy! _aquire_lock! args = _build_args.dup @_raw_instance = args.shift.unshelled_new( *args.first, &args.last ) _raw_instance._zoidberg_proxy(self) if(_raw_instance.respond_to?(:restarted!)) _raw_instance.restarted! end _release_lock! true end |
#_zoidberg_link ⇒ Object, NilClass
72 73 74 |
# File 'lib/zoidberg/proxy.rb', line 72 def _zoidberg_link @_zoidberg_link end |
#_zoidberg_link=(inst) ⇒ Object
67 68 69 |
# File 'lib/zoidberg/proxy.rb', line 67 def _zoidberg_link=(inst) @_zoidberg_link = inst end |
#_zoidberg_locked? ⇒ TrueClass, FalseClass
Returns currently locked.
57 58 59 |
# File 'lib/zoidberg/proxy.rb', line 57 def _zoidberg_locked? false end |
#_zoidberg_object ⇒ self
199 200 201 |
# File 'lib/zoidberg/proxy.rb', line 199 def _zoidberg_object self end |
#_zoidberg_signal(sig) ⇒ TrueClass, FalseClass
Send a signal if the optional signal instance has been set
88 89 90 91 92 93 94 95 |
# File 'lib/zoidberg/proxy.rb', line 88 def _zoidberg_signal(sig) if(@_zoidberg_signal) @_zoidberg_signal.signal(sig) true else false end end |
#_zoidberg_signal=(signal) ⇒ Signal
Set an optional state signal instance
80 81 82 |
# File 'lib/zoidberg/proxy.rb', line 80 def _zoidberg_signal=(signal) @_zoidberg_signal = signal end |
#_zoidberg_unexpected_error(e) ⇒ Object
Properly handle an unexpected exception when encountered
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/zoidberg/proxy.rb', line 100 def _zoidberg_unexpected_error(e) ::Zoidberg.logger.error "Unexpected exception: #{e.class} - #{e}" unless((defined?(Timeout) && e.is_a?(Timeout::Error)) || e.is_a?(::Zoidberg::DeadException)) if(_zoidberg_link) if(_zoidberg_link.class.trap_exit) ::Zoidberg.logger.warn "Calling linked exit trapper #{@_raw_instance.class.name} -> #{_zoidberg_link.class}: #{e.class} - #{e}" _zoidberg_link.async.send( _zoidberg_link.class.trap_exit, @_raw_instance, e ) end else if(@_supervised) ::Zoidberg.logger.warn "Unexpected error for supervised class `#{@_raw_instance.class.name}`. Handling error (#{e.class} - #{e})" ::Zoidberg.logger.debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}" _zoidberg_handle_unexpected_error(e) end end end end |