whi-cassie 1.0.5 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,61 @@
1
+ require "spec_helper"
2
+
3
+ describe Cassie::Subscribers do
4
+ it "should be able to add and remove a subscriber" do
5
+ subscribers = Cassie::Subscribers.new
6
+ expect(subscribers.empty?).to eq true
7
+ data_1 = []
8
+ data_2 = []
9
+ subscriber_1 = lambda { |info| data_1 << info }
10
+ subscriber_2 = lambda { |info| data_2 << info }
11
+ subscribers.add(subscriber_1)
12
+ subscribers << subscriber_2
13
+ expect(subscribers.empty?).to eq false
14
+ expect(subscribers.size).to eq 2
15
+ expect(subscribers.include?(subscriber_1)).to eq true
16
+ expect(subscribers.include?(subscriber_2)).to eq true
17
+
18
+ subscribers.each { |s| s.call(:payload) }
19
+ expect(data_1).to eq [:payload]
20
+ expect(data_2).to eq [:payload]
21
+
22
+ subscribers.remove(subscriber_2)
23
+ expect(subscribers.size).to eq 1
24
+ expect(subscribers.include?(subscriber_1)).to eq true
25
+ expect(subscribers.include?(subscriber_2)).to eq false
26
+
27
+ subscribers.each { |s| s.call(:more) }
28
+ expect(data_1).to eq [:payload, :more]
29
+ expect(data_2).to eq [:payload]
30
+
31
+ subscribers.delete(subscriber_1)
32
+ expect(subscribers.size).to eq 0
33
+ end
34
+
35
+ it "should have a hierarchy of subscribers" do
36
+ subscribers_1 = Cassie::Subscribers.new
37
+ subscribers_2 = Cassie::Subscribers.new(subscribers_1)
38
+ subscribers_3 = Cassie::Subscribers.new(subscribers_1)
39
+ data_1 = []
40
+ data_2 = []
41
+ data_3 = []
42
+ subscribers_1 << lambda { |info| data_1 << info }
43
+ subscribers_2 << lambda { |info| data_2 << info }
44
+
45
+ expect(subscribers_1.size).to eq 1
46
+ expect(subscribers_2.size).to eq 2
47
+ expect(subscribers_3.size).to eq 1
48
+
49
+ subscribers_1.each { |subscriber| subscriber.call(:payload_1) }
50
+ subscribers_2.each { |subscriber| subscriber.call(:payload_2) }
51
+ subscribers_3.each { |subscriber| subscriber.call(:payload_3) }
52
+
53
+ expect(data_1).to eq [:payload_1, :payload_2, :payload_3]
54
+ expect(data_2).to eq [:payload_2]
55
+
56
+ subscribers_2.clear
57
+ expect(subscribers_2.size).to eq 1
58
+ subscribers_1.clear
59
+ expect(subscribers_2.size).to eq 0
60
+ end
61
+ end
@@ -1,173 +1,218 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe Cassie do
4
-
5
- let(:instance){ Cassie.instance }
6
- let(:table){ "cassie_specs.things" }
7
-
4
+ let(:instance) { Cassie.instance }
5
+ let(:table) { "cassie_specs.things" }
6
+
8
7
  describe "prepare" do
9
8
  it "should keep a cache of prepared statements" do
10
9
  statement_1 = instance.prepare("SELECT * FROM #{table} LIMIT ?")
11
10
  statement_2 = instance.prepare("SELECT * FROM #{table} LIMIT ?")
12
- statement_1.object_id.should == statement_2.object_id
11
+ expect(statement_1.object_id).to eq(statement_2.object_id)
13
12
  end
14
-
13
+
15
14
  it "should clear the prepared statement cache when reconnecting" do
16
15
  statement_1 = instance.prepare("SELECT * FROM #{table} LIMIT ?")
17
16
  instance.disconnect
18
17
  instance.connect
19
18
  statement_2 = instance.prepare("SELECT * FROM #{table} LIMIT ?")
20
- statement_1.object_id.should_not == statement_2.object_id
19
+ expect(statement_1.object_id).not_to eq(statement_2.object_id)
21
20
  end
22
21
  end
23
-
22
+
24
23
  describe "find" do
25
24
  before :each do
