marty 2.5.2 → 2.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +4 -0
  3. data/.rubocop.yml +7 -0
  4. data/.rubocop_todo.yml +11 -589
  5. data/Gemfile +9 -9
  6. data/Gemfile.lock +1 -1
  7. data/Rakefile +1 -3
  8. data/app/components/marty/api_auth_view.rb +3 -3
  9. data/app/components/marty/api_config_view.rb +8 -8
  10. data/app/components/marty/api_log_view.rb +16 -20
  11. data/app/components/marty/auth_app.rb +6 -6
  12. data/app/components/marty/base_rule_view.rb +27 -19
  13. data/app/components/marty/config_view.rb +12 -9
  14. data/app/components/marty/data_grid_view.rb +26 -26
  15. data/app/components/marty/delorean_rule_view.rb +0 -1
  16. data/app/components/marty/event_view.rb +27 -27
  17. data/app/components/marty/extras/layout.rb +26 -26
  18. data/app/components/marty/extras/misc.rb +2 -2
  19. data/app/components/marty/grid.rb +13 -13
  20. data/app/components/marty/grid_append_only.rb +0 -1
  21. data/app/components/marty/import_type_view.rb +13 -13
  22. data/app/components/marty/import_view.rb +17 -16
  23. data/app/components/marty/log_view.rb +16 -14
  24. data/app/components/marty/main_auth_app.rb +59 -59
  25. data/app/components/marty/main_auth_app/client/main_auth_app.js +3 -3
  26. data/app/components/marty/mcfly_grid_panel.rb +10 -10
  27. data/app/components/marty/new_posting_form.rb +11 -11
  28. data/app/components/marty/new_posting_window.rb +0 -1
  29. data/app/components/marty/posting_grid.rb +12 -13
  30. data/app/components/marty/promise_view.rb +6 -6
  31. data/app/components/marty/report_form.rb +50 -53
  32. data/app/components/marty/report_select.rb +27 -27
  33. data/app/components/marty/reporting.rb +4 -4
  34. data/app/components/marty/script_form.rb +40 -42
  35. data/app/components/marty/script_grid.rb +24 -24
  36. data/app/components/marty/script_tester.rb +40 -42
  37. data/app/components/marty/scripting.rb +25 -27
  38. data/app/components/marty/simple_app.rb +24 -9
  39. data/app/components/marty/tag_grid.rb +12 -13
  40. data/app/components/marty/user_view.rb +35 -35
  41. data/app/controllers/marty/application_controller.rb +3 -4
  42. data/app/controllers/marty/components_controller.rb +1 -1
  43. data/app/controllers/marty/delayed_job_controller.rb +1 -0
  44. data/app/controllers/marty/diagnostic/controller.rb +4 -6
  45. data/app/controllers/marty/job_controller.rb +6 -6
  46. data/app/controllers/marty/report_controller.rb +11 -11
  47. data/app/controllers/marty/rpc_controller.rb +15 -16
  48. data/app/helpers/marty/script_set.rb +4 -4
  49. data/app/models/marty/api_auth.rb +4 -5
  50. data/app/models/marty/api_config.rb +1 -1
  51. data/app/models/marty/base.rb +9 -8
  52. data/app/models/marty/base_rule.rb +18 -13
  53. data/app/models/marty/config.rb +4 -5
  54. data/app/models/marty/data_grid.rb +157 -181
  55. data/app/models/marty/delorean_rule.rb +63 -62
  56. data/app/models/marty/enum.rb +1 -1
  57. data/app/models/marty/event.rb +56 -59
  58. data/app/models/marty/helper.rb +38 -6
  59. data/app/models/marty/import_type.rb +6 -6
  60. data/app/models/marty/log.rb +3 -2
  61. data/app/models/marty/name_validator.rb +3 -2
  62. data/app/models/marty/pg_enum.rb +3 -4
  63. data/app/models/marty/posting.rb +20 -24
  64. data/app/models/marty/promise.rb +28 -30
  65. data/app/models/marty/script.rb +30 -28
  66. data/app/models/marty/tag.rb +8 -8
  67. data/app/models/marty/token.rb +2 -2
  68. data/app/models/marty/user.rb +24 -23
  69. data/app/models/marty/vw_promise.rb +10 -11
  70. data/config/routes.rb +2 -2
  71. data/delorean/blame_report.dl +268 -0
  72. data/{spec/dummy/delorean/fields.dl → delorean/marty_fields.dl} +8 -0
  73. data/delorean/table_report.dl +34 -0
  74. data/docker-compose.dummy.yml +2 -3
  75. data/lib/marty/aws/base.rb +8 -8
  76. data/lib/marty/aws/request.rb +4 -4
  77. data/lib/marty/cache_adapters/mcfly_ruby_cache.rb +1 -0
  78. data/lib/marty/content_handler.rb +25 -25
  79. data/lib/marty/data_change.rb +49 -71
  80. data/lib/marty/data_conversion.rb +20 -28
  81. data/lib/marty/data_exporter.rb +25 -28
  82. data/lib/marty/data_importer.rb +25 -27
  83. data/lib/marty/engine.rb +1 -2
  84. data/lib/marty/json_schema.rb +22 -24
  85. data/lib/marty/logger.rb +6 -9
  86. data/lib/marty/mcfly_model.rb +20 -24
  87. data/lib/marty/migrations.rb +37 -35
  88. data/lib/marty/monkey.rb +33 -33
  89. data/lib/marty/permissions.rb +18 -18
  90. data/lib/marty/promise_job.rb +17 -17
  91. data/lib/marty/promise_proxy.rb +6 -6
  92. data/lib/marty/relation.rb +6 -7
  93. data/lib/marty/rpc_call.rb +13 -12
  94. data/lib/marty/rule_script_set.rb +32 -28
  95. data/lib/marty/schema_helper.rb +37 -51
  96. data/lib/marty/util.rb +25 -24
  97. data/lib/marty/version.rb +1 -1
  98. data/lib/marty/xl.rb +121 -115
  99. data/make-dummy.mk +3 -0
  100. data/marty.gemspec +21 -21
  101. data/other/marty/api/base.rb +34 -35
  102. data/other/marty/diagnostic/aws/ec2_instance.rb +8 -8
  103. data/other/marty/diagnostic/base.rb +13 -14
  104. data/other/marty/diagnostic/collection.rb +2 -1
  105. data/other/marty/diagnostic/connections.rb +8 -6
  106. data/other/marty/diagnostic/database.rb +1 -0
  107. data/other/marty/diagnostic/delayed_job_version.rb +7 -9
  108. data/other/marty/diagnostic/delayed_job_worker_total_count.rb +1 -1
  109. data/other/marty/diagnostic/delayed_job_workers.rb +1 -1
  110. data/other/marty/diagnostic/environment_variables.rb +17 -15
  111. data/other/marty/diagnostic/fatal.rb +1 -1
  112. data/other/marty/diagnostic/node.rb +5 -9
  113. data/other/marty/diagnostic/nodes.rb +7 -5
  114. data/other/marty/diagnostic/packer.rb +7 -7
  115. data/other/marty/diagnostic/reporter.rb +24 -27
  116. data/other/marty/diagnostic/version.rb +3 -5
  117. data/script/rails +2 -1
  118. data/spec/controllers/application_controller_spec.rb +6 -6
  119. data/spec/controllers/delayed_job_controller_spec.rb +4 -4
  120. data/spec/controllers/diagnostic/controller_spec.rb +59 -60
  121. data/spec/controllers/job_controller_spec.rb +68 -69
  122. data/spec/controllers/rpc_controller_spec.rb +353 -359
  123. data/spec/controllers/rpc_import_spec.rb +15 -16
  124. data/spec/dummy/delorean/blame_report.dl +110 -15
  125. data/spec/dummy/delorean/data_report.dl +4 -4
  126. data/spec/dummy/delorean/marty_fields.dl +63 -0
  127. data/spec/dummy/delorean/table_report.dl +34 -0
  128. data/spec/features/auth_app_spec.rb +1 -2
  129. data/spec/features/data_import_spec.rb +2 -3
  130. data/spec/features/enum_spec.rb +42 -46
  131. data/spec/features/jobs_dashboard_spec.rb +14 -8
  132. data/spec/features/log_view_spec.rb +40 -43
  133. data/spec/features/reporting_spec.rb +15 -15
  134. data/spec/features/rule_spec.rb +195 -190
  135. data/spec/features/scripting_spec.rb +17 -20
  136. data/spec/features/scripting_test_spec.rb +32 -33
  137. data/spec/features/user_view_spec.rb +15 -17
  138. data/spec/job_helper.rb +11 -11
  139. data/spec/lib/data_blame_spec.rb +82 -0
  140. data/spec/lib/data_exporter_spec.rb +31 -32
  141. data/spec/lib/data_importer_spec.rb +382 -395
  142. data/spec/lib/delorean_query_spec.rb +117 -119
  143. data/spec/lib/json_schema_spec.rb +382 -392
  144. data/spec/lib/logger_spec.rb +23 -24
  145. data/spec/lib/mcfly_model_spec.rb +112 -109
  146. data/spec/lib/migrations_spec.rb +10 -10
  147. data/spec/lib/struct_compare_spec.rb +6 -6
  148. data/spec/lib/table_report_spec.rb +90 -0
  149. data/spec/lib/xl_spec.rb +63 -65
  150. data/spec/lib/xl_styles_spec.rb +16 -19
  151. data/spec/models/api_auth_spec.rb +30 -30
  152. data/spec/models/config_spec.rb +32 -32
  153. data/spec/models/data_grid_spec.rb +642 -655
  154. data/spec/models/event_spec.rb +96 -88
  155. data/spec/models/import_type_spec.rb +20 -20
  156. data/spec/models/posting_spec.rb +35 -35
  157. data/spec/models/promise_spec.rb +5 -5
  158. data/spec/models/rule_spec.rb +280 -269
  159. data/spec/models/script_spec.rb +27 -18
  160. data/spec/models/user_spec.rb +9 -9
  161. data/spec/other/diagnostic/base_spec.rb +20 -19
  162. data/spec/other/diagnostic/collection_spec.rb +6 -5
  163. data/spec/other/diagnostic/delayed_job_version_spec.rb +1 -1
  164. data/spec/other/diagnostic/delayed_job_workers_spec.rb +8 -8
  165. data/spec/other/diagnostic/reporter_spec.rb +31 -33
  166. data/spec/spec_helper.rb +5 -5
  167. data/spec/support/chromedriver.rb +3 -5
  168. data/spec/support/components/netzke_combobox.rb +1 -1
  169. data/spec/support/components/netzke_grid.rb +17 -17
  170. data/spec/support/custom_matchers.rb +2 -2
  171. data/spec/support/download_helper.rb +1 -1
  172. data/spec/support/helper.rb +1 -2
  173. data/spec/support/netzke.rb +31 -31
  174. data/spec/support/performance_helper.rb +8 -8
  175. data/spec/support/post_run_logger.rb +1 -2
  176. data/spec/support/setup.rb +1 -4
  177. data/spec/support/shared_connection.rb +2 -2
  178. data/spec/support/structure_compare.rb +21 -22
  179. data/spec/support/suite.rb +1 -2
  180. data/spec/support/users.rb +5 -6
  181. metadata +32 -26
