lib/ruote/couch/database.rb in ruote-couch-2.1.10 vs lib/ruote/couch/database.rb in ruote-couch-2.1.11
- old
+ new
@@ -37,16 +37,12 @@
attr_reader :type
attr_reader :couch
- def initialize (host, port, type, name)
+ def initialize (host, port, type, name, opts={})
- #opts = { :re_put_ok => re_put_ok }
- opts = {}
- #opts[:timeout] = TODO
-
@couch = Rufus::Jig::Couch.new(host, port, name, opts)
@couch.put('.') unless @couch.get('.')
@type = type
@@ -77,33 +73,53 @@
#p [ :del, doc['_id'], Thread.current.object_id.to_s[-3..-1], r.nil? ]
Thread.pass
# without this, test/functional/ct_0 fails after 1 to 10 runs...
r
+
+ rescue Rufus::Jig::TimeoutError => te
+ true
end
+ # The get_many used by msgs, configurations and variables.
+ #
def get_many (key, opts)
- rs = @couch.get("_all_docs?include_docs=true#{query_options(opts)}")
+ return query('_all_docs?include_docs=true') if ( ! key) && opts.size < 1
- rs = rs['rows'].collect { |e| e['doc'] }
+ is = ids
- rs = rs.select { |doc| doc['_id'].match(key) } if key
- # naive...
+ return is.length if opts[:count]
- rs.select { |doc| ! doc['_id'].match(/^\_design\//) }
- end
+ is = is.reverse if opts[:descending]
- DESIGN_DOC_REGEX = /^\_design\//
+ if key
+ keys = Array(key).map { |k| k.is_a?(String) ? "!#{k}" : k }
+ is = is.select { |i| Ruote::StorageBase.key_match?(keys, i) }
+ end
+ skip = opts[:skip] || 0
+ limit = opts[:limit] || is.length
+
+ is = is[skip, limit]
+
+ query_by_post('_all_docs?include_docs=true', is)
+
+ # TODO
+ # maybe _count come be of use here
+ # http://wiki.apache.org/couchdb/Built-In_Reduce_Functions
+ end
+
# Returns a sorted list of the ids of all the docs in this database.
#
def ids
- rs = @couch.get('_all_docs')
-
- rs['rows'].collect { |r| r['id'] }.reject { |i| i.match(DESIGN_DOC_REGEX) }
+ @couch.get('_all_docs')['rows'].collect { |r|
+ r['id']
+ }.reject { |i|
+ DESIGN_DOC_REGEX.match(i)
+ }
end
def dump
s = "=== #{@type} ===\n"
@@ -114,22 +130,26 @@
s2 << " #{k} => #{e[k].inspect}\n"
end
end
end
- #def shutdown
- # @couch.close
- #end
- # jig > 0.1.17 is OK without that
+ # Makes sure to close the HTTP connection down.
+ #
+ def shutdown
+ @couch.close
+ end
+
# Deletes all the documents in this database.
#
def purge!
+ @couch.http.cache.clear
@couch.get('_all_docs')['rows'].each do |row|
+ next if row['id'].match(/^\_design\//)
doc = { '_id' => row['id'], '_rev' => row['value']['rev'] }
- @couch.delete(doc) unless doc['_id'].match(/^\_design\//)
+ @couch.delete(doc)
end
#
# which is faster than
#
#@couch.delete('.')
@@ -142,64 +162,74 @@
def prepare
# nothing to do for a index-less database
end
- # (for now, the only option is :limit)
+ # These options are known and passed to CouchDB.
#
+ QUERY_OPTIONS = [ :skip, :limit, :descending ]
+
+ # :limit and :skip support
+ #
def query_options (opts)
- opts = opts.select { |k, v| [ :limit, :skip ].include?(k) && v != nil }
+ opts = opts.select { |k, v| QUERY_OPTIONS.include?(k) && v != nil }
s = opts.collect { |k, v| "#{k}=#{v}" }.join('&')
s.length > 0 ? "&#{s}" : ''
end
+ # Used by #get_many and #ids when filtering design documents out of
+ # '_all_docs'.
+ #
+ DESIGN_DOC_REGEX = /^\_design\//
+
+ def filter_design_docs (docs)
+
+ docs.reject { |d| DESIGN_DOC_REGEX.match(d['_id']) }
+ end
+
def query (uri)
rs = @couch.get(uri)
- rs['rows'].collect { |e| e['doc'] }
+ filter_design_docs(rs['rows'].collect { |e| e['doc'] })
end
def query_by_post (uri, keys)
keys = { 'keys' => keys }
rs = @couch.post(uri, keys)
- rs['rows'].collect { |e| e['doc'] }.uniq
+ filter_design_docs(rs['rows'].collect { |e| e['doc'] }.uniq)
end
end
#
# A Couch database with a by_wfid view.
#
class WfidIndexedDatabase < Database
+ # The get_many used by errors, expressions and schedules.
+ #
def get_many (key, opts)
- if key && m = key.source.match(/!?(.+)\$$/)
- # let's use the couch view...
+ return super(key, opts) unless key.is_a?(String)
- query(
- "_design/ruote/_view/by_wfid?key=%22#{m[1]}%22" +
- "&include_docs=true#{query_options(opts)}")
+ # key is a wfid
- else
- # let's use the naive default implementation
-
- super
- end
+ query("_design/ruote/_view/by_wfid?key=%22#{key}%22&include_docs=true")
end
# Used by WorkitemDatabase#query
#
def by_wfid (wfid)
- get_many(/!#{wfid}$/, {})
+ #get_many(/!#{wfid}$/, {})
+ get_many(wfid, {})
end
# Returns the design document that goes with this class of database
#
def self.design_doc
@@ -213,12 +243,16 @@
{
'_id' => '_design/ruote',
'views' => {
'by_wfid' => {
- 'map' =>
- 'function (doc) { if (doc.fei) emit(doc.fei.wfid, null); }'
+ 'map' => %{
+ function (doc) {
+ if (doc.wfid) emit(doc.wfid, null);
+ else if (doc.fei) emit(doc.fei.wfid, null);
+ }
+ }
}
}
}
end
@@ -276,11 +310,10 @@
if criteria.empty? && (wfid.nil? ^ pname.nil?)
return by_participant(pname) if pname
return by_wfid(wfid) # if wfid
end
- return get_many(nil, {}).collect { |hwi| Ruote::Workitem.new(hwi) } \
- if criteria.empty?
+ return get_many(nil, {}) if criteria.empty?
cr = criteria.collect { |fname, fvalue| { fname => fvalue } }
opts = { :skip => offset, :limit => limit }