openc3 5.11.0 → 5.11.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of openc3 might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: beada8d3ae31acc7a45fff23d454f4667b552a5de293f6c17f6da72626dd8490
4
- data.tar.gz: 950b07bf2f6a3173284d41a77ae7abf4cf6f9582a885dbedc585d50001fadcd8
3
+ metadata.gz: 5026df00ed04704e22029423bc09cae31eaebb798517ee02f1fcef3d60c4dfc0
4
+ data.tar.gz: 96c671d4a686c15d1db84489528f0551cb0cb54b42d21410839fc65f927c5360
5
5
  SHA512:
6
- metadata.gz: 7b0e9f874d5a88c167ba9bd78c3718d1b646ab80560106e01fb109189c27d6b399a3f51531b23815129ea24f4b9194770c9448d8e4be832c0926a6f5b8c3f9ad
7
- data.tar.gz: e5c20e0648e27b311de33c0d06eb27bb229110eac0fcf197619dac6a3232b239334cbda07bf3f79e88ddb7425b773191c04f9929883a6042b36633c99924285a
6
+ metadata.gz: 76cdc1efc5b5094da9c84fde2ce27fe9b850f594a2ffa09ab736b6ec98f3f1a73c20700ac4e409dd1c3632cdb208e1695b37aada33af2dce548633b771035021
7
+ data.tar.gz: 4142f4251262cc43f60bdfa4d54300e2282a2c2759991ebfd623a046c1e97a8ac929aec764b05fae59fa874b99957bfc492199219e9ec70dfa3a9315afb9206a
data/README.md CHANGED
@@ -17,7 +17,6 @@ set OPENC3_REDIS_USERNAME=openc3
17
17
  set OPENC3_REDIS_PASSWORD=openc3password
18
18
  set OPENC3_BUCKET_USERNAME=openc3minio
19
19
  set OPENC3_BUCKET_PASSWORD=openc3miniopassword
20
- set OPENC3_SERVICE_PASSWORD=openc3service
21
20
  set OPENC3_SR_REDIS_USERNAME=scriptrunner
22
21
  set OPENC3_SR_REDIS_PASSWORD=scriptrunnerpassword
23
22
  set OPENC3_SR_BUCKET_USERNAME=scriptrunnerminio
@@ -31,7 +30,6 @@ OPENC3_REDIS_USERNAME=openc3
31
30
  OPENC3_REDIS_PASSWORD=openc3password
32
31
  OPENC3_BUCKET_USERNAME=openc3minio
33
32
  OPENC3_BUCKET_PASSWORD=openc3miniopassword
34
- OPENC3_SERVICE_PASSWORD=openc3service
35
33
  OPENC3_SR_REDIS_USERNAME=scriptrunner
36
34
  OPENC3_SR_REDIS_PASSWORD=scriptrunnerpassword
37
35
  OPENC3_SR_BUCKET_USERNAME=scriptrunnerminio
@@ -36,9 +36,12 @@ module OpenC3
36
36
 
37
37
  DURATION_METRICS = {}
38
38
  DURATION_METRICS['decom_duration_seconds'] = 0.0
39
- DURATION_METRICS['reducer_minute_processing_seconds'] = 0
40
- DURATION_METRICS['reducer_hour_processing_seconds'] = 0
41
- DURATION_METRICS['reducer_day_processing_seconds'] = 0
39
+ DURATION_METRICS['reducer_minute_processing_sample_seconds'] = 0.0
40
+ DURATION_METRICS['reducer_hour_processing_sample_seconds'] = 0.0
41
+ DURATION_METRICS['reducer_day_processing_sample_seconds'] = 0.0
42
+ DURATION_METRICS['reducer_minute_processing_max_seconds'] = 0.0
43
+ DURATION_METRICS['reducer_hour_processing_max_seconds'] = 0.0
44
+ DURATION_METRICS['reducer_day_processing_max_seconds'] = 0.0
42
45
 
43
46
  SUM_METRICS = {}