26
- instance.insert(table, :owner => 1, :id => 2, :val => 'foo')
27
- instance.insert(table, :owner => 10, :id => 2, :val => 'bar')
25
+ instance.insert(table, owner: 1, id: 2, val: "foo")
26
+ instance.insert(table, owner: 10, id: 2, val: "bar")
28
27
  end
29
-
28
+
30
29
  it "should construct a CQL query from the options" do
31
30
  results = instance.find("SELECT owner, id, val FROM #{table} WHERE owner = 1")
32
- results.rows.collect{|r| r["val"]}.should == ['foo']
31
+ expect(results.rows.collect { |r| r["val"] }).to eq(["foo"])
33
32
  end
34
-
33
+
35
34
  it "should construct a CQL query from a statement with variables" do
36
35
  results = instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ? LIMIT ?", [10, 1])
37
- results.rows.collect{|r| r["val"]}.should == ['bar']
36
+ expect(results.rows.collect { |r| r["val"] }).to eq(["bar"])
38
37
  end
39
-
38
+
40
39
  it "should not batch find statements" do
41
40
  instance.batch do
42
41
  results = instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ? LIMIT ?", [10, 1])
43
- results.rows.collect{|r| r["val"]}.should == ['bar']
42
+ expect(results.rows.collect { |r| r["val"] }).to eq(["bar"])
44
43
  end
45
44
  end
46
45
  end
47
-
46
+
48
47
  describe "insert" do
49
48
  it "should insert a row from a hash of values" do
50
49
  results = instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1)
51
- results.size.should == 0
52
- instance.insert(table, :owner => 1, :id => 2, :val => 'foo')
50
+ expect(results.size).to eq(0)
51
+ instance.insert(table, owner: 1, id: 2, val: "foo")
53
52
  results = instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1)
54
- results.rows.collect{|r| r['val']}.should == ['foo']
53
+ expect(results.rows.collect { |r| r["val"] }).to eq(["foo"])
55
54
  end
56
-
55
+
57
56
  it "should add statements to the current batch" do
58
57
  instance.batch do
59
- instance.insert(table, :owner => 1, :id => 2, :val => 'foo')
58
+ instance.insert(table, owner: 1, id: 2, val: "foo")
60
59
  results = instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1)
61
- results.size.should == 0
60
+ expect(results.size).to eq(0)
62
61
  end
63
62
  results = instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1)
64
- results.size.should == 1
63
+ expect(results.size).to eq(1)
65
64
  end
66
65
  end
67
-
66
+
68
67
  describe "update" do
69
68
  it "should update a row from a hash of values and a primary key" do
70
- instance.insert(table, :owner => 1, :id => 2, :val => 'foo')
71
- instance.update(table, {:val => 'bar'}, :owner => 1, :id => 2)
69
+ instance.insert(table, owner: 1, id: 2, val: "foo")
70
+ instance.update(table, {val: "bar"}, owner: 1, id: 2)
72
71
  results = instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1)
73
- results.rows.collect{|r| r["val"]}.should == ['bar']
72
+ expect(results.rows.collect { |r| r["val"] }).to eq(["bar"])
74
73
  end
75
74
 
76
75
  it "should add statements to the current batch" do
77
- instance.insert(table, :owner => 1, :id => 2, :val => 'foo')
76
+ instance.insert(table, owner: 1, id: 2, val: "foo")
78
77
  instance.batch do
79
- instance.update(table, {:val => 'bar'}, :owner => 1, :id => 2)
78
+ instance.update(table, {val: "bar"}, owner: 1, id: 2)
80
79
  results = instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1)
81
- results.rows.collect{|r| r['val']}.should == ['foo']
80
+ expect(results.rows.collect { |r| r["val"] }).to eq(["foo"])
82
81
  end
83
82
  results = instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1)
84
- results.rows.collect{|r| r['val']}.should == ['bar']
83
+ expect(results.rows.collect { |r| r["val"] }).to eq(["bar"])
85
84
  end
86
85
  end
87
-
86
+
88
87
  describe "delete" do
89
88
  it "should update a row from a primary key hash" do
90
- instance.insert(table, :owner => 1, :id => 2, :val => 'foo')
91
- instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1).size.should == 1
92
- instance.delete(table, :owner => 1)
93
- instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1).size.should == 0
89
+ instance.insert(table, owner: 1, id: 2, val: "foo")
90
+ expect(instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1).size).to eq(1)
91
+ instance.delete(table, owner: 1)
92
+ expect(instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1).size).to eq(0)
94
93
  end
