rethinkdb 2.0.0.1 → 2.1.0

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.
Files changed (7) hide show
  1. checksums.yaml +4 -4
  2. data/lib/exc.rb +15 -4
  3. data/lib/func.rb +2 -2
  4. data/lib/net.rb +88 -28
  5. data/lib/ql2.pb.rb +13 -0
  6. data/lib/shim.rb +22 -11
  7. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dae3d5d3b038eca2d30595a269cb259351d5bd98
4
- data.tar.gz: 7a03e7c5f271bbb2a7e2e63f74a2757864c4cdbb
3
+ metadata.gz: 4dbe3bed2b00fa519fa84f136b6b140da9e97c49
4
+ data.tar.gz: 478001c0afd50dcbad8d02d843ffa2602d7cec6d
5
5
  SHA512:
6
- metadata.gz: 308251a1089f50555e2e8177af64235bea9b5a36d35615aca7852f8f72530f17cb0c70569d6a727012aad0f273c6912262cedd9e6b6e1748d60d59e5ec4feb91
7
- data.tar.gz: 6f31e8e16757cdaa9fc98137fd732323fa32c7d03c0af3edc2fcad299dfa9dff0c3bad2db838e2e7db1426c07bf3ed3729b8c723b38d3f784396722b3ccfbe5a
6
+ metadata.gz: 34d05e329c5c523c91f324e67205cef95ad57c2af7ae9b01977ddd76e2bb03be110b45165fd42fbe36535865548bef1e8b82cb37925a21cc98dea9e25e1b9a6d
7
+ data.tar.gz: 07a54b27fba8686fd47b9a6a814f18e417400fc4636240f015c255aa7e52358ffc623fb2c375c66fc1b2a2f07d0fa044b07d609e1441ced43eab383b61f472de
data/lib/exc.rb CHANGED
@@ -1,6 +1,17 @@
1
1
  module RethinkDB
2
- RqlError = Class.new(RuntimeError)
3
- RqlRuntimeError = Class.new(RqlError)
4
- RqlDriverError = Class.new(RqlError)
5
- RqlCompileError = Class.new(RqlError)
2
+ ReqlError = RqlError = Class.new(RuntimeError)
3
+
4
+ ReqlRuntimeError = RqlRuntimeError = Class.new(ReqlError)
5
+ ReqlInternalError = RqlInternalError = Class.new(ReqlRuntimeError)
6
+ ReqlResourceLimitError = RqlResourceLimitError = Class.new(ReqlRuntimeError)
7
+ ReqlQueryLogicError = RqlQueryLogicError = Class.new(ReqlRuntimeError)
8
+ ReqlNonExistenceError = RqlNonExistenceError = Class.new(ReqlQueryLogicError)
9
+ ReqlAvailabilityError = RqlAvailabilityError = Class.new(ReqlRuntimeError)
10
+ ReqlOpFailedError = RqlOpFailedError = Class.new(ReqlAvailabilityError)
11
+ ReqlOpIndeterminateError = RqlOpIndeterminateError = Class.new(ReqlAvailabilityError)
12
+ ReqlUserError = RqlUserError = Class.new(ReqlRuntimeError)
13
+
14
+ ReqlDriverError = RqlDriverError = Class.new(ReqlError)
15
+ ReqlAuthError = RqlAuthError = Class.new(ReqlDriverError)
16
+ ReqlCompileError = RqlCompileError = Class.new(ReqlError)
6
17
  end
data/lib/func.rb CHANGED
@@ -88,7 +88,7 @@ module RethinkDB
88
88
  "This is almost always a precedence error.\n" +
89
89
  "Note that `a < b | b < c` <==> `a < (b | b) < c`.\n" +
90
90
  "If you really want this behavior, use `.or` or `.and` instead."
91
- raise RqlDriverError, err
91
+ raise ReqlDriverError, err
92
92
  end
93
93
  }
94
94
  end
@@ -151,7 +151,7 @@ module RethinkDB
151
151
  def do(*args, &b)
152
152
  a = ((@body != RQL) ? [self] : []) + args.dup
153
153
  if a == [] && !b
154
- raise RqlDriverError, "Expected 1 or more arguments but found 0."
154
+ raise ReqlDriverError, "Expected 1 or more arguments but found 0."
155
155
  end
156
156
  funcall_args = (b ? [new_func(&b)] : [a.pop]) + a
157
157
  # PP.pp funcall_args
