# encoding: utf-8 require "mongoid/collections/operations" require "mongoid/collections/cyclic_iterator" require "mongoid/collections/mimic" require "mongoid/collections/master" require "mongoid/collections/slaves" module Mongoid #:nodoc class Collection include Collections::Mimic attr_reader :counter, :name # All write operations should delegate to the master connection. These # operations mimic the methods on a Mongo:Collection. # # Example: # # collection.save({ :name => "Al" }) proxy(:master, Collections::Operations::WRITE) # All read operations should be intelligently directed to either the master # or the slave, depending on where the read counter is and what it's # maximum was configured at. # # Example: # # collection.find({ :name => "Al" }) proxy(:directed, (Collections::Operations::READ - [:find])) # Determines where to send the next read query. If the slaves are not # defined then send to master. If the read counter is under the configured # maximum then return the master. In any other case return the slaves. # # Example: # # collection.directed # # Return: # # Either a +Master+ or +Slaves+ collection. def directed if under_max_counter? || slaves.empty? @counter = @counter + 1 master else @counter = 0 slaves end end # Find documents from the database given a selector and options. # # Options: # # selector: A +Hash+ selector that is the query. # options: The options to pass to the db. # # Example: # # collection.find({ :test => "value" }) def find(selector = {}, options = {}) cursor = Mongoid::Cursor.new(self, directed.find(selector, options)) if block_given? yield cursor; cursor.close else cursor end end # Initialize a new Mongoid::Collection, setting up the master, slave, and # name attributes. Masters will be used for writes, slaves for reads. # # Example: # # Mongoid::Collection.new(masters, slaves, "test") def initialize(name) @name, @counter = name, 0 end # Return the object responsible for reading documents from the database. # This is usually the slave databases, but in their absence the master will # handle the task. # # Example: # # collection.reader def slaves @slaves ||= Collections::Slaves.new(Mongoid.slaves, @name) end # Return the object responsible for writes to the database. This will # always return a collection associated with the Master DB. # # Example: # # collection.writer def master @master ||= Collections::Master.new(Mongoid.master, @name) end protected def under_max_counter? @counter < Mongoid.max_successive_reads end end end