sessionm-cassandra_object 4.0.1 → 4.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6052d6c720f923eec9b114106e5a49d970348bcf
4
- data.tar.gz: b3258446a414824776c5e4fd7cc6515448b6220a
3
+ metadata.gz: 3e1cdbe60a0e5d0445c81ca4a2cbbfe124392c1f
4
+ data.tar.gz: 8dbd7771413345f0477fdd98d8ae2198bdb6d26f
5
5
  SHA512:
6
- metadata.gz: 3a42956c3dcbd6ebf8ea93c6029a4b3dad8e3eebe59287ff0c77b6e06937a0f673b5375eb73c7c42a93bf5205582535c3ff481d1695e0ff403f1924b32106995
7
- data.tar.gz: 254dadc67d4d95237075a962cd6037bad649afd0c4541a82d5fb209388ad06d6aac5e2992b69e4857c926f5cf1ebaf4ea819ebc47ce55a298c78f9eabc23915e
6
+ metadata.gz: 47dc210f1595a73cbd8a900021facd42bfae16e81292d2b079f9ffb053e7f6dc72ad6864ccfe832110167f566c77540c417b4e75457e48347eabacac639a7c9a
7
+ data.tar.gz: 580fc7a117c73831b5b4cc6857a714e2cffdfb89187c741f0838afea11c701eec968b4f63f17b11985e6b52a4e73b9b70a201f8d74e4d4f13ad5d8bca861c4b6
data/.gitignore CHANGED
@@ -1,2 +1,10 @@
1
- Gemfile.lock
1
+ .bundle
2
+ tmp/
3
+ !.gitignore
4
+ *~
5
+ \#*\#
6
+ .\#*
7
+ cms/
8
+ .DS_Store
9
+ .*.swp
2
10
  *.gem
data/Gemfile CHANGED
@@ -1,6 +1,12 @@
1
1
  source 'http://gems.prod.sessionm.com'
2
2
 
3
- gem 'rails', :require => 'rails/all'
3
+ gem 'activesupport', :require => 'active_support/all'
4
+ gem 'activerecord', :require => 'active_record'
4
5
 
5
6
  gem 'simple_uuid', '0.2.2'
6
7
  gem 'cassandra-driver', :require => 'cassandra'
8
+
9
+ group :test, :spec do
10
+ gem 'rspec'
11
+ gem "mocha"
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,60 @@
1
+ GEM
2
+ remote: http://gems.prod.sessionm.com/
3
+ specs:
4
+ activemodel (4.2.1)
5
+ activesupport (= 4.2.1)
6
+ builder (~> 3.1)
7
+ activerecord (4.2.1)
8
+ activemodel (= 4.2.1)
9
+ activesupport (= 4.2.1)
10
+ arel (~> 6.0)
11
+ activesupport (4.2.1)
12
+ i18n (~> 0.7)
13
+ json (~> 1.7, >= 1.7.7)
14
+ minitest (~> 5.1)
15
+ thread_safe (~> 0.3, >= 0.3.4)
16
+ tzinfo (~> 1.1)
17
+ arel (6.0.0)
18
+ builder (3.2.2)
19
+ cassandra-driver (2.1.3)
20
+ ione (~> 1.2)
21
+ diff-lcs (1.2.5)
22
+ i18n (0.7.0)
23
+ ione (1.2.0)
24
+ json (1.8.2)
25
+ macaddr (1.6.1)
26
+ systemu (~> 2.5.0)
27
+ metaclass (0.0.4)
28
+ minitest (5.6.1)
29
+ mocha (1.1.0)
30
+ metaclass (~> 0.0.1)
31
+ rspec (3.2.0)
32
+ rspec-core (~> 3.2.0)
33
+ rspec-expectations (~> 3.2.0)
34
+ rspec-mocks (~> 3.2.0)
35
+ rspec-core (3.2.3)
36
+ rspec-support (~> 3.2.0)
37
+ rspec-expectations (3.2.1)
38
+ diff-lcs (>= 1.2.0, < 2.0)
39
+ rspec-support (~> 3.2.0)
40
+ rspec-mocks (3.2.1)
41
+ diff-lcs (>= 1.2.0, < 2.0)
42
+ rspec-support (~> 3.2.0)
43
+ rspec-support (3.2.2)
44
+ simple_uuid (0.2.2)
45
+ macaddr (= 1.6.1)
46
+ systemu (2.5.2)
47
+ thread_safe (0.3.5)
48
+ tzinfo (1.2.2)
49
+ thread_safe (~> 0.1)
50
+
51
+ PLATFORMS
52
+ ruby
53
+
54
+ DEPENDENCIES
55
+ activerecord
56
+ activesupport
57
+ cassandra-driver
58
+ mocha
59
+ rspec
60
+ simple_uuid (= 0.2.2)
data/config/cassandra.yml CHANGED
@@ -1,26 +1,9 @@
1
- development: &id001
2
- servers: ['127.0.0.1:9160']
3
- keyspace: greyhound_development
4
- replication:
5
- strategy: org.apache.cassandra.locator.SimpleStrategy
6
- factor: 1
7
- consistency:
8
- read_default: quorum
9
- write_default: quorum
10
- column_family_defaults:
11
- compaction_strategy: org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy
12
- row_cache_provider: org.apache.cassandra.cache.ConcurrentLinkedHashCacheProvider
13
- thrift:
14
- connect_timeout: 0.5
15
- timeout: 3
16
- retries: 2
17
- production: *id001
18
1
  test:
19
- servers: ['127.0.0.1:9160']
20
- keyspace: greyhound_test
2
+ servers: ['127.0.0.1']
3
+ keyspace: cassandra_object_test
21
4
  replication:
22
5
  strategy: org.apache.cassandra.locator.SimpleStrategy
23
- factor: 1
6
+ replication_factor: 1
24
7
  consistency:
25
8
  read_default: quorum
26
9
  write_default: quorum
@@ -31,6 +14,3 @@ test:
31
14
  connect_timeout: 0.5
32
15
  timeout: 3
33
16
  retries: 2
34
- exception_class_overrides:
35
- - CassandraThrift::InvalidRequestException
36
- - CassandraThrift::NotFoundException
@@ -1,4 +1,5 @@
1
- require 'rails/all'
1
+ require 'active_support/all'
2
+ require 'active_record'
2
3
 
3
4
  module CassandraObject
4
5
  extend ActiveSupport::Autoload
@@ -12,7 +12,11 @@ module CassandraObject
12
12
  end
13
13
 
14
14
  def client
15
- @client ||= Client.new(cluster.connect(config[:keyspace]))
15
+ @client ||= self.new_client
16
+ end
17
+
18
+ def new_client
19
+ Client.new(cluster.connect(config[:keyspace]), cluster)
16
20
  end
17
21
 
18
22
  def close
@@ -26,21 +30,22 @@ module CassandraObject
26
30
  :port => config[:port] || 9042,
27
31
  :connect_timeout => config[:thrift][:connect_timeout] || 10,
28
32
  :timeout => config[:thrift][:timeout] || 10,
29
- :logger => Rails.logger || Logger.new(STDOUT),
33
+ :logger => config[:logger] || (defined?(Rails) && Rails.logger) || Logger.new(STDOUT),
30
34
  :consistency => (config[:consistency] || {})[:write_default].try(:to_sym) || :one,
31
35
  }
32
36
  end
33
37
 
34
38
  # The client class acts like the old cassandra gem
35
39
  class Client
36
- attr_reader :session
40
+ attr_reader :session, :cluster
37
41
 
38
42
  KEY_FIELD = 'key'
39
43
  NAME_FIELD = 'column1'
40
44
  VALUE_FIELD = 'value'
41
45
 
42
- def initialize(session)
46
+ def initialize(session, cluster)
43
47
  @session = session
48
+ @cluster = cluster
44
49
  end
45
50
 
46
51
  def close
@@ -106,6 +111,40 @@ module CassandraObject
106
111
  async ? self.execute_async(query, execute_options(opts)) : self.execute(query, execute_options(opts))
107
112
  end
108
113
 
114
+ def remove(column_family, key, *args)
115
+ opts = args.pop if args.last.is_a?(Hash)
116
+ async = opts.try(:[], :async)
117
+ key = "textAsBlob('#{key}')"
118
+
119
+ query =
120
+ if args.first.nil? || args.first.is_a?(Hash)
121
+ "DELETE FROM \"#{column_family}\" WHERE #{KEY_FIELD} = #{key};"
122
+ else
123
+ "DELETE \"#{column_family}\" WHERE #{KEY_FIELD} = #{key} AND #{NAME_FIELD} = '#{args.first}';"
124
+ end
125
+
126
+ async ? self.execute_async(query, execute_options(opts)) : self.execute(query, execute_options(opts))
127
+ end
128
+
129
+ def get_range(column_family, opts={}, &blk)
130
+ key_count = opts[:key_count] || 100
131
+ query = "SELECT #{KEY_FIELD} FROM \"#{column_family}\" LIMIT #{key_count}"
132
+ keys = self.execute(query, execute_options(opts)).map { |result| result[KEY_FIELD] }
133
+ keys.size > 0 ? multi_get(column_family, keys) : {}
134
+ end
135
+
136
+ def multi_get(column_family, keys, *args)
137
+ opts = args.pop if args.last.is_a?(Hash)
138
+ keys = keys.map { |key| "textAsBlob('#{key}')" }.join(',')
139
+ results = {}
140
+ query = "SELECT * FROM \"#{column_family}\" WHERE #{KEY_FIELD} IN(#{keys})"
141
+ self.execute(query, execute_options(opts)).each do |row|
142
+ results[row[KEY_FIELD]] ||= {}
143
+ results[row[KEY_FIELD]][row[NAME_FIELD]] = row[VALUE_FIELD]
144
+ end
145
+ results
146
+ end
147
+
109
148
  def execute_options(opts)
110
149
  opts.try(:slice,
111
150
  :consistency,
@@ -115,6 +154,10 @@ module CassandraObject
115
154
  :serial_consistency
116
155
  ) || {}
117
156
  end
157
+
158
+ def has_table?(name)
159
+ self.cluster.keyspace(session.keyspace).has_table? name
160
+ end
118
161
  end
119
162
  end
120
163
  end
@@ -52,16 +52,19 @@ module CassandraObject
52
52
  end
53
53
 
54
54
  def remove(key)
55
- begin
56
- CassandraObject::Base.with_connection(key, :write) do
57
- ActiveSupport::Notifications.instrument("remove.cassandra_object", column_family: relationships_column_family, key: key) do
58
- connection.remove(relationships_column_family, key.to_s, consistency: thrift_write_consistency)
55
+ if connection.has_table?(relationships_column_family)
56
+ begin
57
+ CassandraObject::Base.with_connection(key, :write) do
58
+ ActiveSupport::Notifications.instrument("remove.cassandra_object", column_family: relationships_column_family, key: key) do
59
+ connection.remove(relationships_column_family, key.to_s, consistency: thrift_write_consistency)
60
+ end
59
61
  end
62
+ rescue Cassandra::Errors::InvalidError => e
63
+ # pretty sure this is not the correct message for cassandra-driver gem, will need to investigate the actual message
64
+ raise e unless e.message =~ /unconfigured columnfamily/i
60
65
  end
61
- rescue Cassandra::Error => e
62
- # pretty sure this is not the correct message for cassandra-driver gem, will need to investigate the actual message
63
- raise e unless e.message =~ /invalid column family/i
64
66
  end
67
+
65
68
  super
66
69
  end
67
70
  end
@@ -8,4 +8,4 @@ module CassandraObject
8
8
  require 'cassandra_object/generators/migration_generator'
9
9
  end
10
10
  end
11
- end
11
+ end if defined?(Rails)
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'sessionm-cassandra_object'
5
- s.version = '4.0.1'
5
+ s.version = '4.0.2'
6
6
  s.description = 'Cassandra ActiveModel'
7
7
  s.summary = 'Cassandra ActiveModel'
8
8
 
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe CassandraObject::Base do
4
+ it "should be able to a create/fetch/destroy an issue" do
5
+ issue = Issue.create! :description => 'web site not working', :worth => 1.5
6
+ expect(issue.persisted?).to be true
7
+ issue = Issue.find issue.id
8
+ expect(issue.worth.to_f).to be 1.5
9
+ issue.destroy
10
+ expect(Issue.find_by_id(issue.id)).to be nil
11
+ end
12
+
13
+ it "should be able to get the first issue" do
14
+ issue = Issue.create! :description => 'web site not working', :worth => 1.5
15
+ expect(Issue.first.id).to eq issue.id
16
+ end
17
+
18
+ it "should be able to get all issues" do
19
+ issue1 = Issue.create! :description => 'web site not working', :worth => 1.5
20
+ issue2 = Issue.create! :description => 'button is disabled', :worth => 0.2
21
+ expect(Issue.all.map(&:id).sort).to eq [issue1.id, issue2.id].sort
22
+ end
23
+
24
+ it "should be able to find issues by id" do
25
+ issue1 = Issue.create! :description => 'web site not working', :worth => 1.5
26
+ issue2 = Issue.create! :description => 'button is disabled', :worth => 0.2
27
+ issue3 = Issue.create! :description => 'button is disabled', :worth => 0.2
28
+ expect(Issue.find_with_ids(issue1.id, issue2.id).map(&:id).sort).to eq [issue1.id, issue2.id].sort
29
+ end
30
+ end
@@ -0,0 +1,60 @@
1
+ require 'rubygems'
2
+
3
+ ENV["RAILS_ENV"] = 'test'
4
+
5
+ require File.expand_path('../../config/environment', __FILE__)
6
+
7
+ Bundler.require :default, :test
8
+
9
+ Dir[BASE_DIR.join("spec/support/**/*.rb")].each { |f| require f }
10
+
11
+ KEYSPACE = 'cassandra_object_test'
12
+
13
+ CassandraObject::Adapters::CassandraDriver.new(CassandraObject::Base.connection_spec).cluster.tap do |cluster|
14
+ cluster.connect.tap do |session|
15
+ session.execute("DROP KEYSPACE #{KEYSPACE}") if cluster.has_keyspace?(KEYSPACE)
16
+ replication = Cassandra::Keyspace::Replication.new('org.apache.cassandra.locator.SimpleStrategy', 'replication_factor' => 1)
17
+ keyspace = Cassandra::Keyspace.new(KEYSPACE, false, replication, [], [])
18
+ session.execute keyspace.to_cql
19
+ session.close
20
+ end
21
+
22
+ cluster.connect(KEYSPACE).tap do |session|
23
+ session.execute <<-CQL
24
+ CREATE TABLE "Issues" (
25
+ key blob,
26
+ column1 text,
27
+ value text,
28
+ PRIMARY KEY (key, column1)
29
+ )
30
+ CQL
31
+
32
+ session.execute <<-CQL
33
+ CREATE TABLE "Counters" (
34
+ key blob,
35
+ column1 text,
36
+ value counter,
37
+ PRIMARY KEY (key, column1)
38
+ )
39
+ CQL
40
+ session.close
41
+ end
42
+
43
+ cluster.close
44
+ end
45
+
46
+ RSpec.configure do |config|
47
+
48
+ config.before(:each) do
49
+ Cassandra::Session.delete_all_populated_column_families
50
+ end
51
+
52
+ config.after(:all) do
53
+ # we need to call this at the end of each set of tests because if the last test in an rspec file inserts data
54
+ # into Cassandra it will not be cleaned up at the beginning of the next test in the next rspec file. This was
55
+ # first spotted in ref #361. The test run in autotest called before_create on UserTransaction and added that
56
+ # class to @@populated_column_families, but when you run an individual file after autotest @@populated_column_families
57
+ # is empty, so Cassandra doesn't get cleaned up properly...
58
+ Cassandra::Session.delete_all_populated_column_families
59
+ end
60
+ end
@@ -0,0 +1,30 @@
1
+ require 'cassandra'
2
+
3
+ module Cassandra
4
+ class Session
5
+ @@populated_column_families = Set.new
6
+ @@test_client = CassandraObject::Adapters::CassandraDriver.new(CassandraObject::Base.connection_spec).client
7
+
8
+ def self.truncate_populated_column_family(column_family)
9
+ @@test_client.execute "TRUNCATE \"#{column_family}\""
10
+ end
11
+
12
+ def self.delete_all_populated_column_families
13
+ unless @@populated_column_families.empty?
14
+ @@populated_column_families.each { |column_family| self.truncate_populated_column_family(column_family) }
15
+ @@populated_column_families.clear
16
+ end
17
+ end
18
+
19
+ [:execute_async].each do |method|
20
+ define_method("#{method}_with_populated_tracking") do |*args|
21
+ send("#{method}_without_populated_tracking", *args).tap do
22
+ if args.first =~ /(insert into|update) "(.+?)"/i
23
+ @@populated_column_families.add $2
24
+ end
25
+ end
26
+ end
27
+ alias_method_chain method, :populated_tracking
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ class Counter < CassandraObject::Base
2
+ self.write_consistency = :all
3
+ end
@@ -0,0 +1,11 @@
1
+ class Issue < CassandraObject::Base
2
+ key :uuid
3
+ attribute :description, :type => :string
4
+ attribute :worth, :type => :decimal, :precision => 100
5
+ attribute :name, :type => :string
6
+ before_validation :set_defaults, :on => :create
7
+
8
+ def set_defaults
9
+ self.name ||= 'default name'
10
+ end
11
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sessionm-cassandra_object
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 4.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Koziarski
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-05-06 00:00:00.000000000 Z
13
+ date: 2015-05-11 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: Cassandra ActiveModel
16
16
  email: doug@sessionm.com
@@ -24,6 +24,7 @@ files:
24
24
  - ".ruby-version"
25
25
  - CHANGELOG
26
26
  - Gemfile
27
+ - Gemfile.lock
27
28
  - LICENSE
28
29
  - MIT-LICENSE
29
30
  - README.markdown
@@ -92,6 +93,11 @@ files:
92
93
  - lib/cassandra_object/validations.rb
93
94
  - script/console.rb
94
95
  - sessionm-cassandra_object.gemspec
96
+ - spec/cassandra_object/base_spec.rb
97
+ - spec/spec_helper.rb
98
+ - spec/support/cassandra.rb
99
+ - spec/support/models/counter.rb
100
+ - spec/support/models/issue.rb
95
101
  - test/README
96
102
  - test/active_model_test.rb
97
103
  - test/attributes_test.rb
@@ -141,6 +147,11 @@ signing_key:
141
147
  specification_version: 4
142
148
  summary: Cassandra ActiveModel
143
149
  test_files:
150
+ - spec/cassandra_object/base_spec.rb
151
+ - spec/spec_helper.rb
152
+ - spec/support/cassandra.rb
153
+ - spec/support/models/counter.rb
154
+ - spec/support/models/issue.rb
144
155
  - test/README
145
156
  - test/active_model_test.rb
146
157
  - test/attributes_test.rb