cequel 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 39be41ec7fa476af8f992f29924fd443953878f6
4
- data.tar.gz: fe9ff8053a6fd8b895451af0e3d873c05a9900b1
3
+ metadata.gz: e428934f7aef3a261e5ee1c06b940ea008fd17de
4
+ data.tar.gz: 49a65b153251cb761a8421c56268d5b9c83d6966
5
5
  SHA512:
6
- metadata.gz: 15247d49c41700123aad6763a7891fd7cf99c216aa3adfc37e00746c531fcb7c10565af34570914358ee8cd8a098745bca0a2c348b0bfd6a193ab1a9ba017030
7
- data.tar.gz: 3f1f170c476ae40e64530c43c9f57f732b2d8ac63f06c9e27e07edd6b69e30b67b68cca25636c0602281802c7bf1d8b27c9be1909af6d3eb0936ed570de9c603
6
+ metadata.gz: 623e015fa5d288ca1302eafaec1ada9aa0224b23a28c854e6e69e3dd7dfaa6d5e32a768291ecb9d23d2b3eb4f80a272fe57ef045cb4651f5a69217a264cafb3e
7
+ data.tar.gz: 5ddbd20b44c69675be0025cea406961dad9a336b91853ae68b30914138e4b78c23baff03be79278a387b24d0a827e676485db78c045d5d5e9ffc40adcf902ed3
@@ -1,3 +1,8 @@
1
+ ## 2.0.2
2
+
3
+ * Fix intermittent failures around preparing statements ([PR 330](https://github.com/cequel/cequel/pull/330))
4
+ * Fix new relic instrumentation ([PR 331](https://github.com/cequel/cequel/pull/331))
5
+
1
6
  ## 2.0.1
2
7
 
3
8
  * Remove requirment on activemodel-serializers-xml ([PR 329](https://github.com/cequel/cequel/pull/329))
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cequel (2.0.1)
4
+ cequel (2.0.2)
5
5
  activemodel (>= 4.0)
6
6
  cassandra-driver (~> 3.0)
7
7
 
@@ -202,29 +202,39 @@ module Cequel
202
202
  def execute_with_options(statement, options={})
203
203
  options[:consistency] ||= default_consistency
204
204
 
205
- retries = max_retries
206
205
  cql, options = *case statement
207
206
  when Statement
208
- [client.prepare(statement.cql),
207
+ [prepare_statement(statement),
209
208
  {arguments: statement.bind_vars}.merge(options)]
210
209
  when Cassandra::Statements::Batch
211
210
  [statement, options]
212
211
  end
213
212
 
214
213
  log('CQL', statement) do
215
- begin
214
+ client_retry do
216
215
  client.execute(cql, options)
217
- rescue Cassandra::Errors::NoHostsAvailable,
218
- Ione::Io::ConnectionError => e
219
- clear_active_connections!
220
- raise if retries == 0
221
- retries -= 1
222
- sleep(retry_delay)
223
- retry
224
216
  end
225
217
  end
226
218
  end
227
219
 
220
+ #
221
+ # Wraps the prepare statement in the default retry strategy
222
+ #
223
+ # @param statement [String,Statement] statement to prepare
224
+ # @return [Cassandra::Statement::Prepared] the prepared statement
225
+ #
226
+ def prepare_statement(statement)
227
+ cql = case statement
228
+ when Statement
229
+ statement.cql
230
+ else
231
+ statement
232
+ end
233
+ client_retry do
234
+ client.prepare(cql)
235
+ end
236
+ end
237
+
228
238
  #
229
239
  # Clears all active connections
230
240
  #
@@ -298,6 +308,20 @@ module Cequel
298
308
  def_delegator :lock, :synchronize
299
309
  private :lock
300
310
 
311
+ def client_retry
312
+ retries = max_retries
313
+ begin
314
+ yield
315
+ rescue Cassandra::Errors::NoHostsAvailable,
316
+ Cassandra::Errors::ExecutionError,
317
+ Cassandra::Errors::TimeoutError
318
+ clear_active_connections!
319
+ raise if retries == 0
320
+ retries -= 1
321
+ sleep(retry_delay)
322
+ retry
323
+ end
324
+ end
301
325
 
302
326
  def client_without_keyspace
303
327
  synchronize do
@@ -13,15 +13,28 @@ module Cequel
13
13
  module NewRelicInstrumentation
14
14
  extend ActiveSupport::Concern
15
15
 
16
- define_method :execute_with_options_with_newrelic do |statement, bind_vars, options|
16
+ define_method :execute_with_options_with_newrelic do |statement, options|
17
+
18
+ operation = nil
19
+ statement_txt = nil
20
+ statement_words = nil
21
+
22
+ if statement.is_a?(::Cequel::Metal::Statement)
23
+ statement_txt = statement.cql
24
+ statement_words = statement_txt.split
25
+ operation = statement_words.first.downcase
26
+ elsif statement.is_a?(::Cassandra::Statements::Batch)
27
+ operation = "batch"
28
+ end
29
+
17
30
  callback = Proc.new do |result, scoped_metric, elapsed|
18
- NewRelic::Agent::Datastores.notice_statement(statement, elapsed)
31
+ NewRelic::Agent::Datastores.notice_statement(statement_txt, elapsed)
19
32
  end
20
33
 
21
- statement_words = statement.split
22
- operation = statement_words.first.downcase
23
34
  table = nil
24
35
  case operation
36
+ when "batch"
37
+ # Nothing to do
25
38
  when "begin"
26
39
  operation = "batch"
27
40
  when "select"
@@ -33,7 +46,7 @@ module Cequel
33
46
  end
34
47
 
35
48
  NewRelic::Agent::Datastores.wrap("Cassandra", operation, table, callback) do
36
- execute_with_options_without_newrelic(statement, bind_vars, options)
49
+ execute_with_options_without_newrelic(statement, options)
37
50
  end
38
51
  end
39
52
 
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module Cequel
3
3
  # The current version of the library
4
- VERSION = '2.0.1'
4
+ VERSION = '2.0.2'
5
5
  end
@@ -118,6 +118,7 @@ describe Cequel::Metal::Keyspace do
118
118
 
119
119
  describe "#execute" do
120
120
  let(:statement) { "SELECT id FROM posts" }
121
+ let(:execution_error) { Cassandra::Errors::OverloadedError.new(1,2,3,4,5,6,7,8,9) }
121
122
 
122
123
  context "without a connection error" do
123
124
  it "executes a CQL query" do
@@ -126,16 +127,71 @@ describe Cequel::Metal::Keyspace do
126
127
  end
127
128
 
128
129
  context "with a connection error" do
129
- it "reconnects to cassandra with a new client after first failed connection" do
130
+ it "reconnects to cassandra with a new client after no hosts could be reached" do
130
131
  allow(cequel.client)
131
132
  .to receive(:execute)
132
133
  .with(->(s){ s.cql == statement},
133
134
  hash_including(:consistency => cequel.default_consistency))
134
- .and_raise(Ione::Io::ConnectionError)
135
+ .and_raise(Cassandra::Errors::NoHostsAvailable)
135
136
  .once
136
137
 
137
138
  expect { cequel.execute(statement) }.not_to raise_error
138
139
  end
140
+
141
+ it "reconnects to cassandra with a new client after execution failed" do
142
+ allow(cequel.client)
143
+ .to receive(:execute)
144
+ .with(->(s){ s.cql == statement},
145
+ hash_including(:consistency => cequel.default_consistency))
146
+ .and_raise(execution_error)
147
+ .once
148
+
149
+ expect { cequel.execute(statement) }.not_to raise_error
150
+ end
151
+
152
+ it "reconnects to cassandra with a new client after timeout occurs" do
153
+ allow(cequel.client)
154
+ .to receive(:execute)
155
+ .with(->(s){ s.cql == statement},
156
+ hash_including(:consistency => cequel.default_consistency))
157
+ .and_raise(Cassandra::Errors::TimeoutError)
158
+ .once
159
+
160
+ expect { cequel.execute(statement) }.not_to raise_error
161
+ end
162
+ end
163
+ end
164
+
165
+ describe "#prepare_statement" do
166
+ let(:statement) { "SELECT id FROM posts" }
167
+ let(:execution_error) { Cassandra::Errors::OverloadedError.new(1,2,3,4,5,6,7,8,9) }
168
+
169
+ context "without a connection error" do
170
+ it "executes a CQL query" do
171
+ expect { cequel.prepare_statement(statement) }.not_to raise_error
172
+ end
173
+ end
174
+
175
+ context "with a connection error" do
176
+ it "reconnects to cassandra with a new client after no hosts could be reached" do
177
+ allow(cequel.client)
178
+ .to receive(:prepare)
179
+ .with(->(s){ s == statement})
180
+ .and_raise(Cassandra::Errors::NoHostsAvailable)
181
+ .once
182
+
183
+ expect { cequel.prepare_statement(statement) }.not_to raise_error
184
+ end
185
+
186
+ it "reconnects to cassandra with a new client after execution failed" do
187
+ allow(cequel.client)
188
+ .to receive(:prepare)
189
+ .with(->(s){ s == statement})
190
+ .and_raise(execution_error)
191
+ .once
192
+
193
+ expect { cequel.prepare_statement(statement) }.not_to raise_error
194
+ end
139
195
  end
140
196
  end
141
197
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mat Brown
@@ -29,7 +29,7 @@ authors:
29
29
  autorequire:
30
30
  bindir: bin
31
31
  cert_chain: []
32
- date: 2016-10-06 00:00:00.000000000 Z
32
+ date: 2016-10-17 00:00:00.000000000 Z
33
33
  dependencies:
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: activemodel