95
94
 
96
95
  it "should add statements to the current batch" do
97
- instance.insert(table, :owner => 1, :id => 2, :val => 'foo')
96
+ instance.insert(table, owner: 1, id: 2, val: "foo")
98
97
  instance.batch do
99
- instance.delete(table, :owner => 1)
100
- instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1).size.should == 1
98
+ instance.delete(table, owner: 1)
99
+ expect(instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1).size).to eq(1)
101
100
  end
102
- instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1).size.should == 0
101
+ expect(instance.find("SELECT owner, id, val FROM #{table} WHERE owner = ?", 1).size).to eq(0)
103
102
  end
104
103
  end
105
-
104
+
106
105
  describe "execute" do
107
106
  before :each do
108
- instance.insert(table, :owner => 1, :id => 2, :val => 'foo')
107
+ instance.insert(table, owner: 1, id: 2, val: "foo")
109
108
  end
110
-
109
+
111
110
  it "should execute a plain CQL statement" do
112
- instance.execute("SELECT owner, id, val FROM #{table} WHERE owner = 1").size.should == 1
111
+ expect(instance.execute("SELECT owner, id, val FROM #{table} WHERE owner = 1").size).to eq(1)
113
112
  end
114
-
113
+
115
114
  it "should execute a prepared statement" do
116
115
  statement = instance.prepare("SELECT owner, id, val FROM #{table} WHERE owner = 1")
117
- instance.execute(statement).size.should == 1
116
+ expect(instance.execute(statement).size).to eq(1)
118
117
  end
119
-
118
+
120
119
  it "should prepare and execute a CQL statement when values are provided" do
121
- instance.execute("SELECT owner, id, val FROM #{table} WHERE owner = ?", [1]).size.should == 1
120
+ expect(instance.execute("SELECT owner, id, val FROM #{table} WHERE owner = ?", [1]).size).to eq(1)
122
121
  end
123
-
122
+
124
123
  it "should call subscribers with details about the call" do
125
124
  instance.subscribers.clear
126
125
  begin
127
126
  messages = []
128
- instance.subscribers << lambda{|details| messages << details}
127
+ instance.subscribers << lambda { |details| messages << details }
129
128
 
130
129
  instance.execute("SELECT owner, id, val FROM #{table} WHERE owner = ?", [1])
131
- messages.size.should == 1
130
+ expect(messages.size).to eq(1)
131
+ message = messages.shift
132
+ expect(message.statement).to be_a(Cassandra::Statement)
133
+ expect(message.options).to eq({arguments: [1], consistency: :local_one})
134
+ expect(message.elapsed_time).to be_a(Float)
135
+
136
+ instance.execute("SELECT owner, id, val FROM #{table} WHERE owner = 1")
137
+ expect(messages.size).to eq(1)
132
138
  message = messages.shift
133
- message.statement.should be_a(Cassandra::Statement)
134
- message.options.should == {:arguments => [1]}
135
- message.elapsed_time.should be_a(Float)
139
+ expect(message.statement).to be_a(Cassandra::Statement)
140
+ expect(message.options).to eq({consistency: :local_one})
141
+ expect(message.elapsed_time).to be_a(Float)
136
142
 
137
143
  instance.batch do
138
- instance.insert(table, :owner => 1, :id => 2, :val => 'foo')
139
- instance.delete(table, :owner => 1)
144
+ instance.insert(table, owner: 1, id: 2, val: "foo")
145
+ instance.delete(table, owner: 1)
140
146
  end
141
- messages.size.should == 1
147
+ expect(messages.size).to eq(1)
142
148
  message = messages.shift
143
- message.statement.should be_a(Cassandra::Statements::Batch)
144
- message.options.should == nil
145
- message.elapsed_time.should be_a(Float)
149
+ expect(message.statement).to be_a(Cassandra::Statements::Batch)
150
+ expect(message.options).to eq({consistency: :local_one})
151
+ expect(message.elapsed_time).to be_a(Float)
146
152
  ensure
147
153
  instance.subscribers.clear
148
154
  end
149
155
  end
150
156
  end
151
-
157
+
152
158
  describe "consistency" do