44
47
  SUM_METRICS['cleanup_total'] = 0
@@ -51,8 +54,12 @@ module OpenC3
51
54
  SUM_METRICS['log_total'] = 0
52
55
  SUM_METRICS['log_error_total'] = 0
53
56
  SUM_METRICS['periodic_total'] = 0
54
- SUM_METRICS['reducer_total'] = 0
55
- SUM_METRICS['reducer_error_total'] = 0
57
+ SUM_METRICS['reducer_minute_total'] = 0
58
+ SUM_METRICS['reducer_hour_total'] = 0
59
+ SUM_METRICS['reducer_day_total'] = 0
60
+ SUM_METRICS['reducer_minute_error_total'] = 0
61
+ SUM_METRICS['reducer_hour_error_total'] = 0
62
+ SUM_METRICS['reducer_day_error_total'] = 0
56
63
  SUM_METRICS['router_cmd_total'] = 0
57
64
  SUM_METRICS['router_tlm_total'] = 0
58
65
  SUM_METRICS['router_directive_total'] = 0
@@ -53,7 +53,7 @@ module OpenC3
53
53
  # generate the auth object
54
54
  def _generate_auth
55
55
  if ENV['OPENC3_API_TOKEN'].nil? and ENV['OPENC3_API_USER'].nil?
56
- if ENV['OPENC3_API_PASSWORD'] || ENV['OPENC3_SERVICE_PASSWORD']
56
+ if ENV['OPENC3_API_PASSWORD']
57
57
  return OpenC3Authentication.new()
58
58
  else
59
59
  return nil
@@ -72,7 +72,7 @@ module OpenC3
72
72
  # generate the auth object
73
73
  def generate_auth
74
74
  if ENV['OPENC3_API_TOKEN'].nil? and ENV['OPENC3_API_USER'].nil?
75
- if ENV['OPENC3_API_PASSWORD'] || ENV['OPENC3_SERVICE_PASSWORD']
75
+ if ENV['OPENC3_API_PASSWORD']
76
76
  return OpenC3Authentication.new()
77
77
  else
78
78
  return nil
@@ -281,7 +281,9 @@ module OpenC3
281
281
  OpenC3.handle_critical_exception(err)
282
282
  end
283
283
 
284
- def prepare_write(time_nsec_since_epoch, data_length, redis_topic = nil, redis_offset = nil, allow_new_file: true)
284
+ # @enforce_time_order requires the timestamps on each write to be greater than the previous
285
+ # process_out_of_order ignores the timestamps for the current entry (used to ignore timestamps on metadata entries, vs actual packets)
286
+ def prepare_write(time_nsec_since_epoch, data_length, redis_topic = nil, redis_offset = nil, allow_new_file: true, process_out_of_order: true)
285
287
  # This check includes logging_enabled again because it might have changed since we acquired the mutex
286
288
  # Ensures new files based on size, and ensures always increasing time order in files
287
289
  if @logging_enabled
@@ -291,7 +293,7 @@ module OpenC3
291
293
  elsif @cycle_size and ((@file_size + data_length) > @cycle_size)
292
294
  Logger.debug("Log writer start new file due to cycle size #{@cycle_size}")
293
295
  start_new_file() if allow_new_file
294
- elsif @enforce_time_order and @previous_time_nsec_since_epoch and (@previous_time_nsec_since_epoch > time_nsec_since_epoch)
296
+ elsif process_out_of_order and @enforce_time_order and @previous_time_nsec_since_epoch and (@previous_time_nsec_since_epoch > time_nsec_since_epoch)
295
297
  # Warning: Creating new files here can cause lots of files to be created if packets make it through out of order
296
298
  # Changed to just a error to prevent file thrashing
297
299
  unless @out_of_order
@@ -301,7 +303,7 @@ module OpenC3
301
303
  end
302
304
  end
303
305
  @last_offsets[redis_topic] = redis_offset if redis_topic and redis_offset # This is needed for the redis offset marker entry at the end of the log file
