Celluloid Pool has dead actors first time called - ruby

Everytime I launch the app, the first time I call it, it returns Dead Actors. After that it returns as expected.
require 'celluloid'
class BatchProcess
include Celluloid
POOL = BatchProcess.pool(size: 6)
attr_accessor :base_url, :futures, :objects, :pool, :array
def initialize(*args)
options = args.extract_options!
#base_url = options[:base_url] || "http://some_site.com"
#futures = []
#objects = {}
end
def fetch(array)
#pool = POOL
#array = array
start
end
def start
#grouped_sites = #array.group_by{|i| i[:main_site]}
#grouped_sites.each do |main_site, queries|
batched_url(main_site, queries)
end
futures.each {|f| #objects.merge!(f.value) if f.value}
end
def batched_urls(main_site, queries)
queries.each do |query|
futures << pool.future(:get_url, main_site, query)
end
end
def get_url(main_site, query)
# get http url and parse information process into json data
end
end
I then call it from my controller BatchProcess.new.fetch(array_of_sites_to_parse)
I did try to put the #pool = BatchProcess.pool in my initializer, it did not error, but actors grew exponentially with every request.

This is because you're instantiating the Pool as a class constant before initialize is defined. At the point your POOL constant is set, initialize does not exist yet, so none of your instance variables are initialized.
Upon the second try, the initialize will be defined.

Related

Troubles when reading clearance source code

def initialize_sign_in_guard_stack
default_guard = DefaultSignInGuard.new(self)
guards = Clearance.configuration.sign_in_guards
guards.inject(default_guard) do |stack, guard_class|
guard_class.new(self, stack)
end
end
class DefaultSignInGuard < SignInGuard
def call
if session.signed_in?
success
else
failure default_failure_message.html_safe
end
end
end
class SignInGuard
def initialize(session, stack = [])
#session = session
#stack = stack
end
private
attr_reader :stack, :session
def signed_in?
session.signed_in?
end
def current_user
session.current_user
end
end
Pry(main)> Clearance.configuration.sign_in_guards # => []
No. 1
Since guards is an empty array, so what the guard_class refers to?
And how could it run the new method? Can you explain what does this line of code do?
No. 2
signed_in? is a private method of SignInGuard. I know that only 'self' can
call it. Here, session.signed_in? Why does it make sense?
No1: To nothing. The block will never execute when you call it on an empty array, therefore a value will not be assigned. It is like asking what is item in [].each { |item| puts item }. The idea is when it is not empty to create objects of a list of guard classes. Then guard_class will refer to each individual guard class.
No2: You can't call private methods with explicit receiver, even if it is self. However, here signed_in? called on session is Session#signed_in?, not SignInGuard#signed_in?, which is public so it is fine.

Represent process as a thread in Ruby

I'm supposed to implement a very simple version of MPI (or rather simulate the behaviour) in ruby.
Part of the assignment is to create a Communicator class which has
different processes running on different hosts.
To prove the "independency" of the processes two consecutive for loops over the array in which the processes are stored should output them in a different order.
The processes should be represented as either instances of a class I made up or as threads.
For the first part I just created a class which has the required attributes and changed the "each" method to shuffle the process list after each call.
However, I'm stuggling with the second part. For now I've just created a subclass of Thread and added the required attributes and methods. I just create as many instances of my subclass with an infinite loop in the block as needed and store them in an array.
Now, on looping through the array, the processes seem to have different response times but still are written to console in order.
As I'm in doubt to whether my approach is right or not, I would like to have some suggestions on how the required behaviour could be achieved:
for process in communicator write rank
for process in communicator write rank
> 1
> 2
> 3
#####
> 3
> 1
> 2
Edit:
The Communicator:
class ThreadKomunikator
attr_reader :hosty, :procesy, :rankPool
##rankPool = (0..100).to_a.reverse
public
def initialize(hosty)
#procesy = []
#hosty = hosty
hosty.each do |name, number|
for i in 1..number
tempProc = ThreadProc.new{while true do continue; end;}
tempProc.init(getRank(),name)
procesy << tempProc
end
end
end
def MPI_Comm_size()
procesy.length
end
def each
procesy.each do |proces|
yield proces
end
# #procesy.shuffle!
end
def [](x)
procesy.each do |proces|
if proces.rank == x
return proces.MPI_Get_processor_name()
end
end
return "No process of that rank found!"
end
def method_missing(method, *args, &block)
if hosty.has_key?("#{method}")
return hosty["#{method}"]
else
return 0
end
end
private
def getRank
##rankPool.pop
end
end
The subclass of Thread:
class ThreadProc< Thread
attr_accessor :rank, :host
def init(rank, host)
#rank = rank
#host = host
end
def MPI_Comm_rank()
#rank
end
def MPI_Get_processor_name()
#host
end
end

Delayed::DeserializationError undefined method `has_key?'

I have a bug only in production. I can't reproduce the problem in development env.
I have a main class that initializes several class for process data in a background job, but this is not going well in delayed_job, here are my two classes simplified.
Handler class
class Handler
def initialize(setting)
#setting = setting
end
def process
0.upto(11) do |index|
# data = some code in local method...
launch_process(data)
end
end
protected
def launch_process(data)
Process.new(
#setting,
data: data
).boot
end
end
Process class with called by Handler class
class Process
def initialize(setting, options = {})
#setting = setting
options.each { |k,v| instance_variable_set("##{k}", v) }
end
def boot
self.delay.launch_retrieve
end
end
But when the process class is executed, I have a error by delayed_job : Delayed::DeserializationError: Job failed to load: undefined method has_key? for nil:NilClass. I don't understand why initialize of class returned this error.
Any idea ?
Thanks
Sometimes when we upgrade libs delayed jobs still keep old references.
Try to find the id of delayed_job in logs and play to parse its handler to ruby to find the wrong reference
j = DelayedJob.find(XXX)
data = YAML.load_dj(j.handler)
data.to_ruby
I made a pull request to help with this problem.
Meanwhile you can use this lines
# config/initializers/delayed_job.rb
# Monkey patch to use old class references
module Psych
class << self; attr_accessor :old_class_references end
#old_class_references = {}
class ClassLoader
private
def find klassname
klassname = ::Psych.old_class_references[klassname] || klassname
#cache[klassname] ||= resolve(klassname)
end
end
module Visitors
class ToRuby < Psych::Visitors::Visitor
def revive klass, node
if klass.is_a? String
klassname = ::Psych.old_class_references[klass] || klass
klass = Kernel.const_get(klassname) rescue klassname
end
s = register(node, klass.allocate)
init_with(s, revive_hash({}, node), node)
end
end
end
end
# Add all old dependencies (hash keys) pointing to new references (hash values)
Psych.old_class_references = {
'ActiveRecord::AttributeSet' => 'ActiveModel::AttributeSet'
# ...
}

how do I create a class that stores instances?

I want something like the following but would like it to be reusable for different classes.
How do I refactor this code, so with minimal effort it can be included in a class and that class will automatically be collecting instances whenever new is called?
I've tried all sorts of things like overriding new or initialize but just can't get the magic to happen.
class Person
##people_instances = []
def initialize
##people_instances << self
end
def self.instances
##people_instances
end
end
People.new
People.new
Poople.instances
=> [#<Person:0x000001071a7e28>, #<Person:0x000001071a3828>]
After some feedback below, I don't think the answer is to put the instances in a class variable as it will stay in memory forever. Rails cache is also not so appropriate as I don't need the instances to persist.
The following code uses class instance variables instead of class variables.
http://www.dzone.com/snippets/class-variables-vs-class
class Employee
class << self; attr_accessor :instances; end
def store
self.class.instances ||= []
self.class.instances << self
end
def initialize name
#name = name
end
end
class Overhead < Employee; end
class Programmer < Employee; end
Overhead.new('Martin').store
Overhead.new('Roy').store
Programmer.new('Erik').store
puts Overhead.instances.size # => 2
puts Programmer.instances.size # => 1
Will these instance variables be unique to every rails request or will they persist?
UPDATED ANSWER
If you want to keep it available during the request alone, none of the previous answers can do it. The solution for keeping it available only during the request-response cycle is to use a thread-local that is assigned in a controller method, example:
class YourController < ApplicationController
around_filter :cache_objects
protected
def cache_objects
Thread.current[:my_objects] = ['my-object', 'my-other-object']
yield
ensure
Thread.current[:my_objects]
end
end
Then, at the code that needs it, you just do Thread.current[:my_objects] and do whatever you would like to do with them. You need to use an around_filter because your web framework or server structure could try to reuse threads and the only real solution is to clean them up once the request is done to avoid memory leaks.
OLD ANSWER
Not sure what you're trying to do, but you can easily pick every single instance of a class using ObjectSpace:
ObjectSpace.each_object(String) { |s| puts(s) }
If what you need is as a database cache just use the Rails cache, load these objects once and then keep them in the cache. When using the Rails cache all you need to do is send your objects to the cache:
Rails.cache.write( "my_cached_objects", [ 'first-object', 'second-object' ] )
And then get them somewhere else:
Rails.cache.fetch("my_cached_objects") do
# generate your objects here if there was a cache miss
[ 'first-object', 'second-object' ]
end
As you can see, you don't even have to call cache.write, you can just use fetch and whenever there is a cache miss the block given will be called and your objects will be created.
You can read more about rails caching here and you can see all supported methods of the ActiveSupport::Cache::Store here.
Another method without using ObjectSpace but still with an ugly solution, now using alias_method:
module Counter
def self.included( base )
base.extend(ClassMethods)
base.class_eval do
alias_method :initialize_without_counter, :initialize
alias_method :initialize, :initialize_with_counter
end
end
def count_class_variable_name
:"###{self.class.name.downcase}_instances"
end
def initialize_with_counter( *args )
unless self.class.class_variable_defined?(count_class_variable_name)
self.class.class_variable_set(count_class_variable_name, [])
end
self.class.class_variable_get(count_class_variable_name) << self
initialize_without_counter(*args)
end
module ClassMethods
def all_instances
class_variable_get(:"###{name.downcase}_instances")
end
end
end
class Person
def initialize
puts 'new person'
end
include Counter
end
p1 = Person.new
p2 = Person.new
p3 = Person.new
puts Person.all_instances.size
lib/keeper.rb
def initialize
instance_eval "###{self.class.to_s.downcase}_instances ||= []"
instance_eval "###{self.class.to_s.downcase}_instances << self"
end
def self.instances
return class_eval "###{self.to_s.downcase}_instances"
end
person.rb
class Person
eval File.open('./lib/keeper.rb','rb').read
end
Then this works:
Person.new
Person.new
Person.instances

customizing ruby .new operator

Let's say I have a class Foo and the constructor takes 2 parameters.
Based on these parameters the initialize method does some heavy calculations and stores them as variables in the instance of the class. Object created.
Now I want to optimize this and create a cache of these objects. When creating a new Foo object, I want to return a existing one from the cache if the parameters match. How can I do this?
I currently have a self.new_using_cache(param1, param2), but I would love to have this integrated in the normal Foo.new().
Is this possible in any way?
I can also deduct that using .new() combined with a cache is not really syntactical correct.
That would mean that the method should be called new_or_from_cache().
clarification
It's not just about the heavy calculation, it's also preferred because of limiting the amount of duplicate objects. I don't want 5000 objects in memory, when I can have 50 unique ones from a cache. So I really need to customize the .new method, not just the cached values.
class Foo
##cache = {}
def self.new(value)
if ##cache[value]
##cache[value]
else
##cache[value] = super(value)
end
end
def initialize(value)
#value = value
end
end
puts Foo.new(1).object_id #2148123860
puts Foo.new(2).object_id #2148123820 (different from first instance)
puts Foo.new(1).object_id #2148123860 (same as first instance)
You can actually define self.new, then call super if you actually want to use Class#new.
Also, this totally approach prevents any instantiation from ever occurring if a new instance isn't actually needed. This is die to the fact the initialize method doesn't actually make the decision.
Here's a solution I came up with by defining a generic caching module. The module expects your class to implement the "retrieve_from_cache" and "store_in_cache" methods. If those methods don't exist, it doesn't attempt to do any fancy caching.
module CacheInitializer
def new(*args)
if respond_to?(:retrieve_from_cache) &&
cache_hit = retrieve_from_cache(*args)
cache_hit
else
object = super
store_in_cache(object, *args) if respond_to?(:store_in_cache)
object
end
end
end
class MyObject
attr_accessor :foo, :bar
extend CacheInitializer
#cache = {}
def initialize(foo, bar)
#foo = foo
#bar = bar
end
def self.retrieve_from_cache(foo, bar)
# grab the object from the cache
#cache[cache_key(foo, bar)]
end
def self.store_in_cache(object, foo, bar)
# write back to cache
#cache[cache_key(foo, bar)] = object
end
private
def self.cache_key(foo, bar)
foo + bar
end
end
Something like this?
class Foo
##cache = {}
def initialize prm1, prm2
if ##cache.key?([prm1, prm2]) then #prm1, #prm2 = ##cache[[prm1, prm2]] else
#prm1 = ...
#prm2 = ...
##cache[[prm1, prm2]] = [#prm1, #prm2]
end
end
end
Edited
To not create an instance when the parameters are the same as before,
class Foo
##cache = {}
def self.new prm1, prm2
return if ##cache.key?([prm1, prm2])
#prm1 = ...
#prm2 = ...
##cache[[prm1, prm2]] = [#prm1, #prm2]
super
end
end
p Foo.new(1, 2)
p Foo.new(3, 4)
p Foo.new(1, 2)
# => #<Foo:0x897c4f0>
# => #<Foo:0x897c478>
# => nil
You could use a class-level instance variable to store results from previous object instantiations:
class Foo
#object_cache = {}
def initialize(param1, param2)
#foo1 = #object_cache[param1] || #object_cache[param1] = expensive_calculation
#foo2 = #object_cache[param2] || #object_cache[param2] = expensive_calculation
end
private
def expensive_calculation
...
enf
end
As you probably know you have reinvented the factory method design pattern and it's a perfectly valid solution using your name for the factory method. In fact, it's probably better to do it without redefining new if anyone else is going to have to understand it.
But, it can be done. Here is my take:
class Test
##cache = {}
class << self
alias_method :real_new, :new
end
def self.new p1
o = ##cache[p1]
if o
s = "returning cached object"
else
##cache[p1] = o = real_new(p1)
s = "created new object"
end
puts "%s (%d: %x)" % [s, p1, o.object_id]
o
end
def initialize p
puts "(initialize #{p})"
end
end
Test.new 1
Test.new 2
Test.new 1
Test.new 2
Test.new 3
And this results in:
(initialize 1)
created new object (1: 81176de0)
(initialize 2)
created new object (2: 81176d54)
returning cached object (1: 81176de0)
returning cached object (2: 81176d54)
(initialize 3)

Resources