153
- let(:session){ instance.send(:session) }
154
-
159
+ let(:session) { instance.send(:session) }
160
+
155
161
  it "should not specify query consistency by default" do
156
- expect(session).to receive(:execute).with("SELECT * FROM dual", {})
162
+ expect(session).to receive(:execute).with(Cassandra::Statements::Simple.new("SELECT * FROM dual"), {consistency: :local_one})
157
163
  instance.execute("SELECT * FROM dual")
164
+ expect(instance.current_consistency).to eq :local_one
158
165
  end
159
-
166
+
160
167
  it "should allow specifying the consistency in a block" do
161
- expect(session).to receive(:execute).with("SELECT * FROM dual", {:consistency => :one})
168
+ expect(session).to receive(:execute).with(Cassandra::Statements::Simple.new("SELECT * FROM dual"), {consistency: :one})
162
169
  Cassie.consistency(:one) do
163
170
  instance.execute("SELECT * FROM dual")
171
+ expect(instance.current_consistency).to eq :one
164
172
  end
165
173
  end
166
-
174
+
175
+ it "should allow specifying the consistency in a block if statement consistency is explicitly nil" do
176
+ expect(session).to receive(:execute).with(Cassandra::Statements::Simple.new("SELECT * FROM dual"), {consistency: :one})
177
+ Cassie.consistency(:one) do
178
+ instance.execute("SELECT * FROM dual", nil, consistency: nil)
179
+ expect(instance.current_consistency).to eq :one
180
+ end
181
+ end
182
+
167
183
  it "should use the consistency specified to execute if provided" do
168
- expect(session).to receive(:execute).with("SELECT * FROM dual", {:consistency => :two})
184
+ expect(session).to receive(:execute).with(Cassandra::Statements::Simple.new("SELECT * FROM dual"), {consistency: :two})
169
185
  Cassie.consistency(:one) do
170
- instance.execute("SELECT * FROM dual", nil, :consistency => :two)
186
+ instance.execute("SELECT * FROM dual", nil, consistency: :two)
187
+ expect(instance.current_consistency).to eq :one
188
+ end
189
+ end
190
+
191
+ it "should use the consistency passed in the batch for all statements in the batch" do
192
+ expect(session).to receive(:execute).with(an_instance_of(Cassandra::Statements::Batch::Logged), {consistency: :two})
193
+ Cassie.instance.batch(consistency: :two) do
194
+ instance.insert(table, owner: 1, id: 2, val: "foo")
195
+ end
196
+ end
197
+
198
+ it "should be able to specify a global consistancy" do
199
+ expect(session).to receive(:execute).with(Cassandra::Statements::Simple.new("SELECT * FROM dual"), {consistency: :one})
200
+ expect(session).to receive(:execute).with(Cassandra::Statements::Simple.new("SELECT COUNT(*) FROM dual"), {consistency: :local_quorum})
201
+ expect(session).to receive(:execute).with(Cassandra::Statements::Simple.new("SELECT COUNT(1) FROM dual"), {consistency: :local_one})
202
+ instance.execute("SELECT COUNT(1) FROM dual", nil)
203
+ expect(instance.current_consistency).to eq :local_one
204
+
205
+ begin
206
+ instance.consistency = :local_quorum
207
+ expect(instance.current_consistency).to eq :local_quorum
208
+ instance.execute("SELECT COUNT(*) FROM dual", nil)
209
+ Cassie.consistency(:one) do
210
+ instance.execute("SELECT * FROM dual", nil)
211
+ expect(instance.current_consistency).to eq :one
212
+ end
213
+ expect(instance.current_consistency).to eq :local_quorum
214
+ ensure
215
+ instance.consistency = :local_one
171
216
  end
172
217
  end
173
218
  end
@@ -1,34 +1,36 @@
1
1
  class Cassie::Thing
2
2
  include Cassie::Model
3
-
3
+
4
4
  self.table_name = "things"
5
5
  self.keyspace = "test"
6
6
  self.primary_key = [:owner, :id]
7
-
7
+ self.read_consistency = :one
8
+ self.write_consistency = :quorum
9
+
8
10
  column :owner, :int
9
- column :id, :int, :as => :identifier
10
- column :val, :varchar, :as => :value
11
-
11
+ column :id, :int, as: :identifier
12
+ column :val, :varchar, as: :value
13
+
12
14
  ordering_key :id, :desc
