cassie 1.0.0.beta.5 → 1.0.0.beta.6
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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 40bb4e39b19017fcef0127c393ccb0280c8ea6bb
|
4
|
+
data.tar.gz: 9ed902fdd76d02a30e91ccb7385d761df6e4936b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 987f316efd2e36ca612f45fc212bcd6c967dd2e3cd6840923b159a1acb1fa35448843411b14d695125b8a277a966dbbd3d0068b7cf47c40ccea5a96a63a8ad53
|
7
|
+
data.tar.gz: 34edc2ed19b618c8297a9e8a925ae26262e627b14b272c57758f33b201d5c9f56191d78d5b958bdbc6e640db05046fb3f990bbf8e1a9367c7c7c5d02002033db
|
@@ -22,7 +22,7 @@ Queries defined on the fly like this tend to create debt for an application in t
|
|
22
22
|
* resist documentation
|
23
23
|
* resist refactoring
|
24
24
|
|
25
|
-
|
25
|
+
Application queries represent distinct application behavior, `cassie` queries are designed to help create query classes that are reusable, testable and maintainable (so you can sleep better at night).
|
26
26
|
|
27
27
|
```ruby
|
28
28
|
# Some PORO user model
|
@@ -9,7 +9,11 @@ module Cassie::Queries::Logging
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def message
|
12
|
-
|
12
|
+
{
|
13
|
+
duration: duration.round(1),
|
14
|
+
query: statement,
|
15
|
+
consistency: consistency.upcase
|
16
|
+
}.extend(Inspector)
|
13
17
|
end
|
14
18
|
|
15
19
|
protected
|
@@ -45,8 +49,20 @@ module Cassie::Queries::Logging
|
|
45
49
|
execution_info.trace
|
46
50
|
end
|
47
51
|
|
48
|
-
|
49
|
-
|
52
|
+
module Inspector
|
53
|
+
def inspect
|
54
|
+
color "(#{fetch(:duration).round(1)}ms) #{fetch(:query)} [#{fetch(:consistency).upcase}]"
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
inspect
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
def color(message)
|
64
|
+
"\e[1m\e[37m#{message}\e[0m\e[22m"
|
65
|
+
end
|
50
66
|
end
|
51
67
|
end
|
52
68
|
end
|
@@ -11,6 +11,23 @@ module Cassie::Queries::Statement
|
|
11
11
|
attr_accessor :stateless_page_size
|
12
12
|
end
|
13
13
|
|
14
|
+
# Uses #fetch_in_batches with a batch size of 1000 (or as
|
15
|
+
# specified by the +:batch_size+ option) to enumerate through all
|
16
|
+
# records, while using batches to limit resource consumption.
|
17
|
+
#
|
18
|
+
# If you do not provide a block to #fetch_each, it will return an Enumerator
|
19
|
+
# for chaining with other methods.
|
20
|
+
#
|
21
|
+
# UsersByPositionQuery.fetch_each.with_index do |user, index|
|
22
|
+
# user.position = index
|
23
|
+
# UserMapper.update_position(user)
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# ==== Options
|
27
|
+
# * <tt>:batch_size</tt> - Specifies the size of the batch. Default to 1000.
|
28
|
+
#
|
29
|
+
# NOTE: Any limit specified on the query will affect the batched set.
|
30
|
+
# Cassandra internal paging is used for batching.
|
14
31
|
def fetch_each(opts={})
|
15
32
|
return to_enum(:fetch_each, opts) unless block_given?
|
16
33
|
|
@@ -28,24 +45,30 @@ module Cassie::Queries::Statement
|
|
28
45
|
# end
|
29
46
|
#
|
30
47
|
# "max score in group: 26"
|
48
|
+
#
|
49
|
+
# ==== Options
|
50
|
+
# * <tt>:batch_size</tt> - Specifies the size of the batch. Default to 1000.
|
51
|
+
#
|
52
|
+
# NOTE: Any limit specified on the query will affect the batched set.
|
53
|
+
# Cassandra internal paging is used for batching.
|
31
54
|
def fetch_in_batches(opts={})
|
32
|
-
# we want to clone the query as soon as the enumerable is
|
33
|
-
# created, not wait until the firt iteration is called
|
34
|
-
# as the client could mutate the object between these states
|
35
|
-
# but we don't want to clone twice if enumerator returned
|
36
|
-
return to_enum(:fetch_in_batches, opts.merge(_paged_query: self.clone)) unless block_given?
|
37
|
-
|
38
55
|
opts[:batch_size] ||= 1000
|
39
56
|
|
57
|
+
# clone the query as soon as the enumerable is created
|
58
|
+
# rather than waiting until the firt iteration is executed
|
59
|
+
# as the client could mutate the object between these states.
|
60
|
+
# However we don't want to clone twice if a block isn't passed
|
61
|
+
paged_query = opts.delete(:_paged_query) || self.clone
|
62
|
+
|
63
|
+
return to_enum(:fetch_in_batches, opts.merge(_paged_query: paged_query)) unless block_given?
|
64
|
+
|
40
65
|
# use Cassandra internal paging
|
41
66
|
# but clone the query to isolate it
|
42
|
-
#
|
67
|
+
# and allow all paging queries
|
43
68
|
# to execute within a Cassie::Query
|
44
69
|
# for use of other features, like logging
|
45
|
-
|
46
|
-
|
47
|
-
# set cassandra internal
|
48
|
-
# stateless page size (independent from limit)
|
70
|
+
#
|
71
|
+
# note: stateless page size is independent from limit
|
49
72
|
paged_query.stateless_page_size = opts[:batch_size]
|
50
73
|
paged_query.paging_state = nil
|
51
74
|
done = false
|
@@ -2,12 +2,12 @@ require_relative 'execution_info'
|
|
2
2
|
|
3
3
|
module Cassie::Testing::Fake
|
4
4
|
class Result
|
5
|
-
|
5
|
+
attr_reader :rows, :statement, :opts
|
6
6
|
|
7
7
|
def initialize(statement, execution_opts={})
|
8
8
|
@statement = statement
|
9
9
|
@opts = execution_opts
|
10
|
-
@rows = @opts[:rows]
|
10
|
+
@rows = @data = opts[:rows] || []
|
11
11
|
end
|
12
12
|
|
13
13
|
def execution_info
|
@@ -15,29 +15,65 @@ module Cassie::Testing::Fake
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def rows
|
18
|
-
|
18
|
+
if paging_enabled?
|
19
|
+
index = current_page - 1
|
20
|
+
offset = index * page_size
|
21
|
+
@data.slice(offset, page_size) || []
|
22
|
+
else
|
23
|
+
@data
|
24
|
+
end
|
19
25
|
end
|
20
26
|
|
21
27
|
def empty?
|
22
28
|
rows.empty?
|
23
29
|
end
|
24
30
|
|
31
|
+
def paging_enabled?
|
32
|
+
!!page_size
|
33
|
+
end
|
34
|
+
|
35
|
+
def page_size
|
36
|
+
return nil unless opts[:page_size]
|
37
|
+
opts[:page_size].to_i
|
38
|
+
end
|
39
|
+
|
40
|
+
def pages
|
41
|
+
return nil unless paging_enabled?
|
42
|
+
(@data.count / page_size.to_f).ceil
|
43
|
+
end
|
44
|
+
|
45
|
+
def previous_page
|
46
|
+
return nil unless previous_paging_state
|
47
|
+
previous_paging_state.bytes[-1]
|
48
|
+
end
|
49
|
+
|
50
|
+
def current_page
|
51
|
+
return 1 unless paging_enabled? && previous_page
|
52
|
+
previous_page + 1
|
53
|
+
end
|
54
|
+
|
25
55
|
def last_page?
|
26
|
-
return nil unless
|
27
|
-
|
28
|
-
true
|
56
|
+
return nil unless paging_enabled?
|
57
|
+
current_page == pages
|
29
58
|
end
|
30
59
|
|
31
|
-
def
|
32
|
-
|
60
|
+
def previous_paging_state
|
61
|
+
return nil unless paging_enabled?
|
62
|
+
@opts[:paging_state]
|
33
63
|
end
|
34
64
|
|
35
65
|
def paging_state
|
36
|
-
return nil unless
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
66
|
+
return nil unless paging_enabled?
|
67
|
+
if previous_paging_state
|
68
|
+
bytes = previous_paging_state.bytes
|
69
|
+
raise 'Too many pages for Cassie testing harness!' if bytes[-1] >= 256
|
70
|
+
bytes[-1] = bytes[-1] + 1
|
71
|
+
bytes.pack('c*')
|
72
|
+
else
|
73
|
+
# use last byte of state string to store pages
|
74
|
+
# presume 255 pages is enough for any testing
|
75
|
+
"paging #{SecureRandom.hex(6)}:" + [1].pack('c*')
|
76
|
+
end
|
41
77
|
end
|
42
78
|
end
|
43
79
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cassie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.beta.
|
4
|
+
version: 1.0.0.beta.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Prothro
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cassandra-driver
|