optic-rails 0.0.6 → 0.1.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/lib/optic/rails.rb +52 -41
- data/lib/optic/rails/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b2cff9fec79805dad7c1257d4510b13a4e253959942930cf60044195f47323c9
|
4
|
+
data.tar.gz: 5d83085f13bba93a899125f0047965d4176056c7260f6772d69af895b9868d89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ee4a8807e8e46da376e3acf326078ef46b07ea94bb4536f7c9bf8875075d31bf80764cef33d453c7a00ac876cbe82dffb1bbce1ebaf366eaa113d0de514ddb81
|
7
|
+
data.tar.gz: d0cc8c92cd20111aa7c24719e22b87e9852006a53102cde5bbd0b256c8c746b75cf541947c8189321a06be902f257bd71b7c1d768c30a76ece5622709951389c
|
data/lib/optic/rails.rb
CHANGED
@@ -103,57 +103,68 @@ module Optic
|
|
103
103
|
}
|
104
104
|
end
|
105
105
|
|
106
|
-
|
106
|
+
# Try to be defensive with our DB connection:
|
107
|
+
# 1) Check a connection out from the thread pool instead of using an implicit one
|
108
|
+
# 2) Make the connection read-only
|
109
|
+
# 3) Time out any queries that take more than 100ms
|
110
|
+
def self.with_connection
|
107
111
|
ActiveRecord::Base.connection_pool.with_connection do |connection|
|
108
|
-
connection.
|
112
|
+
connection.transaction do
|
113
|
+
connection.execute "SET TRANSACTION READ ONLY"
|
114
|
+
connection.execute "SET LOCAL statement_timeout = 100"
|
115
|
+
yield connection
|
116
|
+
end
|
109
117
|
end
|
110
118
|
end
|
111
119
|
|
112
120
|
def self.get_metrics(pivot_name)
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
121
|
+
with_connection do |connection|
|
122
|
+
pivot = pivot_name.constantize
|
123
|
+
pivot_values = connection.execute(pivot.unscoped.select("*").to_sql).to_a
|
124
|
+
|
125
|
+
result = {
|
126
|
+
entity_totals: [],
|
127
|
+
pivot_name: pivot.name,
|
128
|
+
# TODO filter columns, spread over multiple queries
|
129
|
+
pivot_values: pivot_values,
|
130
|
+
pivoted_totals: []
|
131
|
+
# TODO also return computed "spanning" tree of objects from the pivot's POV (using the dijkstra paths from below)
|
132
|
+
}
|
133
|
+
|
134
|
+
graph = entity_graph
|
135
|
+
|
136
|
+
# Spit out counts for each entity by the customer pivot
|
137
|
+
|
138
|
+
edge_weights = lambda { |_| 1 }
|
139
|
+
|
140
|
+
graph.vertices.each do |vertex|
|
141
|
+
count_query = vertex.unscoped.select("COUNT(*)").to_sql
|
142
|
+
result[:entity_totals] << { name: vertex.name, total: connection.execute(count_query).first["count"] }
|
143
|
+
|
144
|
+
next if vertex == pivot # Skip pivoted metrics if this is the pivot
|
145
|
+
|
146
|
+
# TODO weight edges to give preference to non-optional belongs_to (and other attributes?)
|
147
|
+
path = graph.dijkstra_shortest_path(edge_weights, vertex, pivot)
|
148
|
+
if path
|
149
|
+
# Generate a SQL query to count the number of vertex instances grouped by pivot id, with appropriate joins from the path
|
150
|
+
belongs_to_names = path.each_cons(2).map do |join_from, join_to|
|
151
|
+
# TODO we shouldn't have to look up the edge again - use a graph model that allows us to annotate the edges with the reflections
|
152
|
+
reflections = join_from.reflect_on_all_associations(:belongs_to).find_all { |reflection| !reflection.options[:polymorphic] && reflection.klass == join_to }
|
153
|
+
raise "Multiple belongs_to unsupported" unless reflections.size == 1 # TODO
|
154
|
+
reflections.first.name
|
155
|
+
end
|
133
156
|
|
134
|
-
|
157
|
+
joins = belongs_to_names.reverse.inject { |acc, elt| { elt => acc } }
|
158
|
+
query = vertex.unscoped.joins(joins).group(qualified_primary_key(pivot)).select(qualified_primary_key(pivot), "COUNT(#{qualified_primary_key(vertex)})").to_sql
|
135
159
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
# Generate a SQL query to count the number of vertex instances grouped by pivot id, with appropriate joins from the path
|
140
|
-
belongs_to_names = path.each_cons(2).map do |join_from, join_to|
|
141
|
-
# TODO we shouldn't have to look up the edge again - use a graph model that allows us to annotate the edges with the reflections
|
142
|
-
reflections = join_from.reflect_on_all_associations(:belongs_to).find_all { |reflection| !reflection.options[:polymorphic] && reflection.klass == join_to }
|
143
|
-
raise "Multiple belongs_to unsupported" unless reflections.size == 1 # TODO
|
144
|
-
reflections.first.name
|
160
|
+
result[:pivoted_totals] << { entity_name: vertex.name, totals: Hash[connection.execute(query).map { |record| [record["id"], record["count"]] }] }
|
161
|
+
else
|
162
|
+
p "WARNING: No path from #{vertex.name} to #{pivot.name}"
|
145
163
|
end
|
146
|
-
|
147
|
-
joins = belongs_to_names.reverse.inject { |acc, elt| { elt => acc } }
|
148
|
-
query = vertex.unscoped.joins(joins).group(qualified_primary_key(pivot)).select(qualified_primary_key(pivot), "COUNT(#{qualified_primary_key(vertex)})").to_sql
|
149
|
-
|
150
|
-
result[:pivoted_totals] << { entity_name: vertex.name, totals: Hash[execute_sql_query(query).map { |record| [record["id"], record["count"]] }] }
|
151
|
-
else
|
152
|
-
p "WARNING: No path from #{vertex.name} to #{pivot.name}"
|
153
164
|
end
|
154
|
-
end
|
155
165
|
|
156
|
-
|
166
|
+
result
|
167
|
+
end
|
157
168
|
end
|
158
169
|
|
159
170
|
end
|
data/lib/optic/rails/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: optic-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anton Vaynshtok
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-05-
|
11
|
+
date: 2018-05-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: action_cable_client
|