whi-cassie 1.0.6 → 1.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY.txt +4 -0
- data/README.md +5 -0
- data/VERSION +1 -1
- data/lib/cassie/model.rb +32 -0
- data/lib/cassie/subscribers.rb +53 -0
- data/lib/cassie.rb +2 -1
- data/spec/cassie/model_spec.rb +10 -0
- data/spec/cassie/subscribers_spec.rb +63 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3ebdf5f386202ccb62aa4e9f4c10599111f18f6
|
4
|
+
data.tar.gz: 15e6f8b61b24160a946f5fd521b0f20bfc258366
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d8e4275b346070a0549d52a782d3a0c403cf13c3b3d7e332469d6fa93b2335ce368e3243b2dce4b9dc49ac339bff3c7d3172095ad39298752b3eaf8808fa462
|
7
|
+
data.tar.gz: f6a73b42ef8301d095b9fa2a6910169cbfb7b42fd9b0fc1d1584c5a959b5350a1829893843179b0b8ab09116591157493778e485d544d5d39ae41c4846c9228b
|
data/HISTORY.txt
CHANGED
data/README.md
CHANGED
@@ -212,6 +212,11 @@ You can add instrumentation via subscribers to the `Cassie.instance`. Subscriber
|
|
212
212
|
Cassie.instance.subscribers << lambda{|message| logger.warn("CQL: #{message.statement.cql} with #{message.options} took #{message.elapsed_time}s") if message.elapsed_time > 0.5 && message.statement.cql}
|
213
213
|
```
|
214
214
|
|
215
|
+
You can instrument the finding code on your model by adding a find subscriber either to the model or to Cassie::Model. These subscribers take a block which is yielded to with the CQL, arguments, options, elapsed time, and rows returned.
|
216
|
+
```
|
217
|
+
Cassie::Model.find_subscribers << lambda{|message| logger.warn("CQL: #{message.cql}; Rows: #{message.rows}; Time: #{message.elapsed_time}")
|
218
|
+
```
|
219
|
+
|
215
220
|
### Limitations
|
216
221
|
|
217
222
|
Ruby 2.0 (or compatible) required.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.7
|
data/lib/cassie/model.rb
CHANGED
@@ -47,10 +47,33 @@ module Cassie::Model
|
|
47
47
|
class_attribute :_column_aliases, :instance_reader => false, :instance_writer => false
|
48
48
|
class_attribute :_ordering_keys, :instance_reader => false, :instance_writer => false
|
49
49
|
class_attribute :_counter_table, :instance_reader => false, :instance_writer => false
|
50
|
+
class_attribute :find_subscribers, :instance_reader => false, :instance_writer => false
|
50
51
|
define_model_callbacks :create, :update, :save, :destroy
|
51
52
|
self._columns = {}
|
52
53
|
self._column_aliases = HashWithIndifferentAccess.new
|
53
54
|
self._ordering_keys = {}
|
55
|
+
self.find_subscribers = Cassie::Subscribers.new(Cassie::Model.find_subscribers)
|
56
|
+
end
|
57
|
+
|
58
|
+
class << self
|
59
|
+
@@find_subscribers = Cassie::Subscribers.new
|
60
|
+
|
61
|
+
def find_subscribers
|
62
|
+
@@find_subscribers
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Message sent to find subscribers for instrumenting find operations.
|
67
|
+
class FindMessage
|
68
|
+
attr_reader :cql, :args, :options, :elapsed_time, :rows
|
69
|
+
|
70
|
+
def initialize(cql, args, options, elapsed_time, rows)
|
71
|
+
@cql = cql
|
72
|
+
@args = args
|
73
|
+
@options = options
|
74
|
+
@elapsed_time = elapsed_time
|
75
|
+
@rows = rows
|
76
|
+
end
|
54
77
|
end
|
55
78
|
|
56
79
|
module ClassMethods
|
@@ -186,6 +209,7 @@ module Cassie::Model
|
|
186
209
|
# You can provide a block to this method in which case it will yield each
|
187
210
|
# record as it is foundto the block instead of returning them.
|
188
211
|
def find_all(where:, select: nil, order: nil, limit: nil, options: nil)
|
212
|
+
start_time = Time.now
|
189
213
|
columns = (select ? Array(select).collect{|c| column_name(c)} : column_names)
|
190
214
|
cql = "SELECT #{columns.join(', ')} FROM #{full_table_name}"
|
191
215
|
values = nil
|
@@ -209,7 +233,9 @@ module Cassie::Model
|
|
209
233
|
|
210
234
|
results = connection.find(cql, values, options)
|
211
235
|
records = [] unless block_given?
|
236
|
+
row_count = 0
|
212
237
|
loop do
|
238
|
+
row_count += results.size
|
213
239
|
results.each do |row|
|
214
240
|
record = new(row)
|
215
241
|
record.instance_variable_set(:@persisted, true)
|
@@ -222,6 +248,12 @@ module Cassie::Model
|
|
222
248
|
break if results.last_page?
|
223
249
|
results = results.next_page
|
224
250
|
end
|
251
|
+
|
252
|
+
if find_subscribers && !find_subscribers.empty?
|
253
|
+
payload = FindMessage.new(cql, values, options, Time.now - start_time, row_count)
|
254
|
+
find_subscribers.each{|subscriber| subscriber.call(payload)}
|
255
|
+
end
|
256
|
+
|
225
257
|
records
|
226
258
|
end
|
227
259
|
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Thread safe list of subscribers. Each subscriber must respond to the :call method.
|
2
|
+
class Cassie::Subscribers
|
3
|
+
|
4
|
+
def initialize(parent_subscribers = nil)
|
5
|
+
@array = [].freeze
|
6
|
+
@lock = Mutex.new
|
7
|
+
@parent_subscribers = parent_subscribers
|
8
|
+
end
|
9
|
+
|
10
|
+
def add(subscriber)
|
11
|
+
@lock.synchronize do
|
12
|
+
new_array = @array.dup
|
13
|
+
new_array << subscriber
|
14
|
+
@array = new_array
|
15
|
+
end
|
16
|
+
end
|
17
|
+
alias_method :<<, :add
|
18
|
+
|
19
|
+
def remove(subscriber)
|
20
|
+
removed = nil
|
21
|
+
@lock.synchronize do
|
22
|
+
new_array = @array.dup
|
23
|
+
removed = new_array.delete(subscriber)
|
24
|
+
@array = new_array
|
25
|
+
end
|
26
|
+
removed
|
27
|
+
end
|
28
|
+
alias_method :delete, :remove
|
29
|
+
|
30
|
+
def clear
|
31
|
+
@array = []
|
32
|
+
end
|
33
|
+
|
34
|
+
def size
|
35
|
+
@array.size + (@parent_subscribers ? @parent_subscribers.size : 0)
|
36
|
+
end
|
37
|
+
|
38
|
+
def empty?
|
39
|
+
size == 0
|
40
|
+
end
|
41
|
+
|
42
|
+
def each(&block)
|
43
|
+
@array.each(&block)
|
44
|
+
if @parent_subscribers
|
45
|
+
@parent_subscribers.each(&block)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def include?(subscriber)
|
50
|
+
@array.include?(subscriber)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/lib/cassie.rb
CHANGED
@@ -4,6 +4,7 @@ require 'cassandra'
|
|
4
4
|
# a foundation for maintaining a connection and constructing CQL statements.
|
5
5
|
class Cassie
|
6
6
|
require File.expand_path("../cassie/config.rb", __FILE__)
|
7
|
+
require File.expand_path("../cassie/subscribers.rb", __FILE__)
|
7
8
|
require File.expand_path("../cassie/model.rb", __FILE__)
|
8
9
|
require File.expand_path("../cassie/schema.rb", __FILE__)
|
9
10
|
require File.expand_path("../cassie/testing.rb", __FILE__)
|
@@ -88,7 +89,7 @@ class Cassie
|
|
88
89
|
@session = nil
|
89
90
|
@prepared_statements = {}
|
90
91
|
@last_prepare_warning = Time.now
|
91
|
-
@subscribers =
|
92
|
+
@subscribers = Subscribers.new
|
92
93
|
end
|
93
94
|
|
94
95
|
# Open a connection to the Cassandra cluster.
|
data/spec/cassie/model_spec.rb
CHANGED
@@ -100,6 +100,16 @@ describe Cassie::Model do
|
|
100
100
|
expect{ Cassie::Thing.find_all(where: {}) }.to raise_error(ArgumentError)
|
101
101
|
Cassie::Thing.find_all(where: :all).size.should == 3
|
102
102
|
end
|
103
|
+
|
104
|
+
it "should be able to add subscribers" do
|
105
|
+
global = nil
|
106
|
+
local = nil
|
107
|
+
Cassie::Model.find_subscribers << lambda{|info| global = info.rows}
|
108
|
+
Cassie::Thing.find_subscribers << lambda{|info| local = info.rows}
|
109
|
+
Cassie::Thing.find_all(where: {:owner => 1}).size.should == 2
|
110
|
+
global.should == 2
|
111
|
+
local.should == 2
|
112
|
+
end
|
103
113
|
end
|
104
114
|
|
105
115
|
describe "offset_to_id" do
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cassie::Subscribers do
|
4
|
+
|
5
|
+
it "should be able to add and remove a subscriber" do
|
6
|
+
subscribers = Cassie::Subscribers.new
|
7
|
+
expect(subscribers.empty?).to eq true
|
8
|
+
data_1 = []
|
9
|
+
data_2 = []
|
10
|
+
subscriber_1 = lambda{|info| data_1 << info}
|
11
|
+
subscriber_2 = lambda{|info| data_2 << info}
|
12
|
+
subscribers.add(subscriber_1)
|
13
|
+
subscribers << subscriber_2
|
14
|
+
expect(subscribers.empty?).to eq false
|
15
|
+
expect(subscribers.size).to eq 2
|
16
|
+
expect(subscribers.include?(subscriber_1)).to eq true
|
17
|
+
expect(subscribers.include?(subscriber_2)).to eq true
|
18
|
+
|
19
|
+
subscribers.each{|s| s.call(:payload)}
|
20
|
+
expect(data_1).to eq [:payload]
|
21
|
+
expect(data_2).to eq [:payload]
|
22
|
+
|
23
|
+
subscribers.remove(subscriber_2)
|
24
|
+
expect(subscribers.size).to eq 1
|
25
|
+
expect(subscribers.include?(subscriber_1)).to eq true
|
26
|
+
expect(subscribers.include?(subscriber_2)).to eq false
|
27
|
+
|
28
|
+
subscribers.each{|s| s.call(:more)}
|
29
|
+
expect(data_1).to eq [:payload, :more]
|
30
|
+
expect(data_2).to eq [:payload]
|
31
|
+
|
32
|
+
subscribers.delete(subscriber_1)
|
33
|
+
expect(subscribers.size).to eq 0
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should have a hierarchy of subscribers" do
|
37
|
+
subscribers_1 = Cassie::Subscribers.new
|
38
|
+
subscribers_2 = Cassie::Subscribers.new(subscribers_1)
|
39
|
+
subscribers_3 = Cassie::Subscribers.new(subscribers_1)
|
40
|
+
data_1 = []
|
41
|
+
data_2 = []
|
42
|
+
data_3 = []
|
43
|
+
subscribers_1 << lambda{|info| data_1 << info}
|
44
|
+
subscribers_2 << lambda{|info| data_2 << info}
|
45
|
+
|
46
|
+
expect(subscribers_1.size).to eq 1
|
47
|
+
expect(subscribers_2.size).to eq 2
|
48
|
+
expect(subscribers_3.size).to eq 1
|
49
|
+
|
50
|
+
subscribers_1.each{|subscriber| subscriber.call(:payload_1)}
|
51
|
+
subscribers_2.each{|subscriber| subscriber.call(:payload_2)}
|
52
|
+
subscribers_3.each{|subscriber| subscriber.call(:payload_3)}
|
53
|
+
|
54
|
+
expect(data_1).to eq [:payload_1, :payload_2, :payload_3]
|
55
|
+
expect(data_2).to eq [:payload_2]
|
56
|
+
|
57
|
+
subscribers_2.clear
|
58
|
+
expect(subscribers_2.size).to eq 1
|
59
|
+
subscribers_1.clear
|
60
|
+
expect(subscribers_2.size).to eq 0
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: whi-cassie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- We Heart It
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-06-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: cassandra-driver
|
@@ -99,10 +99,12 @@ files:
|
|
99
99
|
- lib/cassie/model.rb
|
100
100
|
- lib/cassie/railtie.rb
|
101
101
|
- lib/cassie/schema.rb
|
102
|
+
- lib/cassie/subscribers.rb
|
102
103
|
- lib/cassie/testing.rb
|
103
104
|
- lib/whi-cassie.rb
|
104
105
|
- spec/cassie/config_spec.rb
|
105
106
|
- spec/cassie/model_spec.rb
|
107
|
+
- spec/cassie/subscribers_spec.rb
|
106
108
|
- spec/cassie_spec.rb
|
107
109
|
- spec/models/thing.rb
|
108
110
|
- spec/models/type_tester.rb
|
@@ -137,6 +139,7 @@ summary: Simple object mapper for Cassandra data tables specifically designed to
|
|
137
139
|
test_files:
|
138
140
|
- spec/cassie/config_spec.rb
|
139
141
|
- spec/cassie/model_spec.rb
|
142
|
+
- spec/cassie/subscribers_spec.rb
|
140
143
|
- spec/cassie_spec.rb
|
141
144
|
- spec/models/thing.rb
|
142
145
|
- spec/models/type_tester.rb
|