cequel 2.0.1 → 2.0.2

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.
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