marty 2.5.2 → 2.5.4
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 +5 -5
- data/.gitignore +4 -0
- data/.rubocop.yml +7 -0
- data/.rubocop_todo.yml +11 -589
- data/Gemfile +9 -9
- data/Gemfile.lock +1 -1
- data/Rakefile +1 -3
- data/app/components/marty/api_auth_view.rb +3 -3
- data/app/components/marty/api_config_view.rb +8 -8
- data/app/components/marty/api_log_view.rb +16 -20
- data/app/components/marty/auth_app.rb +6 -6
- data/app/components/marty/base_rule_view.rb +27 -19
- data/app/components/marty/config_view.rb +12 -9
- data/app/components/marty/data_grid_view.rb +26 -26
- data/app/components/marty/delorean_rule_view.rb +0 -1
- data/app/components/marty/event_view.rb +27 -27
- data/app/components/marty/extras/layout.rb +26 -26
- data/app/components/marty/extras/misc.rb +2 -2
- data/app/components/marty/grid.rb +13 -13
- data/app/components/marty/grid_append_only.rb +0 -1
- data/app/components/marty/import_type_view.rb +13 -13
- data/app/components/marty/import_view.rb +17 -16
- data/app/components/marty/log_view.rb +16 -14
- data/app/components/marty/main_auth_app.rb +59 -59
- data/app/components/marty/main_auth_app/client/main_auth_app.js +3 -3
- data/app/components/marty/mcfly_grid_panel.rb +10 -10
- data/app/components/marty/new_posting_form.rb +11 -11
- data/app/components/marty/new_posting_window.rb +0 -1
- data/app/components/marty/posting_grid.rb +12 -13
- data/app/components/marty/promise_view.rb +6 -6
- data/app/components/marty/report_form.rb +50 -53
- data/app/components/marty/report_select.rb +27 -27
- data/app/components/marty/reporting.rb +4 -4
- data/app/components/marty/script_form.rb +40 -42
- data/app/components/marty/script_grid.rb +24 -24
- data/app/components/marty/script_tester.rb +40 -42
- data/app/components/marty/scripting.rb +25 -27
- data/app/components/marty/simple_app.rb +24 -9
- data/app/components/marty/tag_grid.rb +12 -13
- data/app/components/marty/user_view.rb +35 -35
- data/app/controllers/marty/application_controller.rb +3 -4
- data/app/controllers/marty/components_controller.rb +1 -1
- data/app/controllers/marty/delayed_job_controller.rb +1 -0
- data/app/controllers/marty/diagnostic/controller.rb +4 -6
- data/app/controllers/marty/job_controller.rb +6 -6
- data/app/controllers/marty/report_controller.rb +11 -11
- data/app/controllers/marty/rpc_controller.rb +15 -16
- data/app/helpers/marty/script_set.rb +4 -4
- data/app/models/marty/api_auth.rb +4 -5
- data/app/models/marty/api_config.rb +1 -1
- data/app/models/marty/base.rb +9 -8
- data/app/models/marty/base_rule.rb +18 -13
- data/app/models/marty/config.rb +4 -5
- data/app/models/marty/data_grid.rb +157 -181
- data/app/models/marty/delorean_rule.rb +63 -62
- data/app/models/marty/enum.rb +1 -1
- data/app/models/marty/event.rb +56 -59
- data/app/models/marty/helper.rb +38 -6
- data/app/models/marty/import_type.rb +6 -6
- data/app/models/marty/log.rb +3 -2
- data/app/models/marty/name_validator.rb +3 -2
- data/app/models/marty/pg_enum.rb +3 -4
- data/app/models/marty/posting.rb +20 -24
- data/app/models/marty/promise.rb +28 -30
- data/app/models/marty/script.rb +30 -28
- data/app/models/marty/tag.rb +8 -8
- data/app/models/marty/token.rb +2 -2
- data/app/models/marty/user.rb +24 -23
- data/app/models/marty/vw_promise.rb +10 -11
- data/config/routes.rb +2 -2
- data/delorean/blame_report.dl +268 -0
- data/{spec/dummy/delorean/fields.dl → delorean/marty_fields.dl} +8 -0
- data/delorean/table_report.dl +34 -0
- data/docker-compose.dummy.yml +2 -3
- data/lib/marty/aws/base.rb +8 -8
- data/lib/marty/aws/request.rb +4 -4
- data/lib/marty/cache_adapters/mcfly_ruby_cache.rb +1 -0
- data/lib/marty/content_handler.rb +25 -25
- data/lib/marty/data_change.rb +49 -71
- data/lib/marty/data_conversion.rb +20 -28
- data/lib/marty/data_exporter.rb +25 -28
- data/lib/marty/data_importer.rb +25 -27
- data/lib/marty/engine.rb +1 -2
- data/lib/marty/json_schema.rb +22 -24
- data/lib/marty/logger.rb +6 -9
- data/lib/marty/mcfly_model.rb +20 -24
- data/lib/marty/migrations.rb +37 -35
- data/lib/marty/monkey.rb +33 -33
- data/lib/marty/permissions.rb +18 -18
- data/lib/marty/promise_job.rb +17 -17
- data/lib/marty/promise_proxy.rb +6 -6
- data/lib/marty/relation.rb +6 -7
- data/lib/marty/rpc_call.rb +13 -12
- data/lib/marty/rule_script_set.rb +32 -28
- data/lib/marty/schema_helper.rb +37 -51
- data/lib/marty/util.rb +25 -24
- data/lib/marty/version.rb +1 -1
- data/lib/marty/xl.rb +121 -115
- data/make-dummy.mk +3 -0
- data/marty.gemspec +21 -21
- data/other/marty/api/base.rb +34 -35
- data/other/marty/diagnostic/aws/ec2_instance.rb +8 -8
- data/other/marty/diagnostic/base.rb +13 -14
- data/other/marty/diagnostic/collection.rb +2 -1
- data/other/marty/diagnostic/connections.rb +8 -6
- data/other/marty/diagnostic/database.rb +1 -0
- data/other/marty/diagnostic/delayed_job_version.rb +7 -9
- data/other/marty/diagnostic/delayed_job_worker_total_count.rb +1 -1
- data/other/marty/diagnostic/delayed_job_workers.rb +1 -1
- data/other/marty/diagnostic/environment_variables.rb +17 -15
- data/other/marty/diagnostic/fatal.rb +1 -1
- data/other/marty/diagnostic/node.rb +5 -9
- data/other/marty/diagnostic/nodes.rb +7 -5
- data/other/marty/diagnostic/packer.rb +7 -7
- data/other/marty/diagnostic/reporter.rb +24 -27
- data/other/marty/diagnostic/version.rb +3 -5
- data/script/rails +2 -1
- data/spec/controllers/application_controller_spec.rb +6 -6
- data/spec/controllers/delayed_job_controller_spec.rb +4 -4
- data/spec/controllers/diagnostic/controller_spec.rb +59 -60
- data/spec/controllers/job_controller_spec.rb +68 -69
- data/spec/controllers/rpc_controller_spec.rb +353 -359
- data/spec/controllers/rpc_import_spec.rb +15 -16
- data/spec/dummy/delorean/blame_report.dl +110 -15
- data/spec/dummy/delorean/data_report.dl +4 -4
- data/spec/dummy/delorean/marty_fields.dl +63 -0
- data/spec/dummy/delorean/table_report.dl +34 -0
- data/spec/features/auth_app_spec.rb +1 -2
- data/spec/features/data_import_spec.rb +2 -3
- data/spec/features/enum_spec.rb +42 -46
- data/spec/features/jobs_dashboard_spec.rb +14 -8
- data/spec/features/log_view_spec.rb +40 -43
- data/spec/features/reporting_spec.rb +15 -15
- data/spec/features/rule_spec.rb +195 -190
- data/spec/features/scripting_spec.rb +17 -20
- data/spec/features/scripting_test_spec.rb +32 -33
- data/spec/features/user_view_spec.rb +15 -17
- data/spec/job_helper.rb +11 -11
- data/spec/lib/data_blame_spec.rb +82 -0
- data/spec/lib/data_exporter_spec.rb +31 -32
- data/spec/lib/data_importer_spec.rb +382 -395
- data/spec/lib/delorean_query_spec.rb +117 -119
- data/spec/lib/json_schema_spec.rb +382 -392
- data/spec/lib/logger_spec.rb +23 -24
- data/spec/lib/mcfly_model_spec.rb +112 -109
- data/spec/lib/migrations_spec.rb +10 -10
- data/spec/lib/struct_compare_spec.rb +6 -6
- data/spec/lib/table_report_spec.rb +90 -0
- data/spec/lib/xl_spec.rb +63 -65
- data/spec/lib/xl_styles_spec.rb +16 -19
- data/spec/models/api_auth_spec.rb +30 -30
- data/spec/models/config_spec.rb +32 -32
- data/spec/models/data_grid_spec.rb +642 -655
- data/spec/models/event_spec.rb +96 -88
- data/spec/models/import_type_spec.rb +20 -20
- data/spec/models/posting_spec.rb +35 -35
- data/spec/models/promise_spec.rb +5 -5
- data/spec/models/rule_spec.rb +280 -269
- data/spec/models/script_spec.rb +27 -18
- data/spec/models/user_spec.rb +9 -9
- data/spec/other/diagnostic/base_spec.rb +20 -19
- data/spec/other/diagnostic/collection_spec.rb +6 -5
- data/spec/other/diagnostic/delayed_job_version_spec.rb +1 -1
- data/spec/other/diagnostic/delayed_job_workers_spec.rb +8 -8
- data/spec/other/diagnostic/reporter_spec.rb +31 -33
- data/spec/spec_helper.rb +5 -5
- data/spec/support/chromedriver.rb +3 -5
- data/spec/support/components/netzke_combobox.rb +1 -1
- data/spec/support/components/netzke_grid.rb +17 -17
- data/spec/support/custom_matchers.rb +2 -2
- data/spec/support/download_helper.rb +1 -1
- data/spec/support/helper.rb +1 -2
- data/spec/support/netzke.rb +31 -31
- data/spec/support/performance_helper.rb +8 -8
- data/spec/support/post_run_logger.rb +1 -2
- data/spec/support/setup.rb +1 -4
- data/spec/support/shared_connection.rb +2 -2
- data/spec/support/structure_compare.rb +21 -22
- data/spec/support/suite.rb +1 -2
- data/spec/support/users.rb +5 -6
- metadata +32 -26
|
@@ -5,43 +5,46 @@ class Marty::DeloreanRule < Marty::BaseRule
|
|
|
5
5
|
|
|
6
6
|
def validate
|
|
7
7
|
super
|
|
8
|
-
return errors[:base] <<
|
|
8
|
+
return errors[:base] << 'Start date must be before end date' if
|
|
9
9
|
start_dt && end_dt && start_dt >= end_dt
|
|
10
10
|
|
|
11
11
|
if computed_guards.present? || results.present?
|
|
12
12
|
begin
|
|
13
13
|
eclass = engine && engine.constantize || Marty::RuleScriptSet
|
|
14
14
|
eng = eclass.new('infinity').get_engine(self_as_hash)
|
|
15
|
-
rescue => e
|
|
16
|
-
return errors[:computed] <<
|
|
15
|
+
rescue StandardError => e
|
|
16
|
+
return errors[:computed] << '- ' + e.message
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def self_as_hash
|
|
22
|
-
|
|
22
|
+
attributes + { 'classname' => self.class.name }
|
|
23
23
|
end
|
|
24
|
+
|
|
24
25
|
def self.find_fixed(results)
|
|
25
26
|
results.each_with_object({}) do |(k, v), h|
|
|
26
|
-
v_wo_comment = /\A([^#]+)/.match(v)[1] if v.include?(
|
|
27
|
+
v_wo_comment = /\A([^#]+)/.match(v)[1] if v.include?('#')
|
|
27
28
|
# if v contains a #, try cut it there and attempt parse that way first
|
|
28
29
|
jp = (v_wo_comment && JSON.parse("[#{v_wo_comment}]") rescue nil) ||
|
|
29
30
|
(JSON.parse("[#{v}]") rescue nil)
|
|
30
31
|
next h[k] = jp[0] if jp
|
|
32
|
+
|
|
31
33
|
# json doesn't like single quotes, so handle those manually
|
|
32
34
|
m = %r{\A'(.*)'\z}.match(v)
|
|
33
35
|
next unless m
|
|
36
|
+
|
|
34
37
|
h[k] = m[1]
|
|
35
38
|
end
|
|
36
39
|
end
|
|
37
40
|
|
|
38
41
|
before_validation(on: [:create, :update]) do
|
|
39
42
|
# identify result values that are fixed, stash them (removing quotes)
|
|
40
|
-
self.fixed_results = self.class.find_fixed(
|
|
43
|
+
self.fixed_results = self.class.find_fixed(results)
|
|
41
44
|
end
|
|
42
45
|
|
|
43
46
|
def self.results_cfg_var
|
|
44
|
-
|
|
47
|
+
'NOT DEFINED'
|
|
45
48
|
end
|
|
46
49
|
|
|
47
50
|
def self.compg_keys(computed_guards)
|
|
@@ -51,11 +54,12 @@ class Marty::DeloreanRule < Marty::BaseRule
|
|
|
51
54
|
def self.comp_res_keys(results, grids, ecl, pcfg)
|
|
52
55
|
# FIXME in May 2019: remove this check (use as passed)
|
|
53
56
|
defkeys = pcfg.is_a?(Hash) ? pcfg.keys : pcfg
|
|
54
|
-
results.keys.map {|k| k.ends_with?(
|
|
55
|
-
select{|k| defkeys.include?(k)} + grid_keys(grids, ecl)
|
|
57
|
+
results.keys.map { |k| k.ends_with?('_grid') ? ecl.grid_final_name(k) : k }.
|
|
58
|
+
select { |k| defkeys.include?(k) } + grid_keys(grids, ecl)
|
|
56
59
|
end
|
|
60
|
+
|
|
57
61
|
def self.grid_keys(grids, eclass)
|
|
58
|
-
grids.keys.map{|k| eclass.grid_final_name(k) }
|
|
62
|
+
grids.keys.map { |k| eclass.grid_final_name(k) }
|
|
59
63
|
end
|
|
60
64
|
|
|
61
65
|
class ComputeError < StandardError
|
|
@@ -69,14 +73,14 @@ class Marty::DeloreanRule < Marty::BaseRule
|
|
|
69
73
|
end
|
|
70
74
|
end
|
|
71
75
|
|
|
72
|
-
def self.base_compute2(ruleh, metadata_opts, params, dgparams=params)
|
|
73
|
-
begin
|
|
76
|
+
def self.base_compute2(ruleh, metadata_opts, params, dgparams = params)
|
|
74
77
|
id, name, eclassname, computed_guards, grids, results, fixed_results =
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
ruleh.values_at('id', 'name', 'engine', 'computed_guards', 'grids',
|
|
79
|
+
'results', 'fixed_results')
|
|
77
80
|
raise "Error in rule '#{id}:#{name}': bad metadata_opts" if !metadata_opts
|
|
81
|
+
|
|
78
82
|
eclass = eclassname && eclassname.constantize || Marty::RuleScriptSet
|
|
79
|
-
engine = eclass.new(params[
|
|
83
|
+
engine = eclass.new(params['pt']).get_engine(ruleh) if
|
|
80
84
|
computed_guards.present? || results.present?
|
|
81
85
|
|
|
82
86
|
result = OpenStruct.new(cg_keys: compg_keys(computed_guards))
|
|
@@ -85,18 +89,18 @@ class Marty::DeloreanRule < Marty::BaseRule
|
|
|
85
89
|
begin
|
|
86
90
|
result.cg_vals = engine.evaluate(eclass.node_name, result.cg_keys,
|
|
87
91
|
params.clone)
|
|
88
|
-
rescue => e
|
|
92
|
+
rescue StandardError => e
|
|
89
93
|
result.err_message = e.message
|
|
90
94
|
result.err_stack = e.backtrace
|
|
91
95
|
result.err_section = 'computed_guards'
|
|
92
96
|
raise ComputeError.new(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
"Error (guard) in rule '#{id}:#{name}': #{result.err_message}",
|
|
98
|
+
result.err_stack,
|
|
99
|
+
params.clone,
|
|
100
|
+
result.err_section)
|
|
97
101
|
end
|
|
98
102
|
result.cg_hash = Hash[result.cg_keys.zip(result.cg_vals)]
|
|
99
|
-
fails = result.cg_hash.select{|k,v| ![v].flatten.first}
|
|
103
|
+
fails = result.cg_hash.select { |k, v| ![v].flatten.first }
|
|
100
104
|
return fails if fails.present?
|
|
101
105
|
end
|
|
102
106
|
|
|
@@ -109,20 +113,20 @@ class Marty::DeloreanRule < Marty::BaseRule
|
|
|
109
113
|
eclass.node_name,
|
|
110
114
|
result.res_keys,
|
|
111
115
|
params + {
|
|
112
|
-
|
|
116
|
+
'dgparams__' => dgparams,
|
|
113
117
|
})
|
|
114
118
|
grids_computed = true
|
|
115
|
-
rescue => e
|
|
119
|
+
rescue StandardError => e
|
|
116
120
|
result.err_message = e.message
|
|
117
121
|
result.err_stack = e.backtrace
|
|
118
122
|
result.err_section = 'results'
|
|
119
123
|
raise ComputeError.new(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
"Error (results) in rule '#{id}:#{name}': #{result.err_message}",
|
|
125
|
+
result.err_stack,
|
|
126
|
+
params + {
|
|
127
|
+
'dgparams__' => dgparams,
|
|
128
|
+
},
|
|
129
|
+
result.err_section)
|
|
126
130
|
end
|
|
127
131
|
result.res_hash = Hash[result.res_keys.zip(result.res_vals)]
|
|
128
132
|
else
|
|
@@ -135,76 +139,73 @@ class Marty::DeloreanRule < Marty::BaseRule
|
|
|
135
139
|
result.gr_hash = grids.each_with_object({}) do |(gvar, gname), h|
|
|
136
140
|
usename = eclass.grid_final_name(gvar)
|
|
137
141
|
next h[usename] = gres[gname] if gres[gname]
|
|
138
|
-
|
|
142
|
+
|
|
143
|
+
dg = Marty::DataGrid.lookup_h(pt, gname)
|
|
139
144
|
dgr = dg && Marty::DataGrid.lookup_grid_distinct_entry_h(pt, dgparams,
|
|
140
145
|
dg)
|
|
141
|
-
h[usename] = gres[gname] = dgr[
|
|
146
|
+
h[usename] = gres[gname] = dgr['result'] if dgr
|
|
142
147
|
end
|
|
143
148
|
end
|
|
144
|
-
(result.res_hash||{}) + (result.gr_hash||{})
|
|
145
|
-
|
|
149
|
+
(result.res_hash || {}) + (result.gr_hash || {})
|
|
150
|
+
ensure
|
|
146
151
|
if ruleh['fixed_results']['log__']
|
|
147
152
|
resh = result.to_h
|
|
148
|
-
[:res_keys, :res_vals].each {|k|resh.delete(k)} if
|
|
153
|
+
[:res_keys, :res_vals].each { |k| resh.delete(k) } if
|
|
149
154
|
result.res_hash.present? || result.res_keys.blank?
|
|
150
|
-
[:cg_keys, :cg_vals].each {|k|resh.delete(k)} if
|
|
155
|
+
[:cg_keys, :cg_vals].each { |k| resh.delete(k) } if
|
|
151
156
|
result.cg_hash.present? || result.cg_keys.blank?
|
|
152
157
|
resh.delete(:gr_keys) if result.gr_hash.present? || result.gr_keys.blank?
|
|
153
158
|
estack_full = resh.delete(:err_stack)
|
|
154
159
|
estack = estack_full && {
|
|
155
|
-
err_stack: estack_full.select{ |l| l.starts_with?('DELOREAN')}} || {}
|
|
156
|
-
detail = { input: params, dgparams: dgparams} + resh + estack
|
|
160
|
+
err_stack: estack_full.select { |l| l.starts_with?('DELOREAN') } } || {}
|
|
161
|
+
detail = { input: params, dgparams: dgparams } + resh + estack
|
|
157
162
|
Marty::Logger.info("Rule Log #{ruleh['name']}",
|
|
158
163
|
Marty::Util.scrub_obj(detail))
|
|
159
164
|
end
|
|
160
|
-
end
|
|
161
165
|
end
|
|
162
166
|
|
|
163
|
-
delorean_fn :route_compute, sig: 4 do
|
|
164
|
-
|
|
165
|
-
kl = ruleh["classname"].constantize
|
|
167
|
+
delorean_fn :route_compute, sig: 4 do |ruleh, pt, params, grid_names_p|
|
|
168
|
+
kl = ruleh['classname'].constantize
|
|
166
169
|
kl.compute(ruleh, nil, pt, params, grid_names_p)
|
|
167
170
|
end
|
|
168
|
-
delorean_fn :route_compute2, sig: 5 do
|
|
169
|
-
|
|
170
|
-
kl = ruleh["classname"].constantize
|
|
171
|
+
delorean_fn :route_compute2, sig: 5 do |ruleh, metadata_opts, pt, params, grid_names_p|
|
|
172
|
+
kl = ruleh['classname'].constantize
|
|
171
173
|
kl.compute(ruleh, metadata_opts, pt, params, grid_names_p)
|
|
172
174
|
end
|
|
173
|
-
delorean_fn :route_compute_rs, sig: 3 do
|
|
174
|
-
|
|
175
|
-
kl = ruleh["classname"].constantize
|
|
175
|
+
delorean_fn :route_compute_rs, sig: 3 do |ruleh, pt, features|
|
|
176
|
+
kl = ruleh['classname'].constantize
|
|
176
177
|
kl.compute_rs(ruleh, pt, features)
|
|
177
178
|
end
|
|
178
|
-
delorean_fn :route_validate_results, sig: [1, 2] do
|
|
179
|
-
|
|
180
|
-
kl = ruleh["classname"].constantize
|
|
179
|
+
delorean_fn :route_validate_results, sig: [1, 2] do |ruleh, reqchk = false|
|
|
180
|
+
kl = ruleh['classname'].constantize
|
|
181
181
|
kl.validate_results(ruleh, reqchk)
|
|
182
182
|
end
|
|
183
|
-
delorean_fn :route_validate_grid_attrs, sig: [2, 3] do
|
|
184
|
-
|
|
185
|
-
kl = ruleh["classname"].constantize
|
|
183
|
+
delorean_fn :route_validate_grid_attrs, sig: [2, 3] do |ruleh, gridname, addl_attrs = nil|
|
|
184
|
+
kl = ruleh['classname'].constantize
|
|
186
185
|
kl.validate_grid_attrs(ruleh, gridname, addl_attrs)
|
|
187
186
|
end
|
|
188
187
|
|
|
189
|
-
def base_compute2(metadata_opts, params, dgparams=params)
|
|
188
|
+
def base_compute2(metadata_opts, params, dgparams = params)
|
|
190
189
|
self.class.base_compute2(self_as_hash, metadata_opts, params, dgparams)
|
|
191
190
|
end
|
|
192
191
|
|
|
193
192
|
def self.get_matches_(pt, attrs, params)
|
|
194
|
-
q = super(pt, attrs.except(
|
|
195
|
-
rule_dt = attrs[
|
|
196
|
-
q=q.where(
|
|
197
|
-
where(
|
|
198
|
-
#puts q.to_sql
|
|
193
|
+
q = super(pt, attrs.except('rule_dt'), params)
|
|
194
|
+
rule_dt = attrs['rule_dt']
|
|
195
|
+
q = q.where('start_dt <= ?', rule_dt).
|
|
196
|
+
where('end_dt >= ? OR end_dt IS NULL', rule_dt) if rule_dt
|
|
197
|
+
# puts q.to_sql
|
|
199
198
|
q
|
|
200
199
|
end
|
|
201
200
|
|
|
202
201
|
def self.get_grid_rename_handler(klass)
|
|
203
|
-
|
|
202
|
+
proc do |old, new|
|
|
204
203
|
klass.where(obsoleted_dt: 'infinity').each do |r|
|
|
205
204
|
r.grids.each { |k, v| r.grids[k] = new if v == old }
|
|
206
|
-
r.results.each
|
|
207
|
-
|
|
205
|
+
r.results.each do |k, v|
|
|
206
|
+
r.results[k] = %Q("#{new}") if
|
|
207
|
+
k.ends_with?('_grid') && r.fixed_results[k] == old
|
|
208
|
+
end
|
|
208
209
|
r.save! if r.changed?
|
|
209
210
|
end
|
|
210
211
|
end
|
data/app/models/marty/enum.rb
CHANGED
data/app/models/marty/event.rb
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
class Marty::Event < Marty::Base
|
|
2
|
-
|
|
3
2
|
class EventValidator < ActiveModel::Validator
|
|
4
3
|
def validate(event)
|
|
5
|
-
event.errors[:base] <<
|
|
4
|
+
event.errors[:base] << 'Must have promise_id or start_dt' unless
|
|
6
5
|
event.promise_id || event.start_dt
|
|
7
6
|
end
|
|
8
7
|
end
|
|
@@ -14,10 +13,10 @@ class Marty::Event < Marty::Base
|
|
|
14
13
|
validates_with EventValidator
|
|
15
14
|
|
|
16
15
|
after_validation(on: [:create, :update]) do
|
|
17
|
-
self.comment =
|
|
16
|
+
self.comment = comment.truncate(255) if comment
|
|
18
17
|
end
|
|
19
18
|
|
|
20
|
-
UPDATE_SQL
|
|
19
|
+
UPDATE_SQL = <<SQL
|
|
21
20
|
UPDATE marty_events as me
|
|
22
21
|
SET start_dt = p.start_dt,
|
|
23
22
|
end_dt = p.end_dt
|
|
@@ -31,7 +30,7 @@ class Marty::Event < Marty::Base
|
|
|
31
30
|
)
|
|
32
31
|
)
|
|
33
32
|
SQL
|
|
34
|
-
BASE_QUERY
|
|
33
|
+
BASE_QUERY = <<SQL
|
|
35
34
|
SELECT id,
|
|
36
35
|
klass,
|
|
37
36
|
subject_id,
|
|
@@ -54,8 +53,8 @@ SQL
|
|
|
54
53
|
|
|
55
54
|
def self.op_is_running?(klass, subject_id, operation)
|
|
56
55
|
all_running.detect do |pm|
|
|
57
|
-
pm[
|
|
58
|
-
pm[
|
|
56
|
+
pm['klass'] == klass && pm['subject_id'].to_i == subject_id.to_i &&
|
|
57
|
+
pm['enum_event_operation'] == operation
|
|
59
58
|
end
|
|
60
59
|
end
|
|
61
60
|
|
|
@@ -64,27 +63,27 @@ SQL
|
|
|
64
63
|
operation,
|
|
65
64
|
start_dt,
|
|
66
65
|
expire_secs,
|
|
67
|
-
comment=nil)
|
|
66
|
+
comment = nil)
|
|
68
67
|
|
|
69
68
|
# use lookup_event instead of all_running which is throttled
|
|
70
|
-
evs =
|
|
71
|
-
running = evs.detect do
|
|
72
|
-
|
|
73
|
-
next
|
|
74
|
-
|
|
75
|
-
(Time.zone.now - ev[
|
|
69
|
+
evs = lookup_event(klass, subject_id, operation)
|
|
70
|
+
running = evs.detect do |ev|
|
|
71
|
+
next if ev['end_dt']
|
|
72
|
+
next true unless ev['expire_secs']
|
|
73
|
+
|
|
74
|
+
(Time.zone.now - ev['start_dt']).truncate < ev['expire_secs']
|
|
76
75
|
end
|
|
77
76
|
|
|
78
77
|
raise "#{operation} is already running for #{klass}/#{subject_id}" if
|
|
79
78
|
running
|
|
80
79
|
|
|
81
|
-
|
|
80
|
+
create!(klass: klass,
|
|
82
81
|
subject_id: subject_id,
|
|
83
82
|
enum_event_operation: operation,
|
|
84
83
|
start_dt: start_dt,
|
|
85
84
|
expire_secs: expire_secs,
|
|
86
85
|
comment: comment,
|
|
87
|
-
|
|
86
|
+
)
|
|
88
87
|
end
|
|
89
88
|
|
|
90
89
|
def self.lookup_event(klass, subject_id, operation)
|
|
@@ -94,33 +93,35 @@ SQL
|
|
|
94
93
|
AND subject_id = #{subject_id}
|
|
95
94
|
AND enum_event_operation = '#{operation}'")
|
|
96
95
|
|
|
97
|
-
#For now we return a bare hash
|
|
98
|
-
#Marty::Event.find_by_id(hash["id"])
|
|
96
|
+
# For now we return a bare hash
|
|
97
|
+
# Marty::Event.find_by_id(hash["id"])
|
|
99
98
|
end
|
|
100
99
|
|
|
101
|
-
def self.finish_event(klass, subject_id, operation, error=false, comment=nil)
|
|
102
|
-
raise
|
|
100
|
+
def self.finish_event(klass, subject_id, operation, error = false, comment = nil)
|
|
101
|
+
raise 'error must be true or false' unless [true, false].include?(error)
|
|
102
|
+
|
|
103
103
|
time_now_s = Time.zone.now.strftime('%Y-%m-%d %H:%M:%S.%6N')
|
|
104
104
|
|
|
105
105
|
event = get_data(running_query(time_now_s)).detect do |ev|
|
|
106
|
-
ev[
|
|
107
|
-
ev[
|
|
106
|
+
ev['klass'] == klass && ev['subject_id'] == subject_id.to_i &&
|
|
107
|
+
ev['enum_event_operation'] == operation
|
|
108
108
|
end
|
|
109
109
|
raise "event #{klass}/#{subject_id}/#{operation} not found" unless
|
|
110
110
|
event
|
|
111
111
|
|
|
112
|
-
ev = Marty::Event.find_by_id(event[
|
|
112
|
+
ev = Marty::Event.find_by_id(event['id'])
|
|
113
113
|
raise "can't explicitly finish a promise event" if ev.promise_id
|
|
114
|
+
|
|
114
115
|
ev.end_dt = Time.zone.now
|
|
115
116
|
ev.error = error
|
|
116
117
|
ev.comment = comment if comment
|
|
117
118
|
ev.save!
|
|
118
119
|
end
|
|
119
120
|
|
|
120
|
-
def self.last_event(klass, subject_id, operation=nil)
|
|
121
|
+
def self.last_event(klass, subject_id, operation = nil)
|
|
121
122
|
hash = all_running.select do |pm|
|
|
122
|
-
pm[
|
|
123
|
-
(operation.nil? || pm[
|
|
123
|
+
pm['klass'] == klass && pm['subject_id'] == subject_id.to_i &&
|
|
124
|
+
(operation.nil? || pm['enum_event_operation'] == operation)
|
|
124
125
|
end.last
|
|
125
126
|
|
|
126
127
|
return hash if hash
|
|
@@ -134,14 +135,13 @@ SQL
|
|
|
134
135
|
ORDER BY end_dt desc").first
|
|
135
136
|
end
|
|
136
137
|
|
|
137
|
-
def self.last_event_multi(klass, subject_ids_arg, operation=nil)
|
|
138
|
+
def self.last_event_multi(klass, subject_ids_arg, operation = nil)
|
|
138
139
|
subject_ids = subject_ids_arg.map(&:to_i)
|
|
139
140
|
events = all_running.select do |pm|
|
|
140
|
-
pm[
|
|
141
|
-
(operation.nil? || pm[
|
|
142
|
-
end.group_by { |ev| ev[
|
|
143
|
-
|
|
144
|
-
h[id] = evs.sort { |a, b| a["start_dt"] <=> b["start_dt"] }.first
|
|
141
|
+
pm['klass'] == klass && subject_ids.include?(pm['subject_id']) &&
|
|
142
|
+
(operation.nil? || pm['enum_event_operation'] == operation)
|
|
143
|
+
end.group_by { |ev| ev['subject_id'] }.each_with_object({}) do |(id, evs), h|
|
|
144
|
+
h[id] = evs.sort { |a, b| a['start_dt'] <=> b['start_dt'] }.first
|
|
145
145
|
end
|
|
146
146
|
|
|
147
147
|
running_ids = events.keys
|
|
@@ -149,7 +149,7 @@ SQL
|
|
|
149
149
|
|
|
150
150
|
if check_fin.present?
|
|
151
151
|
op_filt = "AND enum_event_operation = '#{operation}'" if operation
|
|
152
|
-
op_col =
|
|
152
|
+
op_col = ', enum_event_operation' if operation
|
|
153
153
|
|
|
154
154
|
fins = get_data("SELECT klass,
|
|
155
155
|
subject_id,
|
|
@@ -179,7 +179,7 @@ SQL
|
|
|
179
179
|
WHERE rnum = 1")
|
|
180
180
|
|
|
181
181
|
fins.each do |fin|
|
|
182
|
-
events[fin[
|
|
182
|
+
events[fin['subject_id']] = fin
|
|
183
183
|
end
|
|
184
184
|
end
|
|
185
185
|
events
|
|
@@ -187,16 +187,16 @@ SQL
|
|
|
187
187
|
|
|
188
188
|
def self.currently_running(klass, subject_id)
|
|
189
189
|
all_running.select do |pm|
|
|
190
|
-
pm[
|
|
191
|
-
end.map { |e| e[
|
|
190
|
+
pm['klass'] == klass && pm['subject_id'] == subject_id.to_i
|
|
191
|
+
end.map { |e| e['enum_event_operation'] }
|
|
192
192
|
end
|
|
193
193
|
|
|
194
194
|
def self.currently_running_multi(klass, subject_id_raw)
|
|
195
195
|
subject_ids = [subject_id_raw].flatten.map(&:to_i)
|
|
196
196
|
all_running.select do |pm|
|
|
197
|
-
pm[
|
|
197
|
+
pm['klass'] == klass && subject_ids.include?(pm['subject_id'])
|
|
198
198
|
end.each_with_object({}) do |e, h|
|
|
199
|
-
(h[e[
|
|
199
|
+
(h[e['subject_id']] ||= []) << e['enum_event_operation']
|
|
200
200
|
end
|
|
201
201
|
end
|
|
202
202
|
|
|
@@ -210,12 +210,12 @@ SQL
|
|
|
210
210
|
def self.pretty_op(hash)
|
|
211
211
|
d = hash['enum_event_operation'].downcase.capitalize
|
|
212
212
|
|
|
213
|
-
|
|
213
|
+
# && !(hash['comment'] =~ /^ERROR/)
|
|
214
214
|
hash['end_dt'] ? d.sub(/ing/, 'ed') : d
|
|
215
215
|
end
|
|
216
216
|
|
|
217
217
|
def self.compact_end_dt(hash)
|
|
218
|
-
hash['end_dt'] ? hash['end_dt'].strftime(
|
|
218
|
+
hash['end_dt'] ? hash['end_dt'].strftime('%H:%M') : '---'
|
|
219
219
|
end
|
|
220
220
|
|
|
221
221
|
def self.update_start_and_end
|
|
@@ -224,13 +224,13 @@ SQL
|
|
|
224
224
|
|
|
225
225
|
def self.get_data(sql)
|
|
226
226
|
ActiveRecord::Base.connection.execute(sql).to_a.map do |h|
|
|
227
|
-
h[
|
|
228
|
-
h[
|
|
229
|
-
h[
|
|
230
|
-
h[
|
|
231
|
-
h[
|
|
232
|
-
h[
|
|
233
|
-
h[
|
|
227
|
+
h['id'] = h['id'].to_i
|
|
228
|
+
h['subject_id'] = h['subject_id'].to_i
|
|
229
|
+
h['start_dt'] = Time.zone.parse(h['start_dt']) if h['start_dt']
|
|
230
|
+
h['end_dt'] = Time.zone.parse(h['end_dt']) if h['end_dt']
|
|
231
|
+
h['expire_secs'] = h['expire_secs'].to_i if h['expire_secs']
|
|
232
|
+
h['comment'] = h['comment']
|
|
233
|
+
h['error'] = h['error']
|
|
234
234
|
h
|
|
235
235
|
end
|
|
236
236
|
end
|
|
@@ -289,17 +289,17 @@ SQL
|
|
|
289
289
|
WHERE row_num = 1")
|
|
290
290
|
@all_finished[:timestamp] = time_now_i
|
|
291
291
|
raw.each_with_object(@all_finished[:data]) do |ev, hash|
|
|
292
|
-
if ev[
|
|
293
|
-
real_ev = Marty::Event.where(id: ev[
|
|
294
|
-
promise = Marty::Promise.where(id: real_ev[
|
|
295
|
-
maybe_error = promise.result[
|
|
296
|
-
ev[
|
|
292
|
+
if ev['end_dt'] && ev['error'].nil?
|
|
293
|
+
real_ev = Marty::Event.where(id: ev['id']).first
|
|
294
|
+
promise = Marty::Promise.where(id: real_ev['promise_id']).first
|
|
295
|
+
maybe_error = promise.result['error']
|
|
296
|
+
ev['error'] = real_ev.error = !!maybe_error
|
|
297
297
|
real_ev.comment = maybe_error
|
|
298
298
|
real_ev.save!
|
|
299
299
|
end
|
|
300
|
-
subhash = hash[[ev[
|
|
301
|
-
subhash[ev[
|
|
302
|
-
ev[
|
|
300
|
+
subhash = hash[[ev['klass'], ev['subject_id']]] ||= {}
|
|
301
|
+
subhash[ev['enum_event_operation']] =
|
|
302
|
+
ev['end_dt'].strftime('%Y-%m-%d %H:%M:%S')
|
|
303
303
|
end
|
|
304
304
|
end
|
|
305
305
|
@all_finished[:data]
|
|
@@ -310,11 +310,8 @@ SQL
|
|
|
310
310
|
end
|
|
311
311
|
|
|
312
312
|
def self.cleanup
|
|
313
|
-
begin
|
|
314
313
|
where('start_dt < ?', Time.zone.now - 48.hours).delete_all
|
|
315
|
-
|
|
314
|
+
rescue StandardError => exc
|
|
316
315
|
Marty::Util.logger.error("event GC error: #{exc}")
|
|
317
|
-
end
|
|
318
316
|
end
|
|
319
|
-
|
|
320
317
|
end
|