13
-
15
+
14
16
  validates_presence_of :owner, :id
15
-
17
+
16
18
  before_save do
17
19
  callbacks << :save
18
20
  end
19
-
21
+
20
22
  before_create do
21
23
  callbacks << :create
22
24
  end
23
-
25
+
24
26
  before_update do
25
27
  callbacks << :update
26
28
  end
27
-
29
+
28
30
  before_destroy do
29
31
  callbacks << :destroy
30
32
  end
31
-
33
+
32
34
  def callbacks
33
35
  @callbacks ||= []
34
36
  end
@@ -1,12 +1,12 @@
1
- require 'securerandom'
1
+ require "securerandom"
2
2
 
3
3
  class Cassie::TypeTester
4
4
  include Cassie::Model
5
-
5
+
6
6
  self.table_name = "type_testers"
7
7
  self.keyspace = "test"
8
8
  self.primary_key = [:id]
9
-
9
+
10
10
  column :id, :varchar
11
11
  column :int_value, :int
12
12
  column :varint_value, :varint
@@ -26,17 +26,17 @@ class Cassie::TypeTester
26
26
  column :list_value, :list
27
27
  column :set_value, :set
28
28
  column :map_value, :map
29
-
30
- before_create{ self.id = SecureRandom.uuid }
29
+
30
+ before_create { self.id = SecureRandom.uuid }
31
31
  end
32
32
 
33
33
  class Cassie::TypeTesterCounter
34
34
  include Cassie::Model
35
-
35
+
36
36
  self.table_name = "type_tester_counters"
37
37
  self.keyspace = "test"
38
38
  self.primary_key = [:id]
39
-
39
+
40
40
  column :id, :varchar
41
41
  column :counter_value, :counter, as: :counter_column
42
42
  end
@@ -1,6 +1,11 @@
1
- require 'whi-cassie'
2
- require File.expand_path('../models/thing', __FILE__)
3
- require File.expand_path('../models/type_tester', __FILE__)
1
+ require "rubygems"
2
+
3
+ require "active_model"
4
+
5
+ require_relative "../lib/whi-cassie"
6
+
7
+ require_relative "models/thing"
8
+ require_relative "models/type_tester"
4
9
 
5
10
  RSpec.configure do |config|
6
11
  config.run_all_when_everything_filtered = true
@@ -10,21 +15,41 @@ RSpec.configure do |config|
10
15
  # order dependency and want to debug it, you can fix the order by providing
11
16
  # the seed, which is printed after each run.
12
17
  # --seed 1234
13
- config.order = 'random'
14
-
18
+ config.order = "random"
19
+
15
20
  config.expect_with(:rspec) { |c| c.syntax = [:should, :expect] }
16
-
21
+
22
+ cassandra_host, cassandra_port = ENV.fetch("CASSANDRA_HOST", "localhost").split(":", 2)
23
+ cassandra_port ||= 9042
17
24
  config.before(:suite) do
18
25
  schema_dir = File.expand_path("../schema", __FILE__)
19
- Cassie.configure!(:cluster => {:host => 'localhost'}, :keyspaces => {"test" => "cassie_specs"}, :schema_directory => schema_dir, :max_prepared_statements => 3)
20
- Cassie::Schema.load_all!
26
+ protocol_version = (ENV["protocol_version"] ? ENV["protocol_version"].to_i : 3)
27
+ Cassie.configure!(
28
+ cluster: {host: cassandra_host, port: cassandra_port.to_i, protocol_version: protocol_version},
29
+ keyspaces: {"test" => "cassie_specs"},
30
+ schema_directory: schema_dir,
31
+ max_prepared_statements: 3
32
+ )
33
+
34
+ attempts = 0
35
+ loop do
36
+ begin
37
+ Cassie::Schema.load_all!
38
+ break
39
+ rescue Cassandra::Errors::NoHostsAvailable => e
40
+ attempts += 1
41
+ raise e if attempts > 30
42
+ sleep(1)
43
+ end
44
+ end
45
+
21
46
  Cassie::Testing.prepare!
22
47
  end
23
-
48
+
24
49
  config.after(:suite) do
25
50
  Cassie::Schema.drop_all!
26
51
  end
27
-
52
+
28
53
  config.around(:each) do |example|
29
54
  Cassie::Testing.cleanup! do
30
55
  example.run