eurydice 1.1.1.b1-java → 1.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- eurydice (1.1.0.b4-java)
4
+ eurydice (1.2.0-java)
5
5
  pelops-jars (>= 1.3.0)
6
6
 
7
7
  GEM
@@ -9,4 +9,5 @@ module Eurydice
9
9
  class KeyspaceExistsError < InvalidRequestError; end
10
10
  class NotFoundError < EurydiceError; end
11
11
  class TimeoutError < EurydiceError; end
12
+ class BatchError < EurydiceError; end
12
13
  end
@@ -118,9 +118,21 @@ module Eurydice
118
118
  transform_thrift_exception(e)
119
119
  end
120
120
  end
121
+
122
+ module ConsistencyLevelHelpers
123
+ def get_cl(options)
124
+ cl = options.fetch(:consistency_level, options.fetch(:cl, :one))
125
+ Cassandra::CONSISTENCY_LEVELS[cl]
126
+ end
127
+
128
+ def default_cl?(options)
129
+ !(options.key?(:consistency_level) || options.key?(:cl))
130
+ end
131
+ end
121
132
  end
122
133
  end
123
134
 
135
+ require_relative 'pelops/mutator'
124
136
  require_relative 'pelops/cluster'
125
137
  require_relative 'pelops/keyspace'
126
138
  require_relative 'pelops/column_family'
@@ -5,6 +5,7 @@ module Eurydice
5
5
  class ColumnFamily
6
6
  include ExceptionHelpers
7
7
  include ByteHelpers
8
+ include ConsistencyLevelHelpers
8
9
 
9
10
  attr_reader :name, :keyspace
10
11
 
@@ -47,20 +48,20 @@ module Eurydice
47
48
  end
48
49
 
49
50
  def delete_column(row_key, column_key, options={})
50
- batch(options) do |b|
51
- b.delete_column(row_key, column_key)
51
+ @keyspace.batch(options) do |b|
52
+ b.delete_column(@name, row_key, column_key)
52
53
  end
53
54
  end
54
55
 
55
56
  def delete_columns(row_key, column_keys, options={})
56
- batch(options) do |b|
57
- b.delete_columns(row_key, column_keys)
57
+ @keyspace.batch(options) do |b|
58
+ b.delete_columns(@name, row_key, column_keys)
58
59
  end
59
60
  end
60
61
 
61
62
  def update(row_key, properties, options={})
62
- batch(options) do |b|
63
- b.update(row_key, properties, options)
63
+ @keyspace.batch(options) do |b|
64
+ b.update(@name, row_key, properties, options)
64
65
  end
65
66
  end
66
67
  alias_method :insert, :update
@@ -247,54 +248,6 @@ module Eurydice
247
248
  end
248
249
  return key, value
249
250
  end
250
-
251
- module ConsistencyLevelHelpers
252
- def get_cl(options)
253
- cl = options.fetch(:consistency_level, options.fetch(:cl, :one))
254
- Cassandra::CONSISTENCY_LEVELS[cl]
255
- end
256
- end
257
-
258
- include ConsistencyLevelHelpers
259
-
260
- class Batch
261
- include ExceptionHelpers
262
- include ByteHelpers
263
- include ConsistencyLevelHelpers
264
-
265
- def initialize(name, keyspace)
266
- @name = name
267
- @keyspace = keyspace
268
- @mutator = @keyspace.create_mutator
269
- end
270
-
271
- def delete_column(row_key, column_key)
272
- @mutator.delete_column(@name, row_key, to_pelops_bytes(column_key))
273
- end
274
-
275
- def delete_columns(row_key, column_keys)
276
- @mutator.delete_columns(@name, row_key, column_keys.map { |k| to_pelops_bytes(k) })
277
- end
278
-
279
- def update(row_key, properties, options={})
280
- types = options[:validations] || {}
281
- key_type = options[:comparator]
282
- columns = properties.map do |k, v|
283
- key = to_pelops_bytes(k, key_type)
284
- value = to_pelops_bytes(v, types[k])
285
- ttl = options.fetch(:ttl, @mutator.class::NO_TTL)
286
- @mutator.new_column(key, value, ttl)
287
- end
288
- @mutator.write_columns(@name, row_key, columns)
289
- end
290
- alias_method :insert, :update
291
-
292
- def execute!(options={})
293
- thrift_exception_handler do
294
- @mutator.execute(get_cl(options))
295
- end
296
- end
297
- end
298
251
  end
299
252
  end
300
253
  end
@@ -4,6 +4,7 @@ module Eurydice
4
4
  module Pelops
5
5
  class Keyspace
6
6
  include ExceptionHelpers
7
+ include ConsistencyLevelHelpers
7
8
 
8
9
  attr_reader :name
9
10
 
@@ -12,6 +13,7 @@ module Eurydice
12
13
  @cluster = cluster
13
14
  @pool_name = pool_name
14
15
  @driver = driver
16
+ @batch_key = "#{@name}-batch"
15
17
  end
16
18
 
17
19
  def definition(reload=false)
