Ejabber structures and roster - erlang

I'm a new to ejabberd but the first thing I noticed is the completely absence of documentation and code comments.
I have many doubts, but the main are:
inside the record jid what is the difference between user and luser, server and lserver, ... and ...?
-record(jid, {user, server, resource,
luser, lserver, lresource}).
what is useful for the record iq?
-record(iq, {id = "",
type,
xmlns = "",
lang = "",
sub_el}).
what is a subscription inside ejabber? a relation between two users?
what is the jid inside the roster?
I know that these questions can be also quite stupid, but I don't really know how to understand without asking, thanks

what is the difference between user and luser?
luser,lserver and lresource are the corresponding parts of the jid after being processed with the appropiate stringprep profile. See https://www.rfc-editor.org/rfc/rfc3920#section-3 . In short, inside ejabberd you will most likely always use the processed versions, and the raw ones only when serializing the JID back to the wire.
what is useful for the record iq?
it make it easier to match on the IQ namespace, id or type (get|set|error) than to retrieve that info from the underling xml each time.
what is a subscription inside ejabber? a relation between two users?
basically, yes. A subscription from user A to user B means A is interested in B presence. But the subscription can be in different states (as the other user has to accept it, etc.). See http://xmpp.org/rfcs/rfc3921.html#sub .
what is the jid inside the roster?
sorry, didn't understand you on that, what do you want to know?

Related

how to tell active record to make an update instead of insert on a (not) new record after dup(ing) an other one?

Or: How does Active record decide what to use update or insert?
I am using UUIDs as keys.
I generate UUIDs client side for new objects to allow asynch work with the server/db.
Example: The user adds a new triangle to his drawing, I create this object set a uuid (lets say AAA), place it in editor and the user can work further. Then I send the update to the server. So the user does not have to wait the RTT.
The user fills the triangle green, I draw that -> AJAX to server (Update (AAA))
The use makes a copy of the green triangle, I copy the object set a new UUID and send an AJAX copy AAA to BBB
the user hits undo - remove BBB from drawing send AJAX remove BBB (but its not deleted its just marked for deletion as a standard in my app)
the user hits redo -> I copy the object set a new UUID (BBB again) and send an AJAX copy AAA to BBB
BANG duplicate key
Server side I make a dup, set the id and save
new_rec=old_rec.dup
new_rec.id=new_id #BBB
new_rec.save (BANG because insert)
So what I need is something like
new_rec=old_rec.dup
new_rec.id=new_id #BBB
new_rec.set_method_to_update if Record.exist?(new_id)
new_rec.save (BANG because insert)
I know, that there are workarounds but is it possible the easy way?
AFAIK rails doesn't let you change the persisted characteristic of a record. You'll need to retrieve the record if it exists and update it.
new_rec = Record.find(new_id)
if new_rec
new_rec.deleted = false
else
new_rec = old_rec.dup
new_rec.id = new_id
end
new_rec.save
Regarding the duplicate entries on server end, considering only the primary keys as identifiers in the DB objects. Fetch the data with ID and create one if not found.
Assuming you are using Rails 4, you can use this method find_or_create_by
As i see your question, on a different note: first thing you can do is instead of making ajax calls on every or specific operations. Put a sync of say 5-10 seconds of work done on the interface, using something like angular/backbone to handle the UI level model hierarchy which you have designed. Replace the temporary UUID's on the browser from the server ID's on sync or keep a mapping of both which could be slightly helpful but somewhat messy to maintain.
What I needed - found accidently: #new_record
Set to false and all is fine ...
Usage in Record (model.rb)
def clear_new_if_not
#new_record=!self.class.exists?(self.id)
end
and logic above:
new_rec=old_rec.dup
new_rec.id=new_id #BBB
new_rec.clear_new_if_not()
new_rec.save (no bang)

Notifications or user activity log implementation