304
- @previous_time_nsec_since_epoch = time_nsec_since_epoch
306
+ @previous_time_nsec_since_epoch = time_nsec_since_epoch if process_out_of_order
305
307
  end
306
308
 
307
309
  # Closing a log file isn't critical so we just log an error. NOTE: This also trims the Redis stream
@@ -95,7 +95,14 @@ module OpenC3
95
95
 
96
96
  @mutex.lock if take_mutex
97
97
  begin
98
- prepare_write(time_nsec_since_epoch, data.length, redis_topic, redis_offset, allow_new_file: allow_new_file)
98
+ if entry_type == :RAW_PACKET or entry_type == :JSON_PACKET
99
+ # Only care about the timestamps on the real packets being in order
100
+ process_out_of_order = true
101
+ else
102
+ # Metadata timestamps don't matter
103
+ process_out_of_order = false
104
+ end
105
+ prepare_write(time_nsec_since_epoch, data.length, redis_topic, redis_offset, allow_new_file: allow_new_file, process_out_of_order: process_out_of_order)
99
106
  write_entry(entry_type, cmd_or_tlm, target_name, packet_name, time_nsec_since_epoch, stored, data, id, received_time_nsec_since_epoch: received_time_nsec_since_epoch, extra: extra) if @file
100
107
  ensure
101
108
  @mutex.unlock if take_mutex
@@ -30,6 +30,7 @@ require 'openc3/models/reducer_model'
30
30
  require 'openc3/logs/buffered_packet_log_writer'
31
31
  require 'openc3/ext/reducer_microservice' if RUBY_ENGINE == 'ruby' and !ENV['OPENC3_NO_EXT']
32
32
  require 'rufus-scheduler'
33
+ require 'thread'
33
34
 
34
35
  module OpenC3
35
36
  class ReducerState
@@ -75,9 +76,9 @@ module OpenC3
75
76
  end
76
77
 
77
78
  class ReducerMicroservice < Microservice
78
- MINUTE_METRIC = 'reducer_minute_processing_seconds'
79
- HOUR_METRIC = 'reducer_hour_processing_seconds'
80
- DAY_METRIC = 'reducer_day_processing_seconds'
79
+ MINUTE_METRIC = 'reducer_minute_processing'
80
+ HOUR_METRIC = 'reducer_hour_processing'
81
+ DAY_METRIC = 'reducer_day_processing'
81
82
 
82
83
  # How long to wait for any currently running jobs to complete before killing them
83
84
  SHUTDOWN_DELAY_SECS = 5
@@ -106,14 +107,28 @@ module OpenC3
106
107
  end
107
108
  end
108
109
 
109
- @buffer_depth = 10 unless @buffer_depth
110
+ @buffer_depth = 60 unless @buffer_depth
110
111
  @max_cpu_utilization = 30.0 unless @max_cpu_utilization
111
112
  @target_name = name.split('__')[-1]
112
113
  @packet_logs = {}
114
+ @mutex = Mutex.new
115
+ @previous_metrics = {}
113
116
 
114
117
  @error_count = 0
115
- @metric.set(name: 'reducer_total', value: @count, type: 'counter')
116
- @metric.set(name: 'reducer_error_total', value: @error_count, type: 'counter')
118
+
119
+ # Initialize metrics
120
+ @metric.set(name: 'reducer_minute_total', value: 0, type: 'counter')
121
+ @metric.set(name: 'reducer_hour_total', value: 0, type: 'counter')
122
+ @metric.set(name: 'reducer_day_total', value: 0, type: 'counter')
123
+ @metric.set(name: 'reducer_minute_error_total', value: 0, type: 'counter')
124
+ @metric.set(name: 'reducer_hour_error_total', value: 0, type: 'counter')
125
+ @metric.set(name: 'reducer_day_error_total', value: 0, type: 'counter')
126
+ @metric.set(name: 'reducer_minute_processing_sample_seconds', value: 0.0, type: 'gauge', unit: 'seconds')
127
+ @metric.set(name: 'reducer_hour_processing_sample_seconds', value: 0.0, type: 'gauge', unit: 'seconds')
128
+ @metric.set(name: 'reducer_day_processing_sample_seconds', value: 0.0, type: 'gauge', unit: 'seconds')
129
+ @metric.set(name: 'reducer_minute_processing_max_seconds', value: 0.0, type: 'gauge', unit: 'seconds')
130
+ @metric.set(name: 'reducer_hour_processing_max_seconds', value: 0.0, type: 'gauge', unit: 'seconds')
131
+ @metric.set(name: 'reducer_day_processing_max_seconds', value: 0.0, type: 'gauge', unit: 'seconds')
117
132
  end
