I have my job class and was wondering if I could define a helper method in such way that the variables initialized in one task are not seen by the next task that runs that job.
In other words, is the following thread safe?
class OrdersUpdateJob < ActiveJob::Base
def perform
p my_method
end
def my_method
#sth ||= 0
end
end
You have class methods and instance methods. As any class, class methods definition starts with self.
ActiveJob::Base.methods.select{|m| m == :perform}
=> []
ActiveJob::Base.instance_methods.select{|m| m == :perform}
=> [:perform]
There's no "perfom" method on the base class, but there's one perfom method on the instance methods.
I think that what you are asking is if the jobs are run by a class or an instance of that class. Seeing that only instace_methods includes :perform, I'd say that ActiveJobs are run as instances. So you should be able to use instance variables with no threading conflicts.
Related
I have 2 workers and both workers are calling a factory who initialize the instance of a class and inside the initialize method I have used the variable caching so that both workers can take the advantage of variable caching while creating an instance of the class.
class BoxFolderDocumentSynchronizerJob < ActiveJob::Base
queue_as :default
def perform(document_store_id, folder_id)
synchronizer = DocumentSynchronizerFactory.get_synchronizer(document_store, folder_id)
end
end
class DeleteBoxFolderDocumentJob < ActiveJob::Base
queue_as :default
def perform(document_store_id, folder_id=nil)
synchronizer = DocumentSynchronizerFactory.get_synchronizer(document_store, folder_id)
end
end
module DocumentSynchronizers
class Base
attr_reader :document_store, :facility
def initialize(document_store, folder_id=nil)
if document_store
#folder_id = folder_id
#document_store = document_store
#facility = document_store.facility
#Fetch all the document store(project) documents from S3/Box service provider
#service_provider_documents_hash ||= DocumentStoreAdapterHandler.new(#document_store).list(folder_id)
#vueops_documents_hashmap ||= #document_store.documents.inject({}){|hash, document| hash[document.file_id] = document; hash}
else
raise "Document store instance should not be nil"
end
end
end
end
My question is - when the variable caching scope ends?
Two consecutive calls of the method could, depending on your setup, end up being executed in
the same process in the same thread (memoization works)
the same process in a different thread (memoization works)
different processes (memoization does not work)
even different machine/vm (memoization does not work)
If the workers use the same instance of DocumentSynchronizers, then caching will work, otherwise not.
In your case (expanding on the comment by #Stefan) the memoization doesn't bring any benefit because it is used inside the initialize method. This method is only executed once and nothing is executed before that could set a value. So there is no difference to #variable = xxx.
Memoization makes more sense if you use it like this:
class Something
def value
#value ||= some_expensive_calculation_that_can_be_cached
end
end
and then do not use #value directly but use the method value. This has the added benefit of deferring the calculation until you actually use it (if, it is not always used)
For example I have some class with this initialization:
class SomeClass < ActiveRecord
call_some_method('bla_bla_bla')
def some_method
return 1
end
# end of initialization or definition(not really sure, sorry)
# and here I want to call some code which can be added in other place of project
end
And I want to add the hook with my own code which can add or call methods of class after initialization. I don't have ability to add some code into class definition directly and here I don't mean about initialization of class instances.
Is there any way to do this?
ActiveRecord has after_initialize and after_find hooks, which you can use to run code after a record is initialized (via new or build) or loaded (via find).
You can use something like:
class SomeClass
after_initialize :do_my_setup
def do_my_setup
# Your code here
end
end
Which would monkeypatch SomeClass to run your setup method after a new record is instantiated. You could use this to patch in new methods to instances of ActiveRecord objects, but this will have some implications for the Ruby method cache, and is generally considered a bad idea if you can avoid it.
If you just need to add new methods to the SomeClass class - instance or class - you can just monkeypatch them in via the standard Ruby class extension mechanisms.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the order of ActiveRecord callbacks and validations?
I comes from the background of Java. One thing I think very weird in Rails is that you can set up call back functions like attributes just under the class, such as before_filter.
class SomeController < ActionController::Base
before_filter Proc.new {.....}
end
I don't really understand how it works. I found this post which explains before_filter . I understand the flow of logic and it's just a method. But I still don't understand when will before_filter being executed to set up the callback chain.
before_filter is not a Ruby feature, it is a class method provided by Ruby on Rails (the web framework) that you can use in your controllers to execute a piece of code before executing any action in your controller.
So, how does Ruby on Rails does that?
When you are defining a class in Ruby you are actually executing code, try this in irb:
class Hello
puts "defining hello..."
def greet
puts "Hello there"
end
end
You'll see that "defining hello..." gets printed in the terminal when you define the class. You have not instantiated any object, you just have defined a class, but you can execute any code in the middle of defining a class.
You know that you can define “class methods” and “instance methods”, and what's interesting is that you can call your class methods while you are still defining your class:
class MyClass
def self.add_component(component)
# Here ##components is a class variable
##components ||= [] # set the variable to an empty array if not already set.
##components << component # add the component to the array
end
add_component(:mouse)
add_component(:keyboard)
add_component(:screen)
def components
##components # The ## gets you the class variable
end
end
MyClass.new.components
=> [:mouse, :keyboard, :screen]
def self.add_component defines a class method that you can call while still defining your class. In this example add_component adds a keyboard to a list in a class variable, and the def components instance method (which is called on an instance of this class) access this class variable. The class method could have been defined in a parent class, and it would have worked the same. That example may be a little bit weird.
Let's do another example.
class RubyOnSlugsController
def self.before_filter(callback)
##callbacks ||= []
##callbacks << callback
end
def execute_callbacks
##callbacks.each { |callback| callback.call() }
return "callbacks executed"
end
end
class MyController < RubyOnSlugsController
before_filter Proc.new { puts "I'm a before filter!" }
before_filter Proc.new { puts "2 + 2 is #{2 + 2}" }
end
controller = MyController.new
controller.execute_callbacks
will output:
I'm a before filter!
2 + 2 is 4
=> "callbacks executed"
Ruby on Rails does something similar (but quite more complex) with before_filter, and it makes sure that all callbacks you define with it are called before your normal controller methods.
I hope this clears things a little bit for you.
The before_filter method itself gets run when your controller file is loaded (i.e. when your server starts). That means that the callback chain is set up as soon as the class is defined.
As for the callbacks that it sets up, the controller has a process method which takes the name of an action (say, "index"), and calls the appropriate action method in process_action. The callbacks module overrides this method with an implementation that runs the callback.
I've been studing Rails for a not such a long time up to now .... so if there are feel free to correct me
I see that there are two ways of defining methods in rails
def method_name(param)
def self.method_name(param)
The difference (as i understand) is that 1 is mainly used in controllers while 2 is used in models... but occasionaly i bump into methods in models that're defined like 1.
Could you explain to me the main difference of thease two methods?
Number 1. This defines a instance method, that can be used in instances of the model.
Number 2. This defines a class method, and can only be used by the class itself.
Example:
class Lol
def instance_method
end
def self.class_method
end
end
l = Lol.new
l.instance_method #=> This will work
l.class_method #=> This will give you an error
Lol.class_method #=> This will work
The method self.method_name defines the method on the class. Basically within the class definition think of self as referring to the class that is being defined. So when you say def self.method_name you are defining the method on the class itself.
class Foo
def method_name(param)
puts "Instance: #{param}"
end
def self.method_name(param)
puts "Class: #{param}"
end
end
> Foo.new.method_name("bar")
Instance: bar
> Foo.method_name("bar")
Class: bar
In order to start delayed_job's on a schedule you need to have helper classes with a perform method that delayed_job can call. These need to be defined before any of the classes that use them to create scheduled delayed_jobs are called. All very short, and many of them in my case. For example:
class AccountUpdateJob < Struct.new(:account_id)
def perform
acct = Account.find(account_id)
acct.api_update
end
end
I'm doing this in a file called "dj_helper_classes" in the initializers folder. Is that the right thing to do?
I keep mine in lib/jobs, one file per class. So, your example would be in lib/jobs/account_update_job.rb
module Jobs
class AccountUpdateJob < Struct.new(:account_id)
def perform
acct = Account.find(account_id)
acct.api_update
end
end
end