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.
- checksums.yaml +5 -5
- data/.github/dependabot.yml +12 -0
- data/.github/workflows/continuous_integration.yml +63 -0
- data/.gitignore +4 -15
- data/.standard.yml +11 -0
- data/Appraisals +13 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +89 -0
- data/HISTORY.md +49 -0
- data/README.md +30 -11
- data/Rakefile +13 -12
- data/VERSION +1 -1
- data/gemfiles/activemodel_4.gemfile +14 -0
- data/gemfiles/activemodel_5.gemfile +14 -0
- data/gemfiles/activemodel_6.gemfile +14 -0
- data/lib/cassie.rb +84 -62
- data/lib/cassie/config.rb +8 -7
- data/lib/cassie/model.rb +162 -107
- data/lib/cassie/railtie.rb +7 -5
- data/lib/cassie/schema.rb +35 -28
- data/lib/cassie/subscribers.rb +51 -0
- data/lib/cassie/testing.rb +22 -20
- data/lib/whi-cassie.rb +2 -0
- data/spec/cassie/config_spec.rb +20 -22
- data/spec/cassie/model_spec.rb +342 -275
- data/spec/cassie/subscribers_spec.rb +61 -0
- data/spec/cassie_spec.rb +116 -71
- data/spec/models/thing.rb +13 -11
- data/spec/models/type_tester.rb +7 -7
- data/spec/spec_helper.rb +35 -10
- data/whi-cassie.gemspec +16 -19
- metadata +21 -38
- data/HISTORY.txt +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cc03cb8a9fdac75018c3c31a5466a681a7e57f4584c5d3c4540d012da48c8bc9
|
4
|
+
data.tar.gz: 7576c9d2d998329cc918cc8c7dad45eda0012d420c123b7cfb9412c82873ab24
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c60020caa9c11330c2c5713bbd0962cf1682f07f351815b60975b608af50031627a08c27d50e1175ffc02d44da368cc64e71f7a337164cf1dddd75da415e6dc6
|
7
|
+
data.tar.gz: 2690d2fb060d226a11d81cba9db78251bce6ca0a744e27ddd1975e82b2db7376bc247c58b6a1af895da0b81a2d21e1e3b6f3eda64234e52a973b3d0ce221743b
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# Dependabot update strategy
|
2
|
+
version: 2
|
3
|
+
updates:
|
4
|
+
- package-ecosystem: bundler
|
5
|
+
directory: "/"
|
6
|
+
schedule:
|
7
|
+
interval: daily
|
8
|
+
allow:
|
9
|
+
# Automatically keep all runtime dependencies updated
|
10
|
+
- dependency-name: "*"
|
11
|
+
dependency-type: "production"
|
12
|
+
versioning-strategy: lockfile-only
|
@@ -0,0 +1,63 @@
|
|
1
|
+
name: Continuous Integration
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches:
|
5
|
+
- master
|
6
|
+
- actions-*
|
7
|
+
tags:
|
8
|
+
- v*
|
9
|
+
pull_request:
|
10
|
+
env:
|
11
|
+
BUNDLE_CLEAN: "true"
|
12
|
+
BUNDLE_PATH: vendor/bundle
|
13
|
+
BUNDLE_JOBS: 3
|
14
|
+
BUNDLE_RETRY: 3
|
15
|
+
jobs:
|
16
|
+
specs:
|
17
|
+
name: ${{ matrix.job }} ruby-${{ matrix.ruby }} ${{ matrix.activemodel && format('activemodel-{0}', matrix.activemodel) }} cassandra-${{ matrix.cassandra_version }}
|
18
|
+
runs-on: ubuntu-latest
|
19
|
+
services:
|
20
|
+
cassandra:
|
21
|
+
image: cassandra:${{ matrix.cassandra_version }}
|
22
|
+
ports:
|
23
|
+
- 9042:9042
|
24
|
+
strategy:
|
25
|
+
fail-fast: false
|
26
|
+
matrix:
|
27
|
+
ruby: [2.7]
|
28
|
+
activemodel: [6]
|
29
|
+
job: [rspec]
|
30
|
+
cassandra_version: ["4.0"]
|
31
|
+
include:
|
32
|
+
- ruby: 2.6
|
33
|
+
activemodel: 5
|
34
|
+
job: rspec
|
35
|
+
cassandra_version: "3"
|
36
|
+
- ruby: 2.4
|
37
|
+
activemodel: 4
|
38
|
+
job: rspec
|
39
|
+
cassandra_version: "2"
|
40
|
+
- ruby: 2.7
|
41
|
+
job: standardrb
|
42
|
+
cassandra_version: "latest"
|
43
|
+
steps:
|
44
|
+
- name: checkout
|
45
|
+
uses: actions/checkout@v2
|
46
|
+
- name: set up Ruby
|
47
|
+
uses: ruby/setup-ruby@v1
|
48
|
+
with:
|
49
|
+
ruby-version: ${{ matrix.ruby }}
|
50
|
+
- name: inject activemodel ${{ matrix.activemodel }}
|
51
|
+
if: matrix.activemodel != 'original' && matrix.activemodel != null
|
52
|
+
run: | # inject a specific version of activemodel into the Gemfile
|
53
|
+
bundle update
|
54
|
+
bundle exec appraisal generate
|
55
|
+
bundle config set gemfile "gemfiles/activemodel_${{ matrix.activemodel }}.gemfile"
|
56
|
+
- name: install dependencies
|
57
|
+
run: bundle install
|
58
|
+
- name: specs
|
59
|
+
if: matrix.job == 'rspec'
|
60
|
+
run: bundle exec rake spec
|
61
|
+
- name: standardrb
|
62
|
+
if: matrix.job == 'standardrb'
|
63
|
+
run: bundle exec rake standard
|
data/.gitignore
CHANGED
data/.standard.yml
ADDED
data/Appraisals
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
whi-cassie (1.2.0)
|
5
|
+
activemodel (>= 4.0)
|
6
|
+
cassandra-driver (~> 3.0)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
activemodel (6.0.3.4)
|
12
|
+
activesupport (= 6.0.3.4)
|
13
|
+
activesupport (6.0.3.4)
|
14
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
15
|
+
i18n (>= 0.7, < 2)
|
16
|
+
minitest (~> 5.1)
|
17
|
+
tzinfo (~> 1.1)
|
18
|
+
zeitwerk (~> 2.2, >= 2.2.2)
|
19
|
+
appraisal (2.3.0)
|
20
|
+
bundler
|
21
|
+
rake
|
22
|
+
thor (>= 0.14.0)
|
23
|
+
ast (2.4.1)
|
24
|
+
cassandra-driver (3.2.5)
|
25
|
+
ione (~> 1.2)
|
26
|
+
concurrent-ruby (1.1.7)
|
27
|
+
diff-lcs (1.4.4)
|
28
|
+
i18n (1.8.5)
|
29
|
+
concurrent-ruby (~> 1.0)
|
30
|
+
ione (1.2.4)
|
31
|
+
minitest (5.14.2)
|
32
|
+
parallel (1.19.2)
|
33
|
+
parser (2.7.2.0)
|
34
|
+
ast (~> 2.4.1)
|
35
|
+
rainbow (3.0.0)
|
36
|
+
rake (13.0.1)
|
37
|
+
regexp_parser (1.8.2)
|
38
|
+
rexml (3.2.4)
|
39
|
+
rspec (3.9.0)
|
40
|
+
rspec-core (~> 3.9.0)
|
41
|
+
rspec-expectations (~> 3.9.0)
|
42
|
+
rspec-mocks (~> 3.9.0)
|
43
|
+
rspec-core (3.9.3)
|
44
|
+
rspec-support (~> 3.9.3)
|
45
|
+
rspec-expectations (3.9.3)
|
46
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
47
|
+
rspec-support (~> 3.9.0)
|
48
|
+
rspec-mocks (3.9.1)
|
49
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
50
|
+
rspec-support (~> 3.9.0)
|
51
|
+
rspec-support (3.9.4)
|
52
|
+
rubocop (1.0.0)
|
53
|
+
parallel (~> 1.10)
|
54
|
+
parser (>= 2.7.1.5)
|
55
|
+
rainbow (>= 2.2.2, < 4.0)
|
56
|
+
regexp_parser (>= 1.8)
|
57
|
+
rexml
|
58
|
+
rubocop-ast (>= 0.6.0)
|
59
|
+
ruby-progressbar (~> 1.7)
|
60
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
61
|
+
rubocop-ast (1.1.0)
|
62
|
+
parser (>= 2.7.1.5)
|
63
|
+
rubocop-performance (1.8.1)
|
64
|
+
rubocop (>= 0.87.0)
|
65
|
+
rubocop-ast (>= 0.4.0)
|
66
|
+
ruby-progressbar (1.10.1)
|
67
|
+
standard (0.8.1)
|
68
|
+
rubocop (= 1.0.0)
|
69
|
+
rubocop-performance (= 1.8.1)
|
70
|
+
thor (1.0.1)
|
71
|
+
thread_safe (0.3.6)
|
72
|
+
tzinfo (1.2.7)
|
73
|
+
thread_safe (~> 0.1)
|
74
|
+
unicode-display_width (1.7.0)
|
75
|
+
zeitwerk (2.4.0)
|
76
|
+
|
77
|
+
PLATFORMS
|
78
|
+
ruby
|
79
|
+
|
80
|
+
DEPENDENCIES
|
81
|
+
appraisal
|
82
|
+
bundler (~> 2.0)
|
83
|
+
rake
|
84
|
+
rspec
|
85
|
+
standard (~> 0.8.1)
|
86
|
+
whi-cassie!
|
87
|
+
|
88
|
+
BUNDLED WITH
|
89
|
+
2.1.4
|
data/HISTORY.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
## 1.2.0
|
2
|
+
|
3
|
+
* Update schema queries to support Cassandra 3.x+
|
4
|
+
* Require Ruby 2.4 or greater
|
5
|
+
|
6
|
+
## 1.1.1
|
7
|
+
* Update dependencies to support Rails 5.
|
8
|
+
|
9
|
+
## 1.1.0
|
10
|
+
|
11
|
+
* Bump supported version of cassandra-driver to 3.x.
|
12
|
+
|
13
|
+
* Add more control over consistency settings.
|
14
|
+
|
15
|
+
* Add read and write consistency on model definitions.
|
16
|
+
|
17
|
+
## 1.0.7
|
18
|
+
|
19
|
+
* Add find_subscribers to Cassie::Model for instrumenting model find calls.
|
20
|
+
|
21
|
+
## 1.0.6
|
22
|
+
|
23
|
+
* Wrap raw CQL in a Simple statement for code consistency in subscribers.
|
24
|
+
|
25
|
+
## 1.0.5
|
26
|
+
|
27
|
+
* Add subscribers for instumenting code.
|
28
|
+
|
29
|
+
* Remove hardcoded log warnings for long running statements since this can now be better handled with instrumentation.
|
30
|
+
|
31
|
+
## 1.0.4
|
32
|
+
|
33
|
+
* Set less cryptic error message for invalid records exceptions.
|
34
|
+
|
35
|
+
## 1.0.3
|
36
|
+
|
37
|
+
* Fix bugs preventing counter and set data types from working on models.
|
38
|
+
|
39
|
+
## 1.0.2
|
40
|
+
|
41
|
+
* Set cluster logger on the Cassandra cluster if not already set.
|
42
|
+
|
43
|
+
## 1.0.1
|
44
|
+
|
45
|
+
* Allow finding the offset to the row from a range.
|
46
|
+
|
47
|
+
## 1.0.0
|
48
|
+
|
49
|
+
* Initial Release
|
data/README.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
![Continuous Integration](https://github.com/weheartit/cassie/workflows/Continuous%20Integration/badge.svg)
|
2
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/129ede20094ea298c687/maintainability)](https://codeclimate.com/github/weheartit/cassie/maintainability)
|
3
|
+
[![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
|
4
|
+
|
1
5
|
# Cassie
|
2
6
|
|
3
7
|
The short and sweet Cassandra object mapper from [We Heart It](http://weheartit.com/)
|
@@ -8,34 +12,34 @@ The short and sweet Cassandra object mapper from [We Heart It](http://weheartit.
|
|
8
12
|
class Thing
|
9
13
|
# Your model must include this
|
10
14
|
include Cassie::Model
|
11
|
-
|
15
|
+
|
12
16
|
# Set the table name where the data lives.
|
13
17
|
self.table_name = "things"
|
14
|
-
|
18
|
+
|
15
19
|
# Set the keyspace where the table lives. Keyspaces can be defined abstractly and mapped
|
16
20
|
# and mapped in a configuration file. This can allow you to have different keyspace names
|
17
21
|
# between different environments and still use the same code.
|
18
22
|
self.keyspace = "default"
|
19
|
-
|
23
|
+
|
20
24
|
# You must defind the primary key. They columns must be listed in the order that they apper
|
21
25
|
# in the Cassandra CQL PRIMARY KEY clause defining the table.
|
22
26
|
self.primary_key = [:owner, :id]
|
23
|
-
|
27
|
+
|
24
28
|
# All columns are explicitly defined with their name and data type and an optional
|
25
29
|
# alias name.
|
26
30
|
column :owner, :int
|
27
31
|
column :id, :int, :as => :identifier
|
28
32
|
column :val, :varchar, :as => :value
|
29
|
-
|
33
|
+
|
30
34
|
# The ordering keys should also be defined along with how they are ordered.
|
31
35
|
ordering_key :id, :desc
|
32
|
-
|
36
|
+
|
33
37
|
# You can use all the standard ActiveModel validations.
|
34
38
|
validates_presence_of :owner, :id
|
35
|
-
|
39
|
+
|
36
40
|
# You also get before and after callbacks for create, update, save, and destroy.
|
37
41
|
before_save :some_callback_method
|
38
|
-
|
42
|
+
|
39
43
|
...
|
40
44
|
end
|
41
45
|
|
@@ -83,7 +87,17 @@ You can use all the standard ActiveModel validation methods on your models. You
|
|
83
87
|
Note that one difference between Cassandra and other data stores is that data is only eventually consistent. Some subtle results of this:
|
84
88
|
|
85
89
|
1. You won't get an error if you try to create a record with the same primary key twice. Cassandra will simple use the second insert as an update statement.
|
86
|
-
2. If you perform any queries in your validation logic (e.g. to ensure a value is unique), you really need to use a high consistency level like quorum. If you use a low consistency level, there is a chance that your query can hit a node in the cluster that hasn't been replicated to and your validation could make decisions based on the wrong data.
|
90
|
+
2. If you perform any queries in your validation logic (e.g. to ensure a value is unique), you really need to use a high consistency level like quorum. If you use a low consistency level, there is a chance that your query can hit a node in the cluster that hasn't been replicated to and your validation could make decisions based on the wrong data.
|
91
|
+
|
92
|
+
### Consistency
|
93
|
+
|
94
|
+
You can specify the consistency for the connection when it is created in the options. This will default to `:local_one`. You can override the global consistency at runtime by setting a new consistency on the instance `Cassie.instance.consistency = :local_quorum`. This will be the default consistency used if nothing else specifies a consistency.
|
95
|
+
|
96
|
+
You can override the default consistency within a block by using the `Cassie.consistency` method. This method will set the default consistency within a block and can be used in instances where you want to force a specific consistency on all queries within a specific scope.
|
97
|
+
|
98
|
+
Finally, you can force a specific consistency by specifying `:consistency` in the options to any of the statements that execute a query. This consistency will override any default consistency you've specified. However, if the statement is a write statement and is wrapped in a batch block, the consistency option will have no effect. You can, though, specify the `:consistency` option in the `batch` call to apply a consistency to all statements in the batch.
|
99
|
+
|
100
|
+
In `Cassie::Model` classes, you can specify `read_consistency` and `write_consistency` that will be applied to all statements generated by the model. You could use this, for instance, to force all write operations to use `:quorum` while letting all read operations user `:one`. These consistency levels will override any default levels if they are set.
|
87
101
|
|
88
102
|
### Prepared statements
|
89
103
|
|
@@ -166,13 +180,13 @@ To use it with rspec you should add this code to your spec_helper.rb file:
|
|
166
180
|
end
|
167
181
|
Cassie::Testing.prepare!
|
168
182
|
end
|
169
|
-
|
183
|
+
|
170
184
|
config.after(:suite) do
|
171
185
|
Cassie::Schema.all do |keyspace|
|
172
186
|
Cassie::Schema.drop!(keyspace)
|
173
187
|
end
|
174
188
|
end
|
175
|
-
|
189
|
+
|
176
190
|
config.around(:each) do |example|
|
177
191
|
Cassie::Testing.cleanup! do
|
178
192
|
example.run
|
@@ -212,6 +226,11 @@ You can add instrumentation via subscribers to the `Cassie.instance`. Subscriber
|
|
212
226
|
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
227
|
```
|
214
228
|
|
229
|
+
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.
|
230
|
+
```
|
231
|
+
Cassie::Model.find_subscribers << lambda{|message| logger.warn("CQL: #{message.cql}; Rows: #{message.rows}; Time: #{message.elapsed_time}")
|
232
|
+
```
|
233
|
+
|
215
234
|
### Limitations
|
216
235
|
|
217
236
|
Ruby 2.0 (or compatible) required.
|
data/Rakefile
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
require "standard/rake"
|
2
4
|
|
3
|
-
|
4
|
-
task :default => :test
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
6
|
|
6
|
-
|
7
|
-
task :tests => :test
|
7
|
+
task default: :spec
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
desc "run the specs using appraisal"
|
10
|
+
task :appraisals do
|
11
|
+
exec "bundle exec appraisal rake spec"
|
12
|
+
end
|
13
|
+
|
14
|
+
namespace :appraisals do
|
15
|
+
desc "install all the appraisal gemspecs"
|
16
|
+
task :install do
|
17
|
+
exec "bundle exec appraisal install"
|
17
18
|
end
|
18
19
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0
|
1
|
+
1.2.0
|