@@ -1,21 +1,53 @@
1
1
  class Marty::Helper
2
2
  include Delorean::Model
3
3
 
4
- delorean_fn :sleep, sig: 1 do
5
- |seconds|
4
+ delorean_fn :sleep, sig: 1 do |seconds|
6
5
  Kernel.sleep seconds
7
6
  end
8
7
 
9
- delorean_fn :range_step, sig: 3 do
10
- |rstart, rend, step|
8
+ delorean_fn :range_step, sig: 3 do |rstart, rend, step|
11
9
  (rstart..rend).step(step).to_a
12
10
  end
13
11
 
14
- delorean_fn :my_ip, sig:0 do
12
+ delorean_fn :my_ip, sig: 0 do
15
13
  Marty::Diagnostic::Node.my_ip
16
14
  end
17
15
 
18
- delorean_fn :git, sig:0 do
16
+ delorean_fn :git, sig: 0 do
19
17
  [my_ip, ENV['DELAYED_VER']]
20
18
  end
19
+
20
+ delorean_fn :infinity_dt, sig: 1 do |pt|
21
+ Mcfly.is_infinity pt
22
+ end
23
+
24
+ delorean_fn :constantize, sig: 1 do |class_name|
25
+ raise 'bad class_name' unless class_name.is_a?(String)
26
+
27
+ class_name.constantize
28
+ end
29
+
30
+ delorean_fn :get_column_types, sig: 1 do |klass|
31
+ Marty::DataConversion.col_types(klass)
32
+ end
33
+
34
+ delorean_fn :parse_csv_to_hash, sig: 3 do |txt, comma_sep, types|
35
+ txt ||= ''
36
+ headers, *rows = CSV.parse(txt.strip,
37
+ headers: true,
38
+ col_sep: (comma_sep ? ',' : "\t")).to_a
39
+ rows.map do |row|
40
+ headers.zip(row).each_with_object({}) do |(h, v), res|
41
+ res[h] = v.blank? ? nil :
42
+ Marty::DataConversion.convert(v, (types[h] || 'text').to_sym)
43
+ end
44
+ end
45
+ end
46
+
47
+ delorean_fn :to_csv, sig: [1, 2] do |*args|
48
+ # NOTE: can't use |data, config| due to delorean_fn weirdness.
49
+ data, config = args
50
+
51
+ Marty::DataExporter.to_csv(data, config)
52
+ end
21
53
  end
