cassandra_migrations 0.2.2 → 0.2.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d089b09a2a03caa0cb2787d2de0e8d2f2db278bc
4
- data.tar.gz: a1f2fbc186ff690aa33c58306f6d193c19fb3643
3
+ metadata.gz: 2adbd178415bd43d539d236b8a2c46b21e8a7f72
4
+ data.tar.gz: 1216e38539fdebb43798770efdefe8c091c19bb4
5
5
  SHA512:
6
- metadata.gz: c2606317f233f502898569d15903ad5816b106e69cd1d29831677a8215bf38cc0d20bffe8fe4bb76df13619e2728ae796751b9b0246acd3039f469b7c9411ee3
7
- data.tar.gz: 36bae513a0ae96563a2c989148baaa24c9d6bde62baba44fa0fcb03cd2f9a12f286dd37bfb3ba30b1b44c99e40059a6e34870a185faf171a99acbc7797ee42a9
6
+ metadata.gz: 015a4ec736b6900eb9fe8a24da10baea299752718ac025b487decf15fbe5cad684951da2e282af0d8df178b35556f7d32fb1cc7127e79f8313a2e5486ab9ba5a
7
+ data.tar.gz: 276c5d3a589d3e73a9f61f96d8cdc78eb76584d8f23c04cfe05f8db37fae59bca11c0cf8e402d13f972e8af92f21121ad2155a313a650c9bd7fe0fc59e77cbe9
@@ -7,16 +7,18 @@ module CassandraMigrations
7
7
 
8
8
  def create_keyspace!(env)
9
9
  config = Config.configurations[env]
10
+ validate_config(config)
11
+
12
+ execute(
13
+ "CREATE KEYSPACE #{config.keyspace} \
14
+ WITH replication = { \
15
+ 'class':'#{config.replication['class']}', \
16
+ 'replication_factor': #{config.replication['replication_factor']} \
17
+ }"
18
+ )
10
19
  begin
11
- execute(
12
- "CREATE KEYSPACE #{config.keyspace} \
13
- WITH replication = { \
14
- 'class':'#{config.replication['class']}', \
15
- 'replication_factor': #{config.replication['replication_factor']} \
16
- }"
17
- )
18
20
  use(config.keyspace)
19
- rescue Exception => exception
21
+ rescue StandardErorr => exception
20
22
  drop_keyspace!(env)
21
23
  raise exception
22
24
  end
@@ -26,11 +28,28 @@ module CassandraMigrations
26
28
  config = Config.configurations[env]
27
29
  begin
28
30
  execute("DROP KEYSPACE #{config.keyspace}")
29
- rescue ::Cassandra::Errors::QueryError
31
+ rescue ::Cassandra::Errors::ConfigurationError
30
32
  raise Errors::UnexistingKeyspaceError, config.keyspace
31
33
  end
32
34
  end
33
35
 
36
+ private
37
+
38
+ def validate_config(config)
39
+ if config.keyspace.nil?
40
+ raise Errors::MissingConfigurationError.new("Configuration of 'keyspace' is required in config.yml, but none is defined.")
41
+ end
42
+ unless config_includes_replication?(config)
43
+ raise Errors::MissingConfigurationError.new("Configuration for 'replication' is required in config.yml, but none is defined.")
44
+ end
45
+ true
46
+ end
47
+
48
+ def config_includes_replication?(config)
49
+ config.replication &&
50
+ config.replication['class'] &&
51
+ config.replication['replication_factor']
52
+ end
34
53
  end
35
54
  end
36
55
  end
@@ -41,6 +41,7 @@ module CassandraMigrations
41
41
 
42
42
  def select(table, options={})
43
43
  query_string = "SELECT #{options[:projection] || '*'} FROM #{table}"
44
+ options[:secondary_options] ||= {}
44
45
 
45
46
  if options[:selection]
46
47
  query_string << " WHERE #{options[:selection]}"
