diff --git a/app/models/post.rb b/app/models/post.rb index b4037e4d6..04fb21fda 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -138,6 +138,10 @@ class Post < ActiveRecord::Base false end + def triggers_caching? + true + end + def comment_email_subject I18n.t('notifier.a_post_you_shared') end diff --git a/lib/diaspora/redis_cache.rb b/lib/diaspora/redis_cache.rb index 3620ee222..6b3492c52 100644 --- a/lib/diaspora/redis_cache.rb +++ b/lib/diaspora/redis_cache.rb @@ -63,6 +63,12 @@ class RedisCache "#{@order_field} DESC" end + def add(score, id) + return unless self.cache_exists? + self.redis.zadd(set_key, score.to_i, id) + self.trim! + end + protected # @return [Redis] def redis diff --git a/lib/postzord/receiver.rb b/lib/postzord/receiver.rb new file mode 100644 index 000000000..5c4feee03 --- /dev/null +++ b/lib/postzord/receiver.rb @@ -0,0 +1,21 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + + +class Postzord::Receiver + require File.join(Rails.root, 'lib/postzord/receiver/private') + require File.join(Rails.root, 'lib/postzord/receiver/public') + + def perform! + receive! + update_cache! if cache? + end + + # @return [Boolean] + def cache? + self.respond_to?(:update_cache!) && AppConfig[:redis_cache] && + @object.respond_to?(:triggers_caching?) && @object.triggers_caching? + end +end + diff --git a/lib/postzord/receiver/local_batch.rb b/lib/postzord/receiver/local_batch.rb index f2da0380d..240da8309 100644 --- a/lib/postzord/receiver/local_batch.rb +++ b/lib/postzord/receiver/local_batch.rb @@ -12,14 +12,11 @@ class Postzord::Receiver::LocalBatch < Postzord::Receiver @users = User.where(:id => @recipient_user_ids) end - def perform! + def receive! if @object.respond_to?(:relayable?) receive_relayable else create_post_visibilities - - # if caching enabled, add to cache - end notify_mentioned_users if @object.respond_to?(:mentions) @@ -28,6 +25,13 @@ class Postzord::Receiver::LocalBatch < Postzord::Receiver notify_users end + def update_cache! + @users.each do |user| + cache = RedisCache.new(user, "created_at") + cache.add(@object.created_at.to_i, @object.id) + end + end + # NOTE(copied over from receiver public) # @return [Object] def receive_relayable diff --git a/lib/postzord/receiver/private.rb b/lib/postzord/receiver/private.rb index 03c799928..a1db66d96 100644 --- a/lib/postzord/receiver/private.rb +++ b/lib/postzord/receiver/private.rb @@ -18,7 +18,7 @@ class Postzord::Receiver::Private < Postzord::Receiver @object = opts[:object] end - def perform! + def receive! if @sender && self.salmon.verified_for_key?(@sender.public_key) parse_and_receive(salmon.parsed_data) else @@ -48,6 +48,11 @@ class Postzord::Receiver::Private < Postzord::Receiver obj end + def update_cache! + cache = RedisCache.new(@user, "created_at") + cache.add(@object.created_at.to_i, @object.id) + end + protected def salmon @salmon ||= Salmon::EncryptedSlap.from_xml(@salmon_xml, @user) diff --git a/lib/postzord/receiver/public.rb b/lib/postzord/receiver/public.rb index 955f97299..a5e55b1a0 100644 --- a/lib/postzord/receiver/public.rb +++ b/lib/postzord/receiver/public.rb @@ -17,7 +17,7 @@ class Postzord::Receiver::Public < Postzord::Receiver end # @return [void] - def perform! + def receive! return false unless verified_signature? return unless save_object diff --git a/spec/lib/diaspora/redis_cache_spec.rb b/spec/lib/diaspora/redis_cache_spec.rb index 790c02574..c92f928a8 100644 --- a/spec/lib/diaspora/redis_cache_spec.rb +++ b/spec/lib/diaspora/redis_cache_spec.rb @@ -136,6 +136,30 @@ describe RedisCache do end end - describe "#add" + describe "#add" do + before do + @cache.stub(:cache_exists?).and_return(true) + @id = 1 + @score = 123 + end + + it "adds an id with a given score" do + @redis.should_receive(:zadd).with(@cache.send(:set_key), @score, @id) + @cache.add(@score, @id) + end + + it 'trims' do + @cache.should_receive(:trim!) + @cache.add(@score, @id) + end + + it "doesn't add if the cache does not exist" do + @cache.stub(:cache_exists?).and_return(false) + + @redis.should_not_receive(:zadd) + @cache.add(@score, @id).should be_false + end + end + describe "#remove" end diff --git a/spec/lib/postzord/receiver/local_batch_spec.rb b/spec/lib/postzord/receiver/local_batch_spec.rb index 421fc9bb4..764c7c596 100644 --- a/spec/lib/postzord/receiver/local_batch_spec.rb +++ b/spec/lib/postzord/receiver/local_batch_spec.rb @@ -17,26 +17,26 @@ describe Postzord::Receiver::LocalBatch do end end - describe '#perform!' do + describe '#receive!' do it 'calls .create_post_visibilities' do receiver.should_receive(:create_post_visibilities) - receiver.perform! + receiver.receive! end it 'sockets to users' do pending 'not currently socketing' receiver.should_receive(:socket_to_users) - receiver.perform! + receiver.receive! end it 'notifies mentioned users' do receiver.should_receive(:notify_mentioned_users) - receiver.perform! + receiver.receive! end it 'notifies users' do receiver.should_receive(:notify_users) - receiver.perform! + receiver.receive! end end @@ -111,4 +111,20 @@ describe Postzord::Receiver::LocalBatch do receiver.perform! end end + + describe '#update_cache!' do + it 'adds to a redis cache for receiving_users' do + users = [alice, eve] + @zord = Postzord::Receiver::LocalBatch.new(@object, users.map{|u| u.id}) + + sort_order = "created_at" + + cache = mock + RedisCache.should_receive(:new).exactly(users.length).times.with(instance_of(User), sort_order).and_return(cache) + + cache.should_receive(:add).exactly(users.length).times.with(@object.created_at.to_i, @object.id) + + @zord.update_cache! + end + end end diff --git a/spec/lib/postzord/receiver/private_spec.rb b/spec/lib/postzord/receiver/private_spec.rb index f86eb6a64..8fe6779cc 100644 --- a/spec/lib/postzord/receiver/private_spec.rb +++ b/spec/lib/postzord/receiver/private_spec.rb @@ -47,7 +47,7 @@ describe Postzord::Receiver::Private do end end - describe '#perform!' do + describe '#receive!' do before do @zord = Postzord::Receiver::Private.new(@user, :salmon_xml => @salmon_xml) @salmon = @zord.instance_variable_get(:@salmon) @@ -67,8 +67,8 @@ describe Postzord::Receiver::Private do context 'returns the sent object' do it 'returns the received object on success' do - object = @zord.perform! - object.should respond_to(:to_diaspora_xml) + @zord.perform! + @zord.instance_variable_get(:@object).should respond_to(:to_diaspora_xml) end end @@ -86,7 +86,7 @@ describe Postzord::Receiver::Private do it 'calls Notification.notify if object responds to notification_type' do cm = Comment.new - cm.stub!(:receive).and_return(cm) + cm.stub(:receive).and_return(cm) Notification.should_receive(:notify).with(@user, cm, @person2) zord = Postzord::Receiver::Private.new(@user, :person => @person2, :object => cm) @@ -103,4 +103,18 @@ describe Postzord::Receiver::Private do @zord.receive_object end end + + describe '#update_cache!' do + it 'adds to redis cache for the given user' do + @original_post.save! + + @zord = Postzord::Receiver::Private.new(@user, :person => @person2, :object => @original_post) + + sort_order = "created_at" + cache = RedisCache.new(@user, sort_order) + RedisCache.should_receive(:new).with(@user, sort_order).and_return(cache) + cache.should_receive(:add).with(@original_post.created_at.to_i, @original_post.id) + @zord.update_cache! + end + end end diff --git a/spec/lib/postzord/receiver_spec.rb b/spec/lib/postzord/receiver_spec.rb new file mode 100644 index 000000000..f51164372 --- /dev/null +++ b/spec/lib/postzord/receiver_spec.rb @@ -0,0 +1,71 @@ +# Copyright (c) 2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +require 'spec_helper' + +require File.join(Rails.root, 'lib/postzord/receiver') + +describe Postzord::Receiver do + before do + @receiver = Postzord::Receiver.new + end + + describe "#perform!" do + before do + @receiver.stub(:receive!) + end + + it 'calls receive!' do + @receiver.should_receive(:receive!) + @receiver.perform! + end + + context 'update_cache!' do + it "gets called if cache?" do + @receiver.stub(:cache?).and_return(true) + @receiver.should_receive(:update_cache!) + @receiver.perform! + end + + it "doesn't get called if !cache?" do + @receiver.stub(:cache?).and_return(false) + @receiver.should_not_receive(:update_cache!) + @receiver.perform! + end + end + end + + describe "#cache?" do + before do + @receiver.stub(:respond_to?).with(:update_cache!).and_return(true) + AppConfig[:redis_cache] = true + @receiver.instance_variable_set(:@object, mock(:triggers_caching? => true)) + end + + it 'returns true if the receiver responds to update_cache and the application has caching enabled' do + @receiver.cache?.should be_true + end + + it 'returns false if the receiver does not respond to update_cache' do + @receiver.stub(:respond_to?).with(:update_cache!).and_return(false) + @receiver.cache?.should be_false + end + + it 'returns false if the application does not have caching set' do + AppConfig[:redis_cache] = false + @receiver.cache?.should be_false + end + + it 'returns false if the object is does not respond to triggers_caching' do + @receiver.instance_variable_set(:@object, mock) + @receiver.cache?.should be_false + end + + it 'returns false if the object is not cacheable' do + @receiver.instance_variable_set(:@object, mock(:triggers_caching? => false)) + @receiver.cache?.should be_false + end + end +end + diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 27ee97472..f5669c7d0 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -131,4 +131,10 @@ describe Post do @post.reload.updated_at.to_i.should == old_time.to_i end end + + describe "triggers_caching?" do + it 'returns true' do + Post.new.triggers_caching?.should be_true + end + end end