openc3 5.14.2 → 5.15.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.
Potentially problematic release.
This version of openc3 might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/bin/openc3cli +1 -1
- data/data/config/_id_items.yaml +2 -3
- data/data/config/telemetry_modifiers.yaml +0 -1
- data/lib/openc3/accessors/accessor.rb +3 -3
- data/lib/openc3/accessors/http_accessor.rb +1 -1
- data/lib/openc3/api/cmd_api.rb +17 -6
- data/lib/openc3/api/tlm_api.rb +16 -5
- data/lib/openc3/logs/buffered_packet_log_writer.rb +5 -0
- data/lib/openc3/microservices/interface_microservice.rb +29 -18
- data/lib/openc3/models/cvt_model.rb +9 -4
- data/lib/openc3/models/gem_model.rb +7 -5
- data/lib/openc3/models/metric_model.rb +8 -0
- data/lib/openc3/models/model.rb +21 -6
- data/lib/openc3/models/plugin_model.rb +8 -2
- data/lib/openc3/models/python_package_model.rb +3 -0
- data/lib/openc3/models/scope_model.rb +2 -2
- data/lib/openc3/models/target_model.rb +21 -28
- data/lib/openc3/models/tool_model.rb +2 -2
- data/lib/openc3/packets/json_packet.rb +5 -3
- data/lib/openc3/script/suite_results.rb +9 -9
- data/lib/openc3/topics/command_decom_topic.rb +2 -1
- data/lib/openc3/topics/command_topic.rb +2 -1
- data/lib/openc3/topics/telemetry_topic.rb +7 -2
- data/lib/openc3/utilities/aws_bucket.rb +21 -15
- data/lib/openc3/utilities/bucket.rb +1 -1
- data/lib/openc3/utilities/logger.rb +3 -3
- data/lib/openc3/utilities/process_manager.rb +15 -9
- data/lib/openc3/utilities/store_autoload.rb +29 -2
- data/lib/openc3/utilities/store_queued.rb +23 -24
- data/lib/openc3/version.rb +6 -6
- data/templates/tool_angular/package.json +2 -2
- data/templates/tool_svelte/package.json +1 -1
- data/templates/tool_vue/package.json +2 -2
- data/templates/widget/package.json +2 -2
- metadata +16 -7
- data/templates/tool_angular/yarn.lock +0 -8155
- data/templates/tool_react/yarn.lock +0 -7201
- data/templates/tool_svelte/yarn.lock +0 -5519
- data/templates/tool_vue/yarn.lock +0 -9455
- data/templates/widget/yarn.lock +0 -9338
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0228b27d56d6fce2f445eb5842ec223be1351aaf09767da803e735ffb80875ec'
|
4
|
+
data.tar.gz: 7f78a835eb8d3d1c678afa7f93490821cac67dcbf3d854ec1973c452b139a647
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 545775f6dd330af7e6e4f566a07ea44f5f5b2e533d2dadb9704e5e1dba142377f4b63dacc89157b0c4b996e20c78851fba4d397d830619fa51ff0a313850935f
|
7
|
+
data.tar.gz: 9eb87fbc7b5410327f0142f1e2bf08ae8070169057a34fbef6eb0f7c9bd846c07aae7e49b70d9b8f4ff5647fe1258155eeb879d0ace4cbe782b1e7b5ca2c8019
|
data/bin/openc3cli
CHANGED
@@ -471,7 +471,7 @@ def load_plugin(plugin_file_path, scope:, plugin_hash_file: nil, force: false)
|
|
471
471
|
OpenC3::LocalMode.update_local_plugin(plugin_file_path, plugin_hash, scope: scope)
|
472
472
|
end
|
473
473
|
rescue => e
|
474
|
-
abort("Error installing plugin: #{scope}: #{plugin_file_path}\n#{e.
|
474
|
+
abort("Error installing plugin: #{scope}: #{plugin_file_path}\n#{e.formatted}")
|
475
475
|
end
|
476
476
|
else
|
477
477
|
# Outside Cluster
|
data/data/config/_id_items.yaml
CHANGED
@@ -4,13 +4,12 @@
|
|
4
4
|
description:
|
5
5
|
Bit size of this telemetry item. Zero or Negative values may be used
|
6
6
|
to indicate that a string fills the packet up to the offset from the end of
|
7
|
-
the packet specified by this value.
|
8
|
-
this is a derived parameter and the Data Type must be set to 'DERIVED'.
|
7
|
+
the packet specified by this value.
|
9
8
|
values: \d+
|
10
9
|
- name: Data Type
|
11
10
|
required: true
|
12
11
|
description: Data Type of this telemetry item
|
13
|
-
values: <%= %w(INT UINT FLOAT STRING BLOCK
|
12
|
+
values: <%= %w(INT UINT FLOAT STRING BLOCK) %>
|
14
13
|
- name: ID Value
|
15
14
|
required: true
|
16
15
|
description: The value of this telemetry item that uniquely identifies this telemetry packet
|
@@ -45,7 +45,6 @@ ID_ITEM:
|
|
45
45
|
required: true
|
46
46
|
description: Bit offset into the telemetry packet of the Most Significant Bit of this item.
|
47
47
|
May be negative to indicate on offset from the end of the packet.
|
48
|
-
Always use a bit offset of 0 for derived item.
|
49
48
|
values: '[-]?\d+'
|
50
49
|
<%= MetaConfigParser.load('_id_items.yaml').to_meta_config_yaml(4) %>
|
51
50
|
APPEND_ID_ITEM:
|
@@ -74,18 +74,18 @@ module OpenC3
|
|
74
74
|
return false
|
75
75
|
end
|
76
76
|
|
77
|
-
# If this is true it will
|
77
|
+
# If this is true it will enforce that COSMOS DERIVED items must have a
|
78
78
|
# write_conversion to be written
|
79
79
|
def enforce_derived_write_conversion(_item)
|
80
80
|
return true
|
81
81
|
end
|
82
82
|
|
83
83
|
def self.read_item(_item, _buffer)
|
84
|
-
raise "Must be defined by subclass"
|
84
|
+
raise "Must be defined by subclass if needed"
|
85
85
|
end
|
86
86
|
|
87
87
|
def self.write_item(_item, _value, _buffer)
|
88
|
-
raise "Must be defined by subclass"
|
88
|
+
raise "Must be defined by subclass if needed"
|
89
89
|
end
|
90
90
|
|
91
91
|
def self.read_items(items, buffer)
|
@@ -176,7 +176,7 @@ module OpenC3
|
|
176
176
|
when 'HTTP_STATUS', 'HTTP_PATH', 'HTTP_METHOD', 'HTTP_PACKET', 'HTTP_ERROR_PACKET', /^HTTP_QUERY_/, /^HTTP_HEADER_/
|
177
177
|
return false
|
178
178
|
else
|
179
|
-
return @body_accessor.enforce_derived_write_conversion
|
179
|
+
return @body_accessor.enforce_derived_write_conversion(item)
|
180
180
|
end
|
181
181
|
end
|
182
182
|
end
|
data/lib/openc3/api/cmd_api.rb
CHANGED
@@ -178,10 +178,21 @@ module OpenC3
|
|
178
178
|
# @since 5.0.6
|
179
179
|
# @param target_name [String] Name of the target
|
180
180
|
# @return [Array<String>] Array of all command packet names
|
181
|
-
def get_all_cmd_names(target_name, scope: $openc3_scope, token: $openc3_token)
|
182
|
-
|
183
|
-
|
184
|
-
|
181
|
+
def get_all_cmd_names(target_name, hidden: false, scope: $openc3_scope, token: $openc3_token)
|
182
|
+
begin
|
183
|
+
packets = get_all_cmds(target_name, scope: scope, token: token)
|
184
|
+
rescue RuntimeError
|
185
|
+
packets = []
|
186
|
+
end
|
187
|
+
names = []
|
188
|
+
packets.each do |packet|
|
189
|
+
if hidden
|
190
|
+
names << packet['packet_name']
|
191
|
+
else
|
192
|
+
names << packet['packet_name'] unless packet['hidden']
|
193
|
+
end
|
194
|
+
end
|
195
|
+
return names
|
185
196
|
end
|
186
197
|
# get_all_command_names is DEPRECATED
|
187
198
|
alias get_all_command_names get_all_cmd_names
|
@@ -474,7 +485,7 @@ module OpenC3
|
|
474
485
|
|
475
486
|
def _build_cmd_output_string(method_name, target_name, cmd_name, cmd_params, packet)
|
476
487
|
output_string = "#{method_name}(\""
|
477
|
-
output_string << target_name + ' ' + cmd_name
|
488
|
+
output_string << (target_name + ' ' + cmd_name)
|
478
489
|
if cmd_params.nil? or cmd_params.empty?
|
479
490
|
output_string << '")'
|
480
491
|
else
|
@@ -511,7 +522,7 @@ module OpenC3
|
|
511
522
|
params << "#{key} #{value}"
|
512
523
|
end
|
513
524
|
params = params.join(", ")
|
514
|
-
output_string << ' with ' + params + '")'
|
525
|
+
output_string << (' with ' + params + '")')
|
515
526
|
end
|
516
527
|
return output_string
|
517
528
|
end
|
data/lib/openc3/api/tlm_api.rb
CHANGED
@@ -139,7 +139,7 @@ module OpenC3
|
|
139
139
|
|
140
140
|
# See if this target has a tlm interface
|
141
141
|
interface_name = nil
|
142
|
-
InterfaceModel.all(scope: scope).each do |
|
142
|
+
InterfaceModel.all(scope: scope).each do |_name, interface|
|
143
143
|
if interface['tlm_target_names'].include? target_name
|
144
144
|
interface_name = interface['name']
|
145
145
|
break
|
@@ -287,10 +287,21 @@ module OpenC3
|
|
287
287
|
# @since 5.0.6
|
288
288
|
# @param target_name [String] Name of the target
|
289
289
|
# @return [Array<String>] Array of all telemetry packet names
|
290
|
-
def get_all_tlm_names(target_name, scope: $openc3_scope, token: $openc3_token)
|
291
|
-
|
292
|
-
|
293
|
-
|
290
|
+
def get_all_tlm_names(target_name, hidden: false, scope: $openc3_scope, token: $openc3_token)
|
291
|
+
begin
|
292
|
+
packets = get_all_tlm(target_name, scope: scope, token: token)
|
293
|
+
rescue RuntimeError
|
294
|
+
packets = []
|
295
|
+
end
|
296
|
+
names = []
|
297
|
+
packets.each do |packet|
|
298
|
+
if hidden
|
299
|
+
names << packet['packet_name']
|
300
|
+
else
|
301
|
+
names << packet['packet_name'] unless packet['hidden']
|
302
|
+
end
|
303
|
+
end
|
304
|
+
return names
|
294
305
|
end
|
295
306
|
alias get_all_telemetry_names get_all_tlm_names
|
296
307
|
|
@@ -80,6 +80,11 @@ module OpenC3
|
|
80
80
|
def buffered_write(entry_type, cmd_or_tlm, target_name, packet_name, time_nsec_since_epoch, stored, data, id = nil, redis_topic = nil, redis_offset = '0-0', received_time_nsec_since_epoch: nil, extra: nil)
|
81
81
|
case entry_type
|
82
82
|
when :RAW_PACKET, :JSON_PACKET
|
83
|
+
# If we have data in the buffer, a file should always be open so that cycle time logic will run
|
84
|
+
unless @file
|
85
|
+
@mutex.synchronize { start_new_file() }
|
86
|
+
end
|
87
|
+
|
83
88
|
@buffer << [entry_type, cmd_or_tlm, target_name, packet_name, time_nsec_since_epoch, stored, data, id, redis_topic, redis_offset, received_time_nsec_since_epoch, extra]
|
84
89
|
@buffer.sort! {|entry1, entry2| entry1[4] <=> entry2[4] }
|
85
90
|
if @buffer.length >= @buffer_depth
|
@@ -126,7 +126,7 @@ module OpenC3
|
|
126
126
|
begin
|
127
127
|
@logger.info "#{@interface.name}: interface_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')}"
|
128
128
|
@interface.interface_cmd(params['cmd_name'], *params['cmd_params'])
|
129
|
-
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
129
|
+
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
|
130
130
|
rescue => e
|
131
131
|
@logger.error "#{@interface.name}: interface_cmd: #{e.formatted}"
|
132
132
|
next e.message
|
@@ -138,7 +138,7 @@ module OpenC3
|
|
138
138
|
begin
|
139
139
|
@logger.info "#{@interface.name}: protocol_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')} read_write: #{params['read_write']} index: #{params['index']}"
|
140
140
|
@interface.protocol_cmd(params['cmd_name'], *params['cmd_params'], read_write: params['read_write'], index: params['index'])
|
141
|
-
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
141
|
+
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
|
142
142
|
rescue => e
|
143
143
|
@logger.error "#{@interface.name}: protocol_cmd: #{e.formatted}"
|
144
144
|
next e.message
|
@@ -206,7 +206,7 @@ module OpenC3
|
|
206
206
|
@interface.write(command)
|
207
207
|
CommandTopic.write_packet(command, scope: @scope)
|
208
208
|
CommandDecomTopic.write_packet(command, scope: @scope)
|
209
|
-
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
209
|
+
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
|
210
210
|
next 'SUCCESS'
|
211
211
|
else
|
212
212
|
next "Interface not connected: #{@interface.name}"
|
@@ -298,7 +298,7 @@ module OpenC3
|
|
298
298
|
begin
|
299
299
|
@logger.info "#{@router.name}: router_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')}"
|
300
300
|
@router.interface_cmd(params['cmd_name'], *params['cmd_params'])
|
301
|
-
RouterStatusModel.set(@router.as_json(:allow_nan => true), scope: @scope)
|
301
|
+
RouterStatusModel.set(@router.as_json(:allow_nan => true), queued: true, scope: @scope)
|
302
302
|
rescue => e
|
303
303
|
@logger.error "#{@router.name}: router_cmd: #{e.formatted}"
|
304
304
|
next e.message
|
@@ -310,7 +310,7 @@ module OpenC3
|
|
310
310
|
begin
|
311
311
|
@logger.info "#{@router.name}: protocol_cmd: #{params['cmd_name']} #{params['cmd_params'].join(' ')} read_write: #{params['read_write']} index: #{params['index']}"
|
312
312
|
@router.protocol_cmd(params['cmd_name'], *params['cmd_params'], read_write: params['read_write'], index: params['index'])
|
313
|
-
RouterStatusModel.set(@router.as_json(:allow_nan => true), scope: @scope)
|
313
|
+
RouterStatusModel.set(@router.as_json(:allow_nan => true), queued: true, scope: @scope)
|
314
314
|
rescue => e
|
315
315
|
@logger.error "#{@router.name}: protoco_cmd: #{e.formatted}"
|
316
316
|
next e.message
|
@@ -335,7 +335,7 @@ module OpenC3
|
|
335
335
|
|
336
336
|
begin
|
337
337
|
@router.write(packet)
|
338
|
-
RouterStatusModel.set(@router.as_json(:allow_nan => true), scope: @scope)
|
338
|
+
RouterStatusModel.set(@router.as_json(:allow_nan => true), queued: true, scope: @scope)
|
339
339
|
next 'SUCCESS'
|
340
340
|
rescue => e
|
341
341
|
@logger.error "#{@router.name}: #{e.formatted}"
|
@@ -352,6 +352,7 @@ module OpenC3
|
|
352
352
|
def initialize(name)
|
353
353
|
@mutex = Mutex.new
|
354
354
|
super(name)
|
355
|
+
|
355
356
|
@interface_or_router = self.class.name.to_s.split("Microservice")[0].upcase.split("::")[-1]
|
356
357
|
if @interface_or_router == 'INTERFACE'
|
357
358
|
@metric.set(name: 'interface_tlm_total', value: @count, type: 'counter')
|
@@ -359,7 +360,6 @@ module OpenC3
|
|
359
360
|
@metric.set(name: 'router_cmd_total', value: @count, type: 'counter')
|
360
361
|
end
|
361
362
|
|
362
|
-
@scope = name.split("__")[0]
|
363
363
|
interface_name = name.split("__")[2]
|
364
364
|
if @interface_or_router == 'INTERFACE'
|
365
365
|
@interface = InterfaceModel.get_model(name: interface_name, scope: @scope).build
|
@@ -400,6 +400,17 @@ module OpenC3
|
|
400
400
|
RouterStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
401
401
|
end
|
402
402
|
|
403
|
+
@queued = false
|
404
|
+
@interface.options.each do |option_name, option_values|
|
405
|
+
case option_name.upcase
|
406
|
+
when 'OPTIMIZE_THROUGHPUT'
|
407
|
+
@queued = true
|
408
|
+
update_interval = option_values[0].to_f
|
409
|
+
EphemeralStoreQueued.instance.set_update_interval(update_interval)
|
410
|
+
StoreQueued.instance.set_update_interval(update_interval)
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
403
414
|
@interface_thread_sleeper = Sleeper.new
|
404
415
|
@cancel_thread = false
|
405
416
|
@connection_failed_messages = []
|
@@ -432,9 +443,9 @@ module OpenC3
|
|
432
443
|
|
433
444
|
@interface.state = 'ATTEMPTING'
|
434
445
|
if @interface_or_router == 'INTERFACE'
|
435
|
-
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
446
|
+
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
|
436
447
|
else
|
437
|
-
RouterStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
448
|
+
RouterStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
|
438
449
|
end
|
439
450
|
@interface # Return the interface/router since we may have recreated it
|
440
451
|
# Need to rescue Exception so we cover LoadError
|
@@ -507,15 +518,15 @@ module OpenC3
|
|
507
518
|
disconnect(false)
|
508
519
|
end
|
509
520
|
if @interface_or_router == 'INTERFACE'
|
510
|
-
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
521
|
+
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
|
511
522
|
else
|
512
|
-
RouterStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
523
|
+
RouterStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
|
513
524
|
end
|
514
525
|
@logger.info "#{@interface.name}: Stopped packet reading"
|
515
526
|
end
|
516
527
|
|
517
528
|
def handle_packet(packet)
|
518
|
-
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
529
|
+
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
|
519
530
|
packet.received_time = Time.now.sys unless packet.received_time
|
520
531
|
|
521
532
|
if packet.stored
|
@@ -557,7 +568,7 @@ module OpenC3
|
|
557
568
|
unknown_packet.extra = packet.extra
|
558
569
|
packet = unknown_packet
|
559
570
|
json_hash = CvtModel.build_json_from_packet(packet)
|
560
|
-
CvtModel.set(json_hash, target_name: packet.target_name, packet_name: packet.packet_name, scope: @scope)
|
571
|
+
CvtModel.set(json_hash, target_name: packet.target_name, packet_name: packet.packet_name, queued: @queued, scope: @scope)
|
561
572
|
num_bytes_to_print = [UNKNOWN_BYTES_TO_PRINT, packet.length].min
|
562
573
|
data = packet.buffer(false)[0..(num_bytes_to_print - 1)]
|
563
574
|
prefix = data.each_byte.map { | byte | sprintf("%02X", byte) }.join()
|
@@ -566,7 +577,7 @@ module OpenC3
|
|
566
577
|
|
567
578
|
# Write to stream
|
568
579
|
packet.received_count += 1
|
569
|
-
TelemetryTopic.write_packet(packet, scope: @scope)
|
580
|
+
TelemetryTopic.write_packet(packet, queued: @queued, scope: @scope)
|
570
581
|
end
|
571
582
|
|
572
583
|
def handle_connection_failed(connect_error)
|
@@ -629,9 +640,9 @@ module OpenC3
|
|
629
640
|
end
|
630
641
|
@interface.state = 'CONNECTED'
|
631
642
|
if @interface_or_router == 'INTERFACE'
|
632
|
-
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
643
|
+
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
|
633
644
|
else
|
634
|
-
RouterStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
645
|
+
RouterStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
|
635
646
|
end
|
636
647
|
@logger.info "#{@interface.name}: Connection Success"
|
637
648
|
end
|
@@ -661,9 +672,9 @@ module OpenC3
|
|
661
672
|
else
|
662
673
|
@interface.state = 'DISCONNECTED'
|
663
674
|
if @interface_or_router == 'INTERFACE'
|
664
|
-
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
675
|
+
InterfaceStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
|
665
676
|
else
|
666
|
-
RouterStatusModel.set(@interface.as_json(:allow_nan => true), scope: @scope)
|
677
|
+
RouterStatusModel.set(@interface.as_json(:allow_nan => true), queued: true, scope: @scope)
|
667
678
|
end
|
668
679
|
end
|
669
680
|
end
|
@@ -21,6 +21,7 @@
|
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/utilities/store'
|
24
|
+
require 'openc3/utilities/store_queued'
|
24
25
|
require 'openc3/models/target_model'
|
25
26
|
|
26
27
|
module OpenC3
|
@@ -42,12 +43,16 @@ module OpenC3
|
|
42
43
|
end
|
43
44
|
|
44
45
|
# Set the current value table for a target, packet
|
45
|
-
def self.set(hash, target_name:, packet_name:, scope: $openc3_scope)
|
46
|
+
def self.set(hash, target_name:, packet_name:, queued: false, scope: $openc3_scope)
|
46
47
|
packet_json = JSON.generate(hash.as_json(:allow_nan => true))
|
47
48
|
key = "#{scope}__tlm__#{target_name}"
|
48
49
|
tgt_pkt_key = key + "__#{packet_name}"
|
49
50
|
@@packet_cache[tgt_pkt_key] = [Time.now, hash]
|
50
|
-
|
51
|
+
if queued
|
52
|
+
StoreQueued.hset(key, packet_name, packet_json)
|
53
|
+
else
|
54
|
+
Store.hset(key, packet_name, packet_json)
|
55
|
+
end
|
51
56
|
end
|
52
57
|
|
53
58
|
# Get the hash for packet in the CVT
|
@@ -68,7 +73,7 @@ module OpenC3
|
|
68
73
|
end
|
69
74
|
|
70
75
|
# Set an item in the current value table
|
71
|
-
def self.set_item(target_name, packet_name, item_name, value, type:, scope: $openc3_scope)
|
76
|
+
def self.set_item(target_name, packet_name, item_name, value, type:, queued: false, scope: $openc3_scope)
|
72
77
|
hash = get(target_name: target_name, packet_name: packet_name, cache_timeout: nil, scope: scope)
|
73
78
|
case type
|
74
79
|
when :WITH_UNITS
|
@@ -87,7 +92,7 @@ module OpenC3
|
|
87
92
|
else
|
88
93
|
raise "Unknown type '#{type}' for #{target_name} #{packet_name} #{item_name}"
|
89
94
|
end
|
90
|
-
set(hash, target_name: target_name, packet_name: packet_name, scope: scope)
|
95
|
+
set(hash, target_name: target_name, packet_name: packet_name, queued: queued, scope: scope)
|
91
96
|
end
|
92
97
|
|
93
98
|
# Get an item from the current value table
|
@@ -102,13 +102,15 @@ module OpenC3
|
|
102
102
|
raise err
|
103
103
|
end
|
104
104
|
|
105
|
-
def self.destroy(name)
|
105
|
+
def self.destroy(name, log_and_raise_needed_errors: true)
|
106
106
|
gem_name, version = self.extract_name_and_version(name)
|
107
107
|
plugin_gem_names = PluginModel.gem_names
|
108
108
|
if plugin_gem_names.include?(name)
|
109
|
-
|
110
|
-
|
111
|
-
|
109
|
+
if log_and_raise_needed_errors
|
110
|
+
message = "Gem file #{name} can't be uninstalled because needed by installed plugin"
|
111
|
+
Logger.error message
|
112
|
+
raise message
|
113
|
+
end
|
112
114
|
else
|
113
115
|
begin
|
114
116
|
Gem::Uninstaller.new(gem_name, {:version => version, :force => true}).uninstall
|
@@ -131,7 +133,7 @@ module OpenC3
|
|
131
133
|
GemModel.names.each do |gem_full_name|
|
132
134
|
gem_name, gem_version = GemModel.extract_name_and_version(gem_full_name)
|
133
135
|
if gem_name == keep_gem_name and gem_version != keep_gem_version
|
134
|
-
GemModel.destroy(gem_full_name)
|
136
|
+
GemModel.destroy(gem_full_name, log_and_raise_needed_errors: false)
|
135
137
|
end
|
136
138
|
end
|
137
139
|
end
|
@@ -42,6 +42,14 @@ module OpenC3
|
|
42
42
|
super("#{scope}#{PRIMARY_KEY}")
|
43
43
|
end
|
44
44
|
|
45
|
+
# Sets (updates) the redis hash of this model
|
46
|
+
# Queued defaults to true for MetricModel
|
47
|
+
def self.set(json, scope:, queued: true)
|
48
|
+
json[:scope] = scope
|
49
|
+
json.transform_keys!(&:to_sym)
|
50
|
+
self.new(**json).create(force: true, queued: queued)
|
51
|
+
end
|
52
|
+
|
45
53
|
def self.destroy(scope:, name:)
|
46
54
|
EphemeralStore.hdel("#{scope}#{PRIMARY_KEY}", name)
|
47
55
|
end
|
data/lib/openc3/models/model.rb
CHANGED
@@ -21,6 +21,7 @@
|
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/utilities/store'
|
24
|
+
require 'openc3/utilities/store_queued'
|
24
25
|
require 'openc3/config/config_parser'
|
25
26
|
|
26
27
|
module OpenC3
|
@@ -34,6 +35,10 @@ module OpenC3
|
|
34
35
|
Store
|
35
36
|
end
|
36
37
|
|
38
|
+
def self.store_queued
|
39
|
+
StoreQueued
|
40
|
+
end
|
41
|
+
|
37
42
|
# NOTE: The following three methods must be reimplemented by Model subclasses
|
38
43
|
# without primary_key to support other class methods.
|
39
44
|
|
@@ -75,10 +80,10 @@ module OpenC3
|
|
75
80
|
end
|
76
81
|
|
77
82
|
# Sets (updates) the redis hash of this model
|
78
|
-
def self.set(json, scope:)
|
83
|
+
def self.set(json, scope:, queued: false)
|
79
84
|
json[:scope] = scope
|
80
85
|
json.transform_keys!(&:to_sym)
|
81
|
-
self.new(**json).create(force: true)
|
86
|
+
self.new(**json).create(force: true, queued: queued)
|
82
87
|
end
|
83
88
|
|
84
89
|
# @return [Model] Model generated from the passed JSON
|
@@ -134,7 +139,7 @@ module OpenC3
|
|
134
139
|
|
135
140
|
# Update the Redis hash at primary_key and set the field "name"
|
136
141
|
# to the JSON generated via calling as_json
|
137
|
-
def create(update: false, force: false)
|
142
|
+
def create(update: false, force: false, queued: false)
|
138
143
|
unless force
|
139
144
|
existing = self.class.store.hget(@primary_key, @name)
|
140
145
|
if existing
|
@@ -144,12 +149,18 @@ module OpenC3
|
|
144
149
|
end
|
145
150
|
end
|
146
151
|
@updated_at = Time.now.to_nsec_from_epoch
|
147
|
-
|
152
|
+
|
153
|
+
if queued
|
154
|
+
write_store = self.class.store_queued
|
155
|
+
else
|
156
|
+
write_store = self.class.store
|
157
|
+
end
|
158
|
+
write_store.hset(@primary_key, @name, JSON.generate(self.as_json(:allow_nan => true), :allow_nan => true))
|
148
159
|
end
|
149
160
|
|
150
161
|
# Alias for create(update: true)
|
151
|
-
def update
|
152
|
-
create(update: true)
|
162
|
+
def update(force: false, queued: false)
|
163
|
+
create(update: true, force: force, queued: queued)
|
153
164
|
end
|
154
165
|
|
155
166
|
# Deploy the model into the OpenC3 system. Subclasses must implement this
|
@@ -206,5 +217,9 @@ module OpenC3
|
|
206
217
|
def self.store
|
207
218
|
EphemeralStore
|
208
219
|
end
|
220
|
+
|
221
|
+
def self.store_queued
|
222
|
+
EphemeralStoreQueued
|
223
|
+
end
|
209
224
|
end
|
210
225
|
end
|
@@ -183,12 +183,18 @@ module OpenC3
|
|
183
183
|
if File.exist?(File.join(gem_path, 'requirements.txt'))
|
184
184
|
begin
|
185
185
|
pypi_url = get_setting('pypi_url', scope: scope)
|
186
|
+
if pypi_url
|
187
|
+
pypi_url += '/simple'
|
188
|
+
end
|
186
189
|
rescue => e
|
187
190
|
Logger.error("Failed to retrieve pypi_url: #{e.formatted}")
|
188
191
|
ensure
|
189
192
|
if pypi_url.nil?
|
190
193
|
# If Redis isn't running try the ENV, then simply pypi.org/simple
|
191
194
|
pypi_url = ENV['PYPI_URL']
|
195
|
+
if pypi_url
|
196
|
+
pypi_url += '/simple'
|
197
|
+
end
|
192
198
|
pypi_url ||= 'https://pypi.org/simple'
|
193
199
|
end
|
194
200
|
end
|
@@ -288,9 +294,9 @@ module OpenC3
|
|
288
294
|
@needs_dependencies = ConfigParser.handle_true_false(needs_dependencies)
|
289
295
|
end
|
290
296
|
|
291
|
-
def create(update: false, force: false)
|
297
|
+
def create(update: false, force: false, queued: false)
|
292
298
|
@name = @name + "__#{Time.now.utc.strftime("%Y%m%d%H%M%S")}" if not update and not @name.index("__")
|
293
|
-
super(update: update, force: force)
|
299
|
+
super(update: update, force: force, queued: queued)
|
294
300
|
end
|
295
301
|
|
296
302
|
def as_json(*a)
|
@@ -74,6 +74,9 @@ module OpenC3
|
|
74
74
|
rescue
|
75
75
|
# If Redis isn't running try the ENV, then simply pypi.org/simple
|
76
76
|
pypi_url = ENV['PYPI_URL']
|
77
|
+
if pypi_url
|
78
|
+
pypi_url += '/simple'
|
79
|
+
end
|
77
80
|
pypi_url ||= 'https://pypi.org/simple'
|
78
81
|
end
|
79
82
|
Logger.info "Installing python package: #{name_or_path}"
|
@@ -95,11 +95,11 @@ module OpenC3
|
|
95
95
|
@children = []
|
96
96
|
end
|
97
97
|
|
98
|
-
def create(update: false, force: false)
|
98
|
+
def create(update: false, force: false, queued: false)
|
99
99
|
# Ensure there are no "." in the scope name - prevents gems accidently becoming scope names
|
100
100
|
raise "Invalid scope name: #{@name}" if @name !~ /^[a-zA-Z0-9_-]+$/
|
101
101
|
@name = @name.upcase
|
102
|
-
super(update: update, force: force)
|
102
|
+
super(update: update, force: force, queued: queued)
|
103
103
|
end
|
104
104
|
|
105
105
|
def destroy
|