@@ -4,7 +4,7 @@ class Marty::ImportType < Marty::Base
4
4
  klass = entry.get_model_class
5
5
 
6
6
  unless klass.is_a?(Class) && klass < ActiveRecord::Base
7
- entry.errors.add :base, "bad model name"
7
+ entry.errors.add :base, 'bad model name'
8
8
  return
9
9
  end
10
10
 
@@ -12,19 +12,19 @@ class Marty::ImportType < Marty::Base
12
12
  entry.cleaner_function,
13
13
  entry.validation_function,
14
14
  entry.preprocess_function,
15
- ].each { |func|
15
+ ].each do |func|
16
16
  entry.errors.add(:base, "unknown class method #{func}") if
17
17
  func && !klass.respond_to?(func.to_sym)
18
- }
18
+ end
19
19
  end
20
20
  end
21
21
 
22
22
  before_validation do
23
23
  # Fix issue with blank strings in popup edit form or grid
24
24
  # being interpreted as a function
25
- self.cleaner_function = nil if self.cleaner_function.blank?
26
- self.validation_function = nil if self.validation_function.blank?
27
- self.preprocess_function = nil if self.preprocess_function.blank?
25
+ self.cleaner_function = nil if cleaner_function.blank?
26
+ self.validation_function = nil if validation_function.blank?
27
+ self.preprocess_function = nil if preprocess_function.blank?
28
28
  end