118
133
 
119
134
  def run
@@ -155,41 +170,65 @@ module OpenC3
155
170
 
156
171
  def metric(name)
157
172
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
158
- yield
173
+ processed = yield
159
174
  elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start # seconds as a float
160
- @metric.set(name: name, value: elapsed, type: 'gauge', unit: 'seconds')
175
+ if processed
176
+ sample_name = name + '_sample_seconds'
177
+ @metric.set(name: sample_name, value: elapsed, type: 'gauge', unit: 'seconds')
178
+ max_name = name + '_max_seconds'
179
+ previous_max = @previous_metrics[max_name] || 0.0
180
+ if elapsed > previous_max
181
+ @metric.set(name: max_name, value: elapsed, type: 'gauge', unit: 'seconds')
182
+ @previous_metrics[max_name] = elapsed
183
+ end
184
+ end
161
185
  end
162
186
 
163
187
  def reduce_minute
164
- metric(MINUTE_METRIC) do
165
- ReducerModel
166
- .all_files(type: :DECOM, target: @target_name, scope: @scope)
167
- .each do |file|
168
- process_file(file, 'minute', MINUTE_ENTRY_NSECS, MINUTE_FILE_NSECS)
169
- ReducerModel.rm_file(file)
188
+ @mutex.synchronize do
189
+ metric(MINUTE_METRIC) do
190
+ processed = false
191
+ ReducerModel
192
+ .all_files(type: :DECOM, target: @target_name, scope: @scope)
193
+ .each do |file|
194
+ process_file(file, 'minute', MINUTE_ENTRY_NSECS, MINUTE_FILE_NSECS)
195
+ ReducerModel.rm_file(file)
196
+ processed = true
170
197
  end
198
+ processed # return to yield
199
+ end
171
200
  end
172
201
  end
173
202
 
174
203
  def reduce_hour
175
- metric(HOUR_METRIC) do
176
- ReducerModel
177
- .all_files(type: :MINUTE, target: @target_name, scope: @scope)
178
- .each do |file|
179
- process_file(file, 'hour', HOUR_ENTRY_NSECS, HOUR_FILE_NSECS)
180
- ReducerModel.rm_file(file)
204
+ @mutex.synchronize do
205
+ metric(HOUR_METRIC) do
206
+ processed = false
207
+ ReducerModel
208
+ .all_files(type: :MINUTE, target: @target_name, scope: @scope)
209
+ .each do |file|
210
+ process_file(file, 'hour', HOUR_ENTRY_NSECS, HOUR_FILE_NSECS)
211
+ ReducerModel.rm_file(file)
212
+ processed = true
181
213
  end
214
+ processed # return to yield
215
+ end
182
216
  end
183
217
  end
184
218
 
185
219
  def reduce_day
186
- metric(DAY_METRIC) do
187
- ReducerModel
188
- .all_files(type: :HOUR, target: @target_name, scope: @scope)
189
- .each do |file|
190
- process_file(file, 'day', DAY_ENTRY_NSECS, DAY_FILE_NSECS)
191
- ReducerModel.rm_file(file)
220
+ @mutex.synchronize do
221
+ metric(DAY_METRIC) do
222
+ processed = false
223
+ ReducerModel
224
+ .all_files(type: :HOUR, target: @target_name, scope: @scope)
225
+ .each do |file|
226
+ process_file(file, 'day', DAY_ENTRY_NSECS, DAY_FILE_NSECS)
227
+ ReducerModel.rm_file(file)
228
+ processed = true
192
229
  end