The application has certain actions that are recorded for each user and recorded in db table notifications. The table has the following structure:
user_id, notification_type, credit, timestamp
notification_type does not store the entire text of the notification but just stores a short type description.
Later when the user wants to view his notifications I use a helper method from my view to fetch the actual text.
def notification_text(type)
case type_id
when 'flagPositive'
return 'A question you flagged has been marked as correct.'
when 'qAccepted'
return 'A question you added has been accepted.'
when 'qModerated'
return 'You moderated a question.'
when 'flagReport'
return 'You moderated a flag.'
end
end
1) Is this an optimum way to do this?
2) Should I replace the type_description with integer values (say 1 -> flagPositive, 2-> qAccepted) for performance benefits?
3) Are there any best practices around the same that I should be following?
1) This highly depends on your application and requirements. What I can say is that I used this approach sometimes and faced no problems so far.
2) If you see a performance problem with the string lookup, you could do so. A general recommendation is to optimize performance only when really needed.
3) Just google for "Ruby", "Rails", "ActiveRecord" and "Enum". You'll find lots of discussions about different solutions for this kind of problem. There are similar questions on this site, e.g., Enums in Ruby or In Rails, how should I implement a Status field for a Tasks app - integer or enum?

Magento SalesOrderList... is there a ligth weight version of this, or a way to trim down the returned value

I am attempting to get all the orders from a magento instance. Once a day we grab all the orders.. (sometimes a few thousand)
Extra stuff that's more why I ask:
I'm using ruby-on-rails to grab the orders. This involves sending the soap call to the magento instance. It's easy as.
Once I have the response, I convert it into a Hash (a tree) and then pick out the increment id's of the orders and proceed to call getOrder with the increment id.
I have two problems with what's going on now, one operational, and one religious.
Grabbing the XML response to the list request takes really really long and when you tack on the work involved in converting the XML to a hash, I'm seeing a really slow processes.
The religious bit is that I just want the increment_ids so why do I have to pay for the processing/bandwidth to support a hugely bloated response.
Ok so the question...
Is there a way to set the response returned from Magento, to include only specific fields? Only the updated_at and the increment_id for instance.
If not, is there another call I'm not aware of, that can get just the increment_ids and date?
Edit
Below is an example of what I'm looking for from magento but it's for ebay. I send this xml up to ebay, and get back a really really specific bit of info about the product. It works for orders and such too. I can say "only this" and get just that. I want the same from Magento
<GetItemRequest xmlns="urn:ebay:apis:eBLBaseComponents">
<SKU>b123-332</SKU><OutputSelector>ItemId</OutputSelector>
</GetItemRequest>
I've created a rubygem that gives you your salesOrderList response in the form of a hash, and you can do what you want with the orders after you've received them back (i.e. select the fields you want including increment_id). Just run
gem install magento_api_wrapper
To do what you want to do, you would do something like this:
api = MagentoApiWrapper::Sales.new(magento_url: "yourmagentostore.com/index.php", magento_username: "soap_api_username", magento_api_key: "userkey123")
orders = api.order_list(simple_filters: [{key: "status" value: "complete"}])
orders.map {|o| [o.increment_id, o.items.first.sku] }
Rough guess, but you get the idea. You would get the array of hashes back and you can do what you want with them after that. Good luck!

Rails using a variable find condition