29
29
 
30
30
  belongs_to :role
@@ -9,7 +9,7 @@ class Marty::Log < Marty::Base
9
9
  message: message,
10
10
  details: details,
11
11
  timestamp: Time.zone.now)
12
- rescue => e
12
+ rescue StandardError => e
13
13
  Marty::Util.logger.error("Marty::Logger failure: #{e.message}")
14
14
  end
15
15
  true
@@ -18,6 +18,7 @@ class Marty::Log < Marty::Base
18
18
  def self.cleanup(days_to_keep)
19
19
  raise "Must give numeric value. (Got '#{days_to_keep}')" unless
20
20
  (Float(days_to_keep) rescue false)
21
- where("timestamp <= ?", Time.zone.now - days_to_keep.to_i.days).delete_all
21
+
22
+ where('timestamp <= ?', Time.zone.now - days_to_keep.to_i.days).delete_all
22
23
  end
23
24
  end
@@ -1,6 +1,7 @@
1
1
  class Marty::NameValidator < ActiveModel::Validator
2
2
  def validate(entry)
3
- raise "need field option" unless options[:field]
3
+ raise 'need field option' unless options[:field]
4
+
4
5
  field = options[:field].to_sym
5
6
  value = entry.send(field)
6
7
 
@@ -9,7 +10,7 @@ class Marty::NameValidator < ActiveModel::Validator
9
10
  # disallow leading, trailing, >1 internal spaces, special chars (|)
10
11
  if value =~ /\A\s|\s\z|\A.*\s\s.*\z|.*\|.*/
11
12
  entry.errors[field] <<
12
- I18n.t("activerecord.errors.messages.extraneous_spaces")
13
+ I18n.t('activerecord.errors.messages.extraneous_spaces')
13
14
  end
14
15
  end
15
16
  end
@@ -1,16 +1,15 @@
1
1
  module Marty::PgEnum
2
-
3
- def [](i0, i1=nil)
2
+ def [](i0, i1 = nil)
4
3
  # if i1 is provided, then i0 is a pt and we ignore it.
5
4
  index = (i1 || i0).to_s
6
5
 
7
- raise "no such #{self.name}: '#{index}'" unless
6
+ raise "no such #{name}: '#{index}'" unless
8
7
  self::VALUES.include?(index)
9
8
 
10
9
  index
11
10
  end
12
11
 
13
- def get_all(pt=nil)
12
+ def get_all(pt = nil)
14
13
  self::VALUES.map(&:to_s)
15
14
  end
16
15
 
@@ -4,7 +4,7 @@ class Marty::Posting < Marty::Base
4
4
  mcfly_validates_uniqueness_of :name
5
5
  validates_presence_of :name, :posting_type_id, :comment
6
6
 
7
- belongs_to :user, class_name: "Marty::User"
7
+ belongs_to :user, class_name: 'Marty::User'
8
8
  belongs_to :posting_type
9
9
 
10
10
  def self.make_name(posting_type, dt)
@@ -22,8 +22,8 @@ class Marty::Posting < Marty::Base
22
22
 
23
23
  before_validation :set_posting_name
24
24
  def set_posting_name
25
- posting_type = Marty::PostingType.find_by_id(self.posting_type_id)
26
- self.name = self.class.make_name(posting_type, self.created_dt)
25
+ posting_type = Marty::PostingType.find_by_id(posting_type_id)
26
+ self.name = self.class.make_name(posting_type, created_dt)
27
27
  true
