jmongo 1.1.4 → 1.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'jmongo'
3
- s.version = '1.1.4'
4
- s.date = '2011-10-19'
3
+ s.version = '1.1.5'
4
+ s.date = '2011-10-22'
5
5
  s.platform = Gem::Platform::RUBY
6
6
  s.authors = ["Chuck Remes","Guy Boertje", "Lee Henson"]
7
7
  s.email = ["cremes@mac.com", "guyboertje@gmail.com", "lee.m.henson@gmail.com"]
@@ -12,7 +12,6 @@ Gem::Specification.new do |s|
12
12
  # = MANIFEST =
13
13
  s.files = %w[
14
14
  Gemfile
15
- Gemfile.lock
16
15
  History.txt
17
16
  LICENSE.txt
18
17
  README.txt
@@ -87,6 +86,7 @@ Gem::Specification.new do |s|
87
86
  test/replica_sets/replication_ack_test.rb
88
87
  test/replica_sets/rs_test_helper.rb
89
88
  test/safe_test.rb
89
+ test/subscribe_test.rb
90
90
  test/support/hash_with_indifferent_access.rb
91
91
  test/support/keys.rb
92
92
  test/support_test.rb
@@ -48,20 +48,37 @@ module Mongo
48
48
  if args.size < 2
49
49
  raise ArgumentError.new("Must supply at least name and db parameters")
50
50
  end
51
- if args.first.respond_to?('collection_names')
52
- db, name = args
53
- else
51
+ if args.first.is_a?(String)
54
52
  name, db = args
53
+ else
54
+ db, name = args
55
55
  end
56
-
57
56
  @name = validate_name(name)
58
57
  @db, @j_db = db, db.j_db
59
58
  @connection = @db.connection
60
59
  @pk_factory = @opts.delete(:pk)|| BSON::ObjectId
61
60
  @hint = nil
61
+
62
+ @monitor = @opts.delete(:monitor)
63
+ if @monitor
64
+ setup_monitor
65
+ elsif @opts.has_key?(:monitor_source)
66
+ @monitor_source = @opts.delete(:monitor_source)
67
+ end
68
+
62
69
  @j_collection = j_collection || @j_db.create_collection(@name, to_dbobject(@opts))
63
70
  end
64
71
 
72
+ def setup_monitor
73
+ mon_opts = @monitor.is_a?(Hash)? @monitor : {}
74
+ size = mon_opts.fetch(:size, 8000)
75
+ @monitor_max = mon_opts.fetch(:max, 100)
76
+ opts = {:capped => true, :max => @monitor_max, :size => size, :monitor_source => self}
77
+ @mon_collection = @db.create_collection("#{@name}-monitor", opts)
78
+ @j_mon_collection = @mon_collection.j_collection
79
+ @monitorable = true
80
+ end
81
+
65
82
  def safe
66
83
  !!@opts.fetch(:safe, false)
67
84
  end
@@ -648,5 +665,46 @@ module Mongo
648
665
  end
649
666
 
650
667
  alias :size :count
651
- end
652
- end
668
+
669
+ def monitor_collection
670
+ raise InvalidOperation, "Monitoring has not been setup, add :monitor - true or Hash" unless @monitorable
671
+ @mon_collection
672
+ end
673
+
674
+ def monitored_collection
675
+ @monitor_source
676
+ end
677
+
678
+ def monitor_subscribe(opts, &callback_doc)
679
+ raise MongoArgumentError, "Not a monitorable collection" if @monitor_source.nil?
680
+ raise MongoArgumentError, "Must supply a block" unless block_given?
681
+ raise MongoArgumentError, "opts needs to be a Hash" unless opts.is_a?(Hash)
682
+ callback_exit = opts[:callback_exit]
683
+ raise MongoArgumentError, "Need a callable for exit callback" unless callback_doc.respond_to?('call')
684
+ exit_check_timeout = opts[:exit_check_timeout]
685
+ raise MongoArgumentError, "Need a positive float for timeout" unless exit_check_timeout.to_f > 0.0
686
+
687
+ tail = Mongo::Cursor.new(self, :timeout => false, :tailable => true, :await_data => 0.5, :order => [['$natural', 1]])
688
+
689
+ loop_th = Thread.new(tail, callback_doc) do |cur, cb|
690
+ while !Thread.current[:stop]
691
+ doc = cur.next
692
+ cb.call(doc) if doc
693
+ end
694
+ end
695
+ loop_th[:stop] = false
696
+
697
+ exit_th = Thread.new(exit_check_timeout.to_f, callback_exit) do |to, cb|
698
+ while true
699
+ sleep to
700
+ must_exit = cb.call
701
+ break if must_exit
702
+ end
703
+ loop_th[:stop] = true
704
+ end
705
+ #
706
+ end
707
+
708
+
709
+ end #class
710
+ end #module
@@ -337,15 +337,6 @@ module Mongo
337
337
  self
338
338
  end
339
339
 
340
- def mask_option(bitfield, bit, set = true)
341
- if set
342
- bitfield |= bit
343
- else
344
- bitfield &= ~bit
345
- end
346
- bitfield
347
- end
348
-
349
340
  def wrap_invalid_op
350
341
  begin
351
342
  yield
@@ -106,6 +106,10 @@ module Mongo
106
106
  else
107
107
  begin
108
108
  @j_collection.insert( to_dbobject(to_do), concern )
109
+ if @monitorable
110
+ mon_do = to_do.map{ |doc| {'_id'=>doc['_id'], 'action'=>1} }
111
+ @j_mon_collection.insert( to_dbobject(mon_do), concern )
112
+ end
109
113
  rescue => ex
110
114
  if ex.message =~ /E11000/
111
115
  msg = "Failed to insert document #{obj.inspect}, duplicate key, E11000"
@@ -125,6 +129,10 @@ module Mongo
125
129
  begin
126
130
  jres = @j_collection.insert( dbo, concern )
127
131
  result = from_dbobject(jres.get_last_error(concern))
132
+ if @monitorable
133
+ mon_obj = one_obj.map{ |doc| {'_id'=>doc['_id'], 'action'=>1} }
134
+ @j_mon_collection.( to_dbobject(mon_obj), concern )
135
+ end
128
136
  rescue => ex
129
137
  if ex.message =~ /E11000/ #noop duplicate key
130
138
  result = {'err'=>ex.message}
@@ -1,3 +1,3 @@
1
1
  module Mongo
2
- VERSION = '1.1.4'
2
+ VERSION = '1.1.5'
3
3
  end
@@ -0,0 +1,84 @@
1
+ require 'minitest/spec'
2
+ require './test/test_helper'
3
+
4
+ Cfg.connection :op_timeout => 10
5
+ Cfg.db
6
+
7
+ describe "Monitorable Pair Collection" do
8
+ before do
9
+ Cfg.clear_all
10
+ end
11
+
12
+ describe "monitoring a collection with defaults" do
13
+
14
+ before do
15
+ opts = {:monitor => true}
16
+ @collection = Cfg.db.create_collection('buffer', opts)
17
+ end
18
+
19
+ it "should have a monitor_collection" do
20
+ assert @collection.monitor_collection
21
+ assert_equal "buffer-monitor", @collection.monitor_collection.name
22
+ end
23
+
24
+ it "should insert into the monitorable collection as well" do
25
+ @collection.insert({'field1' => 'some value', 'field2' => 99})
26
+ assert_equal 1, @collection.size
27
+ rec = @collection.find().to_a.first
28
+ assert_equal 1, @collection.monitor_collection.size
29
+ mon_rec = @collection.monitor_collection.find().to_a.first
30
+ assert_equal rec['_id'], mon_rec['_id']
31
+ assert_equal 1, mon_rec['action']
32
+ end
33
+
34
+ it "should raise when the subscribe method is called on a normal collection" do
35
+ normal = Cfg.db.create_collection('normal')
36
+ assert normal.respond_to?('monitor_subscribe')
37
+ assert_raises Mongo::MongoArgumentError do
38
+ normal.monitor_subscribe(2)
39
+ end
40
+ end
41
+
42
+ it "should raise for invalid options" do
43
+ @stop_callback = lambda{ true }
44
+ @monitored = @collection.monitor_collection
45
+ assert_raises Mongo::MongoArgumentError do
46
+ @monitored.monitor_subscribe({}) #no block
47
+ end
48
+ assert_raises Mongo::MongoArgumentError do
49
+ @monitored.monitor_subscribe({:callback_exit => ''}) {|doc| apr(doc,'doc')} #not callable
50
+ end
51
+ assert_raises Mongo::MongoArgumentError do
52
+ @monitored.monitor_subscribe({ :callback_exit => @stop_callback }) {|doc| apr(doc,'doc')} #no timeout
53
+ end
54
+ assert_raises Mongo::MongoArgumentError do
55
+ @monitored.monitor_subscribe({:callback_exit => @stop_callback, :exit_check_timeout => 0}) {|doc| apr(doc,'doc')} #timeout not positive float
56
+ end
57
+ end
58
+
59
+ it "the monitored collection should have a subscribe method" do
60
+ @stop = 0
61
+ @count = 0
62
+ @values = []
63
+ @stop_callback = lambda{ @stop += 1; true }
64
+ @monitored = @collection.monitor_collection
65
+ assert_equal @collection, @monitored.monitored_collection
66
+
67
+ @monitored.monitor_subscribe({:callback_exit => @stop_callback, :exit_check_timeout => 1.0}) do |doc|
68
+ if doc
69
+ id, act = doc.values_at('_id','action')
70
+ @count += (act || 0)
71
+ orig = @monitored.monitored_collection.find_one('_id'=>id)
72
+ @values << orig['field2'] if orig
73
+ end
74
+ end
75
+ @collection.insert({'field1' => 'some value', 'field2' => 99})
76
+ @collection.insert({'field1' => 'some value', 'field2' => 98})
77
+
78
+ sleep 1.2
79
+ assert_equal 1, @stop
80
+ assert_equal 2, @count
81
+ assert_equal [99,98], @values
82
+ end
83
+ end
84
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jmongo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 1.1.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,11 +11,11 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2011-10-19 00:00:00.000000000 Z
14
+ date: 2011-10-22 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: require_all
18
- requirement: &15446080 !ruby/object:Gem::Requirement
18
+ requirement: &9275500 !ruby/object:Gem::Requirement
19
19
  none: false
20
20
  requirements:
21
21
  - - ~>
@@ -23,10 +23,10 @@ dependencies:
23
23
  version: '1.2'
24
24
  type: :runtime
25
25
  prerelease: false
26
- version_requirements: *15446080
26
+ version_requirements: *9275500
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: awesome_print
29
- requirement: &15445600 !ruby/object:Gem::Requirement
29
+ requirement: &9275020 !ruby/object:Gem::Requirement
30
30
  none: false
31
31
  requirements:
32
32
  - - ~>
@@ -34,10 +34,10 @@ dependencies:
34
34
  version: '0.4'
35
35
  type: :development
36
36
  prerelease: false
37
- version_requirements: *15445600
37
+ version_requirements: *9275020
38
38
  - !ruby/object:Gem::Dependency
39
39
  name: fuubar
40
- requirement: &15444720 !ruby/object:Gem::Requirement
40
+ requirement: &9274520 !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
43
  - - ~>
@@ -45,10 +45,10 @@ dependencies:
45
45
  version: '0.0'
46
46
  type: :development
47
47
  prerelease: false
48
- version_requirements: *15444720
48
+ version_requirements: *9274520
49
49
  - !ruby/object:Gem::Dependency
50
50
  name: rspec
51
- requirement: &15444260 !ruby/object:Gem::Requirement
51
+ requirement: &9273680 !ruby/object:Gem::Requirement
52
52
  none: false
53
53
  requirements:
54
54
  - - ~>
@@ -56,7 +56,7 @@ dependencies:
56
56
  version: '2.6'
57
57
  type: :development
58
58
  prerelease: false
59
- version_requirements: *15444260
59
+ version_requirements: *9273680
60
60
  description: Thin jruby wrapper around Mongo Java Driver
61
61
  email:
62
62
  - cremes@mac.com
@@ -68,7 +68,6 @@ extensions: []
68
68
  extra_rdoc_files: []
69
69
  files:
70
70
  - Gemfile
71
- - Gemfile.lock
72
71
  - History.txt
73
72
  - LICENSE.txt
74
73
  - README.txt
@@ -143,6 +142,7 @@ files:
143
142
  - test/replica_sets/replication_ack_test.rb
144
143
  - test/replica_sets/rs_test_helper.rb
145
144
  - test/safe_test.rb
145
+ - test/subscribe_test.rb
146
146
  - test/support/hash_with_indifferent_access.rb
147
147
  - test/support/keys.rb
148
148
  - test/support_test.rb
@@ -1,44 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- jmongo (1.1.1)
5
- require_all (~> 1.2)
6
-
7
- GEM
8
- remote: http://rubygems.org/
9
- specs:
10
- awesome_print (0.4.0)
11
- diff-lcs (1.1.3)
12
- fuubar (0.0.6)
13
- rspec (~> 2.0)
14
- rspec-instafail (~> 0.1.8)
15
- ruby-progressbar (~> 0.0.10)
16
- metaclass (0.0.1)
17
- mocha (0.10.0)
18
- metaclass (~> 0.0.1)
19
- rake (0.9.2)
20
- require_all (1.2.0)
21
- rspec (2.6.0)
22
- rspec-core (~> 2.6.0)
23
- rspec-expectations (~> 2.6.0)
24
- rspec-mocks (~> 2.6.0)
25
- rspec-core (2.6.4)
26
- rspec-expectations (2.6.0)
27
- diff-lcs (~> 1.1.2)
28
- rspec-instafail (0.1.8)
29
- rspec-mocks (2.6.0)
30
- ruby-progressbar (0.0.10)
31
- shoulda (2.11.3)
32
-
33
- PLATFORMS
34
- java
35
- ruby
36
-
37
- DEPENDENCIES
38
- awesome_print (~> 0.4)
39
- fuubar (~> 0.0)
40
- jmongo!
41
- mocha
42
- rake
43
- rspec (~> 2.6)
44
- shoulda