extendi-cassandra_object 1.0.17 → 1.0.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +24 -9
- data/README.md +16 -18
- data/extendi-cassandra_object.gemspec +2 -2
- data/lib/cassandra_object/adapters/cassandra_adapter.rb +27 -22
- data/lib/cassandra_object/adapters/cassandra_schemaless_adapter.rb +31 -25
- data/lib/cassandra_object/attribute_methods.rb +2 -2
- data/lib/cassandra_object/persistence.rb +1 -1
- data/lib/cassandra_object/timestamps.rb +5 -1
- data/test/unit/timestamps_test.rb +24 -1
- metadata +13 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35c334a18f8c02dcc3fa80aedd61b32d750ad798199d4ead39c4fc5948cf6bc8
|
4
|
+
data.tar.gz: 5d31df130a07772d2334d0c8dc97d14cfd6dd6e7d2bf3f5369d5d84206698a34
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4dce7aed3855ebacfef2b79df27b0b598ca3f7caaa144e468560acbf1b823435ed3564ecd12922909fda502f5f2db69562823fd4e304a533a13af5cf9352d339
|
7
|
+
data.tar.gz: f78455454cb989f92c9190a6c421570e3cbd402b7aa3613aa18d4a334c038ef65b3dafa054b477c0c5d7e5ddf9c587893cf1a69db4489f2aa6e8050b528efd30
|
data/.travis.yml
CHANGED
@@ -1,20 +1,21 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- 2.4.0
|
4
|
-
- 2.4.1
|
5
|
-
- 2.4.2
|
6
3
|
- 2.5.1
|
4
|
+
- 2.6.1
|
7
5
|
env:
|
8
|
-
-
|
6
|
+
- SCYLLA_VERSION=3.0.2
|
9
7
|
- CASSANDRA_VERSION=3.0.10
|
10
8
|
- CASSANDRA_VERSION=3.9
|
11
|
-
-
|
9
|
+
- SCYLLA_VERSION=3.0.2 ACTIVEMODEL_VERSION='< 5'
|
12
10
|
- CASSANDRA_VERSION=3.0.10 ACTIVEMODEL_VERSION='< 5'
|
13
11
|
- CASSANDRA_VERSION=3.9 ACTIVEMODEL_VERSION='< 5'
|
14
12
|
|
15
13
|
jdk:
|
16
14
|
- oraclejdk8
|
17
15
|
|
16
|
+
services:
|
17
|
+
- docker
|
18
|
+
|
18
19
|
before_install:
|
19
20
|
- sudo apt-get install libjna-java
|
20
21
|
- sudo apt-get install python-support
|
@@ -23,7 +24,21 @@ before_install:
|
|
23
24
|
- sudo pip install ccm
|
24
25
|
|
25
26
|
install:
|
26
|
-
-
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
- |
|
28
|
+
if [ -n "$CASSANDRA_VERSION" ];then
|
29
|
+
ccm create -n 1 -v $CASSANDRA_VERSION -i 127.0.0. -s -b test-cluster;
|
30
|
+
ccm start;
|
31
|
+
fi
|
32
|
+
if [ -n "$SCYLLA_VERSION" ];then
|
33
|
+
SCYLLA_IMAGE=scylladb/scylla:$SCYLLA_VERSION
|
34
|
+
docker pull $SCYLLA_IMAGE
|
35
|
+
docker run --name cassandra_test -d -p "9042:9042" -p "9160:9160" $SCYLLA_IMAGE
|
36
|
+
function check_scylla(){ docker exec -it cassandra_test nodetool status | grep UN; }
|
37
|
+
until check_scylla; do
|
38
|
+
echo "waiting..."
|
39
|
+
done
|
40
|
+
fi
|
41
|
+
if [ -n "$ACTIVEMODEL_VERSION" ];then
|
42
|
+
bundle add activemodel --version "$ACTIVEMODEL_VERSION";
|
43
|
+
fi
|
44
|
+
bundle install
|
data/README.md
CHANGED
@@ -11,22 +11,20 @@ CREATE TABLE keyspace.table (
|
|
11
11
|
column1 text,
|
12
12
|
value blob,
|
13
13
|
PRIMARY KEY (key, column1)
|
14
|
-
) WITH
|
15
|
-
|
16
|
-
AND CLUSTERING ORDER BY (column1 ASC)
|
17
|
-
AND bloom_filter_fp_chance = 0.001
|
18
|
-
AND caching = '{"keys":"ALL", "rows_per_partition":"NONE"}'
|
14
|
+
) WITH bloom_filter_fp_chance = 0.01
|
15
|
+
AND caching = {'keys': 'ALL', 'rows_per_partition': 'ALL'}
|
19
16
|
AND comment = ''
|
20
|
-
AND compaction = {'
|
21
|
-
AND compression = {'
|
22
|
-
AND
|
17
|
+
AND compaction = {'class': 'SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
|
18
|
+
AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
|
19
|
+
AND crc_check_chance = 1.0
|
20
|
+
AND dclocal_read_repair_chance = 0.1
|
23
21
|
AND default_time_to_live = 0
|
24
22
|
AND gc_grace_seconds = 864000
|
25
23
|
AND max_index_interval = 2048
|
26
24
|
AND memtable_flush_period_in_ms = 0
|
27
25
|
AND min_index_interval = 128
|
28
|
-
AND read_repair_chance =
|
29
|
-
AND speculative_retry = '
|
26
|
+
AND read_repair_chance = 0.0
|
27
|
+
AND speculative_retry = '99.0PERCENTILE';
|
30
28
|
```
|
31
29
|
|
32
30
|
You can also use the a custom schema structure with the possible options at [this link](https://docs.datastax.com/en/cql/3.3/cql/cql_reference/cqlCreateTable.html#tabProp):
|
@@ -39,20 +37,20 @@ CREATE TABLE keyspace.table (
|
|
39
37
|
field2 varchar,
|
40
38
|
field3 float,
|
41
39
|
PRIMARY KEY (key)
|
42
|
-
) WITH
|
43
|
-
|
44
|
-
AND caching = {'keys':'ALL', 'rows_per_partition':'NONE'}'
|
40
|
+
) WITH bloom_filter_fp_chance = 0.01
|
41
|
+
AND caching = {'keys': 'ALL', 'rows_per_partition': 'ALL'}
|
45
42
|
AND comment = ''
|
46
|
-
AND compaction = {'
|
47
|
-
AND compression = {'
|
48
|
-
AND
|
43
|
+
AND compaction = {'class': 'SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
|
44
|
+
AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
|
45
|
+
AND crc_check_chance = 1.0
|
46
|
+
AND dclocal_read_repair_chance = 0.1
|
49
47
|
AND default_time_to_live = 0
|
50
48
|
AND gc_grace_seconds = 864000
|
51
49
|
AND max_index_interval = 2048
|
52
50
|
AND memtable_flush_period_in_ms = 0
|
53
51
|
AND min_index_interval = 128
|
54
|
-
AND read_repair_chance =
|
55
|
-
AND speculative_retry = '
|
52
|
+
AND read_repair_chance = 0.0
|
53
|
+
AND speculative_retry = '99.0PERCENTILE';
|
56
54
|
```
|
57
55
|
|
58
56
|
## Installation
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'extendi-cassandra_object'
|
5
|
-
s.version = '1.0.
|
5
|
+
s.version = '1.0.18'
|
6
6
|
s.description = 'Cassandra ActiveModel'
|
7
7
|
s.summary = 'Cassandra ActiveModel'
|
8
8
|
s.authors = ['Duccio Giovannelli', 'gotime']
|
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.test_files = `git ls-files -- {test}/*`.split("\n")
|
18
18
|
s.require_paths = ['lib']
|
19
19
|
|
20
|
-
s.add_runtime_dependency('activemodel', '
|
20
|
+
s.add_runtime_dependency('activemodel', '>= 4.2.0', '< 6.0.0')
|
21
21
|
s.add_runtime_dependency('cassandra-driver', '>= 3.2.3')
|
22
22
|
s.add_runtime_dependency('lz4-ruby', '>= 0.3.3')
|
23
23
|
|
@@ -30,19 +30,24 @@ module CassandraObject
|
|
30
30
|
str << "ALLOW FILTERING" if @scope.klass.allow_filtering
|
31
31
|
return [] << str.delete_if(&:blank?) * ' '
|
32
32
|
end
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
33
|
+
|
34
|
+
str = [
|
35
|
+
"SELECT #{select_string} FROM #{@scope.klass.column_family}",
|
36
|
+
where_string_async(@scope.id_values)
|
37
|
+
]
|
38
|
+
str << 'ALLOW FILTERING' if @scope.klass.allow_filtering
|
39
|
+
[str.delete_if(&:blank?) * ' ']
|
41
40
|
end
|
42
41
|
|
43
|
-
def where_string_async(
|
42
|
+
def where_string_async(ids)
|
44
43
|
wheres = @scope.where_values.dup.select.each_with_index { |_, i| i.even? }
|
45
|
-
|
44
|
+
if ids.present?
|
45
|
+
wheres << if ids.size > 1
|
46
|
+
"#{@scope._key} IN (#{ids.map { |id| "'#{id}'" }.join(',')})"
|
47
|
+
else
|
48
|
+
"#{@scope._key} = '#{ids.first}'"
|
49
|
+
end
|
50
|
+
end
|
46
51
|
"WHERE #{wheres * ' AND '}" if wheres.any?
|
47
52
|
end
|
48
53
|
end
|
@@ -266,7 +271,7 @@ module CassandraObject
|
|
266
271
|
AND caching = '{\"keys\":\"ALL\", \"rows_per_partition\":\"NONE\"}'
|
267
272
|
AND comment = ''
|
268
273
|
AND compaction = {'min_sstable_size': '52428800', 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy'}
|
269
|
-
AND compression = {'chunk_length_kb': '64', '
|
274
|
+
AND compression = {'chunk_length_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
|
270
275
|
AND dclocal_read_repair_chance = 0.0
|
271
276
|
AND default_time_to_live = 0
|
272
277
|
AND gc_grace_seconds = 864000
|
@@ -276,24 +281,24 @@ module CassandraObject
|
|
276
281
|
AND read_repair_chance = 1.0
|
277
282
|
AND speculative_retry = 'NONE';"
|
278
283
|
else
|
279
|
-
"#{stmt} WITH
|
280
|
-
AND
|
281
|
-
AND gc_grace_seconds = 864000
|
282
|
-
AND bloom_filter_fp_chance = 0.01
|
283
|
-
AND caching = { 'keys' : 'ALL', 'rows_per_partition' : 'NONE' }
|
284
|
+
"#{stmt} WITH bloom_filter_fp_chance = 0.01
|
285
|
+
AND caching = {'keys': 'ALL', 'rows_per_partition': 'ALL'}
|
284
286
|
AND comment = ''
|
285
|
-
AND compaction = {
|
286
|
-
AND compression = {
|
287
|
+
AND compaction = {'class': 'SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
|
288
|
+
AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
|
289
|
+
AND crc_check_chance = 1.0
|
290
|
+
AND dclocal_read_repair_chance = 0.1
|
287
291
|
AND default_time_to_live = 0
|
288
|
-
AND
|
289
|
-
AND min_index_interval = 128
|
292
|
+
AND gc_grace_seconds = 864000
|
290
293
|
AND max_index_interval = 2048
|
291
|
-
AND
|
294
|
+
AND memtable_flush_period_in_ms = 0
|
295
|
+
AND min_index_interval = 128
|
296
|
+
AND read_repair_chance = 0.0
|
297
|
+
AND speculative_retry = '99.0PERCENTILE';
|
292
298
|
"
|
293
299
|
end
|
294
300
|
end
|
295
301
|
end
|
296
|
-
|
297
302
|
end
|
298
303
|
end
|
299
304
|
end
|
@@ -26,34 +26,39 @@ module CassandraObject
|
|
26
26
|
|
27
27
|
if @scope.id_values.empty?
|
28
28
|
str = [
|
29
|
-
|
30
|
-
|
29
|
+
"SELECT #{select_string} FROM #{@scope.klass.column_family}",
|
30
|
+
where_string_async(nil)
|
31
31
|
]
|
32
32
|
str << 'ALLOW FILTERING' if @scope.klass.allow_filtering
|
33
33
|
return [] << str.delete_if(&:blank?) * ' '
|
34
34
|
end
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
str.delete_if(&:blank?) * ' '
|
42
|
-
end
|
35
|
+
str = [
|
36
|
+
"SELECT #{select_string} FROM #{@scope.klass.column_family}",
|
37
|
+
where_string_async(@scope.id_values)
|
38
|
+
]
|
39
|
+
str << 'ALLOW FILTERING' if @scope.klass.allow_filtering
|
40
|
+
[str.delete_if(&:blank?) * ' ']
|
43
41
|
end
|
44
42
|
|
45
|
-
def where_string_async(
|
43
|
+
def where_string_async(ids)
|
46
44
|
conditions = []
|
47
|
-
|
45
|
+
|
46
|
+
if ids.present?
|
47
|
+
conditions << if ids.size > 1
|
48
|
+
"#{@adapter.primary_key_column} IN (#{ids.map { |id| "'#{id}'" }.join(',')})"
|
49
|
+
else
|
50
|
+
"#{@adapter.primary_key_column} = '#{ids.first}'"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
48
54
|
select_values = @scope.select_values.select { |sv| sv != :column1 }
|
49
55
|
if select_values.size > 0
|
50
56
|
select_str = select_values.size > 1 ? "column1 IN (#{select_values.map { |sv| '?' }.join(',')})" : 'column1 = ?'
|
51
57
|
conditions << select_str
|
52
58
|
end
|
53
59
|
conditions += @scope.where_values.select.each_with_index { |_, i| i.even? }
|
54
|
-
|
60
|
+
conditions.any? ? "WHERE #{conditions.join(' AND ')}" : nil
|
55
61
|
end
|
56
|
-
|
57
62
|
end
|
58
63
|
|
59
64
|
def primary_key_column
|
@@ -299,7 +304,7 @@ module CassandraObject
|
|
299
304
|
AND caching = '{\"keys\":\"ALL\", \"rows_per_partition\":\"NONE\"}'
|
300
305
|
AND comment = ''
|
301
306
|
AND compaction = {'min_sstable_size': '52428800', 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy'}
|
302
|
-
AND compression = {'chunk_length_kb': '64', '
|
307
|
+
AND compression = {'chunk_length_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
|
303
308
|
AND dclocal_read_repair_chance = 0.0
|
304
309
|
AND default_time_to_live = 0
|
305
310
|
AND gc_grace_seconds = 864000
|
@@ -309,19 +314,20 @@ module CassandraObject
|
|
309
314
|
AND read_repair_chance = 1.0
|
310
315
|
AND speculative_retry = 'NONE';"
|
311
316
|
else
|
312
|
-
"#{stmt} WITH
|
313
|
-
AND
|
314
|
-
AND gc_grace_seconds = 864000
|
315
|
-
AND bloom_filter_fp_chance = 0.01
|
316
|
-
AND caching = { 'keys' : 'ALL', 'rows_per_partition' : 'NONE' }
|
317
|
+
"#{stmt} WITH bloom_filter_fp_chance = 0.01
|
318
|
+
AND caching = {'keys': 'ALL', 'rows_per_partition': 'ALL'}
|
317
319
|
AND comment = ''
|
318
|
-
AND compaction = {
|
319
|
-
AND compression = {
|
320
|
+
AND compaction = {'class': 'SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
|
321
|
+
AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
|
322
|
+
AND crc_check_chance = 1.0
|
323
|
+
AND dclocal_read_repair_chance = 0.1
|
320
324
|
AND default_time_to_live = 0
|
321
|
-
AND
|
322
|
-
AND min_index_interval = 128
|
325
|
+
AND gc_grace_seconds = 864000
|
323
326
|
AND max_index_interval = 2048
|
324
|
-
AND
|
327
|
+
AND memtable_flush_period_in_ms = 0
|
328
|
+
AND min_index_interval = 128
|
329
|
+
AND read_repair_chance = 0.0
|
330
|
+
AND speculative_retry = '99.0PERCENTILE';
|
325
331
|
"
|
326
332
|
|
327
333
|
end
|
@@ -5,9 +5,9 @@ module CassandraObject
|
|
5
5
|
|
6
6
|
included do
|
7
7
|
if ActiveModel::VERSION::STRING < '3.2'
|
8
|
-
attribute_method_suffix(
|
8
|
+
attribute_method_suffix('', '=')
|
9
9
|
else
|
10
|
-
attribute_method_suffix(
|
10
|
+
attribute_method_suffix('=')
|
11
11
|
end
|
12
12
|
|
13
13
|
# (Alias for the protected read_attribute method).
|
@@ -15,7 +15,11 @@ module CassandraObject
|
|
15
15
|
|
16
16
|
before_update if: :changed? do
|
17
17
|
if self.class.timestamps
|
18
|
-
|
18
|
+
if store_updated_at.present?
|
19
|
+
self.updated_at = store_updated_at
|
20
|
+
else
|
21
|
+
self.updated_at = Time.current
|
22
|
+
end
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
@@ -21,7 +21,30 @@ class CassandraObject::TimestampsTest < CassandraObject::TestCase
|
|
21
21
|
test 'created_at sets only if nil' do
|
22
22
|
time = 5.days.ago
|
23
23
|
issue = Issue.create created_at: time
|
24
|
-
|
25
24
|
assert_equal time, issue.created_at
|
26
25
|
end
|
26
|
+
|
27
|
+
test 'set updated_at to now when not passed as an attribute' do
|
28
|
+
udate = 1.year.ago
|
29
|
+
issue = Issue.create(description: 'foo', updated_at: udate)
|
30
|
+
assert_equal udate, issue.updated_at
|
31
|
+
issue.update_attributes(description: 'test')
|
32
|
+
assert_not_equal udate, issue.updated_at
|
33
|
+
end
|
34
|
+
|
35
|
+
test 'set updated_at to passed value' do
|
36
|
+
issue = Issue.create(description: 'foo')
|
37
|
+
updated_at = issue.updated_at
|
38
|
+
new_updated_at = updated_at + 5.days
|
39
|
+
issue.update_attributes(description: 'bar', store_updated_at: new_updated_at)
|
40
|
+
assert_equal new_updated_at, issue.updated_at
|
41
|
+
end
|
42
|
+
|
43
|
+
test 'set updated_at to passed value even if is equal to the stored value' do
|
44
|
+
udate = 1.year.ago
|
45
|
+
issue = Issue.create(description: 'foo', updated_at: udate)
|
46
|
+
assert_equal udate, issue.updated_at
|
47
|
+
issue.update_attributes(description: 'bar', store_updated_at: issue.updated_at)
|
48
|
+
assert_equal udate, issue.updated_at
|
49
|
+
end
|
27
50
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: extendi-cassandra_object
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Duccio Giovannelli
|
@@ -9,22 +9,28 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2019-02-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activemodel
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - "
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 4.2.0
|
21
|
+
- - "<"
|
19
22
|
- !ruby/object:Gem::Version
|
20
|
-
version:
|
23
|
+
version: 6.0.0
|
21
24
|
type: :runtime
|
22
25
|
prerelease: false
|
23
26
|
version_requirements: !ruby/object:Gem::Requirement
|
24
27
|
requirements:
|
25
|
-
- - "
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 4.2.0
|
31
|
+
- - "<"
|
26
32
|
- !ruby/object:Gem::Version
|
27
|
-
version:
|
33
|
+
version: 6.0.0
|
28
34
|
- !ruby/object:Gem::Dependency
|
29
35
|
name: cassandra-driver
|
30
36
|
requirement: !ruby/object:Gem::Requirement
|
@@ -198,8 +204,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
198
204
|
- !ruby/object:Gem::Version
|
199
205
|
version: 1.3.5
|
200
206
|
requirements: []
|
201
|
-
|
202
|
-
rubygems_version: 2.7.6
|
207
|
+
rubygems_version: 3.0.2
|
203
208
|
signing_key:
|
204
209
|
specification_version: 4
|
205
210
|
summary: Cassandra ActiveModel
|