28
28
  end
29
29
 
@@ -41,7 +41,7 @@ class Marty::Posting < Marty::Base
41
41
  end
42
42
 
43
43
  def self.get_struct_attrs
44
- self.struct_attrs ||= super + ["created_dt", "name"]
44
+ self.struct_attrs ||= super + ['created_dt', 'name']
45
45
  end
46
46
 
47
47
  # Not using mcfly_lookup since we don't want these time-warp markers
@@ -49,43 +49,39 @@ class Marty::Posting < Marty::Base
49
49
  # may allow deletion of postings. i.e. a new one with same name
50
50
  # might be created. Or, use regular validates_uniqueness_of instead
51
51
  # of mcfly_validates_uniqueness_of.
52
- delorean_fn :lookup, sig: 1 do
53
- |name|
52
+ delorean_fn :lookup, sig: 1 do |name|
54
53
  p = select(get_struct_attrs).find_by_name(name)
55
54
  make_openstruct(p)
56
55
  end
57
56
 
58
- delorean_fn :lookup_dt, sig: 1 do
59
- |name|
57
+ delorean_fn :lookup_dt, sig: 1 do |name|
60
58
  find_by_name(name).try(:created_dt)
61
59
  end
62
60
 
63
- delorean_fn :first_match, sig: [1, 2] do
64
- |dt, posting_type=nil|
65
- raise "bad posting type" if
61
+ delorean_fn :first_match, sig: [1, 2] do |dt, posting_type = nil|
62
+ raise 'bad posting type' if
66
63
  posting_type && !posting_type.is_a?(Marty::PostingType)
67
64
 
68
- q = where("created_dt <= ?", dt)
65
+ q = where('created_dt <= ?', dt)
69
66
  q = q.where(posting_type_id: posting_type.id) if posting_type
70
- q.order("created_dt DESC").first.attributes
67
+ q.order('created_dt DESC').first.attributes
71
68
  end
72
69
 
73
- def self.get_latest(limit, is_test=nil)
70
+ def self.get_latest(limit, is_test = nil)
74
71
  # IMPORTANT: is_test arg is ignored (KEEP for backward compat.)
75
72
 
76
- q=where("created_dt <> 'infinity'").
77
- order("created_dt DESC").limit(limit)
73
+ q = where("created_dt <> 'infinity'").
74
+ order('created_dt DESC').limit(limit)
78
75
  end
79
76
 
80
- delorean_fn :get_latest_by_type, sig: [1, 2] do
81
- |limit, posting_types=[]|
82
- raise "missing posting types list" unless posting_types
83
- raise "bad posting types list" unless posting_types.is_a?(Array)
77
+ delorean_fn :get_latest_by_type, sig: [1, 2] do |limit, posting_types = []|
78
+ raise 'missing posting types list' unless posting_types
79
+ raise 'bad posting types list' unless posting_types.is_a?(Array)
84
80
 
85
- q=joins(:posting_type).where("created_dt <> 'infinity'").
86
- where(marty_posting_types: { name: posting_types } ).
81
+ q = joins(:posting_type).where("created_dt <> 'infinity'").
82
+ where(marty_posting_types: { name: posting_types }).
87
83
  select(get_struct_attrs).
88
- order("created_dt DESC").limit(limit || 1)
89
- q.map{|ar| ar.attributes}
84
+ order('created_dt DESC').limit(limit || 1)
85
+ q.map(&:attributes)
90
86
  end
91
87
  end
@@ -1,28 +1,27 @@
1
1
  class Marty::Promise < Marty::Base
2
-
3
2
  # default timeout (seconds) to wait for promise values
4
3
  DEFAULT_PROMISE_TIMEOUT = Rails.configuration.marty.promise_timeout || 30
5
4
 
6
5
  # default timeout (seconds) to wait for jobs to start
7
6
  DEFAULT_JOB_TIMEOUT = Rails.configuration.marty.job_timeout || 10
8
7
 
9
- def result(force=false)
8
+ def result(force = false)
10
9
  res = super()
11
10
  Marty::Promise.load_result(res, force)
12
11
  end
13
12
 
14
- def self.load_result(obj, force=false)
13
+ def self.load_result(obj, force = false)
15
14
  if force && obj.respond_to?(:__force__)
16
15
  obj = obj.__force__
17
16
  end
18
17
 
19
18
  case obj
20
19
  when Array
21
- obj.map {|x| load_result(x, force)}
20
+ obj.map { |x| load_result(x, force) }
22
21
  when Hash
23
22
  p = obj['__promise__']
24
23
 
