openc3 5.14.2 → 5.15.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -97,7 +97,7 @@ module OpenC3
|
|
97
97
|
# All targets with indication of modified targets
|
98
98
|
def self.all_modified(scope:)
|
99
99
|
targets = self.all(scope: scope)
|
100
|
-
targets.each { |
|
100
|
+
targets.each { |_target_name, target| target['modified'] = false }
|
101
101
|
|
102
102
|
if ENV['OPENC3_LOCAL_MODE']
|
103
103
|
modified_targets = OpenC3::LocalMode.modified_targets(scope: scope)
|
@@ -191,13 +191,6 @@ module OpenC3
|
|
191
191
|
return result
|
192
192
|
end
|
193
193
|
|
194
|
-
# @return [Array] Array of all the packet names
|
195
|
-
def self.packet_names(target_name, type: :TLM, scope:)
|
196
|
-
raise "Unknown type #{type} for #{target_name}" unless VALID_TYPES.include?(type)
|
197
|
-
# If the key doesn't exist or if there are no packets we return empty array
|
198
|
-
Store.hkeys("#{scope}__openc3#{type.to_s.downcase}__#{target_name}").sort
|
199
|
-
end
|
200
|
-
|
201
194
|
# @return [Hash] Packet hash or raises an exception
|
202
195
|
def self.packet(target_name, packet_name, type: :TLM, scope:)
|
203
196
|
raise "Unknown type #{type} for #{target_name} #{packet_name}" unless VALID_TYPES.include?(type)
|
@@ -216,7 +209,7 @@ module OpenC3
|
|
216
209
|
|
217
210
|
result = []
|
218
211
|
packets = Store.hgetall("#{scope}__openc3#{type.to_s.downcase}__#{target_name}")
|
219
|
-
packets.sort.each do |
|
212
|
+
packets.sort.each do |_packet_name, packet_json|
|
220
213
|
result << JSON.parse(packet_json, :allow_nan => true, :create_additions => true)
|
221
214
|
end
|
222
215
|
result
|
@@ -232,9 +225,9 @@ module OpenC3
|
|
232
225
|
|
233
226
|
begin
|
234
227
|
Store.hset("#{scope}__openc3#{type.to_s.downcase}__#{target_name}", packet_name, JSON.generate(packet.as_json(:allow_nan => true)))
|
235
|
-
rescue JSON::GeneratorError =>
|
228
|
+
rescue JSON::GeneratorError => e
|
236
229
|
Logger.error("Invalid text present in #{target_name} #{packet_name} #{type.to_s.downcase} packet")
|
237
|
-
raise
|
230
|
+
raise e
|
238
231
|
end
|
239
232
|
end
|
240
233
|
|
@@ -403,7 +396,7 @@ module OpenC3
|
|
403
396
|
@children = []
|
404
397
|
end
|
405
398
|
|
406
|
-
def as_json(*
|
399
|
+
def as_json(*_a)
|
407
400
|
{
|
408
401
|
'name' => @name,
|
409
402
|
'folder_name' => @folder_name,
|
@@ -586,13 +579,13 @@ module OpenC3
|
|
586
579
|
end
|
587
580
|
end
|
588
581
|
end
|
589
|
-
rescue =>
|
582
|
+
rescue => e
|
590
583
|
# ERB error parsing a screen is just a logger error because life can go on
|
591
584
|
# With cmd/tlm or scripts this is a serious error and we raise
|
592
585
|
if (filename.include?('/screens/'))
|
593
|
-
Logger.error("ERB error parsing #{key} due to #{
|
586
|
+
Logger.error("ERB error parsing #{key} due to #{e.message}")
|
594
587
|
else
|
595
|
-
raise "ERB error parsing #{key} due to #{
|
588
|
+
raise "ERB error parsing #{key} due to #{e.message}"
|
596
589
|
end
|
597
590
|
end
|
598
591
|
local_path = File.join(temp_dir, @name, target_folder_path)
|
@@ -667,8 +660,8 @@ module OpenC3
|
|
667
660
|
@@item_map_cache[@name] = nil
|
668
661
|
|
669
662
|
ConfigTopic.write({ kind: 'deleted', type: 'target', name: @name, plugin: @plugin }, scope: @scope)
|
670
|
-
rescue Exception =>
|
671
|
-
Logger.error("Error undeploying target model #{@name} in scope #{@scope} due to #{
|
663
|
+
rescue Exception => e
|
664
|
+
Logger.error("Error undeploying target model #{@name} in scope #{@scope} due to #{e}")
|
672
665
|
end
|
673
666
|
|
674
667
|
##################################################
|
@@ -702,8 +695,8 @@ module OpenC3
|
|
702
695
|
return ERB.new(data.force_encoding("UTF-8").comment_erb(), trim_mode: "-").result(b)
|
703
696
|
end
|
704
697
|
end
|
705
|
-
rescue =>
|
706
|
-
raise "ERB error parsing: #{path}: #{
|
698
|
+
rescue => e
|
699
|
+
raise "ERB error parsing: #{path}: #{e.formatted}"
|
707
700
|
end
|
708
701
|
end
|
709
702
|
|
@@ -763,9 +756,9 @@ module OpenC3
|
|
763
756
|
Logger.info "Configuring tlm packet: #{target_name} #{packet_name}"
|
764
757
|
begin
|
765
758
|
Store.hset("#{@scope}__openc3tlm__#{target_name}", packet_name, JSON.generate(packet.as_json(:allow_nan => true)))
|
766
|
-
rescue JSON::GeneratorError =>
|
759
|
+
rescue JSON::GeneratorError => e
|
767
760
|
Logger.error("Invalid text present in #{target_name} #{packet_name} tlm packet")
|
768
|
-
raise
|
761
|
+
raise e
|
769
762
|
end
|
770
763
|
json_hash = Hash.new
|
771
764
|
packet.sorted_items.each do |item|
|
@@ -783,9 +776,9 @@ module OpenC3
|
|
783
776
|
Logger.info "Configuring cmd packet: #{target_name} #{packet_name}"
|
784
777
|
begin
|
785
778
|
Store.hset("#{@scope}__openc3cmd__#{target_name}", packet_name, JSON.generate(packet.as_json(:allow_nan => true)))
|
786
|
-
rescue JSON::GeneratorError =>
|
779
|
+
rescue JSON::GeneratorError => e
|
787
780
|
Logger.error("Invalid text present in #{target_name} #{packet_name} cmd packet")
|
788
|
-
raise
|
781
|
+
raise e
|
789
782
|
end
|
790
783
|
end
|
791
784
|
end
|
@@ -795,9 +788,9 @@ module OpenC3
|
|
795
788
|
system.limits.groups.each do |group, items|
|
796
789
|
begin
|
797
790
|
Store.hset("#{@scope}__limits_groups", group, JSON.generate(items))
|
798
|
-
rescue JSON::GeneratorError =>
|
791
|
+
rescue JSON::GeneratorError => e
|
799
792
|
Logger.error("Invalid text present in #{group} limits group")
|
800
|
-
raise
|
793
|
+
raise e
|
801
794
|
end
|
802
795
|
end
|
803
796
|
end
|
@@ -1107,7 +1100,7 @@ module OpenC3
|
|
1107
1100
|
|
1108
1101
|
# Figure out if there are individual packets assigned to this microservice
|
1109
1102
|
target_microservices.sort! {|a, b| a.length <=> b.length}
|
1110
|
-
target_microservices.each_with_index do |packet_names,
|
1103
|
+
target_microservices.each_with_index do |packet_names, _index|
|
1111
1104
|
topics = []
|
1112
1105
|
packet_names.each do |packet_name|
|
1113
1106
|
topics << "#{topic_prefix}__#{packet_name}"
|
@@ -1146,7 +1139,7 @@ module OpenC3
|
|
1146
1139
|
packet_topic_list = []
|
1147
1140
|
decom_topic_list = []
|
1148
1141
|
begin
|
1149
|
-
system.commands.packets(@name).each do |packet_name,
|
1142
|
+
system.commands.packets(@name).each do |packet_name, _packet|
|
1150
1143
|
command_topic_list << "#{@scope}__COMMAND__{#{@name}}__#{packet_name}"
|
1151
1144
|
decom_command_topic_list << "#{@scope}__DECOMCMD__{#{@name}}__#{packet_name}"
|
1152
1145
|
end
|
@@ -1154,7 +1147,7 @@ module OpenC3
|
|
1154
1147
|
# No command packets for this target
|
1155
1148
|
end
|
1156
1149
|
begin
|
1157
|
-
system.telemetry.packets(@name).each do |packet_name,
|
1150
|
+
system.telemetry.packets(@name).each do |packet_name, _packet|
|
1158
1151
|
packet_topic_list << "#{@scope}__TELEMETRY__{#{@name}}__#{packet_name}"
|
1159
1152
|
decom_topic_list << "#{@scope}__DECOM__{#{@name}}__#{packet_name}"
|
1160
1153
|
end
|
@@ -157,7 +157,7 @@ module OpenC3
|
|
157
157
|
@disable_erb = disable_erb
|
158
158
|
end
|
159
159
|
|
160
|
-
def create(update: false, force: false)
|
160
|
+
def create(update: false, force: false, queued: false)
|
161
161
|
tools = self.class.all(scope: @scope)
|
162
162
|
|
163
163
|
# Make sure a tool with this folder_name doesn't already exist
|
@@ -181,7 +181,7 @@ module OpenC3
|
|
181
181
|
end
|
182
182
|
end
|
183
183
|
|
184
|
-
super(update: update, force: force)
|
184
|
+
super(update: update, force: force, queued: queued)
|
185
185
|
end
|
186
186
|
|
187
187
|
def as_json(*a)
|
@@ -67,7 +67,9 @@ module OpenC3
|
|
67
67
|
def read(name, value_type = :CONVERTED, reduced_type = nil)
|
68
68
|
value = nil
|
69
69
|
array_index = nil
|
70
|
-
|
70
|
+
# Check for array index to handle array items but also make sure there
|
71
|
+
# isn't a REAL item that has brackets in the name
|
72
|
+
if name[-1] == ']' and !@json_hash.include?(name)
|
71
73
|
open_bracket_index = name.index('[')
|
72
74
|
if open_bracket_index
|
73
75
|
array_index = name[(open_bracket_index + 1)..-2].to_i
|
@@ -212,12 +214,12 @@ module OpenC3
|
|
212
214
|
else
|
213
215
|
postfix = nil if value_type == :RAW
|
214
216
|
end
|
215
|
-
@json_hash.each do |key,
|
217
|
+
@json_hash.each do |key, _value|
|
216
218
|
key_split = key.split("__")
|
217
219
|
result[key_split[0]] = true if key_split[1] == postfix
|
218
220
|
end
|
219
221
|
else
|
220
|
-
@json_hash.each { |key,
|
222
|
+
@json_hash.each { |key, _value| result[key.split("__")[0]] = true }
|
221
223
|
end
|
222
224
|
return result.keys
|
223
225
|
end
|
@@ -14,7 +14,7 @@
|
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
|
-
# All changes Copyright
|
17
|
+
# All changes Copyright 2024, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
20
|
# This file may also be used under the terms of a commercial license
|
@@ -22,7 +22,7 @@
|
|
22
22
|
|
23
23
|
module OpenC3
|
24
24
|
class SuiteResults
|
25
|
-
attr_accessor :metadata
|
25
|
+
attr_accessor :metadata, :context
|
26
26
|
|
27
27
|
def initialize
|
28
28
|
@report = nil
|
@@ -41,13 +41,13 @@ module OpenC3
|
|
41
41
|
@report = []
|
42
42
|
|
43
43
|
if test_case
|
44
|
-
# Executing a
|
44
|
+
# Executing a script
|
45
45
|
@context = "#{test_suite_class.name}:#{test_class.name}:#{test_case} #{test_type}"
|
46
46
|
elsif test_class
|
47
|
-
# Executing
|
47
|
+
# Executing a group
|
48
48
|
@context = "#{test_suite_class.name}:#{test_class.name} #{test_type}"
|
49
49
|
else
|
50
|
-
# Executing a
|
50
|
+
# Executing a suite
|
51
51
|
@context = "#{test_suite_class.name} #{test_type}"
|
52
52
|
end
|
53
53
|
|
@@ -75,7 +75,7 @@ module OpenC3
|
|
75
75
|
line.chomp!
|
76
76
|
line = line.inspect.remove_quotes
|
77
77
|
end
|
78
|
-
@report << ' ' + line.strip
|
78
|
+
@report << (' ' + line.strip)
|
79
79
|
end
|
80
80
|
end
|
81
81
|
if result.exceptions
|
@@ -90,7 +90,7 @@ module OpenC3
|
|
90
90
|
line.chomp!
|
91
91
|
line = line.inspect.remove_quotes
|
92
92
|
end
|
93
|
-
@report << ' ' + line.strip
|
93
|
+
@report << (' ' + line.strip)
|
94
94
|
end
|
95
95
|
@report << '' if index != (result.exceptions.length - 1)
|
96
96
|
end
|
@@ -172,11 +172,11 @@ module OpenC3
|
|
172
172
|
end
|
173
173
|
|
174
174
|
def write(string)
|
175
|
-
@report << Time.now.sys.formatted + ': ' + string
|
175
|
+
@report << (Time.now.sys.formatted + ': ' + string)
|
176
176
|
end
|
177
177
|
|
178
178
|
def puts(string)
|
179
|
-
@report << Time.now.sys.formatted + ': ' + string
|
179
|
+
@report << (Time.now.sys.formatted + ': ' + string)
|
180
180
|
end
|
181
181
|
|
182
182
|
# def collect_metadata(parent = nil)
|
@@ -21,6 +21,7 @@
|
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/topics/topic'
|
24
|
+
require 'openc3/utilities/store_queued'
|
24
25
|
|
25
26
|
module OpenC3
|
26
27
|
class CommandDecomTopic < Topic
|
@@ -39,7 +40,7 @@ module OpenC3
|
|
39
40
|
json_hash[item.name + "__U"] = packet.read_item(item, :WITH_UNITS) if item.units
|
40
41
|
end
|
41
42
|
msg_hash['json_data'] = JSON.generate(json_hash.as_json(:allow_nan => true))
|
42
|
-
|
43
|
+
EphemeralStoreQueued.write_topic(topic, msg_hash)
|
43
44
|
end
|
44
45
|
|
45
46
|
def self.get_cmd_item(target_name, packet_name, param_name, type: :WITH_UNITS, scope: $openc3_scope)
|
@@ -21,6 +21,7 @@
|
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/topics/topic'
|
24
|
+
require 'openc3/utilities/store_queued'
|
24
25
|
require 'openc3/utilities/open_telemetry'
|
25
26
|
|
26
27
|
module OpenC3
|
@@ -36,7 +37,7 @@ module OpenC3
|
|
36
37
|
received_count: packet.received_count,
|
37
38
|
stored: packet.stored.to_s,
|
38
39
|
buffer: packet.buffer(false) }
|
39
|
-
|
40
|
+
EphemeralStoreQueued.write_topic(topic, msg_hash)
|
40
41
|
end
|
41
42
|
|
42
43
|
# @param command [Hash] Command hash structure read to be written to a topic
|
@@ -21,10 +21,11 @@
|
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/topics/topic'
|
24
|
+
require 'openc3/utilities/store_queued'
|
24
25
|
|
25
26
|
module OpenC3
|
26
27
|
class TelemetryTopic < Topic
|
27
|
-
def self.write_packet(packet, scope:)
|
28
|
+
def self.write_packet(packet, queued: false, scope:)
|
28
29
|
msg_hash = {
|
29
30
|
:time => packet.packet_time.to_nsec_from_epoch,
|
30
31
|
:received_time => packet.received_time.to_nsec_from_epoch,
|
@@ -35,7 +36,11 @@ module OpenC3
|
|
35
36
|
:buffer => packet.buffer(false)
|
36
37
|
}
|
37
38
|
msg_hash[:extra] = JSON.generate(packet.extra.as_json, allow_nan: true) if packet.extra
|
38
|
-
|
39
|
+
if queued
|
40
|
+
EphemeralStoreQueued.write_topic("#{scope}__TELEMETRY__{#{packet.target_name}}__#{packet.packet_name}", msg_hash)
|
41
|
+
else
|
42
|
+
Topic.write_topic("#{scope}__TELEMETRY__{#{packet.target_name}}__#{packet.packet_name}", msg_hash)
|
43
|
+
end
|
39
44
|
end
|
40
45
|
end
|
41
46
|
end
|
@@ -26,7 +26,9 @@ module OpenC3
|
|
26
26
|
CREATE_CHECK_COUNT = 100 # 10 seconds
|
27
27
|
|
28
28
|
def initialize
|
29
|
+
super()
|
29
30
|
@client = Aws::S3::Client.new
|
31
|
+
@aws_arn = ENV['OPENC3_AWS_ARN_PREFIX'] || 'arn:aws'
|
30
32
|
end
|
31
33
|
|
32
34
|
def create(bucket)
|
@@ -59,7 +61,7 @@ module OpenC3
|
|
59
61
|
]
|
60
62
|
},
|
61
63
|
"Resource": [
|
62
|
-
"
|
64
|
+
"#{@aws_arn}:s3:::#{bucket}"
|
63
65
|
],
|
64
66
|
"Sid": ""
|
65
67
|
},
|
@@ -74,7 +76,7 @@ module OpenC3
|
|
74
76
|
]
|
75
77
|
},
|
76
78
|
"Resource": [
|
77
|
-
"
|
79
|
+
"#{@aws_arn}:s3:::#{bucket}/*"
|
78
80
|
],
|
79
81
|
"Sid": ""
|
80
82
|
}
|
@@ -198,19 +200,23 @@ module OpenC3
|
|
198
200
|
end
|
199
201
|
|
200
202
|
# @returns [Boolean] Whether the file exists
|
201
|
-
def check_object(bucket:, key:)
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
203
|
+
def check_object(bucket:, key:, retries: true)
|
204
|
+
if retries
|
205
|
+
@client.wait_until(:object_exists,
|
206
|
+
{
|
207
|
+
bucket: bucket,
|
208
|
+
key: key
|
209
|
+
},
|
210
|
+
{
|
211
|
+
max_attempts: 30,
|
212
|
+
delay: 0.1, # seconds
|
213
|
+
}
|
214
|
+
)
|
215
|
+
true
|
216
|
+
else
|
217
|
+
head_object(bucket: bucket, key: key)
|
218
|
+
end
|
219
|
+
rescue NotFound, Aws::Waiters::Errors::TooManyAttemptsError
|
214
220
|
false
|
215
221
|
end
|
216
222
|
|
@@ -69,7 +69,7 @@ module OpenC3
|
|
69
69
|
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
70
70
|
end
|
71
71
|
|
72
|
-
def check_object(bucket:, key:)
|
72
|
+
def check_object(bucket:, key:, retries: true)
|
73
73
|
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
|
74
74
|
end
|
75
75
|
|
@@ -22,7 +22,7 @@
|
|
22
22
|
|
23
23
|
require 'openc3/core_ext/class'
|
24
24
|
require 'openc3/core_ext/time'
|
25
|
-
require 'openc3/
|
25
|
+
require 'openc3/utilities/store_queued'
|
26
26
|
require 'socket'
|
27
27
|
require 'logger'
|
28
28
|
require 'time'
|
@@ -206,9 +206,9 @@ module OpenC3
|
|
206
206
|
end
|
207
207
|
unless @no_store
|
208
208
|
if scope
|
209
|
-
|
209
|
+
EphemeralStoreQueued.write_topic("#{scope}__openc3_log_messages", data)
|
210
210
|
else
|
211
|
-
|
211
|
+
EphemeralStoreQueued.write_topic("NOSCOPE__openc3_log_messages", data)
|
212
212
|
end
|
213
213
|
end
|
214
214
|
end
|
@@ -68,9 +68,9 @@ module OpenC3
|
|
68
68
|
@monitor_thread = Thread.new do
|
69
69
|
begin
|
70
70
|
monitor()
|
71
|
-
rescue =>
|
72
|
-
Logger.error("ProcessManager unexpectedly died\n#{
|
73
|
-
raise "ProcessManager unexpectedly died\n#{
|
71
|
+
rescue => e
|
72
|
+
Logger.error("ProcessManager unexpectedly died\n#{e.formatted}", scope: 'DEFAULT')
|
73
|
+
raise "ProcessManager unexpectedly died\n#{e.formatted}"
|
74
74
|
end
|
75
75
|
end
|
76
76
|
end
|
@@ -96,7 +96,9 @@ module OpenC3
|
|
96
96
|
process.status.output = output
|
97
97
|
if process.exit_code != 0
|
98
98
|
process.status.state = "Crashed"
|
99
|
-
elsif output.include?('"level":"ERROR"')
|
99
|
+
elsif output.include?('"level":"ERROR"')
|
100
|
+
process.status.state = "Error"
|
101
|
+
elsif output.include?('"level":"WARN"')
|
100
102
|
process.status.state = "Warning"
|
101
103
|
else
|
102
104
|
process.status.state = "Complete"
|
@@ -115,11 +117,15 @@ module OpenC3
|
|
115
117
|
process.status.update
|
116
118
|
end
|
117
119
|
processes_to_delete.each do |process|
|
118
|
-
|
119
|
-
|
120
|
+
message = "Process #{process.status.name}:#{process.process_type}:#{process.detail} completed with state #{process.status.state}\nProcess Output:\n#{process.status.output}"
|
121
|
+
if process.status.state != "Complete"
|
122
|
+
if process.status.state == "Warning"
|
123
|
+
Logger.warn(message, scope: process.scope)
|
124
|
+
else
|
125
|
+
Logger.error(message, scope: process.scope)
|
126
|
+
end
|
120
127
|
else
|
121
|
-
Logger.
|
122
|
-
Logger.error("Process Output:\n#{process.status.output}", scope: process.scope)
|
128
|
+
Logger.info(message, scope: process.scope)
|
123
129
|
end
|
124
130
|
|
125
131
|
@processes.delete(process)
|
@@ -131,7 +137,7 @@ module OpenC3
|
|
131
137
|
scopes = ScopeModel.names
|
132
138
|
scopes.each do |scope|
|
133
139
|
statuses = ProcessStatusModel.get_all_models(scope: scope)
|
134
|
-
statuses.each do |
|
140
|
+
statuses.each do |_status_name, status|
|
135
141
|
if (current_time - Time.from_nsec_from_epoch(status.updated_at)) > CLEANUP_CYCLE_SECONDS
|
136
142
|
status.destroy
|
137
143
|
end
|
@@ -21,6 +21,7 @@
|
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'redis'
|
24
|
+
require "hiredis-client"
|
24
25
|
require 'json'
|
25
26
|
require 'connection_pool'
|
26
27
|
|
@@ -32,6 +33,32 @@ else
|
|
32
33
|
end
|
33
34
|
|
34
35
|
module OpenC3
|
36
|
+
class StoreConnectionPool < ConnectionPool
|
37
|
+
NO_OPTIONS = {}
|
38
|
+
|
39
|
+
def pipelined
|
40
|
+
with(NO_OPTIONS) do |redis|
|
41
|
+
redis.pipelined do |pipeline|
|
42
|
+
Thread.current[:pipeline] = pipeline
|
43
|
+
begin
|
44
|
+
yield
|
45
|
+
ensure
|
46
|
+
Thread.current[:pipeline] = nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def with(options = NO_OPTIONS, &block)
|
53
|
+
pipeline = Thread.current[:pipeline]
|
54
|
+
if pipeline
|
55
|
+
yield pipeline
|
56
|
+
else
|
57
|
+
super(options, &block)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
35
62
|
class Store
|
36
63
|
# Variable that holds the singleton instance
|
37
64
|
@instance = nil
|
@@ -67,7 +94,7 @@ module OpenC3
|
|
67
94
|
@redis_username = ENV['OPENC3_REDIS_USERNAME']
|
68
95
|
@redis_key = ENV['OPENC3_REDIS_PASSWORD']
|
69
96
|
@redis_url = "redis://#{ENV['OPENC3_REDIS_HOSTNAME']}:#{ENV['OPENC3_REDIS_PORT']}"
|
70
|
-
@redis_pool =
|
97
|
+
@redis_pool = StoreConnectionPool.new(size: pool_size) { build_redis() }
|
71
98
|
end
|
72
99
|
|
73
100
|
unless $openc3_redis_cluster
|
@@ -212,7 +239,7 @@ module OpenC3
|
|
212
239
|
def initialize(pool_size = 10)
|
213
240
|
super(pool_size)
|
214
241
|
@redis_url = "redis://#{ENV['OPENC3_REDIS_EPHEMERAL_HOSTNAME']}:#{ENV['OPENC3_REDIS_EPHEMERAL_PORT']}"
|
215
|
-
@redis_pool =
|
242
|
+
@redis_pool = StoreConnectionPool.new(size: pool_size) { build_redis() }
|
216
243
|
end
|
217
244
|
end
|
218
245
|
end
|
@@ -60,19 +60,29 @@ module OpenC3
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
+
def set_update_interval(interval)
|
64
|
+
if interval < @update_interval and interval > 0.0
|
65
|
+
@update_interval = interval
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def process_queue
|
70
|
+
unless @store_queue.empty?
|
71
|
+
# Pipeline the requests to redis to improve performance
|
72
|
+
@store.redis_pool.pipelined do
|
73
|
+
while !@store_queue.empty?
|
74
|
+
action = @store_queue.pop()
|
75
|
+
@store.public_send(action.message, *action.args, **action.kwargs, &action.block)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
63
81
|
def store_thread_body
|
64
82
|
while true
|
65
83
|
start_time = Time.now
|
66
84
|
|
67
|
-
|
68
|
-
# Pipeline the requests to redis to improve performance
|
69
|
-
@store.pipelined do
|
70
|
-
while !@store_queue.empty?
|
71
|
-
action = @store_queue.pop()
|
72
|
-
@store.method_missing(action.message, *action.args, **action.kwargs, &action.block)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
85
|
+
process_queue()
|
76
86
|
|
77
87
|
# Only check whether to update at a set interval
|
78
88
|
run_time = Time.now - start_time
|
@@ -87,25 +97,14 @@ module OpenC3
|
|
87
97
|
OpenC3.kill_thread(self, @update_thread) if @update_thread
|
88
98
|
@update_thread = nil
|
89
99
|
# Drain the queue before shutdown
|
90
|
-
|
91
|
-
# Pipeline the requests to redis to improve performance
|
92
|
-
@store.pipelined do
|
93
|
-
while !@store_queue.empty?
|
94
|
-
action = @store_queue.pop()
|
95
|
-
@store.method_missing(action.message, *action.args, **action.kwargs, &action.block)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
100
|
+
process_queue()
|
99
101
|
end
|
100
102
|
|
103
|
+
MessageStruct = Struct.new(:message, :args, :kwargs, :block)
|
104
|
+
|
101
105
|
# Record the message for pipelining by the thread
|
102
106
|
def method_missing(message, *args, **kwargs, &block)
|
103
|
-
|
104
|
-
o.message = message
|
105
|
-
o.args = args
|
106
|
-
o.kwargs = kwargs
|
107
|
-
o.block = block
|
108
|
-
@store_queue.push(o)
|
107
|
+
@store_queue.push(MessageStruct.new(message, args, kwargs, block))
|
109
108
|
end
|
110
109
|
|
111
110
|
# Returns the store we're working with
|
data/lib/openc3/version.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# encoding: ascii-8bit
|
2
2
|
|
3
|
-
OPENC3_VERSION = '5.
|
3
|
+
OPENC3_VERSION = '5.15.0'
|
4
4
|
module OpenC3
|
5
5
|
module Version
|
6
6
|
MAJOR = '5'
|
7
|
-
MINOR = '
|
8
|
-
PATCH = '
|
7
|
+
MINOR = '15'
|
8
|
+
PATCH = '0'
|
9
9
|
OTHER = ''
|
10
|
-
BUILD = '
|
10
|
+
BUILD = 'a7dd92ddb0ba4d378da1b611cafc5ad7e89a9223'
|
11
11
|
end
|
12
|
-
VERSION = '5.
|
13
|
-
GEM_VERSION = '5.
|
12
|
+
VERSION = '5.15.0'
|
13
|
+
GEM_VERSION = '5.15.0'
|
14
14
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "<%= tool_name %>",
|
3
|
-
"version": "5.
|
3
|
+
"version": "5.15.0",
|
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.
|
15
|
+
"@openc3/tool-common": "5.15.0",
|
16
16
|
"@angular/animations": "^17.0.8",
|
17
17
|
"@angular/cdk": "^17.0.4",
|
18
18
|
"@angular/common": "^17.0.8",
|
@@ -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.
|
14
|
+
"@openc3/tool-common": "5.15.0",
|
15
15
|
"@astrouxds/astro-web-components": "7.20.0",
|
16
16
|
"@smui/button": "^7.0.0-beta.16",
|
17
17
|
"@smui/card": "^7.0.0-beta.16",
|
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "<%= tool_name %>",
|
3
|
-
"version": "5.
|
3
|
+
"version": "5.15.0",
|
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.
|
14
|
+
"@openc3/tool-common": "5.15.0",
|
15
15
|
"@astrouxds/astro-web-components": "7.20.0",
|
16
16
|
"axios": "1.6.5",
|
17
17
|
"date-fns": "2.30.0",
|