230
+ processed # return to yield
231
+ end
193
232
  end
194
233
  end
195
234
 
@@ -197,8 +236,12 @@ module OpenC3
197
236
  throttle = OpenC3::Throttle.new(@max_cpu_utilization)
198
237
  file = BucketFile.new(filename)
199
238
  file.retrieve
200
- unless file.local_path
201
- @logger.warn("Reducer Warning: #{filename}: Could not be retrieved")
239
+ unless File.exist?(file.local_path)
240
+ @logger.warn("Reducer Warning: #{file.local_path}: Does not exist")
241
+ return
242
+ end
243
+ unless File.size(file.local_path) > 0
244
+ @logger.warn("Reducer Warning: #{file.local_path}: Is zero bytes")
202
245
  return
203
246
  end
204
247
  throttle.throttle_sleep
@@ -270,17 +313,38 @@ module OpenC3
270
313
  @logger.debug("Reducer Throttle: #{filename}: total_time: #{Time.now - throttle.reset_time}, sleep_time: #{throttle.total_sleep_time}")
271
314
 
272
315
  @count += 1
273
- @metric.set(name: 'reducer_total', value: @count, type: 'counter')
316
+ if type == 'minute'
317
+ metric_name = 'reducer_minute_total'
318
+ elsif type == 'hour'
319
+ metric_name = 'reducer_hour_total'
320
+ else
321
+ metric_name = 'reducer_day_total'
322
+ end
323
+ @previous_metrics[metric_name] ||= 0
324
+ @previous_metrics[metric_name] += 1
325
+ @metric.set(name: metric_name, value: @previous_metrics[metric_name], type: 'counter')
274
326
 
275
327
  true
276
328
  rescue => e
277
329
  if file.local_path and File.exist?(file.local_path)
278
- @logger.error("Reducer Error: #{filename}: #{File.size(file.local_path)} bytes: \n#{e.formatted}")
330
+ @logger.error("Reducer Error: #{file.local_path}: #{File.size(file.local_path)} bytes: \n#{e.formatted}")
279
331
  else
280
332
  @logger.error("Reducer Error: #{filename}: \n#{e.formatted}")
281
333
  end
334
+
282
335
  @error_count += 1
283
- @metric.set(name: 'reducer_error_total', value: @error_count, type: 'counter')
336
+ if type == 'minute'
337
+ metric_name = 'reducer_minute_error_total'
338
+ elsif type == 'hour'
339
+ metric_name = 'reducer_hour_error_total'
340
+ else
341
+ metric_name = 'reducer_day_error_total'
342
+ end
343
+ @previous_metrics[metric_name] ||= 0
344
+ @previous_metrics[metric_name] += 1
345
+ @metric.set(name: metric_name, value: @previous_metrics[metric_name], type: 'counter')
346
+
347
+ file.delete
284
348
  false
285
349
  end
286
350
 
@@ -26,13 +26,10 @@ require 'openc3/utilities/store'
26
26
  module OpenC3
27
27
  class AuthModel
28
28
  PRIMARY_KEY = 'OPENC3__TOKEN'
29
- SERVICE_KEY = 'OPENC3__SERVICE__TOKEN'
30
29
 
31
30
  TOKEN_CACHE_TIMEOUT = 5
32
31
  @@token_cache = nil
33
32
  @@token_cache_time = nil
34
- @@service_token_cache = nil
35
- @@service_token_cache_time = nil
36
33
 
37
34
  def self.is_set?(key = PRIMARY_KEY)
38
35
  Store.exists(key) == 1
@@ -43,20 +40,15 @@ module OpenC3
43
40
 
44
41
  token_hash = hash(token)
