rethinkdb 2.0.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/exc.rb +15 -4
- data/lib/func.rb +2 -2
- data/lib/net.rb +88 -28
- data/lib/ql2.pb.rb +13 -0
- data/lib/shim.rb +22 -11
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4dbe3bed2b00fa519fa84f136b6b140da9e97c49
|
4
|
+
data.tar.gz: 478001c0afd50dcbad8d02d843ffa2602d7cec6d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34d05e329c5c523c91f324e67205cef95ad57c2af7ae9b01977ddd76e2bb03be110b45165fd42fbe36535865548bef1e8b82cb37925a21cc98dea9e25e1b9a6d
|
7
|
+
data.tar.gz: 07a54b27fba8686fd47b9a6a814f18e417400fc4636240f015c255aa7e52358ffc623fb2c375c66fc1b2a2f07d0fa044b07d609e1441ced43eab383b61f472de
|
data/lib/exc.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
module RethinkDB
|
2
|
-
RqlError
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
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
|
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
|
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
|
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
|
428
|
+
raise ReqlRuntimeError, "Cannot call `next` on a cursor after calling `each`."
|
416
429
|
end
|
417
430
|
if @more && out_of_date
|
418
|
-
raise
|
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
|
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
|
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
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
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
|
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
|
-
|
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.
|
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
|
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
|
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
|
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.
|
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
|
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
|
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
|
766
|
-
|
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
|
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
|
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
|
63
|
-
when rt::SUCCESS_PARTIAL
|
64
|
-
when rt::SUCCESS_SEQUENCE
|
65
|
-
when rt::RUNTIME_ERROR
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
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
|
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
|
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
|
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.
|
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-
|
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
|