25
- if p && obj.length==1
24
+ if p && obj.length == 1
26
25
  load_result(Marty::PromiseProxy.new(*p), force)
27
26
  else
28
27
  obj.each_with_object({}) { |(k, v), h| h[k] = load_result(v, force) }
@@ -34,21 +33,19 @@ class Marty::Promise < Marty::Base
34
33
 
35
34
  has_many :children,
36
35
  foreign_key: 'parent_id',
37
- class_name: "Marty::Promise",
36
+ class_name: 'Marty::Promise',
38
37
  dependent: :destroy
39
38
 
40
39
  validates_presence_of :title
41
40
 
42
- belongs_to :parent, class_name: "Marty::Promise"
43
- belongs_to :user, class_name: "Marty::User"
41
+ belongs_to :parent, class_name: 'Marty::Promise'
42
+ belongs_to :user, class_name: 'Marty::User'
44
43
 
45
- def self.cleanup(all=false)
46
- begin
44
+ def self.cleanup(all = false)
47
45
  where('start_dt < ? AND parent_id IS NULL',
48
46
  DateTime.now - (all ? 0.hours : 4.hours)).destroy_all
49
- rescue => exc
47
+ rescue StandardError => exc
50
48
  Marty::Util.logger.error("promise GC error: #{exc}")
51
- end
52
49
  end
53
50
 
54
51
  def raw_conn
@@ -60,38 +57,38 @@ class Marty::Promise < Marty::Base
60
57
  end
61
58
 
62
59
  def set_start
63
- if self.start_dt || self.result != {}
60
+ if start_dt || result != {}
64
61
  Marty::Util.logger.error("promise already started: #{self}")
65
62
  return
66
63
  end
67
64
 
68
65
  # mark promise as started
69
66
  self.start_dt = DateTime.now
70
- self.save!
67
+ save!
71
68
  end
72
69
 
73
70
  def set_result(res)
74
71
  # log "SETRES #{Process.pid} #{self}"
75
72
 
76
73
  # promise must have been started and not yet ended
77
- if !self.start_dt || self.end_dt || self.result != {}
74
+ if !start_dt || end_dt || result != {}
78
75
  # log "SETERR #{Process.pid} #{self}"
79
76
  Marty::Util.logger.error("unexpected promise state: #{self}")
80
77
  return
81
78
  end
82
79
 
83
- raise "bad result" unless res.is_a?(Hash)
80
+ raise 'bad result' unless res.is_a?(Hash)
84
81
 
85
- self.status = res["error"].nil?
82
+ self.status = res['error'].nil?
86
83
  self.result = res
87
84
 
88
85
  # update title/format from result hash (somewhat hacky)
89
- self.title = res["title"].to_s if res["title"]
90
- self.cformat = res["format"].to_s if res["format"]
86
+ self.title = res['title'].to_s if res['title']
87
+ self.cformat = res['format'].to_s if res['format']
91
88
 
92
89
  # mark promise as ended
93
90
  self.end_dt = DateTime.now
94
- self.save!
91
+ save!
95
92
 
96
93
  # log "NOTIFY #{Process.pid}"
97
94
  pg_notify
@@ -106,11 +103,11 @@ class Marty::Promise < Marty::Base
106
103
  # end
107
104
 
108
105
  def wait_for_my_notify(timeout)
109
- while true do
106
+ while true
110
107
  # FIXME: we keep using the same timeout. The timeout should be
111
108
  # reduced by total time spent here.
112
109
  n = raw_conn.wait_for_notify(timeout)
113
- return n if !n || n=="promise_#{id}"
110
+ return n if !n || n == "promise_#{id}"
114
111
  end
115
112
  end
116
113
 
@@ -120,17 +117,17 @@ class Marty::Promise < Marty::Base
120
117
  # seems to work.
121
118
 
122
119
  # get latest uncached version
123
- Marty::Promise.uncached {Marty::Promise.find(id)}
120
+ Marty::Promise.uncached { Marty::Promise.find(id) }
124
121
  end
125
122
 
126
123
  def self.job_by_id(job_id)
127
- Delayed::Job.uncached {Delayed::Job.find_by_id(job_id)}
124
+ Delayed::Job.uncached { Delayed::Job.find_by_id(job_id) }
128
125
  end
129
126
 
130
127
  def work_off_job(job)
131
128
  # Create a temporary worker to work off the job
132
129
  Delayed::Job.where(id: job.id).
133
- update_all(locked_at: Delayed::Job.db_time_now, locked_by: "Temp")
130
+ update_all(locked_at: Delayed::Job.db_time_now, locked_by: 'Temp')
134
131
  w = Delayed::Worker.new
