superstore 1.2.0 → 2.0.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.
- 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
|