@@ -74,10 +76,67 @@ module Eurydice
74
76
  @column_family_manger ||= @driver.create_column_family_manager(@cluster, @name)
75
77
  end
76
78
 
79
+ def batch(options={})
80
+ if batch_in_progress?
81
+ check_batch_options!(options)
82
+ yield current_batch_mutator
83
+ else
84
+ start_batch(options)
85
+ begin
86
+ yield current_batch_mutator
87
+ rescue
88
+ clear_batch!
89
+ raise
90
+ end
91
+ end_batch!
92
+ end
93
+ end
94
+
77
95
  private
78
96
 
79
97
  DEFAULT_STRATEGY_CLASS = Cassandra::LOCATOR_STRATEGY_CLASSES[:simple]
80
98
  DEFAULT_STRATEGY_OPTIONS = {:replication_factor => 1}.freeze
99
+
100
+ def start_batch(options={})
101
+ thread_local_storage[@batch_key] ||= {
102
+ :mutator => Mutator.new(self),
103
+ :options => options
104
+ }
105
+ end
106
+
107
+ def batch_in_progress?
108
+ !!thread_local_storage[@batch_key]
109
+ end
110
+
111
+ def check_batch_options!(options)
112
+ unless default_cl?(options)
113
+ required_cl = get_cl(options)
114
+ current_cl = get_cl(current_batch_options)
115
+ raise BatchError, %(Inconsistent consistency levels! Current batch: #{current_cl}, required: #{required_cl}) unless required_cl == current_cl
116
+ end
117
+ end
118
+
119
+ def current_batch_mutator
120
+ thread_local_storage[@batch_key][:mutator]
121
+ end
122
+
123
+ def current_batch_options
124
+ thread_local_storage[@batch_key][:options]
125
+ end
126
+
127
+ def clear_batch!
128
+ thread_local_storage.delete(@batch_key)
129
+ nil
130
+ end
131
+
132
+ def end_batch!
133
+ current_batch_mutator.execute!(current_batch_options)
134
+ clear_batch!
135
+ end
136
+
137
+ def thread_local_storage
138
+ Thread.current[:eurydice_pelops] ||= {}
139
+ end
81
140
  end
82
141
  end
83
142
  end
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+
3
+ module Eurydice
4
+ module Pelops
5
+ class Mutator
6
+ include ExceptionHelpers
7
+ include ConsistencyLevelHelpers
8
+ include ByteHelpers
9
+
10
+ def initialize(keyspace)
11
+ @keyspace = keyspace
12
+ @mutator = @keyspace.create_mutator
13
+ end
14
+
15
+ def delete_column(cf_name, row_key, column_key)
16
+ @mutator.delete_column(cf_name, row_key, to_pelops_bytes(column_key))
17
+ end
18
+
19
+ def delete_columns(cf_name, row_key, column_keys)
20
+ @mutator.delete_columns(cf_name, row_key, column_keys.map { |k| to_pelops_bytes(k) })
21
+ end
22
+
23
+ def update(cf_name, row_key, properties, options={})
24
+ types = options[:validations] || {}
25
+ key_type = options[:comparator]
26
+ columns = properties.map do |k, v|
27
+ key = to_pelops_bytes(k, key_type)
28
+ value = to_pelops_bytes(v, types[k])
29
+ ttl = options.fetch(:ttl, @mutator.class::NO_TTL)
30
+ @mutator.new_column(key, value, ttl)
31
+ end
32
+ @mutator.write_columns(cf_name, row_key, columns)
33
+ end
34
+ alias_method :insert, :update
35
+
36
+ def execute!(options={})
37
+ thrift_exception_handler do
38
+ @mutator.execute(get_cl(options))
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
 
4
4
  module Eurydice
5
- VERSION = '1.1.1.b1'
5
+ VERSION = '1.2.0'
6
6
  end
@@ -568,26 +568,5 @@ module Eurydice
568
568
  end
569
569
  end
570
570
  end
571
-
572
- context 'batch mutation' do
573
- before do
574
- @cf = @keyspace.column_family('test_family')
575
- @cf.truncate!
576
- end
577
-
578
- describe '#batch' do
579
- it 'yields a batch object which can be used to perform multiple mutations' do
580
- @cf.batch do |batch|
581
- batch.update('first_row', 'col1' => 'hello1', 'col2' => 'hello2')
582
- batch.update('second_row', 'col1' => 'hello3', 'xyz' => 'hello', 'abc' => 'hello')
583
- batch.delete_column('first_row', 'col2')
584
- batch.delete_columns('second_row', %w(xyz abc))
585
- batch.update('first_row', 'col3' => 'hello4')
586
- end
587
- @cf.get('first_row').should == {'col1' => 'hello1', 'col3' => 'hello4'}
588
- @cf.get('second_row').should == {'col1' => 'hello3'}
589
- end
590
- end
591
- end
592
571
  end
593
572
  end
@@ -76,5 +76,102 @@ module Eurydice
76
76
  definition[:strategy_options].should == {:replication_factor => 1}
77
77
  end
78
78
  end
79
+
80
+ describe '#batch' do
81
+ before do
82
+ @keyspace = @cluster.keyspace(@keyspace_name)
83
+ @cf1 = @keyspace.column_family('cf1')
84
+ @cf2 = @keyspace.column_family('cf2')
85
+ end
86
+
87
+ it 'starts and executes a batch' do
88
+ @keyspace.batch do
89
+ @cf1.insert('row1', 'foo' => 'bar', 'baz' => 'qux')
90
+ @cf1.insert('row2', 'xyz' => '123', 'abc' => '123')
91
+ @cf2.insert('item1', 'hello' => 'world')
92
+ @cf1.delete_column('row2', 'abc')
93
+ @cf1.get('row1').should be_nil
94
+ @cf1.get('row2').should be_nil
95
+ @cf2.get('item1').should be_nil
96
+ end
97
+ @cf1.get('row1').should == {'foo' => 'bar', 'baz' => 'qux'}
98
+ @cf1.get('row2').should == {'xyz' => '123'}
99
+ @cf2.get('item1').should == {'hello' => 'world'}
100
+ end
101
+
102
+ it 'only has one active batch' do
103
+ @keyspace.batch do
104
+ @keyspace.batch do
105
+ @keyspace.batch do
106
+ @cf1.insert('row1', 'foo' => 'bar')
107
+ end
108
+ @cf1.get('row1').should be_nil
109
+ @keyspace.batch do
110
+ @cf1.insert('row1', 'baz' => 'qux')
111
+ end
112
+ @cf1.get('row1').should be_nil
113
+ end
114
+ @cf1.get('row1').should be_nil
115
+ end
116
+ @cf1.get('row1').should == {'foo' => 'bar', 'baz' => 'qux'}
117
+ end
118
+
119
+ it 'aborts the batch on error' do
120
+ begin
121
+ @keyspace.batch do
122
+ @cf1.insert('row1', 'foo' => 'bar')
123
+ @cf1.insert('row2', 'foo' => 'bar')
124
+ raise 'hurgh!'
125
+ end
126
+ rescue
127
+ end
128
+ @cf1.get('row1').should be_nil
129
+ @cf1.get('row2').should be_nil
130
+ end
131
+
132
+ context 'conflicting batch options' do
133
+ it 'complains when the options given to the #batch contain different consistency levels' do
134
+ expect {
135
+ @keyspace.batch(:cl => :one) do
136
+ @keyspace.batch(:cl => :quorum) do
137
+ @cf1.insert('row1', 'foo' => 'bar')
138
+ end
139
+ end
140
+ }.to raise_error(BatchError)
141
+ end
142
+
143
+ it 'complains when the options given to a mutation call has different consistency levels than the options to the #batch call' do
144
+ expect {
145
+ @keyspace.batch(:cl => :one) do
146
+ @keyspace.batch do
147
+ @cf1.insert('row1', {'foo' => 'bar'}, {:cl => :quorum})
148
+ end
149
+ end
150
+ }.to raise_error(BatchError)
151
+ end
152
+
153
+ it 'does not complain when no explicit options are specified' do
154
+ expect {
155
+ @keyspace.batch(:cl => :quorum) do
156
+ @keyspace.batch do
157
+ @cf1.insert('row1', {'foo' => 'bar'})
158
+ end
159
+ end
160
+ }.not_to raise_error(BatchError)
161
+ end
162
+
163
+ it 'aborts the batch on conflicting consistency levels' do
164
+ begin
165
+ @keyspace.batch(:cl => :quorum) do
166
+ @cf1.insert('row1', {'foo' => 'bar'}, {:cl => :quorum})
167
+ @cf1.insert('row2', {'foo' => 'bar'}, {:cl => :one})
168
+ end
169
+ rescue
170
+ end
171
+ @cf1.get('row1').should be_nil
172
+ @cf1.get('row2').should be_nil
173
+ end
174
+ end
175
+ end
79
176
  end
80
177
  end
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eurydice
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: 6
5
- version: 1.1.1.b1
4
+ prerelease:
5
+ version: 1.2.0
6
6
  platform: java
7
7
  authors:
8
8
  - Theo Hultberg
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-03-02 00:00:00 Z
13
+ date: 2012-03-03 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: pelops-jars
@@ -54,6 +54,7 @@ files:
54
54
  - lib/eurydice/pelops/cluster.rb
55
55
  - lib/eurydice/pelops/column_family.rb
56
56
  - lib/eurydice/pelops/keyspace.rb
57
+ - lib/eurydice/pelops/mutator.rb
57
58
  - lib/eurydice/version.rb
58
59
  - spec/eurydice/pelops/cluster_spec.rb
59
60
  - spec/eurydice/pelops/column_family_spec.rb
@@ -79,9 +80,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
80
  required_rubygems_version: !ruby/object:Gem::Requirement
80
81
  none: false
81
82
  requirements:
82
- - - ">"
83
+ - - ">="
83
84
  - !ruby/object:Gem::Version
84
- version: 1.3.1
85
+ version: "0"
85
86
  requirements: []
86
87
 
87
88
  rubyforge_project: eurydice