45
42
  return true if @@token_cache and (Time.now - @@token_cache_time) < TOKEN_CACHE_TIMEOUT and @@token_cache == token_hash
46
- return true if @@service_token_cache and (Time.now - @@service_token_cache_time) < TOKEN_CACHE_TIMEOUT and @@service_token_cache == token_hash and permission != 'admin'
47
43
 
48
44
  @@token_cache = Store.get(PRIMARY_KEY)
49
45
  @@token_cache_time = Time.now
50
46
  return true if @@token_cache == token_hash
51
47
 
52
- @@service_token_cache = Store.get(SERVICE_KEY)
53
- @@service_token_cache_time = @@token_cache_time
54
- if ENV['OPENC3_SERVICE_PASSWORD'] and hash(ENV['OPENC3_SERVICE_PASSWORD']) != @@service_token_cache
55
- set_hash = hash(ENV['OPENC3_SERVICE_PASSWORD'])
56
- OpenC3::Store.set(SERVICE_KEY, set_hash)
57
- @@service_token_cache = set_hash
58
- end
59
- return true if @@service_token_cache == token_hash and permission != 'admin'
48
+ # Handle a service password - Generally only used by ScriptRunner
49
+ service_password = ENV['OPENC3_SERVICE_PASSWORD']
50
+ return true if service_password and service_password == token and permission != 'admin'
51
+
60
52
  return false
61
53
  end
62
54
 
@@ -926,6 +926,7 @@ module OpenC3
926
926
  work_dir: '/openc3/lib/openc3/microservices',
927
927
  options: [
928
928
  ["MAX_CPU_UTILIZATION", @reducer_max_cpu_utilization],
929
+ ["BUFFER_DEPTH", @tlm_buffer_depth]
929
930
  ],
930
931
  topics: topics,
931
932
  plugin: @plugin,
@@ -222,7 +222,7 @@ module OpenC3
222
222
  # generate the auth object
223
223
  def generate_auth
224
224
  if ENV['OPENC3_API_TOKEN'].nil? and ENV['OPENC3_API_USER'].nil?
225
- if ENV['OPENC3_API_PASSWORD'] || ENV['OPENC3_SERVICE_PASSWORD']
225
+ if ENV['OPENC3_API_PASSWORD']
226
226
  return OpenC3Authentication.new()
227
227
  else
228
228
  return nil
@@ -260,7 +260,7 @@ module OpenC3
260
260
  disconnect = kw_params.delete(:disconnect)
261
261
  # The only commands allowed through in disconnect mode are read-only
262
262
  # Thus we allow the get, list, tlm and limits_enabled and subscribe methods
263
- if method_name =~ /get_\w*|list_\w*|^tlm|limits_enabled|subscribe/
263
+ if method_name =~ /\w*_get$|^get_\w*|\w*_list$|^list_\w*|^tlm|^limits_enabled$|^subscribe$/
264
264
  result = @json_drb.method_missing(method_name, *method_params, **kw_params)
265
265
  end
266
266
  # If they overrode the return value using the disconnect keyword then return that
@@ -292,7 +292,7 @@ module OpenC3
292
292
  # generate the auth object
293
293
  def generate_auth
294
294
  if ENV['OPENC3_API_TOKEN'].nil? and ENV['OPENC3_API_USER'].nil?
295
- if ENV['OPENC3_API_PASSWORD'] || ENV['OPENC3_SERVICE_PASSWORD']
295
+ if ENV['OPENC3_API_PASSWORD']
296
296
  return OpenC3Authentication.new()
297
297
  else
298
298
  return nil
@@ -161,7 +161,7 @@ module OpenC3
161
161
  # Generate the appropriate token for OpenC3
162
162
  def generate_auth
163
163
  if ENV['OPENC3_API_TOKEN'].nil? and ENV['OPENC3_API_USER'].nil?
164
- if ENV['OPENC3_API_PASSWORD'] || ENV['OPENC3_SERVICE_PASSWORD']
164
+ if ENV['OPENC3_API_PASSWORD']
165
165
  return OpenC3Authentication.new()