135
132
  w.run(job)
136
133
  end
@@ -138,7 +135,7 @@ class Marty::Promise < Marty::Base
138
135
  def wait_for_result(timeout)
139
136
  # FIXME: Not sure that comparing result with empty hash if a good idea
140
137
  # perhaps it's better to use .present? or .blank?
141
- return self.result if self.result != {}
138
+ return result if result != {}
142
139
 
143
140
  begin
144
141
  # start listening on promise's notification
@@ -150,7 +147,8 @@ class Marty::Promise < Marty::Base
150
147
  if !last.start_dt
151
148
  job = Marty::Promise.job_by_id(last.job_id)
152
149
 
153
- # FIXME: this block is needed since a lot of specs rely on delayed job being runned in the same thread as promise
150
+ # FIXME: this block is needed since a lot of specs rely on
151
+ # delayed job being runned in the same thread as promise
154
152
  # Can be deleted later and replaces with simple timeout below
155
153
  if !job || job.locked_at
156
154
  # job has been locked, so it looks like it started already
@@ -162,7 +160,7 @@ class Marty::Promise < Marty::Base
162
160
  # log "OFF0 #{Process.pid} #{last}"
163
161
  begin
164
162
  work_off_job(job)
165
- rescue => exc
163
+ rescue StandardError => exc
166
164
  # log "OFFERR #{exc}"
167
165
  res = Delorean::Engine.grok_runtime_exception(exc)
168
166
  last.set_result(res)
@@ -179,7 +177,7 @@ class Marty::Promise < Marty::Base
179
177
  # timeout error.
180
178
  if !last.start_dt
181
179
  # log "TO11 #{Process.pid} #{last}"
182
- return {"error" => "promise #{last.id} timed out (never started)"}
180
+ return { 'error' => "promise #{last.id} timed out (never started)" }
183
181
  end
184
182
  end
185
183
 
@@ -192,7 +190,7 @@ class Marty::Promise < Marty::Base
192
190
  last = latest
193
191
 
194
192
  if !last.end_dt
195
- return {"error" => "promise #{last.id} timed out (didn't end)"}
193
+ return { 'error' => "promise #{last.id} timed out (didn't end)" }
196
194
  end
197
195
  end
198
196
 
@@ -3,24 +3,23 @@ class Marty::Script < Marty::Base
3
3
 
4
4
  validates_presence_of :name, :body
5
5
  mcfly_validates_uniqueness_of :name
6
- validates_format_of :name, {
7
- with: /\A[A-Z][a-zA-Z0-9]*\z/,
8
- message: I18n.t('script.save_error'),
9
- }
6
+ validates_format_of :name,
7
+ with: /\A[A-Z][a-zA-Z0-9]*\z/,
8
+ message: I18n.t('script.save_error')
10
9
 
11
- belongs_to :user, class_name: "Marty::User"
10
+ belongs_to :user, class_name: 'Marty::User'
12
11
 
13
12
  gen_mcfly_lookup :lookup, [:name], cache: true
14
13
 
15
14
  # find script by name/tag (not cached)
16
- def self.find_script(sname, tag=nil)
15
+ def self.find_script(sname, tag = nil)
17
16
  tag = Marty::Tag.map_to_tag(tag)
18
17
  Marty::Script.mcfly_pt(tag.created_dt).find_by(name: sname)
19
18
  end
20
19
 
21
20
  def find_tag
22
21
  # find the first tag created after this script.
23
- Marty::Tag.where("created_dt >= ?", created_dt).order(:created_dt).first
22
+ Marty::Tag.where('created_dt >= ?', created_dt).order(:created_dt).first
24
23
  end
25
24
 
26
25
  def self.create_script(name, body)
@@ -31,7 +30,7 @@ class Marty::Script < Marty::Base
31
30
  script
32
31
  end
33
32
 
34
- def self.load_a_script(sname, body, dt=nil)
33
+ def self.load_a_script(sname, body, dt = nil)
35
34
  s = Marty::Script.find_by(obsoleted_dt: 'infinity', name: sname)
36
35
 
37
36
  if !s
@@ -47,28 +46,27 @@ class Marty::Script < Marty::Base
47
46
  end
48
47
  end
49
48
 
50
- def self.load_script_bodies(bodies, dt=nil)
51
- bodies.each {
52
- |sname, body|
49
+ def self.load_script_bodies(bodies, dt = nil)
50
+ bodies.each do |sname, body|
53
51
  load_a_script(sname, body, dt)
54
- }
52
+ end
55
53
 
56
54
  # Create a new tag if scripts were modified after the last tag
57
55
  tag = Marty::Tag.get_latest1