@@ -58,7 +59,40 @@ module CassandraMigrations
58
59
  query_string << " ALLOW FILTERING"
59
60
  end
60
61
 
61
- execute(query_string)
62
+ #Secondary options
63
+ if options[:page_size]
64
+ options[:secondary_options][:page_size] = options[:page_size]
65
+ end
66
+
67
+ if options[:consistency]
68
+ options[:secondary_options][:consistency] = options[:consistency]
69
+ end
70
+
71
+ if options[:trace]
72
+ options[:secondary_options][:trace] = options[:trace]
73
+ end
74
+
75
+ if options[:timeout]
76
+ options[:secondary_options][:timeout] = options[:timeout]
77
+ end
78
+
79
+ if options[:serial_consistency]
80
+ options[:secondary_options][:serial_consistency] = options[:serial_consistency]
81
+ end
82
+
83
+ if options[:paging_state]
84
+ options[:secondary_options][:paging_state] = options[:paging_state]
85
+ end
86
+
87
+ if options[:arguments]
88
+ options[:secondary_options][:arguments] = options[:arguments]
89
+ end
90
+
91
+ if options[:secondary_options].length > 0
92
+ execute(query_string, options[:secondary_options])
93
+ else
94
+ execute(query_string)
95
+ end
62
96
  end
63
97
 
64
98
  def delete!(table, selection, options={})
@@ -93,7 +127,7 @@ module CassandraMigrations
93
127
 
94
128
  def get_column_type(table, column)
95
129
  column_info = client.execute("SELECT VALIDATOR FROM system.schema_columns WHERE keyspace_name = '#{client.keyspace}' AND columnfamily_name = '#{table}' AND column_name = '#{column}'")
96
- SYMBOL_FOR_TYPE[column_info.first['validator']]
130
+ SYMBOL_FOR_TYPE[(column_info.first['validator'].split(/[\.(]/) & SYMBOL_FOR_TYPE.keys).first]
97
131
  end
98
132
 
99
133
  def to_cql_value(column, value, table, options={})
@@ -113,13 +147,13 @@ module CassandraMigrations
113
147
  if value == ""
114
148
  value = 'null'
115
149
  else
116
- value = value
150
+ value = value.gsub("'", "''")
117
151
  end
118
152
  end
119
153
  end
120
154
 
121
155
  def string_to_cql(value)
122
- "'#{value}'"
156
+ "'#{value.gsub("'", "''")}'"
123
157
  end
124
158
 
125
159
  def datetime_to_cql(value)
@@ -138,7 +172,7 @@ module CassandraMigrations
138
172
  end
139
173
 
140
174
  def hash_to_cql(value, operation)
141
- "#{operation}{ #{value.reduce([]) {|sum, (key, value)| sum << "'#{key}': '#{value}'" }.join(", ") } }"
175
+ "#{operation}{ #{value.reduce([]) {|sum, (k, v)| sum << "'#{k}': #{to_cql_value(nil, v, nil)}" }.join(", ") } }"
142
176
  end
143
177
 
144
178
  end
@@ -28,8 +28,15 @@ module CassandraMigrations
28
28
  def self.restart!
29
29
  raise Errors::ClientNotStartedError unless client
30
30
 
31
- client.close if client && client.connected?
32
- self.client = nil
31
+ restart
32
+ end
33
+
34
+ def self.restart
35
+ if client
36
+ client.close if client.connected?
37
+ self.client = nil
38
+ end
39
+
33
40
  start!
34
41
  end
35
42
 
@@ -57,10 +64,10 @@ module CassandraMigrations
57
64
  end
58
65
  end
59
66
 
60
- def self.execute(cql)
67
+ def self.execute(*cql)
61
68
  connect_to_server unless client
62
69
  Rails.logger.try(:info, "\e[1;35m [Cassandra Migrations] \e[0m #{cql.to_s}")
63
- result = client.execute(cql)
70
+ result = client.execute(*cql)
64
71
  QueryResult.new(result) if result
65
72
  end
66
73
 
@@ -68,7 +75,6 @@ module CassandraMigrations
68
75
 
69
76
  def self.connect_to_server
70
77
  connection_params = Config.connection_config_for_env
71
- Rails.logger.try(:info, "Connecting to Cassandra on #{connection_params}")
72
78
 
73
79
  begin
74
80
  self.client = Client.connect(connection_params)
@@ -34,13 +34,12 @@ end
34
34
 
35
35
  class Client
36
36
  def self.connect(options)
37
- if defined?(Spring)
38
- Spring.after_fork do
39
- @cluster = Cassandra.cluster(options)
40
- end
41
- else
42
- @cluster = Cassandra.cluster(options)
37
+ Rails.logger.try(:info, "Connecting to Cassandra cluster: #{options}")
38
+
39
+ unless @cluster = Cassandra.cluster(options)
40
+ raise CassandraMigrations::Errors::ClusterError.new(options)
43
41
  end
42
+
44
43
  self.new(@cluster)
45
44
  end
46
45
 
@@ -48,6 +47,7 @@ class Client
48
47
  if @sessions[keyspace]
49
48
  @session = @sessions[keyspace]
50
49
  else
50
+ Rails.logger.try(:info, "Creating Cassandra session: #{keyspace.inspect}")
51
51
  @session = @cluster.connect(keyspace)
52
52
  @sessions[keyspace] = @session
53
53
  end
@@ -57,9 +57,11 @@ class Client
57
57
  @cluster = cluster
58
58
  @sessions = {}
59
59
  if keyspace
60
+ Rails.logger.try(:info, "Creating Cassandra session: #{keyspace.inspect}")
60
61
  @session = cluster.connect(keyspace)
61
62
  @sessions[keyspace] = @session
62
63
  else
64
+ Rails.logger.try(:info, "Creating Cassandra session: [no keyspace]")
63
65
  @session = @cluster.connect()
64
66
  @sessions[:default] = @session
65
67
  end
@@ -85,6 +87,7 @@ class Client
85
87
  end
86
88
 
87
89
  def close
90
+ Rails.logger.try(:info, "Closing Cassandra session: #{@session.inspect}")
88
91
  @session.close
89
92
  end
90
93
 
@@ -34,6 +34,12 @@ module CassandraMigrations
34
34
  end
35
35
  end
36
36
 
37
+ class ClusterError < CassandraError
38
+ def initialize(cluster_opts, e = nil)
39
+ super(%[Could not connect to cluster at #{cluster_opts}. Is Cassandra running? #{"(#{e.message})" if e}])
40
+ end
41
+ end
42
+
37
43
  class ConnectionError < CassandraError
38
44
  def initialize(msg)
39
45
  super(msg)
@@ -65,26 +65,6 @@ module CassandraMigrations
65
65
  execute drop_index_cql
66
66
  end
67
67
 
68
- def create_table(table_name, options = {})
69
- table_definition = TableDefinition.new
70
- table_definition.define_primary_keys(options[:primary_keys]) if options[:primary_keys]
71
- table_definition.define_partition_keys(options[:partition_keys]) if options[:partition_keys]
72
- table_definition.define_options(options[:options]) if options[:options]
73
-
74
- yield table_definition if block_given?
75
-
76
- announce_operation "create_table(#{table_name})"
77
-
78
- create_cql = "CREATE TABLE #{table_name} ("
79
- create_cql << table_definition.to_create_cql
80
- create_cql << ")"
81
- create_cql << table_definition.options
82
-
83
- announce_suboperation create_cql
84
-
85
- execute create_cql
86
- end
87
-
88
68
  end
89
69
  end
90
70
  end
@@ -43,7 +43,7 @@ module CassandraMigrations
43
43
  def self.read_current_version
44
44
  begin
45
45
  Cassandra.select(METADATA_TABLE, :selection => "data_name='version'", :projection => 'data_value').first['data_value'].to_i
46
- rescue ::Cassandra::Errors::QueryError => e # table cassandra_migrations_metadata does not exist
46
+ rescue ::Cassandra::Errors::InvalidError => e # table cassandra_migrations_metadata does not exist
47
47
  Cassandra.execute("CREATE TABLE #{METADATA_TABLE} (data_name varchar PRIMARY KEY, data_value varchar)")
48
48
  Cassandra.write!(METADATA_TABLE, {:data_name => 'version', :data_value => '0'})
49
49
  return 0
@@ -0,0 +1,11 @@
1
+ Description:
2
+ Generates a default cassandra database configuration
3
+
4
+ Example:
5
+ rails generate cassandra_configuration
6
+
7
+ This will create:
8
+ config/cassandra.yml
9
+
10
+ Inside this file a default configuration will be ready for completion:
11
+
@@ -0,0 +1,32 @@
1
+ class CassandraConfigurationGenerator < Rails::Generators::Base
2
+ source_root File.expand_path('templates', File.dirname(__FILE__))
3
+
4
+ # Creates configuration file and migration directory
5
+ #
6
+ # Any public method in the generator is run automatically when
7
+ # the generator is run. To understand fully see
8
+ # http://asciicasts.com/episodes/218-making-generators-in-rails-3
9
+
10
+ def generate_configuration
11
+ require 'fileutils'
12
+ require 'colorize'
13
+
14
+ # create cassandra.yaml
15
+ if File.exists?(File.expand_path('config/cassandra.yml'))
16
+ puts "[skip] 'config/cassandra.yml' already exists".yellow
17
+ else
18
+ puts "[new] creating 'config/cassandra.yml' (please update with your own configurations!)".green
19
+ template "cassandra.yml", "config/cassandra.yml"
20
+ end
21
+
22
+ # create db/cassandra_migrations
23
+ if File.exists?(File.expand_path('db/cassandra_migrate'))
24
+ puts "[skip] 'db/cassandra_migrate' already exists".yellow
25
+ else
26
+ puts "[new] creating 'db/cassandra_migrate' directory".green
27
+ FileUtils.mkdir(File.expand_path('db/cassandra_migrate'))
28
+ end
29
+
30
+ puts '[done]'.green
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ development:
2
+ hosts:
3
+ - 127.0.0.1
4
+ port: 9042
5
+ keyspace: my_keyspace_dev
6
+ replication:
7
+ class: SimpleStrategy
8
+ replication_factor: 1
9
+
10
+ test:
11
+ hosts:
12
+ - 127.0.0.1
13
+ port: 9042
14
+ keyspace: cassandra_migrations_test
15
+ replication:
16
+ class: 'SimpleStrategy'
17
+ replication_factor: 1
18
+
19
+ production:
20
+ hosts:
21
+ - 'cass1.my_app.biz'
22
+ - 'cass2.my_app.biz'
23
+ - 'cass3.my_app.biz'
24
+ port: 9042
25
+ keyspace: cassandra_migrations_production
26
+ username: myappuser
27
+ password: password1
28
+ replication:
29
+ class: NetworkTopologyStrategy
30
+ datacenter1: 3
31
+ datacenter2: 2
@@ -11,20 +11,19 @@
11
11
 
12
12
  module CassandraMigrations
13
13
 
14
+ Cassandra.start!
15
+
16
+ if defined?(Spring)
17
+ Spring.after_fork do
18
+ Cassandra.restart
19
+ end
20
+ end
21
+
14
22
  if defined?(PhusionPassenger)
15
23
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
16
24
  if forked
17
- if Cassandra.client
18
- Rails.logger.info "Passenger process forked: reconnecting to Cassandra..."
19
- Cassandra.restart!
20
- else
21
- Rails.logger.info "Passenger process forked: connecting to Cassandra..."
22
- Cassandra.start!
23
- end
25
+ Cassandra.restart
24
26
  end
25
27
  end
26
- else
27
- Cassandra.start!
28
28
  end
29
-
30
29
  end
@@ -51,18 +51,26 @@ namespace :cassandra do
51
51
  end
52
52
  end
53
53
 
54
- desc 'Resets and prepares cassandra database (all data will be lost)'
54
+ namespace :migrate do
55
+ desc 'Resets and prepares cassandra database (all data will be lost)'
56
+ task :reset do
57
+ Rake::Task['cassandra:drop'].execute
58
+ Rake::Task['cassandra:create'].execute
59
+ Rake::Task['cassandra:migrate'].execute
60
+ end
61
+ end
62
+
55
63
  task :setup do
56
- Rake::Task['cassandra:drop'].execute
64
+ puts "DEPRECATION WARNING: `cassandra:setup` rake task has been deprecated, use `cassandra:migrate:reset` instead"
57
65
  Rake::Task['cassandra:create'].execute
58
66
  Rake::Task['cassandra:migrate'].execute
59
67
  end
60
68
 
61
69
  namespace :test do
62
- desc 'Load the development schema in to the test keyspace'
70
+ desc 'Load the development schema in to the test keyspace via a full reset'
63
71
  task :prepare do
64
72
  Rails.env = 'test'
65
- Rake::Task['cassandra:setup'].execute
73
+ Rake::Task['cassandra:migrate:reset'].execute
66
74
  end
67
75
  end
68
76
 
@@ -71,4 +79,6 @@ namespace :cassandra do
71
79
  puts "Current version: #{CassandraMigrations::Migrator.read_current_version}"
72
80
  end
73
81
 
82
+ task
83
+
74
84
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cassandra_migrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henrique Gubert
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-03-01 00:00:00.000000000 Z
12
+ date: 2015-11-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cassandra-driver
@@ -82,19 +82,19 @@ dependencies:
82
82
  - !ruby/object:Gem::Version
83
83
  version: 3.1.0
84
84
  - !ruby/object:Gem::Dependency
85
- name: debugger
85
+ name: byebug
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
88
  - - "~>"
89
89
  - !ruby/object:Gem::Version
90
- version: '1.6'
90
+ version: '8.2'
91
91
  type: :development
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
95
  - - "~>"
96
96
  - !ruby/object:Gem::Version
97
- version: '1.6'
97
+ version: '8.2'
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: bundler
100
100
  requirement: !ruby/object:Gem::Requirement
@@ -142,12 +142,10 @@ description: A gem to manage Cassandra database schema for Rails. This gem offer
142
142
  email:
143
143
  - guberthenrique@hotmail.com
144
144
  - bsbodden@integrallis.com
145
- executables:
146
- - prepare_for_cassandra
145
+ executables: []
147
146
  extensions: []
148
147
  extra_rdoc_files: []
149
148
  files:
150
- - bin/prepare_for_cassandra
151
149
  - lib/cassandra_migrations.rb
152
150
  - lib/cassandra_migrations/capistrano.rb
153
151
  - lib/cassandra_migrations/cassandra.rb
@@ -163,12 +161,14 @@ files:
163
161
  - lib/cassandra_migrations/migration/table_operations.rb
164
162
  - lib/cassandra_migrations/migrator.rb
165
163
  - lib/cassandra_migrations/railtie.rb
164
+ - lib/cassandra_migrations/railtie/generators/cassandra_configuration/USAGE
165
+ - lib/cassandra_migrations/railtie/generators/cassandra_configuration/cassandra_configuration_generator.rb
166
+ - lib/cassandra_migrations/railtie/generators/cassandra_configuration/templates/cassandra.yml
166
167
  - lib/cassandra_migrations/railtie/generators/cassandra_migration/USAGE
167
168
  - lib/cassandra_migrations/railtie/generators/cassandra_migration/cassandra_migration_generator.rb
168
169
  - lib/cassandra_migrations/railtie/generators/cassandra_migration/templates/empty_migration.rb.erb
169
170
  - lib/cassandra_migrations/railtie/initializer.rb
170
171
  - lib/cassandra_migrations/railtie/tasks.rake
171
- - template/cassandra.yml
172
172
  homepage: https://github.com/hsgubert/cassandra_migrations
173
173
  licenses:
174
174
  - MIT
@@ -189,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
189
189
  version: 1.8.0
190
190
  requirements: []
191
191
  rubyforge_project:
192
- rubygems_version: 2.2.2
192
+ rubygems_version: 2.4.8
193
193
  signing_key:
194
194
  specification_version: 4
195
195
  summary: Cassandra schema management for a multi-environment developer.
@@ -1,62 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'optparse'
4
- require 'fileutils'
5
- require 'colorize'
6
-
7
- OptionParser.new do |opts|
8
- opts.banner = "Usage: #{File.basename($0)} [path]"
9
-
10
- opts.on("-h", "--help", "Displays this help info") do
11
- puts opts
12
- exit 0
13
- end
14
-
15
- begin
16
- opts.parse!(ARGV)
17
- rescue OptionParser::ParseError => e
18
- warn e.message
19
- puts opts
20
- exit 1
21
- end
22
- end
23
-
24
- if ARGV.empty?
25
- abort "Please specify the directory of a rails appilcation, e.g. `#{File.basename($0)} .'"
26
- elsif !File.directory?(ARGV.first)
27
- abort "`#{ARGV.first}' is not a directory."
28
- elsif ARGV.length > 1
29
- abort "Too many arguments; please specify only the directory of the rails application."
30
- end
31
-
32
- rails_root = ARGV.first
33
-
34
- # create cassandra.yaml
35
- if File.exists?(File.expand_path('config/cassandra.yml', rails_root))
36
- puts "[skip] 'config/cassandra.yml' already exists".yellow
37
- else
38
- puts "[new] creating 'config/cassandra.yml' (please update with your own configurations!)".green
39
- FileUtils.cp(
40
- File.expand_path('../template/cassandra.yml', File.dirname(__FILE__)),
41
- File.expand_path('config/cassandra.yml', rails_root)
42
- )
43
- end
44
-
45
- # create db/cassandra_migrations
46
- if File.exists?(File.expand_path('db/cassandra_migrate', rails_root))
47
- puts "[skip] 'db/cassandra_migrate' already exists".yellow
48
- else
49
- puts "[new] creating 'db/cassandra_migrate' directory".green
50
- FileUtils.mkdir(File.expand_path('db/cassandra_migrate', rails_root))
51
- end
52
-
53
- puts '[done] prepared for cassandra!'.green
54
- puts ''
55
- puts 'Your steps from here are:'.green
56
- puts ' 1. configure '.green + 'config/cassandra.yml'.red
57
- puts ' 2. run '.green + 'rake cassandra:setup'.red + ' and try starting your application'.green
58
- puts ' 3. create your first migration with '.green + 'rails g cassandra_migration'.red
59
- puts ' 4. apply your migration with '.green + 'rake cassandra:migrate'.red
60
- puts ' 5. run '.green + 'rake cassandra:test:prepare'.red + ' and start testing'.green
61
- puts ' 6. have lots of fun!'.green.blink
62
-
@@ -1,23 +0,0 @@
1
- development:
2
- hosts: ['127.0.0.1']
3
- port: 9042
4
- keyspace: 'my_keyspace_name'
5
- replication:
6
- class: 'SimpleStrategy'
7
- replication_factor: 1
8
-
9
- test:
10
- hosts: ['127.0.0.1']
11
- port: 9042
12
- keyspace: 'my_keyspace_name_test'
13
- replication:
14
- class: 'SimpleStrategy'
15
- replication_factor: 1
16
-
17
- production:
18
- hosts: ['127.0.0.1']
19
- port: 9042
20
- keyspace: 'my_keyspace_name_production'
21
- replication:
22
- class: 'SimpleStrategy'
23
- replication_factor: 1