166
166
  else
167
167
  raise "Environment Variables Not Set for Authentication"
@@ -31,9 +31,9 @@ module OpenC3
31
31
  # OpenC3 base / open source authentication code
32
32
  class OpenC3Authentication
33
33
  def initialize()
34
- @token = ENV['OPENC3_API_PASSWORD'] || ENV['OPENC3_SERVICE_PASSWORD']
34
+ @token = ENV['OPENC3_API_PASSWORD']
35
35
  if @token.nil?
36
- raise OpenC3AuthenticationError, "Authentication requires environment variables OPENC3_API_PASSWORD or OPENC3_SERVICE_PASSWORD"
36
+ raise OpenC3AuthenticationError, "Authentication requires environment variable OPENC3_API_PASSWORD"
37
37
  end
38
38
  end
39
39
 
@@ -68,12 +68,30 @@ class BucketFile
68
68
  @topic_prefix = "#{scope}__#{type}__{#{target_name}}"
69
69
  end
70
70
 
71
+ # Returns true if the file was retrieved and added to the disk
72
+ # Returns false if the file already exists
73
+ # Raises an error on retrieval errors
71
74
  def retrieve(client = @bucket, uncompress = true)
72
75
  @mutex.synchronize do
73
76
  local_path = "#{BucketFileCache.instance.cache_dir}/#{File.basename(@bucket_path)}"
74
77
  unless File.exist?(local_path)
75
78
  OpenC3::Logger.debug "Retrieving #{@bucket_path} from logs bucket"
76
- client.get_object(bucket: ENV['OPENC3_LOGS_BUCKET'], key: @bucket_path, path: local_path)
79
+
80
+ retry_count = 0
81
+ begin
82
+ client_result = client.get_object(bucket: ENV['OPENC3_LOGS_BUCKET'], key: @bucket_path, path: local_path)
83
+ unless File.exist?(local_path)
84
+ raise "Local file does not exist after get_object: #{client_result.inspect}"
85
+ end
86
+ rescue => err
87
+ # Try to retrieve the file three times
88
+ retry_count += 1
89
+ raise err if retry_count >= 3
90
+ Logger.warn("Error retrieving log file from bucket - retry #{retry_count}: #{@bucket_path}\n#{err.formatted}")
91
+ sleep(1)
92
+ retry
93
+ end
94
+
77
95
  if File.exist?(local_path)
78
96
  basename = File.basename(local_path)
79
97
  if uncompress and File.extname(basename) == ".gz"
@@ -1,14 +1,14 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- OPENC3_VERSION = '5.11.0'
3
+ OPENC3_VERSION = '5.11.1'
4
4
  module OpenC3
5
5
  module Version
6
6
  MAJOR = '5'
7
7
  MINOR = '11'
8
- PATCH = '0'
8
+ PATCH = '1'
9
9
  OTHER = ''
10
- BUILD = 'f994eee0c2fadfc67ffbf0865ba798ed11ec1f5c'
10
+ BUILD = 'b87f91f54de92aa77746d8be150f85d2f3ceeec8'
11
11
  end
12
- VERSION = '5.11.0'
13
- GEM_VERSION = '5.11.0'
12
+ VERSION = '5.11.1'
13
+ GEM_VERSION = '5.11.1'
14
14
  end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "<%= tool_name %>",
3
- "version": "5.11.0",
3
+ "version": "5.11.1",
4
4
  "scripts": {
5
5
  "ng": "ng",
6
6
  "start": "ng serve",
@@ -12,7 +12,7 @@
12
12
  },
13
13
  "private": true,
