Making design doc thread safe for checking status of design doc
This commit is contained in:
parent
77cb8160c7
commit
5fd1c3903b
7 changed files with 43 additions and 57 deletions
|
@ -336,7 +336,7 @@ module CouchRest
|
|||
end
|
||||
|
||||
def clear_extended_doc_fresh_cache
|
||||
::CouchRest::ExtendedDocument.subclasses.each{|klass| klass.design_doc_fresh = false if klass.respond_to?(:design_doc_fresh=) }
|
||||
::CouchRest::ExtendedDocument.subclasses.each{|klass| klass.req_design_doc_refresh if klass.respond_to?(:req_design_doc_refresh)}
|
||||
end
|
||||
|
||||
def uri_for_attachment(doc, name)
|
||||
|
|
|
@ -107,16 +107,12 @@ module CouchRest
|
|||
@klass.design_doc
|
||||
end
|
||||
|
||||
def design_doc_fresh
|
||||
@klass.design_doc_fresh
|
||||
end
|
||||
|
||||
def refresh_design_doc
|
||||
@klass.refresh_design_doc_on(@database)
|
||||
@klass.refresh_design_doc(@database)
|
||||
end
|
||||
|
||||
def save_design_doc
|
||||
@klass.save_design_doc_on(@database)
|
||||
@klass.save_design_doc(@database)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,23 +9,23 @@ module CouchRest
|
|||
end
|
||||
|
||||
module ClassMethods
|
||||
attr_accessor :design_doc, :design_doc_slug_cache, :design_doc_fresh
|
||||
|
||||
def design_doc
|
||||
@design_doc ||= Design.new(default_design_doc)
|
||||
end
|
||||
|
||||
# Use when something has been changed, like a view, so that on the next request
|
||||
# the design docs will be updated.
|
||||
def req_design_doc_refresh
|
||||
@design_doc_fresh = { }
|
||||
end
|
||||
|
||||
def design_doc_id
|
||||
"_design/#{design_doc_slug}"
|
||||
end
|
||||
|
||||
def design_doc_slug
|
||||
return design_doc_slug_cache if (design_doc_slug_cache && design_doc_fresh)
|
||||
funcs = []
|
||||
design_doc['views'].each do |name, view|
|
||||
funcs << "#{name}/#{view['map']}#{view['reduce']}"
|
||||
end
|
||||
self.design_doc_slug_cache = self.to_s
|
||||
self.to_s
|
||||
end
|
||||
|
||||
def default_design_doc
|
||||
|
@ -43,45 +43,44 @@ module CouchRest
|
|||
}
|
||||
end
|
||||
|
||||
def refresh_design_doc
|
||||
reset_design_doc
|
||||
save_design_doc
|
||||
end
|
||||
|
||||
def refresh_design_doc_on(db)
|
||||
reset_design_doc
|
||||
save_design_doc_on(db)
|
||||
end
|
||||
|
||||
# Save the design doc onto the default database, and update the
|
||||
# design_doc attribute
|
||||
def save_design_doc
|
||||
reset_design_doc unless design_doc_fresh
|
||||
self.design_doc = update_design_doc(design_doc)
|
||||
def refresh_design_doc(db = database)
|
||||
unless design_doc_fresh(db)
|
||||
reset_design_doc(db)
|
||||
save_design_doc(db)
|
||||
end
|
||||
end
|
||||
|
||||
# Save the design doc onto a target database in a thread-safe way,
|
||||
# not modifying the model's design_doc
|
||||
def save_design_doc_on(db)
|
||||
def save_design_doc(db = database)
|
||||
update_design_doc(Design.new(design_doc), db)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def reset_design_doc
|
||||
current = self.database.get(design_doc_id) rescue nil
|
||||
protected
|
||||
|
||||
def design_doc_fresh(db, fresh = nil)
|
||||
@design_doc_fresh ||= {}
|
||||
if fresh.nil?
|
||||
@design_doc_fresh[db.uri] || false
|
||||
else
|
||||
@design_doc_fresh[db.uri] = fresh
|
||||
end
|
||||
end
|
||||
|
||||
def reset_design_doc(db)
|
||||
current = db.get(design_doc_id) rescue nil
|
||||
design_doc['_id'] = design_doc_id
|
||||
if current.nil?
|
||||
design_doc.delete('_rev')
|
||||
else
|
||||
design_doc['_rev'] = current['_rev']
|
||||
end
|
||||
self.design_doc_fresh = true
|
||||
design_doc_fresh(db, true)
|
||||
end
|
||||
|
||||
# Writes out a design_doc to a given database, returning the
|
||||
# updated design doc
|
||||
def update_design_doc(design_doc, db = database)
|
||||
def update_design_doc(design_doc, db)
|
||||
saved = db.get(design_doc['_id']) rescue nil
|
||||
if saved
|
||||
design_doc['views'].each do |name, view|
|
||||
|
@ -100,4 +99,4 @@ module CouchRest
|
|||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -83,8 +83,8 @@ module CouchRest
|
|||
opts[:guards].push "(doc['couchrest-type'] == '#{self.to_s}')"
|
||||
end
|
||||
keys.push opts
|
||||
self.design_doc.view_by(*keys)
|
||||
self.design_doc_fresh = false
|
||||
design_doc.view_by(*keys)
|
||||
req_design_doc_refresh
|
||||
end
|
||||
|
||||
# returns stored defaults if the there is a view named this in the design doc
|
||||
|
@ -96,9 +96,7 @@ module CouchRest
|
|||
# Dispatches to any named view.
|
||||
def view(name, query={}, &block)
|
||||
db = query.delete(:database) || database
|
||||
unless design_doc_fresh
|
||||
refresh_design_doc_on(db)
|
||||
end
|
||||
refresh_design_doc(db)
|
||||
query[:raw] = true if query[:reduce]
|
||||
raw = query.delete(:raw)
|
||||
fetch_view_with_docs(db, name, query, raw, &block)
|
||||
|
@ -119,13 +117,6 @@ module CouchRest
|
|||
end
|
||||
end
|
||||
|
||||
# Deletes the current design doc for the current class.
|
||||
# Running it to early could mean that live code has to regenerate
|
||||
# potentially large indexes.
|
||||
def cleanup_design_docs!(db = database)
|
||||
save_design_doc_on(db)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fetch_view_with_docs(db, name, opts, raw=false, &block)
|
||||
|
@ -156,7 +147,7 @@ module CouchRest
|
|||
# the design doc may not have been saved yet on this database
|
||||
rescue HttpAbstraction::ResourceNotFound => e
|
||||
if retryable
|
||||
save_design_doc_on(db)
|
||||
save_design_doc(db)
|
||||
retryable = false
|
||||
retry
|
||||
else
|
||||
|
|
|
@ -327,7 +327,7 @@ describe "ExtendedDocument" do
|
|||
|
||||
describe "finding all instances of a model" do
|
||||
before(:all) do
|
||||
WithTemplateAndUniqueID.design_doc_fresh = false
|
||||
WithTemplateAndUniqueID.req_design_doc_refresh
|
||||
WithTemplateAndUniqueID.all.map{|o| o.destroy(true)}
|
||||
WithTemplateAndUniqueID.database.bulk_delete
|
||||
WithTemplateAndUniqueID.new('important-field' => '1').save
|
||||
|
@ -349,7 +349,7 @@ describe "ExtendedDocument" do
|
|||
describe "counting all instances of a model" do
|
||||
before(:each) do
|
||||
@db = reset_test_db!
|
||||
WithTemplateAndUniqueID.design_doc_fresh = false
|
||||
WithTemplateAndUniqueID.req_design_doc_refresh
|
||||
end
|
||||
|
||||
it ".count should return 0 if there are no docuemtns" do
|
||||
|
@ -368,7 +368,7 @@ describe "ExtendedDocument" do
|
|||
describe "finding the first instance of a model" do
|
||||
before(:each) do
|
||||
@db = reset_test_db!
|
||||
WithTemplateAndUniqueID.design_doc_fresh = false
|
||||
WithTemplateAndUniqueID.req_design_doc_refresh
|
||||
WithTemplateAndUniqueID.new('important-field' => '1').save
|
||||
WithTemplateAndUniqueID.new('important-field' => '2').save
|
||||
WithTemplateAndUniqueID.new('important-field' => '3').save
|
||||
|
|
|
@ -76,9 +76,9 @@ describe "Subclassing an ExtendedDocument" do
|
|||
|
||||
it "should have its own design_doc_fresh" do
|
||||
Animal.refresh_design_doc
|
||||
Dog.design_doc_fresh.should_not == true
|
||||
Dog.send(:design_doc_fresh, Dog.database).should_not == true
|
||||
Dog.refresh_design_doc
|
||||
Dog.design_doc_fresh.should == true
|
||||
Dog.send(:design_doc_fresh, Dog.database).should == true
|
||||
end
|
||||
|
||||
it "should not add views to the parent's design_doc" do
|
||||
|
|
|
@ -126,7 +126,7 @@ describe "ExtendedDocument views" do
|
|||
lambda{Unattached.all}.should raise_error
|
||||
end
|
||||
it "should query all" do
|
||||
Unattached.cleanup_design_docs!(@db)
|
||||
# Unattached.cleanup_design_docs!(@db)
|
||||
rs = Unattached.all :database => @db
|
||||
rs.length.should == 4
|
||||
end
|
||||
|
@ -187,7 +187,7 @@ describe "ExtendedDocument views" do
|
|||
Unattached.view_by :questions
|
||||
Unattached.by_questions(:database => @db)
|
||||
original_revision = Unattached.model_design_doc(@db)['_rev']
|
||||
Unattached.cleanup_design_docs!(@db)
|
||||
Unattached.save_design_doc(@db)
|
||||
Unattached.model_design_doc(@db)['_rev'].should_not == original_revision
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue