Magento -> Is this an anonymous function? - magento-1.4

We have a lot of code in our codebase that was done by a third-party developer. They modified many places in the core and we wanted to figure out exactly what is happening.
They have code like this:
$pidsess = Mage::getSingleton('core/session', array('name'=>'frontend'));
$pidsess->setNA_pid(array("PID" => $pid, "PartInfo" => $return_data['result']));
What this does is store a "globally available variable" that can be called at anytime the Magento Session is alive like this:
$pidsess = Mage::getSingleton('core/session', array('name' => 'frontend'));
$piddata = $pidsess->getNA_pid();
Where can I find the code that is setting this "variable"? I have searched for 'setNA_' and found several calls but none of them the actual function call.
Is this a part of Magento's stupid EAV architecture where you can make up your own functions to set EAV values? If so, where would the values be stored?

Calling something stupid just because you didn't have time to understand and/or didn't like it certainly isn't going to help. However, as with many magento base classes, it probably just sets a variable into the magento session that ends somewhere in the session storage.
I'd start with Mage::log(print_r($_SESSION,1) to see if there is really an ['NA_pid'].
And it has nothing to do with EAV.

Related

Object variables in multithreaded Sneaker works like a global mutable data

I have a sneaker worker(given below) as a backend of a chatbot.
class RabbitMQWorker
include Sneakers::Worker
from_queue "message"
def work(options)
parsed_options = JSON.parse(options)
# Initializing some object variables
#question_id = parsed_options[:question_id]
#answer = parsed_option[:answer]
#session_id = parsed_option[:session_id]
ActiveRecord::Base.connection_pool.with_connection do
# send next question to the session_id based on answer
end
ack!
end
end
What's happening
The problem I am facing here is that when I run sneaker with more than 1 thread and multiple users are chatting at the same time, then the ampq event which comes slightly later cause to override the #session_id and as a result, the second user gets two questions and the first one gets none. This happens because by the time 1st event is getting process the second event came and override #session_id. Now when it's time to send the next question to the first user by using #session_id, the question get's send to the second user.
My Questions
Do the work method and any instance variables I create in it works like global mutable data for sneaker's threads?
If yes then I am guessing I need to make them as thread-local variables. If I do that, then do I need to make these changes deep down in my Rails logic as well? As this worker works with Rails.
Curiosity question
How does Puma manage these things? It is a multi-threaded app server and we use instance variables in controllers and it manages to serve multiple requests simultaneously. Does it mean that Puma handles this multi-contexting implicitly and Sneakers don't?
What I have done till now
I read the documentation of Sneaker and couldn't found anything regarding this.
I perform a load tests to verify the problem and it is the problem as I stated above.
I tried getting my logic clear on how actually multi-threading works but everywhere there is only general stuff. The curiosity question I asked above will help a lot in terms of clearing the concepts, I am searching for an explanation of it for days but couldn't found any.
After 2 days of searching for an issue where messages seemed to get mixed up I was finally able to solve this by removing all instance variables from my workers.
This thread gave me the clue to do so: https://github.com/jondot/sneakers/issues/244
maybe we should simply disallow instance variables in workers since
changing the behavior to instantiate multiple worker instances might
break existing code somehow
and:
I think that an instance per thread is the way to go.
So when you remove your instance variables you should be fine!

Put class instance to class constant in initializers

