bang! kill redis cache.

This commit is contained in:
danielgrippi 2012-02-02 12:45:19 -08:00
parent d1a82d288d
commit 4f7dda6012
22 changed files with 3 additions and 863 deletions

View file

@ -12,7 +12,6 @@ class ShareVisibilitiesController < ApplicationController
params[:shareable_type] ||= 'Post' params[:shareable_type] ||= 'Post'
vis = current_user.toggle_hidden_shareable(accessible_post) vis = current_user.toggle_hidden_shareable(accessible_post)
RedisCache.update_cache_for(current_user, accessible_post, vis)
render :nothing => true, :status => 200 render :nothing => true, :status => 200
end end

View file

@ -21,9 +21,7 @@ class Contact < ActiveRecord::Base
validates_presence_of :user validates_presence_of :user
validates_uniqueness_of :person_id, :scope => :user_id validates_uniqueness_of :person_id, :scope => :user_id
before_destroy :destroy_notifications, before_destroy :destroy_notifications
:repopulate_cache!
scope :all_contacts_of_person, lambda {|x| where(:person_id => x.id)} scope :all_contacts_of_person, lambda {|x| where(:person_id => x.id)}
@ -53,13 +51,6 @@ class Contact < ActiveRecord::Base
:type => "Notifications::StartedSharing").delete_all :type => "Notifications::StartedSharing").delete_all
end end
def repopulate_cache!
if RedisCache.configured? && self.user.present?
cache = RedisCache.new(self.user)
cache.repopulate!
end
end
def dispatch_request def dispatch_request
request = self.generate_request request = self.generate_request
Postzord::Dispatcher.build(self.user, request).post Postzord::Dispatcher.build(self.user, request).post

View file

@ -52,8 +52,6 @@ class Post < ActiveRecord::Base
belongs_to :o_embed_cache belongs_to :o_embed_cache
after_create :cache_for_author
#scopes #scopes
scope :includes_for_a_stream, includes(:o_embed_cache, {:author => :profile}, :mentions => {:person => :profile}) #note should include root and photos, but i think those are both on status_message scope :includes_for_a_stream, includes(:o_embed_cache, {:author => :profile}, :mentions => {:person => :profile}) #note should include root and photos, but i think those are both on status_message
@ -123,19 +121,4 @@ class Post < ActiveRecord::Base
def comment_email_subject def comment_email_subject
I18n.t('notifier.a_post_you_shared') I18n.t('notifier.a_post_you_shared')
end end
# @return [Boolean]
def cache_for_author
if self.should_cache_for_author?
cache = RedisCache.new(self.author.owner, 'created_at')
cache.add(self.created_at.to_i, self.id)
end
true
end
# @return [Boolean]
def should_cache_for_author?
self.triggers_caching? && RedisCache.configured? &&
RedisCache.acceptable_types.include?(self.type) && user = self.author.owner
end
end end

View file

@ -26,27 +26,6 @@ defaults: &defaults
# leave it empty for the default (localhost) # leave it empty for the default (localhost)
redis_url: '' redis_url: ''
# Redis cache
# Enable the cache layer (Redis)
# If you expect to have thousands of users on your pod,
# we *highly* suggest you enable this.
# IMPORTANT: THE CACHE REQUIRES REDIS 2.4 OR LATER.
#
# By default, the cache layer will piggyback off of the Redis
# database used by your Resque workers.
redis_cache: false
# The location of your redis cache.
# IMPORTANT: DO NOT CHANGE THIS IF YOU DO NOT KNOW WHAT YOU ARE DOING!
#
# Leave this blank to use the same Redis database
# that your Resque workers use (happy path).
#
# This takes an ip (or DNS record). It assumes that your Redis database
# is running on the default Redis port.
redis_location: ''
# Amazon S3 for photos # Amazon S3 for photos
# s3 config - if set, carrierwave will store your photos on s3. Otherwise they're on the filesystem. # s3 config - if set, carrierwave will store your photos on s3. Otherwise they're on the filesystem.

View file