58
- latest = Marty::Script.order("created_dt DESC").first
56
+ latest = Marty::Script.order('created_dt DESC').first
59
57
 
60
58
  tag_time = (dt || [latest.try(:created_dt), Time.now].compact.max) +
61
59
  1.second
62
60
 
63
61
  # If no tag_time is provided, the tag created_dt will be the same
64
62
  # as the scripts.
65
- tag = Marty::Tag.do_create(tag_time, "tagged from load scripts") if
63
+ tag = Marty::Tag.do_create(tag_time, 'tagged from load scripts') if
66
64
  !(tag && latest) || tag.created_dt <= latest.created_dt
67
65
 
68
66
  tag
69
67
  end
70
68
 
71
- def self.load_scripts(path=nil, dt=nil)
69
+ def self.load_scripts(path = nil, dt = nil)
72
70
  files = get_script_filenames(path)
73
71
 
74
72
  bodies = read_script_files(files)
@@ -77,10 +75,10 @@ class Marty::Script < Marty::Base
77
75
  end
78
76
 
79
77
  def self.read_script_files(files)
80
- files.collect { |fpath|
78
+ files.collect do |fpath|
81
79
  fname = File.basename(fpath)[0..-4].camelize
82
80
  [fname, File.read(fpath)]
83
- }
81
+ end
84
82
  end
85
83
 
86
84
  def self.get_script_filenames(paths = nil)
@@ -90,7 +88,7 @@ class Marty::Script < Marty::Base
90
88
  paths.each do |path|
91
89
  Dir.glob("#{path}/*.dl").each do |filename|
92
90
  basename = File.basename(filename)
93
- filenames[basename] = filename unless filenames.has_key?(basename)
91
+ filenames[basename] = filename unless filenames.key?(basename)
94
92
  end
95
93
  end
96
94
 
@@ -114,15 +112,15 @@ class Marty::Script < Marty::Base
114
112
 
115
113
  def self.delete_scripts
116
114
  ActiveRecord::Base.connection.
117
- execute("ALTER TABLE marty_scripts DISABLE TRIGGER USER;")
115
+ execute('ALTER TABLE marty_scripts DISABLE TRIGGER USER;')
118
116
  Marty::Script.delete_all
119
117
  ActiveRecord::Base.connection.
120
- execute("ALTER TABLE marty_scripts ENABLE TRIGGER USER;")
118
+ execute('ALTER TABLE marty_scripts ENABLE TRIGGER USER;')
121
119
  end
122
120
 
123
- delorean_fn :eval_to_hash, sig: 5 do
124
- |dt, script, node, attrs, params|
125
- tag = Marty::Tag.find_match(dt) || raise("no tag found for #{dt}")
121
+ delorean_fn :eval_to_hash, sig: 5 do |dt, script, node, attrs, params|
122
+ tag = Marty::Tag.find_match(dt) if dt.present?
123
+ raise("no tag for #{dt}") if tag.nil? && dt.present?
126
124
 
127
125
  engine = Marty::ScriptSet.new(tag).get_engine(script)
128
126
  # IMPORTANT: engine evals (e.g. eval_to_hash) modify the
@@ -134,11 +132,16 @@ class Marty::Script < Marty::Base
134
132
  # current tag can caused problems.
135
133
  end
136
134
 
137
- delorean_fn :evaluate, sig: 5 do
138
- |dt, script, node, attr, params|
139
- tag = Marty::Tag.find_match(dt) || raise("no tag found for #{dt}")
135
+ # evaluate script's node attribute (attr) with the given params. dt
136
+ # is used to determine which script tag to use. The latest tag is
137
+ # used if dt is nil.
138
+ delorean_fn :evaluate, sig: 5 do |dt, script, node, attr, params|
139
+ tag = Marty::Tag.find_match(dt) if dt.present?
140
+ raise("no tag for #{dt}") if tag.nil? && dt.present?
140
141
 
142
+ # nil tag, uses the latest one
141
143
  engine = Marty::ScriptSet.new(tag).get_engine(script)
144
+
142
145
  # IMPORTANT: engine evals (e.g. eval_to_hash) modify the
143
146
  # params, but it is possible that we may be passing in
144
147
  # a frozen hash. To avoid performance impacts, we should first check if
@@ -146,8 +149,7 @@ class Marty::Script < Marty::Base
146
149
  engine.evaluate(node, attr, params.frozen? ? params.dup : params.clone)
147
150
  end
148
151
 
149
- delorean_fn :pretty_print, sig: 1 do
150
- |id|
152
+ delorean_fn :pretty_print, sig: 1 do |id|
151
153
  script = find_by_id id
152
154
 
153
155
  next "unknown script #{id}" unless script