marty 6.1.0 → 8.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.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.gitlab-ci.yml +17 -3
  4. data/.rubocop.yml +5 -0
  5. data/.rubocop_todo.yml +3 -2
  6. data/Gemfile +2 -1
  7. data/app/assets/javascripts/marty/extjs/extensions/marty.js +23 -1
  8. data/app/assets/stylesheets/marty/application.css +4 -1
  9. data/app/assets/stylesheets/marty/dark_mode.css +17 -0
  10. data/app/components/marty/auth_app.rb +10 -1
  11. data/app/components/marty/auth_app/client/auth_app.js +4 -0
  12. data/app/components/marty/extras/layout.rb +2 -2
  13. data/app/components/marty/extras/misc.rb +1 -1
  14. data/app/components/marty/log_view.rb +0 -1
  15. data/app/components/marty/main_auth_app.rb +9 -12
  16. data/app/components/marty/promise_view.rb +5 -0
  17. data/app/components/marty/promise_view/client/promise_view.js +11 -0
  18. data/app/components/marty/schedule_jobs_dashboard.rb +30 -96
  19. data/app/components/marty/schedule_jobs_grid.rb +118 -0
  20. data/app/controllers/marty/application_controller.rb +6 -2
  21. data/app/models/marty/base.rb +48 -48
  22. data/app/models/marty/config.rb +14 -2
  23. data/app/models/marty/user.rb +12 -0
  24. data/app/services/marty/background_job/fetch_missing_in_schedule_cron_jobs.rb +19 -0
  25. data/app/services/marty/enums/report.rb +18 -0
  26. data/app/services/marty/promises/delorean/create.rb +16 -27
  27. data/app/services/marty/promises/ruby/create.rb +10 -1
  28. data/app/views/layouts/marty/application.html.erb +4 -1
  29. data/app/views/marty/diagnostic/op.html.erb +3 -1
  30. data/config/locales/en.yml +2 -0
  31. data/db/migrate/512_add_promise_priority.rb +9 -0
  32. data/db/migrate/513_add_priority_to_promise_view.rb +44 -0
  33. data/db/migrate/514_remove_marty_events.rb +13 -0
  34. data/delorean/enum_report.dl +11 -0
  35. data/delorean/table_report.dl +7 -0
  36. data/docker-compose.dummy.yml +7 -4
  37. data/lib/marty.rb +5 -2
  38. data/lib/marty/api/base.rb +15 -9
  39. data/lib/marty/cache_adapters.rb +2 -0
  40. data/lib/marty/cache_adapters/mcfly_ruby_cache.rb +1 -5
  41. data/lib/marty/cache_adapters/memory_and_redis.rb +93 -0
  42. data/lib/marty/cache_adapters/redis.rb +63 -0
  43. data/lib/marty/delayed_job/scheduled_job_plugin.rb +33 -0
  44. data/lib/marty/diagnostic/database.rb +1 -2
  45. data/lib/marty/logger.rb +50 -17
  46. data/lib/marty/monkey.rb +26 -6
  47. data/lib/marty/promise_ruby_job.rb +2 -0
  48. data/lib/marty/rails_app.rb +29 -0
  49. data/lib/marty/railtie.rb +1 -0
  50. data/lib/marty/version.rb +1 -1
  51. data/marty.gemspec +1 -0
  52. data/spec/controllers/job_controller_spec.rb +2 -2
  53. data/spec/dummy/app/components/gemini/cm_auth_app.rb +12 -0
  54. data/spec/dummy/app/components/gemini/simple_view.rb +17 -0
  55. data/spec/dummy/app/jobs/test_failing_job.rb +14 -0
  56. data/spec/dummy/app/models/gemini/helper.rb +90 -1
  57. data/spec/dummy/config/application.rb +1 -0
  58. data/spec/dummy/db/migrate/20191101132729_add_activity_flag_to_simple.rb +10 -0
  59. data/spec/dummy/delorean/blame_report.dl +1 -0
  60. data/spec/dummy/delorean/enum_report.dl +1 -0
  61. data/spec/dummy/delorean/marty_fields.dl +1 -0
  62. data/spec/dummy/delorean/table_report.dl +1 -0
  63. data/spec/features/data_blame_report_spec.rb +66 -0
  64. data/spec/features/data_grid_spec.rb +1 -1
  65. data/spec/features/enum_values_report_spec.rb +76 -0
  66. data/spec/features/inline_editing_spec.rb +33 -0
  67. data/spec/features/rule_spec.rb +1 -1
  68. data/spec/features/schedule_jobs_dashboard_spec.rb +1 -1
  69. data/spec/features/scripting_spec.rb +1 -1
  70. data/spec/features/user_list_report_spec.rb +74 -0
  71. data/spec/fixtures/misc/struct_compare_tests.txt +15 -5
  72. data/spec/job_helper.rb +39 -0
  73. data/spec/jobs/cron_job_spec.rb +91 -0
  74. data/spec/lib/mcfly_model_spec.rb +9 -0
  75. data/spec/models/promise_spec.rb +168 -1
  76. data/spec/other/diagnostic/delayed_job_workers_spec.rb +1 -1
  77. data/spec/performance/caching_spec.rb +99 -0
  78. data/spec/services/background_job/fetch_missing_in_schedule_cron_jobs_spec.rb +34 -0
  79. data/spec/support/delayed_job_helpers.rb +3 -3
  80. data/spec/support/shared_connection.rb +9 -1
  81. data/spec/support/structure_compare.rb +19 -3
  82. metadata +39 -6
  83. data/app/components/marty/event_view.rb +0 -129
  84. data/app/models/marty/event.rb +0 -317
  85. data/spec/dummy/db/migrate/20160923183516_add_bulk_pricing_event_ops.rb +0 -8
  86. data/spec/dummy/delorean/blame_report.dl +0 -268
  87. data/spec/dummy/delorean/marty_fields.dl +0 -63
  88. data/spec/dummy/delorean/table_report.dl +0 -34
  89. data/spec/models/event_spec.rb +0 -272