I am using Braintree for managing subscriptions in my Rails app.
I have a Subscription model that stores the braintree customer ID and subscription ID.
I want to filter active subscriptions in my Subscription model. So far I have
def find_active_subscriptions
#active_subscriptions = Braintree::Subscription.search do |search|
search.status.is "Active"
end
But now I want to use the subscription IDs in #active_subscriptions to find all of the objects in my local Subscription model with the same subscription IDs and put that into a variable such as #local_active_subscriptions.
The reason I have to do this is to use the local info to access Braintree::Address and only pull active addresses.
Thanks for the help.
One you have the #active_subscriptions you can collect all of the ids into an array and pass them right into the find method of your local Subscription model. I don't know what attributes you are using here, so I'm just making some guesses:
#active_subscription_ids = #active_subscriptions.collect(&:subscription_id)
#local_active_subscriptions = LocalSubscriptionModel.find(#active_subscription_ids)
I'm not sure what Braintree::Subscription.search returns, but if it's something akin to ActiveRecords, could you use something like:
#local_active_subscriptions = Subscription.where("id IN(?)", #active_subscriptions.map{ |act_subs| act_subs.id })
The .map function should put all the IDs into an array, and then ActiveRecord query would look for all the Subscriptions in your subscriptions table whose ID is in that array.
I'm not certain about mapping on Braintree::Subscriptions; I've never used that.
Edit
Like ctcherry said, you can also do the search with find. And I guess collect is good for mapping the ids into an array too. You could also maybe use #active_subscriptions.map(&:id)

validates_uniqueness_of failing on heroku?

In my User model, I have:
validates_uniqueness_of :fb_uid (I'm using facebook connect).
However, at times, I'm getting duplicate rows upon user sign up. This is Very Bad.
The creation time of the two records is within 100ms. I haven't been able to determine if it happens in two separate requests or not (heroku logging sucks and only goes back so far and it's only happened twice).
Two things:
Sometimes the request takes some time, because I query FB API for name info, friends, and picture.
I'm using bigint to store fb_uid (backend is postgres).
I haven't been able to replicate in dev.
Any ideas would be extremely appreciated.
The signin function
def self.create_from_cookie(fb_cookie, remote_ip = nil)
return nil unless fb_cookie
return nil unless fb_hash = authenticate_cookie(fb_cookie)
uid = fb_hash["uid"].join.to_i
#Make user and set data
fb_user = FacebookUser.new
fb_user.fb_uid = uid
fb_user.fb_authorized = true
fb_user.email_confirmed = true
fb_user.creation_ip = remote_ip
fb_name_data, fb_friends_data, fb_photo_data, fb_photo_ext = fb_user.query_data(fb_hash)
return nil unless fb_name_data
fb_user.set_name(fb_name_data)
fb_user.set_photo(fb_photo_data, fb_photo_ext)
#Save user and friends to the db
return nil unless fb_user.save
fb_user.set_friends(fb_friends_data)
return fb_user
end
I'm not terribly familiar with facebook connect, but is it possible to get two of the same uuid if two separate users from two separate accounts post a request in very quick succession before either request has completed? (Otherwise known as a race condition) validates_uniqueness_of can still suffer from this sort of race condition, details can be found here:
http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates_uniqueness_of
Because this check is performed
outside the database there is still a
chance that duplicate values will be
inserted in two parallel transactions.
To guarantee against this you should
create a unique index on the field.
See add_index for more information.
You can really make sure this will never happen by adding a database constraint. Add this to a database migration and then run it:
add_index :user, :fb_uid, :unique => true
Now a user would get an error instead of being able to complete the request, which is usually preferable to generating illegal data in your database which you have to debug and clean out manually.
From Ruby on Rails v3.0.5 Module ActiveRecord::Validations::ClassMethods
http://s831.us/dK6mFQ
Concurrency and integrity
Using this [validates_uniqueness_of]
validation method in conjunction with
ActiveRecord::Base#save does not
guarantee the absence of duplicate
record insertions, because uniqueness
checks on the application level are
inherently prone to race conditions.
For example, suppose that two users
try to post a Comment at the same
time, and a Comment’s title must be
unique. At the database-level, the
actions performed by these users could
be interleaved in the following
manner: ...
It seems like there is some sort of a race condition inside your code. To check this, i would first change the code so that facebook values are first extracted and only then i would create a new facebook object.
Then i would highly suggest that you write a test to check whether your function gets executed once. It seems that it's executed two times.
And upon this, there seems to be a race condition upon waiting to get the facebook results.

Resources