gotime-cassandra_object 0.8.7 → 0.9.0
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.
- data/gotime-cassandra_object.gemspec +6 -6
- data/lib/cassandra_object/associations.rb +12 -3
- data/lib/cassandra_object/associations/one_to_many.rb +2 -2
- data/lib/cassandra_object/associations/one_to_one.rb +9 -3
- data/lib/cassandra_object/identity.rb +3 -0
- data/lib/cassandra_object/identity/custom_key_factory.rb +50 -0
- data/lib/cassandra_object/log_subscriber.rb +9 -6
- data/lib/cassandra_object/persistence.rb +15 -18
- data/lib/cassandra_object/timestamps.rb +2 -2
- data/lib/cassandra_object/types.rb +0 -1
- metadata +43 -10
@@ -2,21 +2,21 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'gotime-cassandra_object'
|
5
|
-
s.version = '0.
|
5
|
+
s.version = '0.9.0'
|
6
6
|
s.description = 'Cassandra ActiveModel'
|
7
7
|
s.summary = 'Cassandra ActiveModel'
|
8
8
|
s.required_rubygems_version = '>= 1.3.5'
|
9
|
-
s.authors = ["Michael Koziarski", "
|
10
|
-
s.email = '
|
9
|
+
s.authors = ["Michael Koziarski", "gotime"]
|
10
|
+
s.email = 'gems@gotime.com'
|
11
11
|
s.homepage = 'http://github.com/gotime/cassandra_object'
|
12
12
|
s.extra_rdoc_files = ["README.markdown"]
|
13
13
|
s.files = `git ls-files`.split("\n")
|
14
14
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
15
|
s.require_paths = ['lib']
|
16
16
|
|
17
|
-
s.add_runtime_dependency('activesupport', "~> 3")
|
18
|
-
s.add_runtime_dependency('activemodel', "~> 3")
|
19
|
-
s.add_runtime_dependency('cassandra')
|
17
|
+
s.add_runtime_dependency('activesupport', "~> 3.0")
|
18
|
+
s.add_runtime_dependency('activemodel', "~> 3.0")
|
19
|
+
s.add_runtime_dependency('cassandra', "~> 0.11.3")
|
20
20
|
|
21
21
|
s.add_development_dependency('shoulda')
|
22
22
|
s.add_development_dependency('bundler', "~> 1.0.0")
|
@@ -11,8 +11,17 @@ module CassandraObject
|
|
11
11
|
end
|
12
12
|
|
13
13
|
module ClassMethods
|
14
|
+
|
15
|
+
def relationships_column_family=(column_family)
|
16
|
+
@relationships_column_family = column_family
|
17
|
+
end
|
18
|
+
|
19
|
+
def relationships_column_family
|
20
|
+
@relationships_column_family || "#{column_family}Relationships"
|
21
|
+
end
|
22
|
+
|
14
23
|
def column_family_configuration
|
15
|
-
super << {:Name=>
|
24
|
+
super << {:Name=>relationships_column_family, :CompareWith=>"UTF8Type", :CompareSubcolumnsWith=>"TimeUUIDType", :ColumnType=>"Super"}
|
16
25
|
end
|
17
26
|
|
18
27
|
def association(association_name, options= {})
|
@@ -25,8 +34,8 @@ module CassandraObject
|
|
25
34
|
|
26
35
|
def remove(key)
|
27
36
|
begin
|
28
|
-
ActiveSupport::Notifications.instrument("remove.cassandra_object", :key => key) do
|
29
|
-
connection.remove(
|
37
|
+
ActiveSupport::Notifications.instrument("remove.cassandra_object", :column_family => relationships_column_family, :key => key) do
|
38
|
+
connection.remove(relationships_column_family, key.to_s, :consistency => write_consistency_for_thrift)
|
30
39
|
end
|
31
40
|
rescue Cassandra::AccessError => e
|
32
41
|
raise e unless e.message =~ /Invalid column family/
|
@@ -27,7 +27,7 @@ module CassandraObject
|
|
27
27
|
def add(owner, record, set_inverse = true)
|
28
28
|
key = owner.key
|
29
29
|
attributes = {@association_name=>{new_key=>record.key.to_s}}
|
30
|
-
ActiveSupport::Notifications.instrument("insert.cassandra_object", :key => key, :attributes => attributes) do
|
30
|
+
ActiveSupport::Notifications.instrument("insert.cassandra_object", :column_family => column_family, :key => key, :attributes => attributes) do
|
31
31
|
connection.insert(column_family, key.to_s, attributes, :consistency => write_consistency_for_thrift)
|
32
32
|
end
|
33
33
|
if has_inverse? && set_inverse
|
@@ -40,7 +40,7 @@ module CassandraObject
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def column_family
|
43
|
-
@owner_class.
|
43
|
+
@owner_class.relationships_column_family
|
44
44
|
end
|
45
45
|
|
46
46
|
def connection
|
@@ -24,7 +24,9 @@ module CassandraObject
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def clear(owner)
|
27
|
-
|
27
|
+
ActiveSupport::Notifications.instrument("remove.cassandra_object", :column_family => column_family, :key => owner.key, :columns => @association_name) do
|
28
|
+
connection.remove(column_family, owner.key.to_s, @association_name)
|
29
|
+
end
|
28
30
|
end
|
29
31
|
|
30
32
|
def find(owner)
|
@@ -37,7 +39,11 @@ module CassandraObject
|
|
37
39
|
|
38
40
|
def set(owner, record, set_inverse = true)
|
39
41
|
clear(owner)
|
40
|
-
|
42
|
+
key = owner.key
|
43
|
+
attributes = {@association_name=>{new_key=>record.key.to_s}}
|
44
|
+
ActiveSupport::Notifications.instrument("insert.cassandra_object", :column_family => column_family, :key => key, :attributes => attributes) do
|
45
|
+
connection.insert(column_family, key.to_s, attributes, :consistency => write_consistency_for_thrift)
|
46
|
+
end
|
41
47
|
if has_inverse? && set_inverse
|
42
48
|
inverse.set_inverse(record, owner)
|
43
49
|
end
|
@@ -60,7 +66,7 @@ module CassandraObject
|
|
60
66
|
end
|
61
67
|
|
62
68
|
def column_family
|
63
|
-
@owner_class.
|
69
|
+
@owner_class.relationships_column_family
|
64
70
|
end
|
65
71
|
|
66
72
|
def connection
|
@@ -10,6 +10,7 @@ module CassandraObject
|
|
10
10
|
autoload :UUIDKeyFactory
|
11
11
|
autoload :NaturalKeyFactory
|
12
12
|
autoload :HashedNaturalKeyFactory
|
13
|
+
autoload :CustomKeyFactory
|
13
14
|
|
14
15
|
module ClassMethods
|
15
16
|
# Indicate what kind of key the model will have: uuid or natural
|
@@ -23,6 +24,8 @@ module CassandraObject
|
|
23
24
|
UUIDKeyFactory.new
|
24
25
|
when :natural
|
25
26
|
NaturalKeyFactory.new(*options)
|
27
|
+
when :custom
|
28
|
+
CustomKeyFactory.new(*options)
|
26
29
|
else
|
27
30
|
name_or_factory
|
28
31
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module CassandraObject
|
2
|
+
module Identity
|
3
|
+
class CustomKeyFactory < AbstractKeyFactory
|
4
|
+
class CustomKey
|
5
|
+
include Key
|
6
|
+
|
7
|
+
attr_reader :value
|
8
|
+
|
9
|
+
def initialize(value)
|
10
|
+
@value = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
value
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_param
|
18
|
+
value
|
19
|
+
end
|
20
|
+
|
21
|
+
def ==(other)
|
22
|
+
other.is_a?(CustomKey) && other.value == value
|
23
|
+
end
|
24
|
+
|
25
|
+
def eql?(other)
|
26
|
+
other == self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :method
|
31
|
+
|
32
|
+
def initialize(options)
|
33
|
+
@method = options[:method]
|
34
|
+
end
|
35
|
+
|
36
|
+
def next_key(object)
|
37
|
+
CustomKey.new(object.send(@method))
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse(paramized_key)
|
41
|
+
CustomKey.new(paramized_key)
|
42
|
+
end
|
43
|
+
|
44
|
+
def create(paramized_key)
|
45
|
+
CustomKey.new(paramized_key)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
@@ -1,31 +1,34 @@
|
|
1
1
|
module CassandraObject
|
2
2
|
class LogSubscriber < ActiveSupport::LogSubscriber
|
3
3
|
def multi_get(event)
|
4
|
-
name = '
|
4
|
+
name = '%s multi_get (%.1fms)' % [event.payload[:column_family], event.duration]
|
5
5
|
|
6
6
|
debug " #{name} (#{event.payload[:keys].size}) #{event.payload[:keys].join(" ")}"
|
7
7
|
end
|
8
8
|
|
9
9
|
def remove(event)
|
10
|
-
name = '
|
10
|
+
name = '%s remove (%.1fms)' % [event.payload[:column_family], event.duration]
|
11
11
|
|
12
|
-
|
12
|
+
message = " #{name} #{event.payload[:key]}"
|
13
|
+
message << " #{Array(event.payload[:attributes]).inspect}" if event.payload[:attributes]
|
14
|
+
|
15
|
+
debug message
|
13
16
|
end
|
14
17
|
|
15
18
|
def truncate(event)
|
16
|
-
name = '
|
19
|
+
name = '%s truncate (%.1fms)' % [event.payload[:column_family], event.duration]
|
17
20
|
|
18
21
|
debug " #{name} #{event.payload[:column_family]}"
|
19
22
|
end
|
20
23
|
|
21
24
|
def insert(event)
|
22
|
-
name = '
|
25
|
+
name = '%s insert (%.1fms)' % [event.payload[:column_family], event.duration]
|
23
26
|
|
24
27
|
debug " #{name} #{event.payload[:key]} #{event.payload[:attributes].inspect}"
|
25
28
|
end
|
26
29
|
|
27
30
|
def get_range(event)
|
28
|
-
name = '
|
31
|
+
name = '%s get_range (%.1fms)' % [event.payload[:column_family], event.duration]
|
29
32
|
|
30
33
|
debug " #{name} (#{event.payload[:count]}) '#{event.payload[:start]}' => '#{event.payload[:finish]}'"
|
31
34
|
end
|
@@ -27,18 +27,18 @@ module CassandraObject
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
def get(key, options
|
30
|
+
def get(key, options={})
|
31
31
|
multi_get([key], options).values.first
|
32
32
|
end
|
33
33
|
|
34
|
-
def multi_get(keys, options
|
35
|
-
options = {:consistency => self.read_consistency
|
34
|
+
def multi_get(keys, options={})
|
35
|
+
options = {:consistency => self.read_consistency}.merge(options)
|
36
36
|
unless valid_read_consistency_level?(options[:consistency])
|
37
37
|
raise ArgumentError, "Invalid read consistency level: '#{options[:consistency]}'. Valid options are [:quorum, :one]"
|
38
38
|
end
|
39
39
|
|
40
|
-
attribute_results = ActiveSupport::Notifications.instrument("multi_get.cassandra_object", :keys => keys) do
|
41
|
-
connection.multi_get(column_family, keys.map(&:to_s), :
|
40
|
+
attribute_results = ActiveSupport::Notifications.instrument("multi_get.cassandra_object", :column_family => column_family, :keys => keys) do
|
41
|
+
connection.multi_get(column_family, keys.map(&:to_s), :consistency => consistency_for_thrift(options[:consistency]))
|
42
42
|
end
|
43
43
|
|
44
44
|
attribute_results.inject(ActiveSupport::OrderedHash.new) do |memo, (key, attributes)|
|
@@ -52,7 +52,7 @@ module CassandraObject
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def remove(key)
|
55
|
-
ActiveSupport::Notifications.instrument("remove.cassandra_object", :key => key) do
|
55
|
+
ActiveSupport::Notifications.instrument("remove.cassandra_object", :column_family => column_family, :key => key) do
|
56
56
|
connection.remove(column_family, key.to_s, :consistency => write_consistency_for_thrift)
|
57
57
|
end
|
58
58
|
end
|
@@ -66,25 +66,22 @@ module CassandraObject
|
|
66
66
|
def all(keyrange = ''..'', options = {})
|
67
67
|
options = {:consistency => self.read_consistency, :limit => 100}.merge(options)
|
68
68
|
count = options[:limit]
|
69
|
-
results = ActiveSupport::Notifications.instrument("get_range.cassandra_object", :start => keyrange.first, :finish => keyrange.last, :
|
70
|
-
connection.get_range(column_family, :start => keyrange.first, :finish => keyrange.last, :
|
69
|
+
results = ActiveSupport::Notifications.instrument("get_range.cassandra_object", :column_family => column_family, :start => keyrange.first, :finish => keyrange.last, :key_count => count) do
|
70
|
+
connection.get_range(column_family, :start => keyrange.first, :finish => keyrange.last, :key_count => count, :consistency => consistency_for_thrift(options[:consistency]))
|
71
71
|
end
|
72
72
|
|
73
|
-
|
74
|
-
|
73
|
+
#get_ranges response changed in cassandra gem 0.11.3 for cassandra 0.8.1, now similar to other method responses like multi_get
|
74
|
+
results.map do |k, v|
|
75
|
+
if v.empty?
|
75
76
|
nil
|
76
77
|
else
|
77
|
-
|
78
|
-
memo[column.column.name] = column.column.value
|
79
|
-
memo
|
80
|
-
end
|
81
|
-
instantiate(result.key, attributes)
|
78
|
+
instantiate(k, v)
|
82
79
|
end
|
83
80
|
end.compact
|
84
81
|
end
|
85
82
|
|
86
83
|
def first(keyrange = ''..'', options = {})
|
87
|
-
all(keyrange, options.merge(:limit=>1)).first
|
84
|
+
all(keyrange, options.merge(:limit => 1)).first
|
88
85
|
end
|
89
86
|
|
90
87
|
def create(attributes)
|
@@ -96,7 +93,7 @@ module CassandraObject
|
|
96
93
|
def write(key, attributes, schema_version)
|
97
94
|
key.tap do |key|
|
98
95
|
attributes = encode_columns_hash(attributes, schema_version)
|
99
|
-
ActiveSupport::Notifications.instrument("insert.cassandra_object", :key => key, :attributes => attributes) do
|
96
|
+
ActiveSupport::Notifications.instrument("insert.cassandra_object", :column_family => column_family, :key => key, :attributes => attributes) do
|
100
97
|
connection.insert(column_family, key.to_s, attributes, :consistency => write_consistency_for_thrift)
|
101
98
|
end
|
102
99
|
end
|
@@ -133,7 +130,7 @@ module CassandraObject
|
|
133
130
|
end
|
134
131
|
|
135
132
|
def column_family_configuration
|
136
|
-
[{:Name=>column_family, :CompareWith=>"UTF8Type"}]
|
133
|
+
[{:Name => column_family, :CompareWith => "UTF8Type"}]
|
137
134
|
end
|
138
135
|
|
139
136
|
end
|
@@ -13,11 +13,11 @@ module CassandraObject
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def set_created_at
|
16
|
-
self.created_at = Time.current unless
|
16
|
+
self.created_at = Time.current unless timestamp_override
|
17
17
|
end
|
18
18
|
|
19
19
|
def set_updated_at
|
20
|
-
self.updated_at = Time.current unless
|
20
|
+
self.updated_at = Time.current unless timestamp_override
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
metadata
CHANGED
@@ -1,17 +1,21 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gotime-cassandra_object
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 9
|
8
|
+
- 0
|
9
|
+
version: 0.9.0
|
6
10
|
platform: ruby
|
7
11
|
authors:
|
8
12
|
- Michael Koziarski
|
9
|
-
-
|
13
|
+
- gotime
|
10
14
|
autorequire:
|
11
15
|
bindir: bin
|
12
16
|
cert_chain: []
|
13
17
|
|
14
|
-
date: 2011-
|
18
|
+
date: 2011-07-18 00:00:00 -07:00
|
15
19
|
default_executable:
|
16
20
|
dependencies:
|
17
21
|
- !ruby/object:Gem::Dependency
|
@@ -22,7 +26,10 @@ dependencies:
|
|
22
26
|
requirements:
|
23
27
|
- - ~>
|
24
28
|
- !ruby/object:Gem::Version
|
25
|
-
|
29
|
+
segments:
|
30
|
+
- 3
|
31
|
+
- 0
|
32
|
+
version: "3.0"
|
26
33
|
type: :runtime
|
27
34
|
version_requirements: *id001
|
28
35
|
- !ruby/object:Gem::Dependency
|
@@ -33,7 +40,10 @@ dependencies:
|
|
33
40
|
requirements:
|
34
41
|
- - ~>
|
35
42
|
- !ruby/object:Gem::Version
|
36
|
-
|
43
|
+
segments:
|
44
|
+
- 3
|
45
|
+
- 0
|
46
|
+
version: "3.0"
|
37
47
|
type: :runtime
|
38
48
|
version_requirements: *id002
|
39
49
|
- !ruby/object:Gem::Dependency
|
@@ -42,9 +52,13 @@ dependencies:
|
|
42
52
|
requirement: &id003 !ruby/object:Gem::Requirement
|
43
53
|
none: false
|
44
54
|
requirements:
|
45
|
-
- -
|
55
|
+
- - ~>
|
46
56
|
- !ruby/object:Gem::Version
|
47
|
-
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
- 11
|
60
|
+
- 3
|
61
|
+
version: 0.11.3
|
48
62
|
type: :runtime
|
49
63
|
version_requirements: *id003
|
50
64
|
- !ruby/object:Gem::Dependency
|
@@ -55,6 +69,8 @@ dependencies:
|
|
55
69
|
requirements:
|
56
70
|
- - ">="
|
57
71
|
- !ruby/object:Gem::Version
|
72
|
+
segments:
|
73
|
+
- 0
|
58
74
|
version: "0"
|
59
75
|
type: :development
|
60
76
|
version_requirements: *id004
|
@@ -66,6 +82,10 @@ dependencies:
|
|
66
82
|
requirements:
|
67
83
|
- - ~>
|
68
84
|
- !ruby/object:Gem::Version
|
85
|
+
segments:
|
86
|
+
- 1
|
87
|
+
- 0
|
88
|
+
- 0
|
69
89
|
version: 1.0.0
|
70
90
|
type: :development
|
71
91
|
version_requirements: *id005
|
@@ -77,6 +97,10 @@ dependencies:
|
|
77
97
|
requirements:
|
78
98
|
- - ~>
|
79
99
|
- !ruby/object:Gem::Version
|
100
|
+
segments:
|
101
|
+
- 1
|
102
|
+
- 5
|
103
|
+
- 1
|
80
104
|
version: 1.5.1
|
81
105
|
type: :development
|
82
106
|
version_requirements: *id006
|
@@ -88,11 +112,13 @@ dependencies:
|
|
88
112
|
requirements:
|
89
113
|
- - ">="
|
90
114
|
- !ruby/object:Gem::Version
|
115
|
+
segments:
|
116
|
+
- 0
|
91
117
|
version: "0"
|
92
118
|
type: :development
|
93
119
|
version_requirements: *id007
|
94
120
|
description: Cassandra ActiveModel
|
95
|
-
email:
|
121
|
+
email: gems@gotime.com
|
96
122
|
executables: []
|
97
123
|
|
98
124
|
extensions: []
|
@@ -127,6 +153,7 @@ files:
|
|
127
153
|
- lib/cassandra_object/generators/templates/migration.rb.erb
|
128
154
|
- lib/cassandra_object/identity.rb
|
129
155
|
- lib/cassandra_object/identity/abstract_key_factory.rb
|
156
|
+
- lib/cassandra_object/identity/custom_key_factory.rb
|
130
157
|
- lib/cassandra_object/identity/hashed_natural_key_factory.rb
|
131
158
|
- lib/cassandra_object/identity/key.rb
|
132
159
|
- lib/cassandra_object/identity/natural_key_factory.rb
|
@@ -184,17 +211,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
184
211
|
requirements:
|
185
212
|
- - ">="
|
186
213
|
- !ruby/object:Gem::Version
|
214
|
+
segments:
|
215
|
+
- 0
|
187
216
|
version: "0"
|
188
217
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
189
218
|
none: false
|
190
219
|
requirements:
|
191
220
|
- - ">="
|
192
221
|
- !ruby/object:Gem::Version
|
222
|
+
segments:
|
223
|
+
- 1
|
224
|
+
- 3
|
225
|
+
- 5
|
193
226
|
version: 1.3.5
|
194
227
|
requirements: []
|
195
228
|
|
196
229
|
rubyforge_project:
|
197
|
-
rubygems_version: 1.
|
230
|
+
rubygems_version: 1.3.7
|
198
231
|
signing_key:
|
199
232
|
specification_version: 3
|
200
233
|
summary: Cassandra ActiveModel
|