superstore 1.2.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -13
- data/CHANGELOG.md +16 -0
- data/Gemfile +0 -5
- data/README.md +15 -33
- data/lib/superstore/adapters/jsonb_adapter.rb +245 -0
- data/lib/superstore/associations/association.rb +38 -0
- data/lib/superstore/associations/belongs_to.rb +35 -0
- data/lib/superstore/associations/builder/association.rb +38 -0
- data/lib/superstore/associations/builder/belongs_to.rb +7 -0
- data/lib/superstore/associations/builder/has_many.rb +7 -0
- data/lib/superstore/associations/builder/has_one.rb +7 -0
- data/lib/superstore/associations/has_many.rb +26 -0
- data/lib/superstore/associations/has_one.rb +24 -0
- data/lib/superstore/associations/reflection.rb +65 -0
- data/lib/superstore/associations.rb +72 -0
- data/lib/superstore/attribute_methods/definition.rb +5 -10
- data/lib/superstore/attribute_methods/dirty.rb +12 -2
- data/lib/superstore/attribute_methods/typecasting.rb +6 -12
- data/lib/superstore/base.rb +3 -4
- data/lib/superstore/connection.rb +3 -5
- data/lib/superstore/core.rb +0 -5
- data/lib/superstore/model.rb +32 -33
- data/lib/superstore/persistence.rb +4 -10
- data/lib/superstore/railtie.rb +2 -20
- data/lib/superstore/scope/batches.rb +17 -22
- data/lib/superstore/scope/finder_methods.rb +33 -35
- data/lib/superstore/scope/query_methods.rb +38 -44
- data/lib/superstore/scope.rb +24 -0
- data/lib/superstore/type.rb +3 -3
- data/lib/superstore/types/array_type.rb +2 -9
- data/lib/superstore/types/base_type.rb +4 -7
- data/lib/superstore/types/boolean_type.rb +2 -1
- data/lib/superstore/types/float_type.rb +6 -5
- data/lib/superstore/types/integer_type.rb +3 -3
- data/lib/superstore/types/json_type.rb +0 -21
- data/lib/superstore.rb +16 -5
- data/superstore.gemspec +2 -1
- data/test/support/jsonb.rb +8 -0
- data/test/support/{issue.rb → models.rb} +9 -0
- data/test/support/pg.rb +11 -15
- data/test/test_helper.rb +7 -6
- data/test/unit/{belongs_to_test.rb → associations/belongs_to_test.rb} +1 -10
- data/test/unit/associations/has_many_test.rb +13 -0
- data/test/unit/associations/has_one_test.rb +14 -0
- data/test/unit/{belongs_to → associations}/reflection_test.rb +2 -2
- data/test/unit/attribute_methods/definition_test.rb +6 -3
- data/test/unit/attribute_methods/dirty_test.rb +17 -14
- data/test/unit/attribute_methods/typecasting_test.rb +0 -14
- data/test/unit/base_test.rb +3 -3
- data/test/unit/connection_test.rb +0 -4
- data/test/unit/persistence_test.rb +4 -4
- data/test/unit/schema_test.rb +9 -17
- data/test/unit/scope/query_methods_test.rb +10 -1
- data/test/unit/types/array_type_test.rb +12 -10
- data/test/unit/types/base_type_test.rb +2 -10
- data/test/unit/types/boolean_type_test.rb +15 -13
- data/test/unit/types/date_type_test.rb +3 -3
- data/test/unit/types/float_type_test.rb +14 -7
- data/test/unit/types/integer_type_test.rb +11 -9
- data/test/unit/types/json_type_test.rb +0 -23
- data/test/unit/types/string_type_test.rb +6 -6
- data/test/unit/types/time_type_test.rb +7 -7
- metadata +35 -26
- data/CHANGELOG +0 -0
- data/lib/superstore/adapters/cassandra_adapter.rb +0 -203
- data/lib/superstore/adapters/hstore_adapter.rb +0 -170
- data/lib/superstore/belongs_to/association.rb +0 -65
- data/lib/superstore/belongs_to/builder.rb +0 -40
- data/lib/superstore/belongs_to/reflection.rb +0 -38
- data/lib/superstore/belongs_to.rb +0 -63
- data/lib/superstore/cassandra_schema/statements.rb +0 -52
- data/lib/superstore/cassandra_schema/tasks.rb +0 -47
- data/lib/superstore/cassandra_schema.rb +0 -9
- data/lib/superstore/log_subscriber.rb +0 -44
- data/lib/superstore/railties/controller_runtime.rb +0 -45
- data/lib/superstore/tasks/ks.rake +0 -59
- data/test/support/cassandra.rb +0 -46
- data/test/support/hstore.rb +0 -24
- data/test/support/user.rb +0 -2
- data/test/unit/cassandra_schema/statements_test.rb +0 -47
- data/test/unit/cassandra_schema/tasks_test.rb +0 -31
- data/test/unit/log_subscriber_test.rb +0 -26
- data/test/unit/railties/controller_runtime_test.rb +0 -48
@@ -1,170 +0,0 @@
|
|
1
|
-
gem 'pg'
|
2
|
-
require 'pg'
|
3
|
-
|
4
|
-
module Superstore
|
5
|
-
module Adapters
|
6
|
-
class HstoreAdapter < AbstractAdapter
|
7
|
-
class QueryBuilder
|
8
|
-
def initialize(adapter, scope)
|
9
|
-
@adapter = adapter
|
10
|
-
@scope = scope
|
11
|
-
end
|
12
|
-
|
13
|
-
def to_query
|
14
|
-
[
|
15
|
-
"SELECT #{select_string} FROM #{@scope.klass.table_name}",
|
16
|
-
where_string,
|
17
|
-
order_string,
|
18
|
-
limit_string
|
19
|
-
].delete_if(&:blank?) * ' '
|
20
|
-
end
|
21
|
-
|
22
|
-
def select_string
|
23
|
-
if @scope.select_values.any?
|
24
|
-
"id, slice(attribute_store, #{@adapter.fields_to_postgres_array(@scope.select_values)}) as attribute_store"
|
25
|
-
else
|
26
|
-
'*'
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def where_string
|
31
|
-
wheres = @scope.where_values.dup
|
32
|
-
if @scope.id_values.any?
|
33
|
-
wheres << @adapter.create_ids_where_clause(@scope.id_values)
|
34
|
-
end
|
35
|
-
|
36
|
-
if wheres.any?
|
37
|
-
"WHERE #{wheres * ' AND '}"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def order_string
|
42
|
-
if @scope.order_values.any?
|
43
|
-
orders = @scope.order_values.join(', ')
|
44
|
-
"ORDER BY #{orders}"
|
45
|
-
elsif @scope.id_values.many?
|
46
|
-
id_orders = @scope.id_values.map { |id| "ID=#{@adapter.quote(id)} DESC" }.join(',')
|
47
|
-
"ORDER BY #{id_orders}"
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def limit_string
|
52
|
-
if @scope.limit_value
|
53
|
-
"LIMIT #{@scope.limit_value}"
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def primary_key_column
|
59
|
-
'id'
|
60
|
-
end
|
61
|
-
|
62
|
-
def connection
|
63
|
-
# conf = {:adapter=>"postgresql", :encoding=>"unicode", :database=>"axle_place_test", :pool=>5, :username=>"postgres"}
|
64
|
-
# @connection ||= ActiveRecord::Base.postgresql_connection(conf)
|
65
|
-
ActiveRecord::Base.connection
|
66
|
-
end
|
67
|
-
|
68
|
-
def execute(statement)
|
69
|
-
ActiveSupport::Notifications.instrument("cql.cassandra_object", cql: statement) do
|
70
|
-
connection.execute statement
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def select(scope)
|
75
|
-
statement = QueryBuilder.new(self, scope).to_query
|
76
|
-
|
77
|
-
connection.execute(statement).each do |attributes|
|
78
|
-
yield attributes[primary_key_column], hstore_to_attributes(attributes['attribute_store'])
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def insert(table, id, attributes)
|
83
|
-
not_nil_attributes = attributes.reject { |key, value| value.nil? }
|
84
|
-
statement = "INSERT INTO #{table} (#{primary_key_column}, attribute_store) VALUES (#{quote(id)}, #{attributes_to_hstore(not_nil_attributes)})"
|
85
|
-
execute_batchable statement
|
86
|
-
end
|
87
|
-
|
88
|
-
def update(table, id, attributes)
|
89
|
-
return if attributes.empty?
|
90
|
-
|
91
|
-
not_nil_attributes = attributes.reject { |key, value| value.nil? }
|
92
|
-
nil_attributes = attributes.select { |key, value| value.nil? }
|
93
|
-
|
94
|
-
if not_nil_attributes.any? && nil_attributes.any?
|
95
|
-
value_update = "(attribute_store - #{fields_to_postgres_array(nil_attributes.keys)}) || #{attributes_to_hstore(not_nil_attributes)}"
|
96
|
-
elsif not_nil_attributes.any?
|
97
|
-
value_update = "attribute_store || #{attributes_to_hstore(not_nil_attributes)}"
|
98
|
-
elsif nil_attributes.any?
|
99
|
-
value_update = "attribute_store - #{fields_to_postgres_array(nil_attributes.keys)}"
|
100
|
-
end
|
101
|
-
|
102
|
-
statement = "UPDATE #{table} SET attribute_store = #{value_update} WHERE #{primary_key_column} = #{quote(id)}"
|
103
|
-
execute_batchable statement
|
104
|
-
end
|
105
|
-
|
106
|
-
def delete(table, ids)
|
107
|
-
statement = "DELETE FROM #{table} WHERE #{create_ids_where_clause(ids)}"
|
108
|
-
|
109
|
-
execute_batchable statement
|
110
|
-
end
|
111
|
-
|
112
|
-
def execute_batch(statements)
|
113
|
-
stmt = [
|
114
|
-
"BEGIN",
|
115
|
-
statements * ";\n",
|
116
|
-
'COMMIT'
|
117
|
-
] * ";\n"
|
118
|
-
|
119
|
-
execute stmt
|
120
|
-
end
|
121
|
-
|
122
|
-
def create_table(table_name, options = {})
|
123
|
-
connection.execute 'CREATE EXTENSION IF NOT EXISTS hstore'
|
124
|
-
ActiveRecord::Migration.create_table table_name, id: false do |t|
|
125
|
-
t.string :id, null: false
|
126
|
-
t.hstore :attribute_store, null: false
|
127
|
-
end
|
128
|
-
connection.execute "ALTER TABLE \"#{table_name}\" ADD CONSTRAINT #{table_name}_pkey PRIMARY KEY (id)"
|
129
|
-
end
|
130
|
-
|
131
|
-
def drop_table(table_name)
|
132
|
-
ActiveRecord::Migration.drop_table table_name
|
133
|
-
end
|
134
|
-
|
135
|
-
def create_ids_where_clause(ids)
|
136
|
-
ids = ids.first if ids.is_a?(Array) && ids.one?
|
137
|
-
|
138
|
-
if ids.is_a?(Array)
|
139
|
-
id_list = ids.map { |id| quote(id) }.join(',')
|
140
|
-
"#{primary_key_column} IN (#{id_list})"
|
141
|
-
else
|
142
|
-
"#{primary_key_column} = #{quote(ids)}"
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
def quote(value)
|
147
|
-
connection.quote(value)
|
148
|
-
end
|
149
|
-
|
150
|
-
def fields_to_postgres_array(fields)
|
151
|
-
quoted_fields = fields.map { |field| "'#{field}'" }.join(',')
|
152
|
-
"ARRAY[#{quoted_fields}]"
|
153
|
-
end
|
154
|
-
|
155
|
-
private
|
156
|
-
|
157
|
-
def hstore_type
|
158
|
-
@hstore_type ||= ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Hstore.new
|
159
|
-
end
|
160
|
-
|
161
|
-
def attributes_to_hstore(attributes)
|
162
|
-
quote hstore_type.type_cast_for_database(attributes)
|
163
|
-
end
|
164
|
-
|
165
|
-
def hstore_to_attributes(string)
|
166
|
-
hstore_type.type_cast_from_database(string)
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
module Superstore
|
2
|
-
module BelongsTo
|
3
|
-
class Association
|
4
|
-
attr_reader :owner, :reflection
|
5
|
-
attr_accessor :record_variable
|
6
|
-
delegate :options, to: :reflection
|
7
|
-
|
8
|
-
def initialize(owner, reflection)
|
9
|
-
@owner = owner
|
10
|
-
@reflection = reflection
|
11
|
-
end
|
12
|
-
|
13
|
-
def reader
|
14
|
-
unless loaded?
|
15
|
-
check_appropriate_primary_key!
|
16
|
-
self.record_variable = get_record
|
17
|
-
@loaded = true
|
18
|
-
end
|
19
|
-
|
20
|
-
record_variable
|
21
|
-
end
|
22
|
-
|
23
|
-
def writer(record)
|
24
|
-
check_appropriate_primary_key!
|
25
|
-
self.record_variable = record
|
26
|
-
@loaded = true
|
27
|
-
owner.send("#{reflection.foreign_key}=", record.try(reflection.primary_key))
|
28
|
-
if reflection.polymorphic?
|
29
|
-
owner.send("#{reflection.polymorphic_column}=", record.class.name)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def association_class
|
34
|
-
association_class_name.constantize
|
35
|
-
end
|
36
|
-
|
37
|
-
def association_class_name
|
38
|
-
reflection.polymorphic? ? owner.send(reflection.polymorphic_column) : reflection.class_name
|
39
|
-
end
|
40
|
-
|
41
|
-
def loaded?
|
42
|
-
@loaded
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def get_record
|
48
|
-
record_id = owner.send(reflection.foreign_key).presence
|
49
|
-
return unless record_id
|
50
|
-
|
51
|
-
if reflection.default_primary_key?
|
52
|
-
association_class.find_by_id(record_id)
|
53
|
-
else
|
54
|
-
association_class.find_by(reflection.primary_key => record_id)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def check_appropriate_primary_key!
|
59
|
-
if !reflection.default_primary_key? && !(association_class <= ActiveRecord::Base)
|
60
|
-
raise ArgumentError, "Association must inherit from ActiveRecord::Base to use custom primary key"
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
module Superstore
|
2
|
-
module BelongsTo
|
3
|
-
class Builder
|
4
|
-
def self.build(model, name, options)
|
5
|
-
new(model, name, options).build
|
6
|
-
end
|
7
|
-
|
8
|
-
attr_reader :model, :name, :options
|
9
|
-
def initialize(model, name, options)
|
10
|
-
@model, @name, @options = model, name, options
|
11
|
-
end
|
12
|
-
|
13
|
-
def build
|
14
|
-
define_writer
|
15
|
-
define_reader
|
16
|
-
|
17
|
-
reflection = Superstore::BelongsTo::Reflection.new(model, name, options)
|
18
|
-
model.belongs_to_reflections = model.belongs_to_reflections.merge(name => reflection)
|
19
|
-
end
|
20
|
-
|
21
|
-
def mixin
|
22
|
-
model.generated_belongs_to_methods
|
23
|
-
end
|
24
|
-
|
25
|
-
def define_writer
|
26
|
-
name = self.name
|
27
|
-
mixin.redefine_method("#{name}=") do |records|
|
28
|
-
belongs_to_association(name).writer(records)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def define_reader
|
33
|
-
name = self.name
|
34
|
-
mixin.redefine_method(name) do
|
35
|
-
belongs_to_association(name).reader
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
module Superstore
|
2
|
-
module BelongsTo
|
3
|
-
class Reflection
|
4
|
-
attr_reader :model, :name, :options
|
5
|
-
def initialize(model, name, options)
|
6
|
-
@model, @name, @options = model, name, options
|
7
|
-
end
|
8
|
-
|
9
|
-
def instance_variable_name
|
10
|
-
"@#{name}"
|
11
|
-
end
|
12
|
-
|
13
|
-
def foreign_key
|
14
|
-
options[:foreign_key] || "#{name}_id"
|
15
|
-
end
|
16
|
-
|
17
|
-
def primary_key
|
18
|
-
options[:primary_key] || "id"
|
19
|
-
end
|
20
|
-
|
21
|
-
def default_primary_key?
|
22
|
-
primary_key == "id"
|
23
|
-
end
|
24
|
-
|
25
|
-
def polymorphic_column
|
26
|
-
"#{name}_type"
|
27
|
-
end
|
28
|
-
|
29
|
-
def polymorphic?
|
30
|
-
options[:polymorphic]
|
31
|
-
end
|
32
|
-
|
33
|
-
def class_name
|
34
|
-
options[:class_name] || name.to_s.camelize
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
module Superstore
|
2
|
-
module BelongsTo
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
included do
|
6
|
-
class_attribute :belongs_to_reflections
|
7
|
-
self.belongs_to_reflections = {}
|
8
|
-
end
|
9
|
-
|
10
|
-
module ClassMethods
|
11
|
-
# === Options
|
12
|
-
# [:class_name]
|
13
|
-
# Use if the class cannot be inferred from the association
|
14
|
-
# [:polymorphic]
|
15
|
-
# Specify if the association is polymorphic
|
16
|
-
# Example:
|
17
|
-
# class Driver < Superstore::Base
|
18
|
-
# end
|
19
|
-
# class Truck < Superstore::Base
|
20
|
-
# end
|
21
|
-
def belongs_to(name, options = {})
|
22
|
-
Superstore::BelongsTo::Builder.build(self, name, options)
|
23
|
-
end
|
24
|
-
|
25
|
-
def generated_belongs_to_methods
|
26
|
-
@generated_belongs_to_methods ||= begin
|
27
|
-
mod = const_set(:GeneratedBelongsToMethods, Module.new)
|
28
|
-
include mod
|
29
|
-
mod
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# Returns the belongs_to instance for the given name, instantiating it if it doesn't already exist
|
35
|
-
def belongs_to_association(name)
|
36
|
-
association = belongs_to_instance_get(name)
|
37
|
-
|
38
|
-
if association.nil?
|
39
|
-
association = Superstore::BelongsTo::Association.new(self, belongs_to_reflections[name])
|
40
|
-
belongs_to_instance_set(name, association)
|
41
|
-
end
|
42
|
-
|
43
|
-
association
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
def clear_belongs_to_cache
|
48
|
-
belongs_to_cache.clear if persisted?
|
49
|
-
end
|
50
|
-
|
51
|
-
def belongs_to_cache
|
52
|
-
@belongs_to_cache ||= {}
|
53
|
-
end
|
54
|
-
|
55
|
-
def belongs_to_instance_get(name)
|
56
|
-
belongs_to_cache[name.to_sym]
|
57
|
-
end
|
58
|
-
|
59
|
-
def belongs_to_instance_set(name, association)
|
60
|
-
belongs_to_cache[name.to_sym] = association
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
module Superstore
|
2
|
-
module Statements
|
3
|
-
DEFAULT_CREATE_KEYSPACE = {
|
4
|
-
'strategy_class' => 'SimpleStrategy',
|
5
|
-
'strategy_options:replication_factor' => 1
|
6
|
-
}
|
7
|
-
|
8
|
-
def create_keyspace(keyspace, options = nil)
|
9
|
-
stmt = "CREATE KEYSPACE #{keyspace}"
|
10
|
-
|
11
|
-
options ||= DEFAULT_CREATE_KEYSPACE
|
12
|
-
|
13
|
-
system_execute adapter.statement_with_options(stmt, options)
|
14
|
-
end
|
15
|
-
|
16
|
-
def drop_keyspace(keyspace)
|
17
|
-
system_execute "DROP KEYSPACE #{keyspace}"
|
18
|
-
end
|
19
|
-
|
20
|
-
def create_column_family(column_family, options = {})
|
21
|
-
create_table column_family, options
|
22
|
-
end
|
23
|
-
|
24
|
-
def alter_column_family(column_family, instruction, options = {})
|
25
|
-
stmt = "ALTER TABLE #{column_family} #{instruction}"
|
26
|
-
keyspace_execute adapter.statement_with_options(stmt, options)
|
27
|
-
end
|
28
|
-
|
29
|
-
def drop_column_family(column_family)
|
30
|
-
drop_table column_family
|
31
|
-
end
|
32
|
-
|
33
|
-
def add_index(column_family, column, index_name = nil)
|
34
|
-
stmt = "CREATE INDEX #{index_name.nil? ? '' : index_name} ON #{column_family} (#{column})"
|
35
|
-
keyspace_execute stmt
|
36
|
-
end
|
37
|
-
|
38
|
-
# If the index was not given a name during creation, the index name is <columnfamily_name>_<column_name>_idx.
|
39
|
-
def drop_index(index_name)
|
40
|
-
keyspace_execute "DROP INDEX #{index_name}"
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
def keyspace_execute(cql)
|
45
|
-
adapter.schema_execute cql, Superstore::Base.config[:keyspace]
|
46
|
-
end
|
47
|
-
|
48
|
-
def system_execute(cql)
|
49
|
-
adapter.schema_execute cql, 'system'
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
module Superstore
|
2
|
-
module Tasks
|
3
|
-
def dump(io)
|
4
|
-
table_names.each do |column_family|
|
5
|
-
io.puts run_command("DESCRIBE COLUMNFAMILY #{column_family}")
|
6
|
-
io.puts
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
def load(io)
|
11
|
-
current_cql = ''
|
12
|
-
|
13
|
-
io.each_line do |line|
|
14
|
-
next if line.blank?
|
15
|
-
|
16
|
-
current_cql << line.rstrip
|
17
|
-
|
18
|
-
if current_cql =~ /;$/
|
19
|
-
keyspace_execute current_cql
|
20
|
-
current_cql = ''
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def table_names
|
26
|
-
run_command('DESCRIBE COLUMNFAMILIES').split.sort
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def run_command(command)
|
32
|
-
`echo "#{command};" | #{cqlsh} -2 -k #{keyspace} #{server}`.sub(/^(.*)$/, '').strip
|
33
|
-
end
|
34
|
-
|
35
|
-
def cqlsh
|
36
|
-
ENV['CQLSH'] || 'cqlsh'
|
37
|
-
end
|
38
|
-
|
39
|
-
def keyspace
|
40
|
-
Superstore::Base.config[:keyspace]
|
41
|
-
end
|
42
|
-
|
43
|
-
def server
|
44
|
-
Superstore::Base.adapter.servers.first.gsub(/:.*/, '')
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module Superstore
|
2
|
-
class LogSubscriber < ActiveSupport::LogSubscriber
|
3
|
-
def self.runtime=(value)
|
4
|
-
Thread.current["cassandra_object_request_runtime"] = value
|
5
|
-
end
|
6
|
-
|
7
|
-
def self.runtime
|
8
|
-
Thread.current["cassandra_object_request_runtime"] ||= 0
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.reset_runtime
|
12
|
-
rt, self.runtime = runtime, 0
|
13
|
-
rt
|
14
|
-
end
|
15
|
-
|
16
|
-
def initialize
|
17
|
-
super
|
18
|
-
@odd_or_even = false
|
19
|
-
end
|
20
|
-
|
21
|
-
def cql(event)
|
22
|
-
self.class.runtime += event.duration
|
23
|
-
|
24
|
-
payload = event.payload
|
25
|
-
name = '%s (%.1fms)' % [payload[:name], event.duration]
|
26
|
-
cql = payload[:cql].squeeze(' ')
|
27
|
-
|
28
|
-
if odd?
|
29
|
-
name = color(name, CYAN, true)
|
30
|
-
cql = color(cql, nil, true)
|
31
|
-
else
|
32
|
-
name = color(name, MAGENTA, true)
|
33
|
-
end
|
34
|
-
|
35
|
-
debug " #{name} #{cql}"
|
36
|
-
end
|
37
|
-
|
38
|
-
def odd?
|
39
|
-
@odd_or_even = !@odd_or_even
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
Superstore::LogSubscriber.attach_to :cassandra_object
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/module/attr_internal'
|
2
|
-
require 'superstore/log_subscriber'
|
3
|
-
|
4
|
-
module Superstore
|
5
|
-
module Railties # :nodoc:
|
6
|
-
module ControllerRuntime #:nodoc:
|
7
|
-
extend ActiveSupport::Concern
|
8
|
-
|
9
|
-
module ClassMethods # :nodoc:
|
10
|
-
def log_process_action(payload)
|
11
|
-
messages, cassandra_object_runtime = super, payload[:cassandra_object_runtime]
|
12
|
-
if cassandra_object_runtime.to_i > 0
|
13
|
-
messages << ("Superstore: %.1fms" % cassandra_object_runtime.to_f)
|
14
|
-
end
|
15
|
-
messages
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
#private
|
20
|
-
|
21
|
-
attr_internal :cassandra_object_runtime
|
22
|
-
|
23
|
-
def process_action(action, *args)
|
24
|
-
# We also need to reset the runtime before each action
|
25
|
-
# because of queries in middleware or in cases we are streaming
|
26
|
-
# and it won't be cleaned up by the method below.
|
27
|
-
Superstore::LogSubscriber.reset_runtime
|
28
|
-
super
|
29
|
-
end
|
30
|
-
|
31
|
-
def cleanup_view_runtime
|
32
|
-
runtime_before_render = Superstore::LogSubscriber.reset_runtime
|
33
|
-
runtime = super
|
34
|
-
runtime_after_render = Superstore::LogSubscriber.reset_runtime
|
35
|
-
self.cassandra_object_runtime = runtime_before_render + runtime_after_render
|
36
|
-
runtime - runtime_after_render
|
37
|
-
end
|
38
|
-
|
39
|
-
def append_info_to_payload(payload)
|
40
|
-
super
|
41
|
-
payload[:cassandra_object_runtime] = (cassandra_object_runtime || 0) + Superstore::LogSubscriber.reset_runtime
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
ks_namespace = namespace :ks do
|
2
|
-
desc 'Create the keyspace in config/superstore.yml for the current environment'
|
3
|
-
task create: :environment do
|
4
|
-
begin
|
5
|
-
Superstore::CassandraSchema.create_keyspace Superstore::Base.config[:keyspace], Superstore::Base.config[:keyspace_options]
|
6
|
-
rescue Exception => e
|
7
|
-
if e.message =~ /conflicts/
|
8
|
-
p "Keyspace #{Superstore::Base.config[:keyspace]} already exists"
|
9
|
-
else
|
10
|
-
raise e
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
desc 'Remove the keyspace in config/superstore.yml for the current environment'
|
16
|
-
task drop: :environment do
|
17
|
-
begin
|
18
|
-
Superstore::CassandraSchema.drop_keyspace Superstore::Base.config[:keyspace]
|
19
|
-
rescue Exception => e
|
20
|
-
if e.message =~ /non existing keyspace/
|
21
|
-
p "Keyspace #{Superstore::Base.config[:keyspace]} does not exist"
|
22
|
-
else
|
23
|
-
raise e
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
desc 'Alias for ks:drop and ks:setup'
|
29
|
-
task reset: [:drop, :setup]
|
30
|
-
|
31
|
-
desc 'Alias for ks:create and ks:structure:load'
|
32
|
-
task setup: [:create, :_load]
|
33
|
-
|
34
|
-
namespace :structure do
|
35
|
-
desc 'Serialize the current structure for the keyspace in config/superstore.yml to the SCHEMA environment variable (defaults to "$RAILS_ROOT/ks/structure.cql")'
|
36
|
-
task dump: :environment do
|
37
|
-
filename = ENV['SCHEMA'] || "#{Rails.root}/ks/structure.cql"
|
38
|
-
File.open(filename, "w:utf-8") do |file|
|
39
|
-
Superstore::CassandraSchema.dump(file)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
desc 'Load the structure for the keyspace in config/superstore.yml from the SCHEMA environment variable (defaults to "$RAILS_ROOT/ks/structure.cql")'
|
44
|
-
task load: :environment do
|
45
|
-
filename = ENV['SCHEMA'] || "#{Rails.root}/ks/structure.cql"
|
46
|
-
File.open(filename) do |file|
|
47
|
-
Superstore::CassandraSchema.load(file)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
task :_dump do
|
53
|
-
ks_namespace["structure:dump"].invoke
|
54
|
-
end
|
55
|
-
|
56
|
-
task :_load do
|
57
|
-
ks_namespace["structure:load"].invoke
|
58
|
-
end
|
59
|
-
end
|
data/test/support/cassandra.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
Bundler.require :cassandra
|
2
|
-
|
3
|
-
Superstore::Base.config = {
|
4
|
-
keyspace: 'superstore_test',
|
5
|
-
servers: '127.0.0.1:9160',
|
6
|
-
consistency: 'QUORUM',
|
7
|
-
thrift: {
|
8
|
-
timeout: 5
|
9
|
-
}
|
10
|
-
}
|
11
|
-
|
12
|
-
begin
|
13
|
-
Superstore::CassandraSchema.drop_keyspace 'superstore_test'
|
14
|
-
rescue Exception => e
|
15
|
-
end
|
16
|
-
|
17
|
-
sleep 1
|
18
|
-
Superstore::CassandraSchema.create_keyspace 'superstore_test'
|
19
|
-
Superstore::CassandraSchema.create_column_family 'Issues'
|
20
|
-
Superstore::CassandraSchema.alter_column_family 'Issues', "ADD title varchar"
|
21
|
-
Superstore::CassandraSchema.add_index 'Issues', 'title', "issues_title_idx"
|
22
|
-
|
23
|
-
Superstore::Base.class_eval do
|
24
|
-
class_attribute :created_records
|
25
|
-
self.created_records = []
|
26
|
-
|
27
|
-
after_create do
|
28
|
-
created_records << self
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.delete_after_test
|
32
|
-
# created_records.reject(&:destroyed?).each(&:destroy)
|
33
|
-
Issue.delete_all
|
34
|
-
created_records.clear
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
module ActiveSupport
|
39
|
-
class TestCase
|
40
|
-
teardown do
|
41
|
-
if Superstore::Base.created_records.any?
|
42
|
-
Superstore::Base.delete_after_test
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|