From 26151263c59c5471b388b10ef7aa444f4cc3817c Mon Sep 17 00:00:00 2001 From: Maxwell Salzberg Date: Sat, 3 Sep 2011 16:04:53 -0700 Subject: [PATCH] put receiving in a transaction, to prevent the crazy duplicate index errors and hopefully fix federation visibility. --- app/models/post.rb | 47 ++++++++++++++++++++------------------- lib/diaspora/relayable.rb | 38 ++++++++++++++++--------------- 2 files changed, 44 insertions(+), 41 deletions(-) diff --git a/app/models/post.rb b/app/models/post.rb index 8447a730b..0aad95f20 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -83,33 +83,34 @@ class Post < ActiveRecord::Base #exists_locally? #you know about it, and it is mutable #you know about it, and it is not mutable - - local_post = Post.where(:guid => self.guid).first - if local_post && local_post.author_id == self.author_id - known_post = user.find_visible_post_by_id(self.guid, :key => :guid) - if known_post - if known_post.mutable? - known_post.update_attributes(self.attributes) + self.class.transaction do + local_post = self.class.where(:guid => self.guid).first + if local_post && local_post.author_id == self.author_id + known_post = user.find_visible_post_by_id(self.guid, :key => :guid) + if known_post + if known_post.mutable? + known_post.update_attributes(self.attributes) + else + Rails.logger.info("event=receive payload_type=#{self.class} update=true status=abort sender=#{self.diaspora_handle} reason=immutable existing_post=#{known_post.id}") + end else - Rails.logger.info("event=receive payload_type=#{self.class} update=true status=abort sender=#{self.diaspora_handle} reason=immutable existing_post=#{known_post.id}") + user.contact_for(person).receive_post(local_post) + user.notify_if_mentioned(local_post) + Rails.logger.info("event=receive payload_type=#{self.class} update=true status=complete sender=#{self.diaspora_handle} existing_post=#{local_post.id}") + return local_post + end + elsif !local_post + if self.save + user.contact_for(person).receive_post(self) + user.notify_if_mentioned(self) + Rails.logger.info("event=receive payload_type=#{self.class} update=false status=complete sender=#{self.diaspora_handle}") + return self + else + Rails.logger.info("event=receive payload_type=#{self.class} update=false status=abort sender=#{self.diaspora_handle} reason=#{self.errors.full_messages}") end else - user.contact_for(person).receive_post(local_post) - user.notify_if_mentioned(local_post) - Rails.logger.info("event=receive payload_type=#{self.class} update=true status=complete sender=#{self.diaspora_handle} existing_post=#{local_post.id}") - return local_post + Rails.logger.info("event=receive payload_type=#{self.class} update=true status=abort sender=#{self.diaspora_handle} reason='update not from post owner' existing_post=#{self.id}") end - elsif !local_post - if self.save - user.contact_for(person).receive_post(self) - user.notify_if_mentioned(self) - Rails.logger.info("event=receive payload_type=#{self.class} update=false status=complete sender=#{self.diaspora_handle}") - return self - else - Rails.logger.info("event=receive payload_type=#{self.class} update=false status=abort sender=#{self.diaspora_handle} reason=#{self.errors.full_messages}") - end - else - Rails.logger.info("event=receive payload_type=#{self.class} update=true status=abort sender=#{self.diaspora_handle} reason='update not from post owner' existing_post=#{self.id}") end end diff --git a/lib/diaspora/relayable.rb b/lib/diaspora/relayable.rb index e45bfb623..09e721d7a 100644 --- a/lib/diaspora/relayable.rb +++ b/lib/diaspora/relayable.rb @@ -36,28 +36,30 @@ module Diaspora end def receive(user, person) - object = self.class.where(:guid => self.guid).first || self + self.class.transaction do + object = self.class.where(:guid => self.guid).first || self - unless object.parent.author == user.person || object.verify_parent_author_signature - Rails.logger.info("event=receive status=abort reason='object signature not valid' recipient=#{user.diaspora_handle} sender=#{self.parent.author.diaspora_handle} payload_type=#{self.class} parent_id=#{self.parent.id}") - return - end + unless object.parent.author == user.person || object.verify_parent_author_signature + Rails.logger.info("event=receive status=abort reason='object signature not valid' recipient=#{user.diaspora_handle} sender=#{self.parent.author.diaspora_handle} payload_type=#{self.class} parent_id=#{self.parent.id}") + return + end - #sign object as the parent creator if you've been hit UPSTREAM - if user.owns? object.parent - object.parent_author_signature = object.sign_with_key(user.encryption_key) - object.save! - end + #sign object as the parent creator if you've been hit UPSTREAM + if user.owns? object.parent + object.parent_author_signature = object.sign_with_key(user.encryption_key) + object.save! + end - #dispatch object DOWNSTREAM, received it via UPSTREAM - unless user.owns?(object) - object.save! - Postzord::Dispatch.new(user, object).post - end + #dispatch object DOWNSTREAM, received it via UPSTREAM + unless user.owns?(object) + object.save + Postzord::Dispatch.new(user, object).post + end - object.socket_to_user(user) if object.respond_to? :socket_to_user - if object.after_receive(user, person) - object + object.socket_to_user(user) if object.respond_to? :socket_to_user + if object.after_receive(user, person) + object + end end end