In one of my old apps, I'm using several API connectors - like AWS or Mandill as example.
For some reason (may be I saw it somewhere, don't remember), I using class constant to initialize this objects on init stage of application.
As example:
/initializers/mandrill.rb:
require 'mandrill'
MANDRILL = Mandrill::API.new ENV['MANDRILL_APIKEY']
Now I can access MANDRILL class constant of my application in any method and use it. (full path MyApplication::Application::MANDRILL, or just MANDRILL). All working fine, example:
def update_mandrill
result = MANDRILL.inbound.update_route id, pattern, url
end
The question is: it is good practice to use such class constants? Or better create new class instance in every method that using this instance, like in example:
def update_mandrill
require 'mandrill'
mandrill = Mandrill::API.new ENV['MANDRILL_APIKEY']
result = mandrill.inbound.update_route id, pattern, url
end
Interesting question.
It's very handy approach but it may have cons in some scenarios.
Imagine you have a constant that either takes a lot of time to initialize or it loads a lot of data into memory. When its initialization takes long you essentially degrade app boot time (which may or may not be a problem, usually it will in development).
If it loads a lot of data into memory it may turn out it's gonna be a problem when running rake tasks for example which load entire environment. You may hit memory boundaries in use cases in which you essentially do not need this data at all.
I know one application which load a lot of data during boot - and it's done very deliberately. Sure, use case is a bit uncommon, but still.
Another thing to consider is - imagine, you're trying to establish connection to external service like Mongo or anything else. If this service is unavailable (what happens) your application won't be able to boot. Maybe this service is essential for app to work, and without it it would be "useless" anyway, but it's also possible that you essentially stop everything because storage in which you keeps log does not work.
I'm not saying you shouldn't use it as you suggested - I do it also in my apps, but you should be aware of potential drawbacks.
Yes, pre-creating a pseudo-constant object (like that api client) is usually a good idea. However, there is, approximately, a thousand ways go about it and the constant is not on top of my personal list.
These days I usually go with setting it in the env files.
# config/environments/production.rb
config.email_client = Mandrill::API.new ENV['MANDRILL_APIKEY'] # the real thing
# config/environments/test.rb
config.email_client = a_null_object # something that conforms to the same api, but does absolutely nothing
# config/environments/development.rb
config.email_client = a_dev_object # post to local smtp, or something
Then you refer to the client like this:
Rails.application.configuration.email_client
And the correct behaviour will be picked up in each env.
If I don't need this per-env variation, then I either use some kind of singleton object (EmailClient.get) or a global variable in the initializer ($email_client). It can be argued that a constant is better than global variable, semantically and because it raises a warning when you try to re-assign it. But I like that global variable stands out more. You see right away that it's something special. (And then again, it's only #3 in the list, so I don't do it very often.).

Finding options to pass to methods in Rails

How are you supposed to find the different options you can pass to methods in Rails? For instance I want to know the options I can pass to validates. I can't find them nowhere in the documentation.
api dock is useful and it also shows the source code http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates
As you know it's not possible to document hash options in the signature so you must either rely on the quality of the documentation or read the source code.
In this case the docs show some examples that cover pretty much all the default validators. Note that it cannot document all the available since they can be expanded dinamically.
>> ActiveModel::EachValidator.descendants
=> [Paperclip::Validators::AttachmentSizeValidator, ActiveModel::Validations::WithValidator, ActiveModel::Validations::ExclusionValidator, ActiveRecord::Validations::AssociatedValidator, ActiveModel::Validations::ConfirmationValidator, ActiveModel::Validations::PresenceValidator, ActiveModel::Validations::FormatValidator, Paperclip::Validators::AttachmentContentTypeValidator, Paperclip::Validators::AttachmentPresenceValidator, ActiveRecord::Validations::UniquenessValidator, ActiveModel::BlockValidator, ActiveModel::Validations::NumericalityValidator, ActiveModel::Validations::AcceptanceValidator, ActiveModel::Validations::InclusionValidator, ActiveModel::Validations::LengthValidator]
Or:
ActiveModel::EachValidator.descendants.map { |klass| klass.name.split("::").last.sub(/Validator$/, '').underscore }
=> ["attachment_size", "with", "exclusion", "associated", "confirmation", "presence", "format", "attachment_content_type", "attachment_presence", "uniqueness", "block", "numericality", "acceptance", "inclusion", "length"]
The starting point is always the official Rails documentation. For instance, here's the documentation of the validates method.
However, keep in mind that Rails is a constantly evolving framework. Unfortunately, this means that not all methods are fully documented and sometimes you need to dig into the source code directly to understand how a method works.

Concurrency and Mongoid

I'm currently trying my hand at developing a simple web based game using rails and Mongoid. I've ran into some concurrency issues that i'm not sure how to solve.
The issue is i'm not sure how to atomically do a check and take an action based upon it in Mongoid.
Here is a sample of the relevant parts of the controller code to give you an idea of what i'm trying to do:
battle = current_user.battle
battle.submitted = true
battle.save
if Battle.where(opponent: current_user._id, submitted: true, resolving: false).any?
battle.update_attribute(:resolving, true)
#Resolve turn
A battle is between two users, but i only want one of the threads to run the #Resolve turn. Now unless i'm completely off both threads could check the condition one after another, but before setting resolving to true, therefore both end up running the '#Resolve turn' code.
I would much appreciate any ideas on how to solve this issue.
I am however getting an increasing feeling that doing user synchronization in this way is fairly impractical and that there's a better way altogether. So suggestions for other techniques that could accomplish the same thing would be greatly appreciated!
Sounds like you want the mongo findAndModify command which allows you to atomically retrieve and update a row.
Unfortunately mongoid doesn't appear to expose this part of the mongo api, so it looks like you'll have to drop down to the driver level for this one bit:
battle = Battle.collection.find_and_modify(query: {oppenent: current_user._id, ...},
update: {'$set' => {resolving: true})
By default the returned object does not include the modification made, but you can turn this on if you want (pass {:new => true})
The value returned is a raw hash, if my memory is correct you can do Battle.instantiate(doc) to get a Battle object back.

Rails organizing code

i happen to be kinda picky when programming something big. I try to find the best way to do it it terms of speed and complexity. Since i've been learning Rails the previous 3 months, i try to find the best techniques for everything. I would like to ask you how you would go about writing some code like this :
#defender = User.find_by_id(user_id)
#attacker = current_user.clone
#attacker_starting_attribs = current_user
#defender_starting_attribs = #defender.clone
#defenderWeapon = #defender.getEquippedWeapon
#attackerWeapon = #attacker.getEquippedWeapon
#combat = Combatant.fight(#attacker, #defender)
This code is about the battle outcome between two persons in a browser game. The code works well, but i've some problems in terms of good coding. In fact, i know that my code is bad here, that's why i ask you what a better version would be. Let me explain what happens in this code.
#defender is given by user_id, so i guess that this part is needed. Now, in #attacker i'm cloning the current_user. The reason is that Rails works on objects and current_user will be changed inside Combatant.fight. I need both the new hp and the old hp and that is why i'm cloning the object. The defender and attacker starting attribs illustrate that concept. Now, i get the weapons in instance variables, so that i can get their information inside the final view.
However, the weapons are needed inside the fight function and i execute the same getEquippedWeapon twice again inside fight(). I was not so comfortable with something like fight(#attacker, #defender, #attacker_weapon, #defender_weapon), but i don't also like the idea of repetition. So, i would like an opinion on that.
#combat is a hash containing the result of the combat. Fight happens and i get that hash back in the view.
I'm not pleased with my coding on that stage and i want your opinion. How would you do it ? Is there maybe a design pattern for that ? Please tell me your opinion.
Thanx :)
I'm finding it difficult to completely understand what you're trying to do. I get the gist of it though (2 people fighting). I won't be able to provide an answer yet, but hopefully this gets the ball rolling:
From the code you provided, #attacker_starting_attribs and #defender_starting_attribs aren't being used.
As far as "good techniques", I try to stay as OO as possible. Instead of
Combatant.fight(#attacker, #defender), I would do #attacker.fight(#defender)
As a ruby convention, method names are underscored. In your case, .get_equipped_weapon instead of .getEquippedWeapon, or even better .equipped_weapon.
Anyways, I bet if you provided more code, you'd get more answers.

Resources