@ -54,12 +54,8 @@ ServiceUser.import((1..40).map{|n| Factory.build(:service_user, :service => eve_
puts "done!" puts "done!"
require File.join(File.dirname(__FILE__), '..', 'spec', 'support', 'fake_resque') require File.join(File.dirname(__FILE__), '..', 'spec', 'support', 'fake_resque')
require File.join(File.dirname(__FILE__), '..', 'spec', 'support', 'fake_redis')
require File.join(File.dirname(__FILE__), '..', 'spec', 'support', 'user_methods') require File.join(File.dirname(__FILE__), '..', 'spec', 'support', 'user_methods')
old_cache_setting = AppConfig[:redis_cache]
AppConfig[:redis_cache] = false
print "Seeding post data..." print "Seeding post data..."
time_interval = 1000 time_interval = 1000
(1..25).each do |n| (1..25).each do |n|
@ -82,8 +78,6 @@ time_interval = 1000
end end
puts " done!" puts " done!"
AppConfig[:redis_cache] = old_cache_setting
puts "Successfully seeded the db with users eve, bob, and alice (password: 'evankorth')" puts "Successfully seeded the db with users eve, bob, and alice (password: 'evankorth')"
puts "" puts ""

View file

@ -50,7 +50,6 @@ require File.join(File.dirname(__FILE__), "database_cleaner_patches")
require File.join(File.dirname(__FILE__), "integration_sessions_controller") require File.join(File.dirname(__FILE__), "integration_sessions_controller")
require File.join(File.dirname(__FILE__), "poor_mans_webmock") require File.join(File.dirname(__FILE__), "poor_mans_webmock")
require File.join(File.dirname(__FILE__), "..", "..", "spec", "support", "fake_redis")
require File.join(File.dirname(__FILE__), "..", "..", "spec", "helper_methods") require File.join(File.dirname(__FILE__), "..", "..", "spec", "helper_methods")
require File.join(File.dirname(__FILE__), "..", "..", "spec", "support","user_methods") require File.join(File.dirname(__FILE__), "..", "..", "spec", "support","user_methods")
include HelperMethods include HelperMethods

View file

@ -1,143 +0,0 @@
# 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 RedisCache
SUPPORTED_CACHES = [:created_at]
CACHE_LIMIT = 100
def initialize(user, order_field=:created_at)
@user = user
@order_field = order_field.to_s
end
# Checks to see if the necessary redis cache variables are set in application.yml
#
# @return [Boolean]
def self.configured?
AppConfig[:redis_cache].present?
end
def self.update_cache_for(user, post, post_was_hidden)
return unless RedisCache.configured?
cache = RedisCache.new(user, 'created_at')
if post_was_hidden
cache.remove(post.id)
else
cache.add(post.created_at.to_i, post.id)
end
end
# @return [Boolean]
def cache_exists?
self.redis.exists(set_key)
end
# @return [Integer] the cardinality of the redis set
def size
redis.zcard(set_key)
end
def post_ids(time=Time.now, limit=15)
post_ids = redis.zrevrangebyscore(set_key, time.to_i, "-inf")
post_ids[0...limit]
end
def ensure_populated!(opts = {})
self.repopulate!(opts) unless cache_exists?
end
def repopulate!(opts = {})
self.purge!
self.populate!(opts) && self.trim!
end
def purge!
self.redis.del(set_key)
end
def populate!(opts = {})
# user executes query and gets back hashes
opts.merge!({
:type => RedisCache.acceptable_types,
:limit => CACHE_LIMIT,
:order => self.order
})
sql = @user.visible_shareable_sql(Post, opts)
hashes = Post.connection.select_all(sql)
# hashes are inserted into set in a single transaction
redis.multi do
hashes.each do |h|
self.redis.zadd(set_key, h[@order_field].to_i, h["id"])
end
end
end
def trim!
self.redis.zremrangebyrank(set_key, 0, -(CACHE_LIMIT+1))
end
# @param order [Symbol, String]
# @return [Boolean]
def self.supported_order?(order)
SUPPORTED_CACHES.include?(order.to_sym)
end
def order
"#{@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
def remove(id)
return unless self.cache_exists?
self.redis.zrem(set_key, id)
end
# exposing the need to tie cache to a stream
# @return [Array<String>] Acceptable Post types for the given cache
def self.acceptable_types
Stream::Base::TYPES_OF_POST_IN_STREAM
end
# Instantiate a redis connection
#
# @return [Redis]
def self.redis_connection
Redis.new(:host => RedisCache.redis_host, :port => RedisCache.redis_port)
end
protected
# @see .redis_connection
# @return [Redis]
def redis
@redis ||= RedisCache.redis_connection
end
def self.redis_host
(AppConfig[:redis_location].blank?) ? nil : AppConfig[:redis_location]
end
def self.redis_port
(AppConfig[:redis_port].blank?) ? nil : AppConfig[:redis_port]
end
# @return [String]
def self.cache_prefix
"cache_stream"
end
# @return [String]
def set_key
@set_key ||= "#{RedisCache.cache_prefix}_#{@user.id}_#{@order_field}"
end
end

View file

@ -2,8 +2,6 @@
# licensed under the Affero General Public License version 3 or later. See # licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file. # the COPYRIGHT file.
require File.join(Rails.root, 'lib', 'diaspora', 'redis_cache')
require File.join(Rails.root, 'lib', 'evil_query') require File.join(Rails.root, 'lib', 'evil_query')
@ -24,31 +22,9 @@ module Diaspora
klass.where(:id => shareable_ids).select('DISTINCT '+klass.to_s.tableize+'.*').limit(opts[:limit]).order(opts[:order_with_table]) klass.where(:id => shareable_ids).select('DISTINCT '+klass.to_s.tableize+'.*').limit(opts[:limit]).order(opts[:order_with_table])
end end
def visible_shareables_from_cache(klass, opts)
cache = RedisCache.new(self, opts[:order_field])
#total hax
if self.contacts.where(:sharing => true, :receiving => true).count > 0
cache.ensure_populated!(opts)
end
name = klass.to_s.downcase + "_ids"
cached_ids = cache.send(name, opts[:max_time], opts[:limit] +1)
if perform_db_query?(cached_ids, cache, opts)
visible_ids_from_sql(klass, opts)
else
cached_ids
end
end
def visible_shareable_ids(klass, opts={}) def visible_shareable_ids(klass, opts={})
opts = prep_opts(klass, opts) opts = prep_opts(klass, opts)
if use_cache?(opts) visible_ids_from_sql(klass, opts)
visible_shareables_from_cache(klass, opts)
else
visible_ids_from_sql(klass, opts)
end
end end
# @return [Array<Integer>] # @return [Array<Integer>]
@ -170,18 +146,6 @@ module Diaspora
end end
protected protected
# @return [Boolean]
def use_cache?(opts)
RedisCache.configured? && RedisCache.supported_order?(opts[:order_field]) && opts[:all_aspects?].present?
end
# @return [Boolean]
def perform_db_query?(shareable_ids, cache, opts)
return true if cache == nil
return false if cache.size <= opts[:limit]
shareable_ids.blank? || shareable_ids.length < opts[:limit]
end
# @return [Hash] # @return [Hash]
def prep_opts(klass, opts) def prep_opts(klass, opts)

View file

@ -8,16 +8,7 @@ class Postzord::Receiver
require File.join(Rails.root, 'lib/postzord/receiver/public') require File.join(Rails.root, 'lib/postzord/receiver/public')
def perform! def perform!
if self.receive! self.receive!
self.update_cache! if cache?
end
end
# @return [Boolean]
def cache?
self.respond_to?(:update_cache!) && RedisCache.configured? &&
@object.respond_to?(:triggers_caching?) && @object.triggers_caching? &&
@object.respond_to?(:type) && RedisCache.acceptable_types.include?(@object.type)
end end
end end

View file

@ -26,17 +26,6 @@ class Postzord::Receiver::LocalBatch < Postzord::Receiver
true true
end end
def update_cache!
@users.each do |user|
# (NOTE) this can be optimized furter to not use n-query
contact = user.contact_for(object.author)
if contact && contact.aspect_memberships.size > 0
cache = RedisCache.new(user, "created_at")
cache.add(@object.created_at.to_i, @object.id)
end
end
end
# NOTE(copied over from receiver public) # NOTE(copied over from receiver public)
# @return [Object] # @return [Object]
def receive_relayable def receive_relayable

View file

@ -48,13 +48,6 @@ class Postzord::Receiver::Private < Postzord::Receiver
obj obj
end end
def update_cache!
if @user.contact_for(@author).aspect_memberships.size > 0
cache = RedisCache.new(@user, "created_at")
cache.add(@object.created_at.to_i, @object.id)
end
end
protected protected
def salmon def salmon
@salmon ||= Salmon::EncryptedSlap.from_xml(@salmon_xml, @user) @salmon ||= Salmon::EncryptedSlap.from_xml(@salmon_xml, @user)

View file

@ -1,19 +0,0 @@
namespace :cache do
desc "Clear all caches"
task :clear => :environment do
if RedisCache.configured?
redis = RedisCache.redis_connection
puts "Clearing Cache..."
redis.keys do |k|
if k.match(/^#{RedisCache.cache_prefix}/).present?
redis.del(k)
end
end
puts "Done!"
else
puts "Redis Cache is not configured"
end
end
end

View file

@ -11,21 +11,12 @@ describe ShareVisibilitiesController do
end end
describe '#update' do describe '#update' do
before do
@controller.stub(:update_cache)
end
context "on a post you can see" do context "on a post you can see" do
it 'succeeds' do it 'succeeds' do
put :update, :format => :js, :id => 42, :post_id => @status.id put :update, :format => :js, :id => 42, :post_id => @status.id
response.should be_success response.should be_success
end end
it 'calls #update_cache' do
RedisCache.should_receive(:update_cache_for).with(an_instance_of(User), an_instance_of(Post), true)
put :update, :format => :js, :id => 42, :post_id => @status.id
end
it 'it calls toggle_hidden_shareable' do it 'it calls toggle_hidden_shareable' do
@controller.current_user.should_receive(:toggle_hidden_shareable).with(an_instance_of(Post)) @controller.current_user.should_receive(:toggle_hidden_shareable).with(an_instance_of(Post))
put :update, :format => :js, :id => 42, :post_id => @status.id put :update, :format => :js, :id => 42, :post_id => @status.id

View file

@ -1,249 +0,0 @@
# Copyright (c) 2010-2011, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
require 'spec_helper'
describe RedisCache do
before do
@redis = MockRedis.new
@cache = RedisCache.new(bob, :created_at)
@cache.stub(:redis).and_return(@redis)
end
it 'gets initialized with user and an created_at order' do
cache = RedisCache.new(bob, :created_at)
[:@user, :@order_field].each do |var|
cache.instance_variable_get(var).should_not be_blank
end
end
describe "#cache_exists?" do
it 'returns true if the sorted set exists' do
timestamp = Time.now.to_i
@redis.zadd("cache_stream_#{bob.id}_created_at", timestamp, "post_1")
@cache.cache_exists?.should be_true
end
it 'returns false if there is nothing in the set' do
@cache.cache_exists?.should be_false
end
end
describe "#post_ids" do
before do
@timestamps = []
@timestamp = Time.now.to_i
30.times do |n|
created_time = @timestamp - n*1000
@redis.zadd("cache_stream_#{bob.id}_created_at", created_time, n.to_s)
@timestamps << created_time
end
end
it 'returns the most recent post ids (default created at, limit 15)' do
@cache.post_ids.should =~ 15.times.map { |n| n.to_s }
end
it 'returns posts ids after the specified time' do
@cache.post_ids(@timestamps[15]).should =~ (15...30).map { |n| n.to_s }
end
it 'returns post ids with a non-default limit' do
@cache.post_ids(@timestamp, 20).should =~ 20.times.map { |n| n.to_s }
end
end
describe "#ensure_populated!" do
it 'does nothing if the cache is populated' do
@cache.stub(:cache_exists?).and_return(true)
@cache.should_not_receive(:repopulate!)
@cache.ensure_populated!
end
it 'calls #repopulate' do
opts = {:here_is => "something"}
@cache.stub(:cache_exists?).and_return(false)
@cache.should_receive(:repopulate!).with(opts)
@cache.ensure_populated!(opts)
end
end
describe "#repopulate!" do
it 'calls #purge!' do
@cache.should_receive(:purge!)
@cache.repopulate!
end
it 'populates' do
opts = {:here_is => "something"}
@cache.stub(:trim!).and_return(true)
@cache.should_receive(:populate!).with(opts).and_return(true)
@cache.repopulate!(opts)
end
it 'trims' do
@cache.stub(:populate!).and_return(true)
@cache.should_receive(:trim!)
@cache.repopulate!
end
end
describe '#purge!' do
it 'clears the set in redis' do
@cache.stub(:redis).and_return(@redis)
@redis.should_receive(:del).with(@cache.send(:set_key))
@cache.purge!
end
end
describe "#populate!" do
it 'queries the db with the visible post sql string' do
sql = "long_sql"
order = "created_at DESC"
@cache.should_receive(:order).and_return(order)
bob.should_receive(:visible_shareable_sql).with(
Post,
hash_including(
:type => RedisCache.acceptable_types,
:limit => RedisCache::CACHE_LIMIT,
:order => order)).
and_return(sql)
Post.connection.should_receive(:select_all).with(sql).and_return([])
@cache.populate!
end
end
describe "#trim!" do
it 'does nothing if the set is smaller than the cache limit' do
@timestamps = []
@timestamp = Time.now.to_i
30.times do |n|
created_time = @timestamp - n*1000
@redis.zadd("cache_stream_#{bob.id}_created_at", created_time, n.to_s)
@timestamps << created_time
end
post_ids = @cache.post_ids(Time.now.to_i, @cache.size)
@cache.trim!
@cache.post_ids(Time.now.to_i, @cache.size).should == post_ids
end
it 'trims the set to the cache limit' do
@timestamps = []
@timestamp = Time.now.to_i
120.times do |n|
created_time = @timestamp - n*1000
@redis.zadd("cache_stream_#{bob.id}_created_at", created_time, n.to_s)
@timestamps << created_time
end
post_ids = 100.times.map { |n| n.to_s }
@cache.trim!
@cache.post_ids(Time.now.to_i, @cache.size).should == post_ids[0...100]
end
end
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)
end
end
describe "#remove" do
before do
@id = 1
end
it "doesn't add if the cache does not exist" do
@cache.stub(:cache_exists?).and_return(false)
@redis.should_not_receive(:zrem)
@cache.remove(@id).should be_false
end
it "removes a given id" do
@cache.stub(:cache_exists?).and_return(true)
@redis.should_receive(:zrem).with(@cache.send(:set_key), @id)
@cache.remove(@id)
end
end
describe "#set_key" do
it 'uses the correct prefix and order' do
user = @cache.instance_variable_get(:@user)
order_field = @cache.instance_variable_get(:@order_field)
@cache.send(:set_key).should == "#{RedisCache.cache_prefix}_#{user.id}_#{order_field}"
end
end
describe '.cache_setup?' do
it 'returns true if configuration is properly set' do
AppConfig[:redis_cache] = true
RedisCache.should be_configured
end
it 'returns false if configuration is not present' do
AppConfig[:redis_cache] = false
RedisCache.should_not be_configured
end
end
describe '.acceptable_types' do
#exposing the need to tie cache to a stream
it 'returns the types from the aspect stream' do
RedisCache.acceptable_types.should =~ Stream::Base::TYPES_OF_POST_IN_STREAM
end
end
describe '#update_cache' do
before do
@cache = RedisCache.new(bob, 'created_at')
RedisCache.stub(:new).and_return(@cache)
RedisCache.stub(:configured?).and_return(true)
@post = Factory(:status_message)
end
it 'does nothing if cache is not configured' do
RedisCache.stub(:configured?).and_return(false)
RedisCache.should_not_receive(:new)
RedisCache.update_cache_for(bob, @post, true)
end
it 'removes the post from the cache if visibility is marked as hidden' do
@cache.should_receive(:remove).with(@post.id)
RedisCache.update_cache_for(bob, @post, true)
end
it 'adds the post from the cache if visibility is unmarked as hidden' do
@cache.should_receive(:add).with(@post.created_at.to_i, @post.id)
RedisCache.update_cache_for(bob, @post, false)
end
end
end

View file

@ -91,43 +91,4 @@ describe Postzord::Receiver::LocalBatch do
receiver.perform! receiver.perform!
end end
end end
describe '#update_cache!' do
before do
end
it 'adds to a redis cache for users sharing with author' do
users = [bob]
@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
it 'does not add to the redis cache of the users not contact with author' do
users = [bob, eve]
@zord = Postzord::Receiver::LocalBatch.new(@object, users.map{|u| u.id})
RedisCache.should_receive(:new).once.with(bob, anything()).and_return(stub.as_null_object)
@zord.update_cache!
end
it 'does not add to the redis cache of users not sharing with the author' do
alice.share_with(eve.person, alice.aspects.first)
users = [bob, eve]
@zord = Postzord::Receiver::LocalBatch.new(@object, users.map{|u| u.id})
RedisCache.should_receive(:new).once.with(bob, anything()).and_return(stub.as_null_object)
@zord.update_cache!
end
end
end end

View file

@ -96,29 +96,4 @@ describe Postzord::Receiver::Private do
@zord.receive_object @zord.receive_object
end end
end end
describe '#update_cache!' do
it 'adds to redis cache if the contact has aspect visibilities' do
@alices_post.save!
@zord = Postzord::Receiver::Private.new(bob, :person => alice.person, :object => @alices_post)
sort_order = "created_at"
cache = RedisCache.new(bob, sort_order)
RedisCache.should_receive(:new).with(bob, sort_order).and_return(cache)
cache.should_receive(:add).with(@alices_post.created_at.to_i, @alices_post.id)
@zord.update_cache!
end
it 'does not add to redis cache if the receiving user is not sharing with the sender' do
alice.share_with(eve.person, alice.aspects.first)
@alices_post.save!
@zord = Postzord::Receiver::Private.new(eve, :person => alice.person, :object => @alices_post)
sort_order = "created_at"
RedisCache.should_not_receive(:new)
@zord.update_cache!
end
end
end end

View file

@ -20,68 +20,6 @@ describe Postzord::Receiver do
@receiver.should_receive(:receive!) @receiver.should_receive(:receive!)
@receiver.perform! @receiver.perform!
end end
context 'update_cache!' do
before do
@receiver.stub(:cache?).and_return(true)
end
it "gets called if cache?" do
@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
it 'does not get called if receive! is false' do
@receiver.stub(:receive!).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
RedisCache.stub(:acceptable_types).and_return(["StatusMessage"])
@receiver.instance_variable_set(:@object, mock(:triggers_caching? => true, :type => "StatusMessage"))
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
it 'returns false if the object is not of acceptable type for the cache' do
@receiver.instance_variable_set(:@object, mock(:triggers_caching? => true, :type => "Photo"))
@receiver.cache?.should be_false
end
end end
end end

View file

@ -10,14 +10,6 @@ describe Stream::Multi do
it_should_behave_like 'it is a stream' it_should_behave_like 'it is a stream'
end end
describe '#is_in?' do
it 'handles when the cache returns strings' do
p = Factory(:status_message)
@stream.should_receive(:aspects_post_ids).and_return([p.id.to_s])
@stream.send(:is_in?, :aspects, p).should be_true
end
end
describe '#publisher_opts' do describe '#publisher_opts' do
it 'prefills, sets public, and autoexpands if welcome? is set' do it 'prefills, sets public, and autoexpands if welcome? is set' do
prefill_text = "sup?" prefill_text = "sup?"

View file

@ -194,31 +194,6 @@ describe Contact do
end end
end end
describe "#repopulate_cache" do
before do
@contact = bob.contact_for(alice.person)
end
it "repopulates the cache if the cache exists" do
cache = stub(:repopulate!)
RedisCache.stub(:configured? => true, :new => cache)
cache.should_receive(:repopulate!)
@contact.repopulate_cache!
end
it "does not touch the cache if it is not configured" do
RedisCache.stub(:configured?).and_return(false)
RedisCache.should_not_receive(:new)
@contact.repopulate_cache!
end
it "gets called on destroy" do
@contact.should_receive(:repopulate_cache!)
@contact.destroy
end
end
describe "#not_blocked_user" do describe "#not_blocked_user" do
before do before do
@contact = alice.contact_for(bob.person) @contact = alice.contact_for(bob.person)

View file

@ -229,74 +229,6 @@ describe Post do
end end
end end
describe "triggers_caching?" do
it 'returns true' do
Post.new.triggers_caching?.should be_true
end
end
describe "after_create" do
it "calls cache_for_author only on create" do
post = Factory.build(:status_message, :author => bob.person)
post.should_receive(:cache_for_author).once
post.save
post.save
end
end
describe '#cache_for_author' do
before do
@post = Factory.build(:status_message, :author => bob.person)
@post.stub(:should_cache_for_author?).and_return(true)
end
it 'caches with valid conditions' do
cache = mock.as_null_object
RedisCache.should_receive(:new).and_return(cache)
cache.should_receive(:add)
@post.cache_for_author
end
it 'does nothing if should not cache' do
@post.stub(:should_cache_for_author?).and_return(false)
RedisCache.should_not_receive(:new)
@post.cache_for_author
end
end
describe "#should_cache_for_author?" do
before do
@post = Factory.build(:status_message, :author => bob.person)
RedisCache.stub(:configured?).and_return(true)
RedisCache.stub(:acceptable_types).and_return(['StatusMessage'])
@post.stub(:triggers_caching?).and_return(true)
end
it 'returns true under valid conditions' do
@post.should_cache_for_author?.should be_true
end
it 'does not cache if the author is not a local user' do
@post.author = Factory(:person)
@post.should_cache_for_author?.should be_false
end
it 'does not cache if the cache is not configured' do
RedisCache.stub(:configured?).and_return(false)
@post.should_cache_for_author?.should be_false
end
it 'does not cache if the object does not triggers caching' do
@post.stub(:triggers_caching?).and_return(false)
@post.should_cache_for_author?.should be_false
end
it 'does not cache if the object is not of an acceptable cache type' do
@post.stub(:type).and_return("Photo")
@post.should_cache_for_author?.should be_false
end
end
describe "#receive" do describe "#receive" do
it 'returns false if the post does not verify' do it 'returns false if the post does not verify' do
@post = Factory(:status_message, :author => bob.person) @post = Factory(:status_message, :author => bob.person)

View file

@ -91,90 +91,6 @@ describe User do
alice.visible_shareable_ids(Post).include?(@status.id).should be_false alice.visible_shareable_ids(Post).include?(@status.id).should be_false
end end
end end
context "RedisCache" do
before do
AppConfig[:redis_cache] = true
@opts = {:order => "created_at DESC", :order_field => "created_at", :all_aspects? => true}
end
after do
AppConfig[:redis_cache] = nil
end
it "populates the cache if the user has a mutual contact" do
RedisCache.any_instance.should_receive(:ensure_populated!)
alice.stub(:use_cache?).and_return(true)
alice.visible_shareable_ids(Post)
end
it 'does not get used if if all_aspects? option is not present' do
RedisCache.should_not_receive(:new)
alice.visible_shareable_ids(Post, @opts.merge({:all_aspects? => false}))
end
describe '#use_cache?' do
before do
cache = mock(:cache_exists? => true, :supported_order? => true, :ensure_populated! => mock, :post_ids => [])
RedisCache.stub(:new).and_return(cache)
end
it 'returns true if redis cache is set' do
AppConfig[:redis_cache] = true
alice.send(:use_cache?, @opts).should be_true
end
it 'returns false if redis cache is set' do
AppConfig[:redis_cache] = nil
alice.send(:use_cache?, @opts).should be_false
end
end
describe '#perform_db_query?' do
before do
@opts = {:limit => 15}
end
it 'returns true if cache is nil' do
alice.send(:perform_db_query?, [1,2,3], nil, @opts).should be_true
end
it 'returns true if cache shareable_ids is blank' do
cache = mock(:size => 100)
alice.send(:perform_db_query?, [], cache, @opts).should be_true
end
it 'returns true if cache shareable_ids length is less than opts[:limit]' do
cache = mock(:size => 100)
alice.send(:perform_db_query?, [1,2,3], cache, @opts).should be_true
end
it 'returns false if cache size is less than opts[:limit]' do
cache = mock(:size => 10)
alice.send(:perform_db_query?, [1,2,3], cache, @opts).should be_false
end
end
context 'populated cache' do
before do
@cache = mock(:cache_exists? => true, :size => 100, :ensure_populated! => mock)
RedisCache.stub(:new).and_return(@cache)
end
it "reads from the cache" do
@cache.should_receive(:post_ids).and_return([1,2,3])
alice.visible_shareable_ids(Post, @opts.merge({:limit => 3})).should == [1,2,3]
end
it "queries if maxtime is later than the last cached post" do
@cache.stub(:post_ids).and_return([])
alice.should_receive(:visible_ids_from_sql)
alice.visible_shareable_ids(Post, @opts)
end
end
end
end end
describe "#prep_opts" do describe "#prep_opts" do

View file

@ -1,11 +0,0 @@
module Diaspora::WebSocket
def self.redis
MockRedis.new
end
end
class RedisCache
def self.redis_connection
MockRedis.new
end
end