14
14
  "dependencies": {
15
- "@openc3/tool-common": "5.11.0",
15
+ "@openc3/tool-common": "5.11.1",
16
16
  "@angular/animations": "^16.2.4",
17
17
  "@angular/cdk": "^16.2.3",
18
18
  "@angular/common": "^16.2.4",
@@ -5,4 +5,4 @@ export const singleSpaPropsSubject = new ReplaySubject<SingleSpaProps>(1);
5
5
 
6
6
  // Add any custom single-spa props you have to this type def
7
7
  // https://single-spa.js.org/docs/building-applications.html#custom-props
8
- export type SingleSpaProps = AppProps & {};
8
+ export type SingleSpaProps = AppProps; // & {};
@@ -11,7 +11,7 @@
11
11
  "smui-theme": "smui-theme compile build/smui.css -i src/theme"
12
12
  },
13
13
  "dependencies": {
14
- "@openc3/tool-common": "5.11.0",
14
+ "@openc3/tool-common": "5.11.1",
15
15
  "@smui/button": "^7.0.0-beta.15",
16
16
  "@smui/card": "^7.0.0-beta.15",
17
17
  "@smui/list": "^7.0.0-beta.15",
@@ -58,7 +58,7 @@ export class ConfigParserService {
58
58
  }
59
59
  }
60
60
  // If they pass null for max_params we don't check for a maximum number
61
- if (max_num_params && !this.parameters[max_num_params] === undefined) {
61
+ if (max_num_params && this.parameters[max_num_params] !== undefined) {
62
62
  throw new ConfigParserError(
63
63
  this,
64
64
  `Too many parameters for ${this.keyword}.`,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "<%= tool_name %>",
3
- "version": "5.11.0",
3
+ "version": "5.11.1",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -11,7 +11,7 @@
11
11
  "test:components": "vue-cli-service test:components"
12
12
  },
13
13
  "dependencies": {
14
- "@openc3/tool-common": "5.11.0",
14
+ "@openc3/tool-common": "5.11.1",
15
15
  "axios": "0.27.2",
16
16
  "date-fns": "2.30.0",
17
17
  "portal-vue": "2.1.7",
@@ -1,4 +1,4 @@
1
- const path = require("path");
1
+ const path = require('path')
2
2
 
3
3
  module.exports = {
4
4
  publicPath: '/tools/<%= tool_name %>',
@@ -20,11 +20,19 @@ module.exports = {
20
20
  },
21
21
  configureWebpack: {
22
22
  output: {
23
- libraryTarget: 'system'
23
+ libraryTarget: 'system',
24
24
  },
25
25
  },
26
26
  chainWebpack: (config) => {
27
27
  config.module.rule('js').use('babel-loader')
28
+ config.module
29
+ .rule('vue')
30
+ .use('vue-loader')
31
+ .tap((options) => {
32
+ return {
33
+ prettify: false,
34
+ }
35
+ })
28
36
  config.externals(['vue', 'vuetify', 'vuex', 'vue-router'])
29
37
  },
30
38
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "widget",
3
- "version": "5.11.0",
3
+ "version": "5.11.1",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "build": "vue-cli-service build --target lib --dest tools/widgets/<%= widget_name %> --formats umd-min <%= widget_path %> --name <%= widget_name %>"
7
7
  },
8
8
  "dependencies": {
9
- "@openc3/tool-common": "5.11.0",
9
+ "@openc3/tool-common": "5.11.1",
10
10
  "vue": "2.7.14",
11
11
  "vuetify": "2.7.1"
12
12
  },
@@ -15,11 +15,14 @@ module.exports = {
15
15
  rootMode: 'upward',
16
16
  }
17
17
  })
18
- config.externals([
19
- 'vue',
20
- 'vuetify',
21
- 'vuex',
22
- 'vue-router',
23
- ])
18
+ config.module
19
+ .rule('vue')
20
+ .use('vue-loader')
21
+ .tap((options) => {
22
+ return {
23
+ prettify: false,
24
+ }
25
+ })
26
+ config.externals(['vue', 'vuetify', 'vuex', 'vue-router'])
24
27
  },
25
28
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openc3
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.11.0
4
+ version: 5.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Melton
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-09-18 00:00:00.000000000 Z
12
+ date: 2023-09-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler