datastax_rails 1.0.16.3 → 1.0.17.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -44,11 +44,11 @@ module DatastaxRails
44
44
  model.attribute_definitions.values.each do |attr|
45
45
  coder = attr.coder
46
46
  if coder.options[:solr_type] && (coder.options[:indexed] || coder.options[:stored])
47
- @fields.push({ :name => attr.name,
48
- :type => coder.options[:solr_type].to_s,
49
- :indexed => coder.options[:indexed].to_s,
50
- :stored => coder.options[:stored].to_s,
51
- :multi_valued => coder.options[:multi_valued].to_s })
47
+ @fields.push({ :name => attr.name,
48
+ :type => coder.options[:solr_type].to_s,
49
+ :indexed => coder.options[:indexed].to_s,
50
+ :stored => coder.options[:stored].to_s,
51
+ :multi_valued => coder.options[:multi_valued].to_s })
52
52
  end
53
53
  if coder.options[:sortable] && coder.options[:tokenized]
54
54
  @fields.push({ :name => "sort_" + attr.name,
@@ -76,7 +76,7 @@ module DatastaxRails
76
76
  column_family ||= :all
77
77
  # Ensure schema migrations CF exists
78
78
  unless connection.schema.column_families['schema_migrations']
79
- connection.execute_cql_query(DatastaxRails::Cql::CreateColumnFamily.new('schema_migrations').key_type(:text).to_cql)
79
+ connection.execute_cql_query(DatastaxRails::Cql::CreateColumnFamily.new('schema_migrations').key_type(:text).columns(:digest => :text, :solrconfig => :text, :stopwords => :text).to_cql)
80
80
  end
81
81
 
82
82
  solrconfig = File.read(File.join(File.dirname(__FILE__),"..","..","..","config","solrconfig.xml"))
@@ -100,61 +100,89 @@ module DatastaxRails
100
100
  puts "models: #{models_to_upload.collect(&:to_s).join(",")}"
101
101
 
102
102
  models_to_upload.each do |model|
103
- schema = generate_solr_schema(model)
104
- schema_digest = Digest::SHA1.hexdigest(schema)
105
-
106
- results = DatastaxRails::Cql::Select.new(SchemaMigration, ['*']).conditions(:key => model.column_family).execute
107
- sm_digests = CassandraCQL::Result.new(results).fetch.to_hash
108
-
109
- solr_url = "#{DatastaxRails::Base.solr_base_url}/resource/#{DatastaxRails::Base.config[:keyspace]}.#{model.column_family}"
110
- uri = URI.parse(solr_url)
111
- http = Net::HTTP.new(uri.host, uri.port)
112
- if uri.scheme == 'https'
113
- http.use_ssl = true
114
- http.cert = OpenSSL::X509::Certificate.new(Rails.root.join("config","pow.crt").read)
115
- http.key = OpenSSL::PKey::RSA.new(Rails.root.join("config","pow.key").read)
116
- http.ca_path = Rails.root.join("config","sade_ca.crt").to_s
117
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
118
- end
119
- http.read_timeout = 300
120
- if force || solrconfig_digest != sm_digests['solrconfig']
121
- loop do
122
- puts "Posting Solr Config file to '#{solr_url}/solrconfig.xml'"
123
- http.post(uri.path+"/solrconfig.xml", solrconfig)
124
- if Rails.env.production?
125
- sleep(5)
126
- resp = http.get(uri.path+"/solrconfig.xml")
127
- continue unless resp.message == 'OK'
103
+ if model.payload_model?
104
+ next if model == DatastaxRails::PayloadModel
105
+ unless connection.schema.column_families[model.column_family.to_s]
106
+ puts "Creating payload model #{model.column_family}"
107
+ columns = {:chunk => :int, :payload => :text}
108
+ cql = DatastaxRails::Cql::CreateColumnFamily.new(model.column_family).key_name(:digest).key_columns("digest\", \"chunk").key_type(:text).columns(columns).with("COMPACT STORAGE").to_cql
109
+ puts cql
110
+ connection.execute_cql_query(cql)
111
+ end
112
+ else
113
+ unless connection.schema.column_families[model.column_family.to_s]
114
+ puts "Creating normal model #{model.column_family}"
115
+ cql = DatastaxRails::Cql::CreateColumnFamily.new(model.column_family).key_type(:text).columns(:updated_at => :text, :created_at => :text).to_cql
116
+ puts cql
117
+ connection.execute_cql_query(cql)
118
+ end
119
+ schema = generate_solr_schema(model)
120
+ schema_digest = Digest::SHA1.hexdigest(schema)
121
+
122
+ results = DatastaxRails::Cql::Select.new(SchemaMigration, ['*']).conditions(:KEY => model.column_family).execute
123
+ sm_digests = CassandraCQL::Result.new(results).fetch.try(:to_hash) || {}
124
+
125
+ solr_url = "#{DatastaxRails::Base.solr_base_url}/resource/#{DatastaxRails::Base.config[:keyspace]}.#{model.column_family}"
126
+ uri = URI.parse(solr_url)
127
+ http = Net::HTTP.new(uri.host, uri.port)
128
+ if uri.scheme == 'https'
129
+ http.use_ssl = true
130
+ http.cert = OpenSSL::X509::Certificate.new(Rails.root.join("config","datastax_rails.crt").read)
131
+ http.key = OpenSSL::PKey::RSA.new(Rails.root.join("config","datastax_rails.key").read)
132
+ http.ca_path = Rails.root.join("config","sade_ca.crt").to_s
133
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
134
+ end
135
+ http.read_timeout = 300
136
+ if force || solrconfig_digest != sm_digests['solrconfig']
137
+ loop do
138
+ puts "Posting Solr Config file to '#{solr_url}/solrconfig.xml'"
139
+ http.post(uri.path+"/solrconfig.xml", solrconfig)
140
+ if Rails.env.production?
141
+ sleep(5)
142
+ resp = http.get(uri.path+"/solrconfig.xml")
143
+ continue unless resp.message == 'OK'
144
+ end
145
+ break
128
146
  end
129
- break
147
+ DatastaxRails::Cql::Update.new(SchemaMigration, model.column_family).columns(:solrconfig => solrconfig_digest).execute
130
148
  end
131
- DatastaxRails::Cql::Update.new(SchemaMigration, model.column_family).columns(:solrconfig => solrconfig_digest).execute
132
- end
133
- if force || stopwords_digest != sm_digests['stopwords']
134
- loop do
135
- puts "Posting Solr Stopwords file to '#{solr_url}/stopwords.txt'"
136
- http.post(uri.path+"/stopwords.txt", stopwords)
137
- if Rails.env.production?
138
- sleep(5)
139
- resp = http.get(uri.path+"/stopwords.txt")
140
- continue unless resp.message == 'OK'
149
+ if force || stopwords_digest != sm_digests['stopwords']
150
+ loop do
151
+ puts "Posting Solr Stopwords file to '#{solr_url}/stopwords.txt'"
152
+ http.post(uri.path+"/stopwords.txt", stopwords)
153
+ if Rails.env.production?
154
+ sleep(5)
155
+ resp = http.get(uri.path+"/stopwords.txt")
156
+ continue unless resp.message == 'OK'
157
+ end
158
+ break
141
159
  end
142
- break
160
+ DatastaxRails::Cql::Update.new(SchemaMigration, model.column_family).columns(:stopwords => stopwords_digest).execute
143
161
  end
144
- DatastaxRails::Cql::Update.new(SchemaMigration, model.column_family).columns(:stopwords => stopwords_digest).execute
145
- end
146
- if force || schema_digest != sm_digests['digest']
147
- loop do
148
- puts "Posting Solr Schema file to '#{solr_url}/schema.xml'"
149
- http.post(uri.path+"/schema.xml", schema)
150
- if Rails.env.production?
151
- sleep(5)
152
- resp = http.get(uri.path+"/schema.xml")
153
- continue unless resp.message == 'OK'
162
+ if force || schema_digest != sm_digests['digest']
163
+ loop do
164
+ puts "Posting Solr Schema file to '#{solr_url}/schema.xml'"
165
+ http.post(uri.path+"/schema.xml", schema)
166
+ if Rails.env.production?
167
+ sleep(5)
168
+ resp = http.get(uri.path+"/schema.xml")
169
+ continue unless resp.message == 'OK'
170
+ end
171
+ break
172
+ end
173
+ DatastaxRails::Cql::Update.new(SchemaMigration, model.column_family).columns(:digest => schema_digest).execute
174
+ end
175
+
176
+ # Check for unindexed columns
177
+ model.attribute_definitions.each do |attribute, definition|
178
+ if !connection.schema.column_families[model.column_family.to_s].columns.has_key?(attribute.to_s)# &&
179
+ #!definition.coder.options[:stored] &&
180
+ #!definition.coder.options[:indexed]
181
+
182
+ puts "Adding column '#{attribute}' to '#{model.column_family}'"
183
+ DatastaxRails::Cql::AlterColumnFamily.new(model.column_family).add(attribute => :text).execute
154
184
  end
155
- break
156
185
  end
157
- DatastaxRails::Cql::Update.new(SchemaMigration, model.column_family).columns(:digest => schema_digest).execute
158
186
  end
159
187
  end
160
188
  end
@@ -7,12 +7,18 @@ module DatastaxRails
7
7
  # attribute :updated_at, :type => :time#_with_zone
8
8
 
9
9
  before_create do #|r|
10
- self.created_at ||= Time.current
11
- self.updated_at ||= Time.current
10
+ if self.respond_to?(:created_at=)
11
+ self.created_at ||= Time.current
12
+ end
13
+ if self.respond_to?(:updated_at=)
14
+ self.updated_at ||= Time.current
15
+ end
12
16
  end
13
17
 
14
18
  before_update :if => :changed? do #|r|
15
- self.updated_at = Time.current
19
+ if self.respond_to?(:updated_at=)
20
+ self.updated_at = Time.current
21
+ end
16
22
  end
17
23
  end
18
24
  end
@@ -7,7 +7,7 @@ module DatastaxRails
7
7
  #
8
8
  # That would give you all the posts that have Technology somewhere in the tags array.
9
9
  class ArrayType < BaseType
10
- DEFAULTS = {:solr_type => 'array', :indexed => true, :stored => true, :multi_valued => false, :sortable => false, :tokenized => true, :fulltext => false}
10
+ DEFAULTS = {:solr_type => 'array', :indexed => true, :stored => true, :multi_valued => false, :sortable => false, :tokenized => true, :fulltext => true}
11
11
 
12
12
  # An extension to normal arrays that allow for tracking of dirty values. This is
13
13
  # used by ActiveModel's change tracking framework.
@@ -4,27 +4,11 @@ module DatastaxRails
4
4
  DEFAULTS = {:solr_type => false, :indexed => false, :stored => false, :multi_valued => false, :sortable => false, :tokenized => false, :fulltext => false}
5
5
  def encode(str)
6
6
  raise ArgumentError.new("#{self} requires a String") unless str.kind_of?(String)
7
- io = StringIO.new(Base64.encode64(str))
8
- #io = StringIO.new(str)
9
- chunks = []
10
- while chunk = io.read(1.megabyte)
11
- chunks << chunk
12
- end
13
- chunks
7
+ Base64.encode64(str)
14
8
  end
15
9
 
16
- def decode(arr)
17
- if(arr.is_a?(Array))
18
- io = StringIO.new("","w+")
19
- arr.each do |chunk|
20
- io.write(chunk)
21
- end
22
- io.rewind
23
- Base64.decode64(io.read)
24
- #io.read
25
- else
26
- arr
27
- end
10
+ def decode(str)
11
+ Base64.decode64(str)
28
12
  end
29
13
 
30
14
  def wrap(record, name, value)
@@ -1,4 +1,4 @@
1
1
  module DatastaxRails
2
2
  # The current version of the gem
3
- VERSION = "1.0.16.3"
3
+ VERSION = "1.0.17.1"
4
4
  end
@@ -18,6 +18,7 @@ module DatastaxRails
18
18
  autoload :GroupedCollection
19
19
  autoload :Identity
20
20
  autoload :Migrations
21
+ autoload :PayloadModel
21
22
  autoload :Persistence
22
23
  autoload :Reflection
23
24
  autoload :Relation
@@ -77,7 +78,12 @@ require "thrift"
77
78
  module Thrift
78
79
  class BinaryProtocol
79
80
  def write_string(str)
80
- write_i32(str.bytesize)
81
+ if(str.respond_to?(:bytesize))
82
+ size = str.bytesize
83
+ else
84
+ size = str.size
85
+ end
86
+ write_i32(size)
81
87
  trans.write(str)
82
88
  end
83
89
  end
@@ -14,8 +14,6 @@ describe DatastaxRails::Base do
14
14
  end
15
15
 
16
16
  it "should raise RecordNotFound when finding a bogus ID" do
17
- pending "Datastax Enterprise 2.2 should fix this" do
18
- lambda { Person.find("xyzzy") }.should raise_exception(DatastaxRails::RecordNotFound)
19
- end
17
+ lambda { Person.find("xyzzy") }.should raise_exception(DatastaxRails::RecordNotFound)
20
18
  end
21
19
  end
@@ -7,8 +7,8 @@ describe DatastaxRails::Cql::Select do
7
7
 
8
8
  it "should generate valid CQL" do
9
9
  cql = DatastaxRails::Cql::Select.new(@model_class, ["*"])
10
- cql.using(DatastaxRails::Cql::Consistency::QUORUM).conditions(:key => '12345').limit(1)
11
- cql.to_cql.should == "SELECT * FROM users USING CONSISTENCY QUORUM WHERE key = '12345' LIMIT 1"
10
+ cql.using(DatastaxRails::Cql::Consistency::QUORUM).conditions(:KEY => '12345').limit(1)
11
+ cql.to_cql.should == "SELECT * FROM users USING CONSISTENCY QUORUM WHERE \"KEY\" = '12345' LIMIT 1 "
12
12
  end
13
13
 
14
14
  it_has_behavior "default_consistency"
@@ -8,7 +8,7 @@ describe DatastaxRails::Cql::Update do
8
8
  it "should generate valid CQL" do
9
9
  cql = DatastaxRails::Cql::Update.new(@model_class, "12345")
10
10
  cql.using(DatastaxRails::Cql::Consistency::QUORUM).columns(:name => 'John', :age => '23')
11
- cql.to_cql.should match(/update users using consistency QUORUM SET (name = 'John', age = '23'|age = '23', name = 'John') WHERE KEY IN \('12345'\)/)
11
+ cql.to_cql.should match(/update users using consistency QUORUM SET ("name" = 'John', "age" = '23'|"age" = '23', "name" = 'John') WHERE "KEY" IN \('12345'\)/)
12
12
  end
13
13
 
14
14
  it_has_behavior "default_consistency"
@@ -4,7 +4,6 @@ describe "DatastaxRails::Base" do
4
4
  describe "persistence" do
5
5
  describe "#create" do
6
6
  it "should persist at the given consistency level" do
7
- DatastaxRails::Base.connection.stub(:execute_cql_query)
8
7
  DatastaxRails::Base.connection.should_receive(:execute_cql_query).with(/USING CONSISTENCY LOCAL_QUORUM/i).and_return(true)
9
8
  Person.create({:name => 'Steven'},{:consistency => 'LOCAL_QUORUM'})
10
9
  end
@@ -12,7 +11,6 @@ describe "DatastaxRails::Base" do
12
11
 
13
12
  describe "#save" do
14
13
  it "should persist at the given consistency level" do
15
- DatastaxRails::Base.connection.stub(:execute_cql_query)
16
14
  DatastaxRails::Base.connection.should_receive(:execute_cql_query).with(/USING CONSISTENCY LOCAL_QUORUM/i).and_return(true)
17
15
  p=Person.new(:name => 'Steven')
18
16
  p.save(:consistency => 'LOCAL_QUORUM')
@@ -22,10 +20,32 @@ describe "DatastaxRails::Base" do
22
20
  describe "#remove" do
23
21
  it "should remove at the given consistency level" do
24
22
  p=Person.create(:name => 'Steven')
25
- DatastaxRails::Base.connection.stub(:execute_cql_query)
26
23
  DatastaxRails::Base.connection.should_receive(:execute_cql_query).with(/USING CONSISTENCY LOCAL_QUORUM/i).and_return(true)
27
24
  p.destroy(:consistency => :local_quorum)
28
25
  end
29
26
  end
27
+
28
+ describe "#store_file" do
29
+ it "should store a file" do
30
+ file = "abcd"*1.megabyte
31
+ CarPayload.create(:digest => 'limo', :payload => file)
32
+ CarPayload.find('limo').payload.should == file
33
+ end
34
+
35
+ it "should store really large files" do
36
+ file = IO.read("/dev/urandom", 25.megabyte)
37
+ CarPayload.create(:digest => 'limo', :payload => file)
38
+ CarPayload.find('limo').payload.should == file
39
+ end
40
+
41
+ it "should successfully overwrite a larger file with a smaller one" do
42
+ file = "abcd"*1.megabyte
43
+ car = CarPayload.create(:digest => 'limo', :payload => file)
44
+ smallfile = "e"*1.kilobyte
45
+ car.payload = smallfile
46
+ car.save
47
+ CarPayload.find('limo').payload.should == smallfile
48
+ end
49
+ end
30
50
  end
31
51
  end
@@ -6,12 +6,8 @@ development:
6
6
  connection_options:
7
7
  timeout: 10
8
8
  solr:
9
- port: 8984
9
+ port: 8983
10
10
  path: /solr
11
- ssl:
12
- use_ssl: true
13
- cert: config/datastax_rails.crt
14
- key: config/datastax_rails.key
15
11
 
16
12
  test:
17
13
  servers: ["127.0.0.1:9160"]
@@ -19,11 +15,7 @@ test:
19
15
  strategy_class: "org.apache.cassandra.locator.SimpleStrategy"
20
16
  strategy_options: {"replication_factor": "1"}
21
17
  connection_options:
22
- timeout: 10
18
+ timeout: 30
23
19
  solr:
24
- port: 8984
20
+ port: 8983
25
21
  path: /solr
26
- ssl:
27
- use_ssl: true
28
- cert: config/datastax_rails.crt
29
- key: config/datastax_rails.key