@@ -1,63 +0,0 @@
1
- PostingField:
2
- field_label = "Posting"
3
- xtype = ":combo"
4
- name = "pt_name"
5
- store = Marty::Posting.
6
- where("created_dt <> 'infinity'").
7
- order("created_dt DESC").limit(10).pluck("name")
8
- value = store[0]
9
-
10
- ######################################################################
11
-
12
- PostingField1: PostingField
13
- field_label = "Posting 1"
14
- name = "pt_name1"
15
-
16
- PostingField2: PostingField
17
- field_label = "Posting 2"
18
- name = "pt_name2"
19
-
20
- ######################################################################
21
-
22
- ClassListField:
23
- field_label = "Tables"
24
- xtype = ":multiselectcombo"
25
- name = "class_list"
26
- store = Marty::DataChange.class_list
27
-
28
- ClassField: ClassListField
29
- xtype = ":combo"
30
- name = "class_name"
31
- store = Marty::DataChange.class_list
32
-
33
- ######################################################################
34
-
35
-
36
- CheckboxField:
37
- xtype = ":checkboxfield"
38
- checked = false
39
- input_value = true
40
- unchecked_value = false
41
-
42
- ######################################################################
43
-
44
- JsonField:
45
- xtype = ":textareafield"
46
- name = "json_field"
47
- field_label = "JSON"
48
- auto_scroll = true
49
- spellcheck = false
50
- field_style = {
51
- "font_family": 'courier new',
52
- "font_size": '12px'
53
- }
54
- height = 400
55
-
56
- CsvField: JsonField
57
- field_label = "CSV"
58
- name = "csv_field"
59
-
60
- TextField:
61
- xtype = ":textfield"
62
- field_label = "Text"
63
- name = "text_field"
@@ -1,34 +0,0 @@
1
- import MartyFields
2
- import Styles
3
-
4
- ReadableField: MartyFields::CheckboxField
5
- name = "readable"
6
- field_label = "Disable Encoding"
7
-
8
- TableReport:
9
- readable =? nil
10
- pt_name =? nil
11
- posting = Marty::Posting.lookup(pt_name)
12
- pt = posting.created_dt
13
- module_name =? nil
14
- class_name =? nil
15
- title =? (class_name || "Table Report") + (
16
- if pt_name then "_" + pt_name else "")
17
- sort_field =? nil
18
- exclude_attrs =? nil
19
-
20
- result_raw = Marty::DataChange.do_export(
21
- pt,
22
- if module_name then module_name + '::' + class_name else class_name,
23
- sort_field,
24
- exclude_attrs || [],
25
- )
26
- row_count = result_raw.length
27
- result = Marty::Helper.to_csv(result_raw, {'readable' : readable})
28
- form = [
29
- MartyFields::PostingField,
30
- MartyFields::ClassField,
31
- ReadableField,
32
- ]
33
- format = "csv"
34
-
@@ -1,272 +0,0 @@
1
- require 'spec_helper'
2
- require 'job_helper'
3
-
4
- describe Marty::Event do
5
- before(:all) do
6
- @clean_file = "/tmp/clean_#{Process.pid}.psql"
7
- @save_file = "/tmp/save_#{Process.pid}.psql"
8
- save_clean_db(@clean_file)
9
-
10
- # transactional fixtures interfere with queueing jobs
11
- self.use_transactional_tests = false
12
-
13
- # Needed here because shutting transactional fixtures off
14
- # means we lose the globally set user
15
- Mcfly.whodunnit = system_user
16
-
17
- Marty::Script.load_script_bodies(promise_bodies, Date.today)
18
- start_delayed_job
19
- Marty::Config['MARTY_EVENT_POLL_SECS'] = 1
20
-
21
- @time = Time.zone.now
22
- @date_string = @time.strftime('%Y-%m-%d')
23
- @old_start = '1970-01-01 08:00:00'
24
- @old_end = '1970-01-01 09:00:00'
25
- # add events
26
- [
27
- ['testcl1', 123, @time, nil, nil, 'AVM', 'a comment',
28
- nil],
29
- ['testcl1', 123, @time + 2.second, nil, nil, 'CRA', 'b comment',
30
- nil],
31
- ['testcl1', 123, @time + 4.seconds, nil, 10000, 'PRICING', 'c comment',
32
- nil],
33
- ['testcl1', 234, @time - 5.seconds, @time, nil, 'PRICING', 'c comment',
34
- false],
35
- ['testcl2', 123, @time, nil, 2, 'AVM', 'e comment', nil],
36
- ['testcl2', 123, @time + 1.second, nil, 4, 'CRA', 'f comment', nil],
37
- ['testcl2', 123, Time.zone.parse(@old_start),
38
- Time.zone.parse(@old_end), nil, 'PRICING', 'old event', 0]
39
- ].each do |klass, subjid, startdt, enddt, expire, op, comment, error|
40
- Marty::Event.create!(klass: klass,
41
- subject_id: subjid,
42
- start_dt: startdt,
43
- end_dt: enddt,
44
- expire_secs: expire,
45
- comment: comment,
46
- enum_event_operation: op,
47
- error: error)
48
- end
49
-
50
- engine = Marty::ScriptSet.new.get_engine(NAME_I)
51
- res = engine.background_eval('SLEEPER', { 'secs' => 5 }, ['a'],
52
- klass: 'testcl3',
53
- id: 987,
54
- operation: 'PRICING')
55
- res.force
56
- engine = Marty::ScriptSet.new.get_engine(NAME_J)
57
- res = engine.background_eval('FAILER', { 'dummy' => 'dummy' }, ['a'],
58
- klass: 'testcl3',
59
- id: 654,
60
- operation: 'PRICING')
61
- res.force rescue nil
62
- sleep 5
63
- save_clean_db(@save_file)
64
- end
65
-
66
- after(:all) do
67
- self.use_transactional_tests = true
68
- restore_clean_db(@clean_file)
69
- stop_delayed_job
70
- end
71
-
72
- before(:each) do
73
- restore_clean_db(@save_file, false)
74
- Marty::Event.clear_cache
75
- end
76
-
77
- it 'reports currently running' do
78
- expect(Marty::Event.currently_running('testcl1', 123)).
79
- to eq(['AVM', 'CRA', 'PRICING'])
80
- expect(Marty::Event.currently_running('testcl2', 123)).to eq([])
81
- expect(Marty::Event.currently_running('testcl3', 987)).to eq([])
82
- expect(Marty::Event.last_event('testcl1', 123)).
83
- to include(
84
- 'klass' => 'testcl1',
85
- 'subject_id' => 123,
86
- 'enum_event_operation' => 'PRICING',
87
- 'comment' => 'c comment', 'expire_secs' => 10000)
88
- expect(Marty::Event.last_event('testcl2', 123)).
89
- to include(
90
- 'klass' => 'testcl2',
91
- 'subject_id' => 123,
92
- 'enum_event_operation' => 'PRICING',
93
- 'comment' => 'old event')
94
- expect(Marty::Event.last_event('testcl3', 987)).
95
- to include(
96
- 'klass' => 'testcl3',
97
- 'subject_id' => 987,
98
- 'enum_event_operation' => 'PRICING',
99
- 'comment' => nil,
100
- 'expire_secs' => nil)
101
-
102
- Timecop.freeze(@time + 1.second)
103
- Marty::Event.clear_cache
104
- expect(Marty::Event.currently_running('testcl1', 123)).
105
- to eq(['AVM', 'CRA', 'PRICING'])
106
- expect(Marty::Event.currently_running('testcl2', 123)).to eq(['AVM', 'CRA'])
107
-
108
- Timecop.freeze(@time + 3.seconds)
109
- Marty::Event.clear_cache
110
- expect(Marty::Event.currently_running('testcl1', 123)).
111
- to eq(['AVM', 'CRA', 'PRICING'])
112
- expect(Marty::Event.currently_running('testcl2', 123)).to eq(['CRA'])
113
-
114
- Timecop.freeze(@time + 6.seconds)
115
- expect(Marty::Event.currently_running('testcl1', 123)).
116
- to eq(['AVM', 'CRA', 'PRICING'])
117
- expect(Marty::Event.currently_running('testcl2', 123)).to eq([])
118
- Timecop.return
119
- end
120
-
121
- it 'misc API tests' do
122
- ev1 = Marty::Event.where(klass: 'testcl3', subject_id: 987).first
123
- ev2 = Marty::Event.where(klass: 'testcl3', subject_id: 654).first
124
- af = Marty::Event.all_finished
125
- ev3 = Marty::Event.where(klass: 'testcl3', subject_id: 987).first
126
- ev4 = Marty::Event.where(klass: 'testcl3', subject_id: 654).first
127
-
128
- # ev1/ev2 should have null start/end
129
- # ev3/ev4 should have start/end populated from promise and error status
130
- expect(ev1.start_dt).to be_nil
131
- expect(ev1.end_dt).to be_nil
132
- expect(ev1.error).to be_falsey
133
- expect(ev2.start_dt).to be_nil
134
- expect(ev2.end_dt).to be_nil
135
- expect(ev2.error).to be_falsey
136
-
137
- expect(ev3.start_dt).not_to be_nil
138
- expect(ev3.end_dt).not_to be_nil
139
- expect(ev3.error).to be_falsey
140
- expect(ev4.start_dt).not_to be_nil
141
- expect(ev4.end_dt).not_to be_nil
142
- expect(ev4.error).to be_truthy
143
-
144
- expect(af.count).to eq(3)
145
- expect(af).to include(['testcl3', 987])
146
- expect(af).to include(['testcl1', 234])
147
- expect(af[['testcl3', 987]]).to include('PRICING')
148
- expect(af[['testcl3', 987]]['PRICING']).to start_with(@date_string)
149
- expect(af[['testcl1', 234]]).to include('PRICING')
150
- expect(af[['testcl1', 234]]['PRICING']).to start_with(@date_string)
151
-
152
- expect(Marty::Event.currently_running('testcl1', 123)).
153
- to eq(['AVM', 'CRA', 'PRICING'])
154
- expect(Marty::Event.op_is_running?('testcl1', 123, 'AVM')).to be_truthy
155
- Marty::Event.finish_event('testcl1', 123, 'AVM', false, 'wassup')
156
- Marty::Event.clear_cache
157
- expect(Marty::Event.currently_running('testcl1', 123)).
158
- to eq(['CRA', 'PRICING'])
159
- expect(Marty::Event.currently_running_multi('testcl1', [123])).
160
- to eq(123 => ['CRA', 'PRICING'])
161
-
162
- expect(Marty::Event.op_is_running?('testcl1', 123, 'AVM')).to be_falsey
163
- expect(Marty::Event.op_is_running?('testcl1', 123, 'CRA')).to be_truthy
164
-
165
- ev = Marty::Event.lookup_event('testcl1', 123, 'AVM')
166
- expect(ev.length).to eq(1)
167
- expect(ev.first).to include('klass' => 'testcl1',
168
- 'subject_id' => 123,
169
- 'enum_event_operation' => 'AVM',
170
- 'comment' => 'wassup',
171
- 'expire_secs' => nil,
172
- 'error' => false)
173
- Marty::Event.update_comment(ev.first, 'updated')
174
- ev = Marty::Event.lookup_event('testcl1', 123, 'AVM')
175
- expect(ev.first).to include('comment' => 'updated')
176
- expect(Marty::Event.compact_end_dt(ev.first)).to match(/\d\d:\d\d/)
177
- expect(Marty::Event.pretty_op(ev.first)).to eq('Avm')
178
- ev = Marty::Event.lookup_event('testcl1', 123, 'PRICING').first
179
- expect(Marty::Event.pretty_op(ev)).to eq('Pricing')
180
- evs = Marty::Event.last_event_multi('testcl1', [123, 234])
181
- expect(evs[123]).to include('klass' => 'testcl1',
182
- 'subject_id' => 123,
183
- 'enum_event_operation' => 'CRA',
184
- 'comment' => 'b comment',
185
- 'expire_secs' => nil,
186
- 'error' => nil)
187
- expect(evs[234]).to include('klass' => 'testcl1',
188
- 'subject_id' => 234,
189
- 'enum_event_operation' => 'PRICING',
190
- 'comment' => 'c comment',
191
- 'expire_secs' => nil,
192
- 'error' => false)
193
-
194
- af = Marty::Event.all_finished
195
- expect(af.count).to eq(4)
196
- expect(af[['testcl3', 987]]).to include('PRICING')
197
- expect(af[['testcl1', 123]]).to include('AVM')
198
- expect(af[['testcl1', 123]]['AVM']).to start_with(@date_string)
199
- end
200
-
201
- it 'raises on error' do
202
- expect do
203
- Marty::Event.create_event('testcl', 1234, 'AVM', Time.zone.now, 600,
204
- 'the comment')
205
- end .not_to raise_error
206
-
207
- expect do
208
- Marty::Event.create_event('testcl', 1234, 'AVM', Time.zone.now, 600,
209
- 'the comment')
210
- end.
211
- to raise_error(%r!AVM is already running for testcl/1234!)
212
- expect do
213
- Marty::Event.create_event('testcl', 2345, 'AVM', Time.zone.now, 600,
214
- 'the comment')
215
- end .not_to raise_error
216
- expect do
217
- Marty::Event.finish_event('testcl', 1234, 'AVM', false,
218
- 'new comment')
219
- end.
220
- not_to raise_error
221
- expect do
222
- Marty::Event.finish_event('testcl', 1234, 'AVM', false,
223
- 'new comment')
224
- end.
225
- to raise_error(%r!event testcl/1234/AVM not found!)
226
- expect { Marty::Event.finish_event('testcl', 2345, 'AVM', false, 'foobar') }.
227
- not_to raise_error
228
- expect { Marty::Event.finish_event('testcl', 2345, 'AVM', false, 'foobar') }.
229
- to raise_error(%r!event testcl/2345/AVM not found!)
230
- expect { Marty::Event.finish_event('testcl', 2345, 'AVM', nil, 'foobar') }.
231
- to raise_error(/error must be true or false/)
232
- expect do
233
- Marty::Event.create_event('testcl', 1234, 'AMV', Time.zone.now, 600,
234
- 'the comment')
235
- end.
236
- to raise_error(%r!PG::.*invalid input value for enum.*"AMV"!)
237
- Marty::Event.clear_cache
238
- af = Marty::Event.all_finished
239
- expect(af.count).to eq(5)
240
- expect(af).to include(['testcl', 1234])
241
- expect(af).to include(['testcl', 2345])
242
- expect(af[['testcl', 1234]]).to include('AVM')
243
- expect(af[['testcl', 2345]]).to include('AVM')
244
- expect(af[['testcl', 1234]]['AVM']).to start_with(@date_string)
245
- expect(af[['testcl', 2345]]['AVM']).to start_with(@date_string)
246
- end
247
-
248
- it 'truncates long comment' do
249
- long_comment = 'comment string abcdefg' * 100
250
- long_comment_truncated = long_comment.truncate(255)
251
- Marty::Event.create_event('testcl', 123, 'PRICING', Time.zone.now, 600,
252
- long_comment)
253
- Marty::Event.create!(klass: 'testcl',
254
- subject_id: 456,
255
- enum_event_operation: 'CRA',
256
- start_dt: Time.zone.now,
257
- expire_secs: 600,
258
- comment: long_comment)
259
-
260
- Marty::Event.create_event('testcl', 789, 'AVM', Time.zone.now, 600,
261
- 'comment')
262
- Marty::Event.finish_event('testcl', 789, 'AVM', false, long_comment)
263
-
264
- e1 = Marty::Event.lookup_event('testcl', 123, 'PRICING').first
265
- e2 = Marty::Event.lookup_event('testcl', 456, 'CRA').first
266
- e3 = Marty::Event.lookup_event('testcl', 789, 'AVM').first
267
-
268
- expect(e1['comment']).to eq(long_comment_truncated)
269
- expect(e2['comment']).to eq(long_comment_truncated)
270
- expect(e3['comment']).to eq(long_comment_truncated)
271
- end
272
- end