data/lib/net.rb CHANGED
@@ -4,6 +4,7 @@ require 'socket'
4
4
  require 'thread'
5
5
  require 'timeout'
6
6
  require 'pp' # This is needed for pretty_inspect
7
+ require 'openssl'
7
8
 
8
9
  module RethinkDB
9
10
  module Faux_Abort
@@ -162,6 +163,12 @@ module RethinkDB
162
163
  handle(:on_close)
163
164
  end
164
165
  end
166
+ def handle_force_close
167
+ if !@closed
168
+ handle(:on_error, ReqlRuntimeError.new("Connection is closed."))
169
+ end
170
+ handle_close
171
+ end
165
172
  def safe_next_tick(&b)
166
173
  EM.next_tick {
167
174
  b.call if !@closed
@@ -194,6 +201,9 @@ module RethinkDB
194
201
  elsif (row.has_key?('new_val') && !row.has_key?('old_val') &&
195
202
  @handler.respond_to?(:on_initial_val))
196
203
  handle(:on_initial_val, row['new_val'])
204
+ elsif (row.has_key?('old_val') && !row.has_key?('new_val') &&
205
+ @handler.respond_to?(:on_uninitial_val))
206
+ handle(:on_uninitial_val, row['old_val'])
197
207
  elsif row.has_key?('error') && @handler.respond_to?(:on_change_error)
198
208
  handle(:on_change_error, row['error'])
199
209
  elsif row.has_key?('state') && @handler.respond_to?(:on_state)
@@ -317,6 +327,9 @@ module RethinkDB
317
327
  def run(*args, &b)
318
328
  unbound_if(@body == RQL)
319
329
  args = parse(*args, &b)
330
+ if args[:block].is_a?(Handler)
331
+ raise RuntimeError, "Cannot call `run` with a handler, did you mean `em_run`?"
332
+ end
320
333
  args[:conn].run(@body, args[:opts], args[:block])
321
334
  end
322
335
  def em_run(*args, &b)
@@ -373,13 +386,13 @@ module RethinkDB
373
386
  end
374
387
 
375
388
  def each(&block) # :nodoc:
376
- raise RqlRuntimeError, "Can only iterate over a cursor once." if @run
389
+ raise ReqlRuntimeError, "Can only iterate over a cursor once." if @run
377
390
  return enum_for(:each) if !block
378
391
  @run = true
379
392
  while true
380
393
  @results.each(&block)
381
394
  return self if !@more
382
- raise RqlRuntimeError, "Connection is closed." if @more && out_of_date
395
+ raise ReqlRuntimeError, "Connection is closed." if @more && out_of_date
383
396
  wait_for_batch(nil)
384
397
  end
385
398
  end
@@ -412,10 +425,10 @@ module RethinkDB
412
425
 
413
426
  def next(wait=true)
414
427
  if @run
415
- raise RqlRuntimeError, "Cannot call `next` on a cursor after calling `each`."
428
+ raise ReqlRuntimeError, "Cannot call `next` on a cursor after calling `each`."
416
429
  end
417
430
  if @more && out_of_date
418
- raise RqlRuntimeError, "Connection is closed."
431
+ raise ReqlRuntimeError, "Connection is closed."
419
432
  end
420
433
  timeout = wait
421
434
  if wait == true
@@ -434,6 +447,7 @@ module RethinkDB
434
447
  end
435
448
 
436
449
  class Connection
450
+ include OpenSSL
437
451
  def auto_reconnect(x=true)
438
452
  @auto_reconnect = x
439
453
  self
@@ -455,6 +469,7 @@ module RethinkDB
455
469
  @auth_key = opts[:auth_key] || ""
456
470
  @timeout = opts[:timeout].to_i
457
471
  @timeout = 20 if @timeout <= 0
472
+ @ssl_opts = opts[:ssl] || {}
458
473
 
459
474
  @@last = self
460
475
  @default_opts = @default_db ? {:db => RQL.new.db(@default_db)} : {}
@@ -475,7 +490,7 @@ module RethinkDB
475
490
  if !opts[:noreply]
476
491
  @mon.synchronize {
477
492
  if @waiters.has_key?(token)
478
- raise RqlDriverError, "Internal driver error, token already in use."
493
+ raise ReqlDriverError, "Internal driver error, token already in use."
479
494
  end
480
495
  @waiters[token] = callback ? callback : @mon.new_cond
481
496
  @opts[token] = opts
@@ -495,7 +510,7 @@ module RethinkDB
495
510
  end
496
511
  def run(msg, opts, b)
497
512
  reconnect(:noreply_wait => false) if @auto_reconnect && !is_open()
498
- raise RqlRuntimeError, "Connection is closed." if !is_open()
513
+ raise ReqlRuntimeError, "Connection is closed." if !is_open()
499
514
 
500
515
  global_optargs = {}
501
516
  all_opts = @default_opts.merge(opts)
@@ -550,14 +565,16 @@ module RethinkDB
550
565
  end
551
566
 
552
567
  def send packet
553
- written = 0
554
- while written < packet.length
555
- # Supposedly slice will not copy the array if it goes all the way to the end
556
- # We use IO::syswrite here rather than IO::write because of incompatibilities in
557
- # JRuby regarding filling up the TCP send buffer.
558
- # Reference: https://github.com/rethinkdb/rethinkdb/issues/3795
559
- written += @socket.syswrite(packet.slice(written, packet.length))
560
- end
568
+ @mon.synchronize {
569
+ written = 0
570
+ while written < packet.length
571
+ # Supposedly slice will not copy the array if it goes all the way to the end
572
+ # We use IO::syswrite here rather than IO::write because of incompatibilities in
573
+ # JRuby regarding filling up the TCP send buffer.
574
+ # Reference: https://github.com/rethinkdb/rethinkdb/issues/3795
575
+ written += @socket.syswrite(packet.slice(written, packet.length))
576
+ end
577
+ }
561
578
  end
562
579
 
563
580
  def dispatch(msg, token)
@@ -579,7 +596,7 @@ module RethinkDB
579
596
  # but this is safer in case someone makes changes to
580
597
  # `close` in the future.
581
598
  if !is_open() || !@waiters.has_key?(token)
582
- raise RqlRuntimeError, "Connection is closed."
599
+ raise ReqlRuntimeError, "Connection is closed."
583
600
  end
584
601
 
585
602
  if end_time
@@ -636,8 +653,7 @@ module RethinkDB
636
653
 
637
654
  def connect()
638
655
  raise RuntimeError, "Connection must be closed before calling connect." if @socket
639
- @socket = TCPSocket.open(@host, @port)
640
- @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
656
+ init_socket
641
657
  @mon = Monitor.new
642
658
  @waiters = {}
643
659
  @opts = {}
@@ -647,6 +663,46 @@ module RethinkDB
647
663
  self
648
664
  end
649
665
 
666
+ def init_socket
667
+ unless @ssl_opts.empty?
668
+ @tcp_socket = base_socket
669
+ context = create_context(@ssl_opts)
670
+ @socket = OpenSSL::SSL::SSLSocket.new(@tcp_socket, context)
671
+ @socket.sync_close = true
672
+ @socket.connect
673
+ verify_cert!(@socket, context)
674
+ else
675
+ @socket = base_socket
676
+ end
677
+ end
678
+
679
+ def base_socket
680
+ socket = TCPSocket.open(@host, @port)
681
+ socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
682
+ socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
683
+ socket
684
+ end
685
+
686
+ def create_context(options)
687
+ context = OpenSSL::SSL::SSLContext.new
688
+ context.ssl_version = :TLSv1_2
689
+ if options[:ca_certs]
690
+ context.ca_file = options[:ca_certs]
691
+ context.verify_mode = OpenSSL::SSL::VERIFY_PEER
692
+ else
693
+ raise 'ssl options provided but missing required "ca_certs" option'
694
+ end
695
+ context
696
+ end
697
+
698
+ def verify_cert!(socket, context)
699
+ if context.verify_mode == OpenSSL::SSL::VERIFY_PEER
700
+ unless OpenSSL::SSL.verify_certificate_identity(socket.peer_cert, host)
701
+ raise 'SSL handshake failed due to a hostname mismatch.'
702
+ end
703
+ end
704
+ end
705
+
650
706
  def is_open
651
707
  @socket && @listener
652
708
  end
@@ -669,7 +725,7 @@ module RethinkDB
669
725
  @waiters.each {|k,v|
670
726
  case v
671
727
  when QueryHandle
672
- v.handle_close
728
+ v.handle_force_close
673
729
  when MonitorMixin::ConditionVariable
674
730
  @waiters[k] = nil
675
731
  v.signal
@@ -690,25 +746,25 @@ module RethinkDB
690
746
  end
691
747
 
692
748
  def noreply_wait
693
- raise RqlRuntimeError, "Connection is closed." if !is_open()
749
+ raise ReqlRuntimeError, "Connection is closed." if !is_open()
694
750
  q = [Query::QueryType::NOREPLY_WAIT]
695
751
  res = run_internal(q, {noreply: false}, new_token)
696
752
  if res['t'] != Response::ResponseType::WAIT_COMPLETE
697
- raise RqlRuntimeError, "Unexpected response to noreply_wait: " + PP.pp(res, "")
753
+ raise ReqlRuntimeError, "Unexpected response to noreply_wait: " + PP.pp(res, "")
698
754
  end
699
755
  nil
700
756
  end
701
757
 
702
758
  def self.last
703
759
  return @@last if @@last
704
- raise RqlRuntimeError, "No last connection. Use RethinkDB::Connection.new."
760
+ raise ReqlRuntimeError, "No last connection. Use RethinkDB::Connection.new."
705
761
  end
706
762
 
707
763
  def remove_em_waiters
708
764
  @mon.synchronize {
709
765
  @waiters.each {|k,v|
710
766
  if v.is_a? QueryHandle
711
- v.handle_close
767
+ v.handle_force_close
712
768
  @waiters.delete(k)
713
769
  end
714
770
  }
@@ -727,7 +783,7 @@ module RethinkDB
727
783
  when nil
728
784
  # nothing
729
785
  else
730
- raise RqlDriverError, "Unrecognized value #{w.inspect} in `@waiters`."
786
+ raise ReqlDriverError, "Unrecognized value #{w.inspect} in `@waiters`."
731
787
  end
732
788
  end
733
789
 
@@ -749,7 +805,7 @@ module RethinkDB
749
805
  maybe_timeout(timeout_sec) {
750
806
  buf = read len
751
807
  if !buf || buf.length != len
752
- raise RqlRuntimeError, "Connection closed by server."
808
+ raise ReqlRuntimeError, "Connection closed by server."
753
809
  end
754
810
  return buf
755
811
  }
@@ -762,12 +818,16 @@ module RethinkDB
762
818
  response += @socket.read_exn(1, @timeout)
763
819
  end
764
820
  response = response[0...-1]
765
- if response != "SUCCESS"
766
- raise RqlRuntimeError, "Server dropped connection with message: \"#{response}\""
821
+ if response == "SUCCESS"
822
+ # do nothing
823
+ elsif response == "ERROR: Incorrect authorization key.\n"
824
+ raise ReqlAuthError, "Incorrect authorization key."
825
+ else
826
+ raise ReqlRuntimeError, "Server dropped connection with message: \"#{response}\""
767
827
  end
768
828
 
769
829
  if @listener
770
- raise RqlDriverError, "Internal driver error, listener already started."
830
+ raise ReqlDriverError, "Internal driver error, listener already started."
771
831
  end
772
832
  @listener = Thread.new {
773
833
  while true
@@ -779,7 +839,7 @@ module RethinkDB
779
839
  begin
780
840
  data = Shim.load_json(response, @opts[token])
781
841
  rescue Exception => e
782
- raise RqlRuntimeError, "Bad response, server is buggy.\n" +
842
+ raise ReqlRuntimeError, "Bad response, server is buggy.\n" +
783
843
  "#{e.inspect}\n" + response
784
844
  end
785
845
  @mon.synchronize{note_data(token, data)}
data/lib/ql2.pb.rb CHANGED
@@ -49,6 +49,16 @@ module RethinkDB
49
49
  RUNTIME_ERROR = 18
50
50
  end
51
51
 
52
+ module ErrorType
53
+ INTERNAL = 1000000
54
+ RESOURCE_LIMIT = 2000000
55
+ QUERY_LOGIC = 3000000
56
+ NON_EXISTENCE = 3100000
57
+ OP_FAILED = 4100000
58
+ OP_INDETERMINATE = 4200000
59
+ USER = 5000000
60
+ end
61
+
52
62
  module ResponseNote
53
63
  SEQUENCE_FEED = 1
54
64
  ATOM_FEED = 2
@@ -100,6 +110,9 @@ module RethinkDB
100
110
  MUL = 26
101
111
  DIV = 27
102
112
  MOD = 28
113
+ FLOOR = 183
114
+ CEIL = 184
115
+ ROUND = 185
103
116
  APPEND = 29
104
117
  PREPEND = 80
105
118
  DIFFERENCE = 95
data/lib/shim.rb CHANGED
@@ -57,17 +57,28 @@ module RethinkDB
57
57
 
58
58
  def self.response_to_native(r, orig_term, opts)
59
59
  rt = Response::ResponseType
60
+ re = Response::ErrorType
60
61
  begin
61
62
  case r['t']
62
- when rt::SUCCESS_ATOM then r['r'][0]
63
- when rt::SUCCESS_PARTIAL then r['r']
64
- when rt::SUCCESS_SEQUENCE then r['r']
65
- when rt::RUNTIME_ERROR then raise RqlRuntimeError, r['r'][0]
66
- when rt::COMPILE_ERROR then raise RqlCompileError, r['r'][0]
67
- when rt::CLIENT_ERROR then raise RqlDriverError, r['r'][0]
68
- else raise RqlRuntimeError, "Unexpected response: #{r.inspect}"
63
+ when rt::SUCCESS_ATOM then r['r'][0]
64
+ when rt::SUCCESS_PARTIAL then r['r']
65
+ when rt::SUCCESS_SEQUENCE then r['r']
66
+ when rt::RUNTIME_ERROR
67
+ case r['e']
68
+ when re::INTERNAL then raise ReqlInternalError, r['r'][0]
69
+ when re::RESOURCE_LIMIT then raise ReqlResourceLimitError, r['r'][0]
70
+ when re::QUERY_LOGIC then raise ReqlQueryLogicError, r['r'][0]
71
+ when re::NON_EXISTENCE then raise ReqlNonExistenceError, r['r'][0]
72
+ when re::OP_FAILED then raise ReqlOpFailedError, r['r'][0]
73
+ when re::OP_INDETERMINATE then raise ReqlOpIndeterminateError, r['r'][0]
74
+ when re::USER then raise ReqlUserError, r['r'][0]
75
+ else raise ReqlRuntimeError, r['r'][0]
76
+ end
77
+ when rt::COMPILE_ERROR then raise ReqlCompileError, r['r'][0]
78
+ when rt::CLIENT_ERROR then raise ReqlDriverError, r['r'][0]
79
+ else raise ReqlRuntimeError, "Unexpected response: #{r.inspect}"
69
80
  end
70
- rescue RqlError => e
81
+ rescue ReqlError => e
71
82
  raise e.class, "#{e.message}\nBacktrace:\n#{RPP.pp(orig_term, r['b'])}"
72
83
  end
73
84
  end
@@ -93,14 +104,14 @@ module RethinkDB
93
104
  case x
94
105
  when String then x
95
106
  when Symbol then x.to_s
96
- else raise RqlDriverError, 'Object keys must be strings or symbols. '+
107
+ else raise ReqlDriverError, 'Object keys must be strings or symbols. '+
97
108
  "(Got object `#{x.inspect}` of class `#{x.class}`.)"
98
109
  end
99
110
  end
100
111
 
101
112
  def self.fast_expr(x, max_depth)
102
113
  if max_depth == 0
103
- raise RqlDriverError, "Maximum expression depth exceeded " +
114
+ raise ReqlDriverError, "Maximum expression depth exceeded " +
104
115
  "(you can override this with `r.expr(X, MAX_DEPTH)`)."
105
116
  end
106
117
  case x
@@ -127,7 +138,7 @@ module RethinkDB
127
138
  RQL.new({ '$reql_type$' => 'TIME',
128
139
  'epoch_time' => epoch_time,
129
140
  'timezone' => tz })
130
- else raise RqlDriverError, "r.expr can't handle #{x.inspect} of class #{x.class}."
141
+ else raise ReqlDriverError, "r.expr can't handle #{x.inspect} of class #{x.class}."
131
142
  end
132
143
  end
133
144
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rethinkdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - RethinkDB Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-14 00:00:00.000000000 Z
11
+ date: 2015-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -30,13 +30,13 @@ executables: []
30
30
  extensions: []
31
31
  extra_rdoc_files: []
32
32
  files:
33
- - lib/ql2.pb.rb
34
33
  - lib/exc.rb
35
34
  - lib/func.rb
36
35
  - lib/net.rb
37
36
  - lib/rethinkdb.rb
38
37
  - lib/rpp.rb
39
38
  - lib/shim.rb
39
+ - lib/ql2.pb.rb
40
40
  homepage: http://rethinkdb.com
41
41
  licenses:
42
42
  - Apache-2