openc3 7.0.1 → 7.1.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.
- checksums.yaml +4 -4
- data/bin/openc3cli +47 -3
- data/data/config/item_modifiers.yaml +1 -1
- data/data/config/microservice.yaml +12 -1
- data/data/config/parameter_modifiers.yaml +49 -7
- data/data/config/target.yaml +11 -0
- data/data/config/target_config.yaml +6 -2
- data/lib/openc3/api/cmd_api.rb +2 -1
- data/lib/openc3/api/metrics_api.rb +11 -1
- data/lib/openc3/api/tlm_api.rb +21 -6
- data/lib/openc3/core_ext/faraday.rb +1 -1
- data/lib/openc3/io/json_api.rb +1 -1
- data/lib/openc3/logs/log_writer.rb +3 -1
- data/lib/openc3/microservices/decom_common.rb +128 -0
- data/lib/openc3/microservices/decom_microservice.rb +26 -95
- data/lib/openc3/microservices/interface_decom_common.rb +6 -2
- data/lib/openc3/microservices/interface_microservice.rb +10 -8
- data/lib/openc3/microservices/log_microservice.rb +1 -1
- data/lib/openc3/microservices/microservice.rb +3 -2
- data/lib/openc3/microservices/queue_microservice.rb +1 -1
- data/lib/openc3/microservices/scope_cleanup_microservice.rb +60 -46
- data/lib/openc3/microservices/text_log_microservice.rb +1 -2
- data/lib/openc3/models/cvt_model.rb +24 -13
- data/lib/openc3/models/db_sharded_model.rb +110 -0
- data/lib/openc3/models/interface_model.rb +9 -0
- data/lib/openc3/models/interface_status_model.rb +33 -3
- data/lib/openc3/models/metric_model.rb +96 -37
- data/lib/openc3/models/microservice_model.rb +7 -0
- data/lib/openc3/models/microservice_status_model.rb +30 -3
- data/lib/openc3/models/reingest_job_model.rb +153 -0
- data/lib/openc3/models/scope_model.rb +3 -2
- data/lib/openc3/models/script_status_model.rb +4 -20
- data/lib/openc3/models/target_model.rb +113 -100
- data/lib/openc3/packets/packet_config.rb +4 -1
- data/lib/openc3/script/script.rb +2 -2
- data/lib/openc3/script/script_runner.rb +4 -4
- data/lib/openc3/script/telemetry.rb +3 -3
- data/lib/openc3/script/web_socket_api.rb +29 -22
- data/lib/openc3/system/system.rb +20 -3
- data/lib/openc3/topics/command_decom_topic.rb +4 -2
- data/lib/openc3/topics/command_topic.rb +8 -5
- data/lib/openc3/topics/decom_interface_topic.rb +15 -10
- data/lib/openc3/topics/interface_topic.rb +71 -29
- data/lib/openc3/topics/limits_event_topic.rb +62 -41
- data/lib/openc3/topics/router_topic.rb +61 -21
- data/lib/openc3/topics/system_events_topic.rb +18 -1
- data/lib/openc3/topics/telemetry_decom_topic.rb +2 -1
- data/lib/openc3/topics/telemetry_topic.rb +4 -2
- data/lib/openc3/topics/topic.rb +77 -5
- data/lib/openc3/utilities/aws_bucket.rb +2 -0
- data/lib/openc3/utilities/cli_generator.rb +3 -2
- data/lib/openc3/utilities/metric.rb +15 -1
- data/lib/openc3/utilities/questdb_client.rb +173 -37
- data/lib/openc3/utilities/reingest_job.rb +377 -0
- data/lib/openc3/utilities/ruby_lex_utils.rb +2 -0
- data/lib/openc3/utilities/store_autoload.rb +78 -52
- data/lib/openc3/utilities/store_queued.rb +20 -12
- data/lib/openc3/version.rb +6 -6
- data/templates/plugin/plugin.gemspec +13 -1
- data/templates/tool_angular/package.json +2 -2
- data/templates/tool_react/package.json +1 -1
- data/templates/tool_svelte/package.json +1 -1
- data/templates/tool_vue/package.json +3 -3
- data/templates/tool_vue/src/router.js +2 -2
- data/templates/widget/package.json +2 -2
- metadata +7 -3
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# encoding: ascii-8bit
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 OpenC3, Inc.
|
|
4
|
+
# All Rights Reserved.
|
|
5
|
+
#
|
|
6
|
+
# This program is distributed in the hope that it will be useful,
|
|
7
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
8
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
9
|
+
# See LICENSE.md for more details.
|
|
10
|
+
#
|
|
11
|
+
# This file may also be used under the terms of a commercial license
|
|
12
|
+
# if purchased from OpenC3, Inc.
|
|
13
|
+
|
|
14
|
+
require 'openc3/models/model'
|
|
15
|
+
|
|
16
|
+
module OpenC3
|
|
17
|
+
# Tracks one run of OpenC3::ReingestJob. The job updates this record from a
|
|
18
|
+
# background thread; the storage_controller status endpoint reads it.
|
|
19
|
+
# `updated_at` doubles as the heartbeat — if a Running record hasn't been
|
|
20
|
+
# touched in STALE_THRESHOLD_SEC, the status endpoint surfaces it as 'Stale'.
|
|
21
|
+
class ReingestJobModel < Model
|
|
22
|
+
PRIMARY_KEY = 'openc3_reingest_job'
|
|
23
|
+
STALE_THRESHOLD_SEC = 60
|
|
24
|
+
|
|
25
|
+
STATES = %w[Queued Running Complete Crashed Stale].freeze
|
|
26
|
+
PHASES = %w[downloading enabling_dedup ingesting dedup_cooldown disabling_dedup].freeze
|
|
27
|
+
|
|
28
|
+
attr_accessor :state
|
|
29
|
+
attr_accessor :files
|
|
30
|
+
attr_accessor :bucket
|
|
31
|
+
attr_accessor :path
|
|
32
|
+
attr_accessor :table_names
|
|
33
|
+
attr_accessor :target_version
|
|
34
|
+
attr_accessor :versions_used
|
|
35
|
+
attr_accessor :warnings
|
|
36
|
+
attr_accessor :progress_phase
|
|
37
|
+
attr_accessor :progress_current
|
|
38
|
+
attr_accessor :progress_total
|
|
39
|
+
attr_accessor :packets_written
|
|
40
|
+
attr_accessor :dedup_enabled_by_us
|
|
41
|
+
attr_accessor :dedup_preexisting
|
|
42
|
+
attr_accessor :dedup_disabled_tables
|
|
43
|
+
attr_accessor :dedup_cooldown_seconds
|
|
44
|
+
attr_accessor :dedup_enabled_at
|
|
45
|
+
attr_accessor :dedup_disabled_at
|
|
46
|
+
attr_accessor :error
|
|
47
|
+
attr_accessor :started_at
|
|
48
|
+
attr_accessor :finished_at
|
|
49
|
+
|
|
50
|
+
def self.get(name:, scope:)
|
|
51
|
+
super("#{scope}__#{PRIMARY_KEY}", name: name)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.names(scope:)
|
|
55
|
+
super("#{scope}__#{PRIMARY_KEY}")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.all(scope:)
|
|
59
|
+
all = super("#{scope}__#{PRIMARY_KEY}")
|
|
60
|
+
all.sort_by { |_key, value| value['updated_at'] }.reverse
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def initialize(
|
|
64
|
+
name:,
|
|
65
|
+
state: 'Queued',
|
|
66
|
+
files: [],
|
|
67
|
+
bucket: nil,
|
|
68
|
+
path: nil,
|
|
69
|
+
table_names: [],
|
|
70
|
+
target_version: 'as_logged',
|
|
71
|
+
versions_used: [],
|
|
72
|
+
warnings: [],
|
|
73
|
+
progress_phase: nil,
|
|
74
|
+
progress_current: 0,
|
|
75
|
+
progress_total: 0,
|
|
76
|
+
packets_written: 0,
|
|
77
|
+
dedup_enabled_by_us: [],
|
|
78
|
+
dedup_preexisting: [],
|
|
79
|
+
dedup_disabled_tables: [],
|
|
80
|
+
dedup_cooldown_seconds: 60,
|
|
81
|
+
dedup_enabled_at: nil,
|
|
82
|
+
dedup_disabled_at: nil,
|
|
83
|
+
error: nil,
|
|
84
|
+
started_at: nil,
|
|
85
|
+
finished_at: nil,
|
|
86
|
+
updated_at: nil,
|
|
87
|
+
plugin: nil,
|
|
88
|
+
scope:
|
|
89
|
+
)
|
|
90
|
+
super("#{scope}__#{PRIMARY_KEY}", name: name, updated_at: updated_at, plugin: plugin, scope: scope)
|
|
91
|
+
@state = state
|
|
92
|
+
@files = files
|
|
93
|
+
@bucket = bucket
|
|
94
|
+
@path = path
|
|
95
|
+
@table_names = table_names
|
|
96
|
+
@target_version = target_version
|
|
97
|
+
@versions_used = versions_used
|
|
98
|
+
@warnings = warnings
|
|
99
|
+
@progress_phase = progress_phase
|
|
100
|
+
@progress_current = progress_current
|
|
101
|
+
@progress_total = progress_total
|
|
102
|
+
@packets_written = packets_written
|
|
103
|
+
@dedup_enabled_by_us = dedup_enabled_by_us
|
|
104
|
+
@dedup_preexisting = dedup_preexisting
|
|
105
|
+
@dedup_disabled_tables = dedup_disabled_tables
|
|
106
|
+
@dedup_cooldown_seconds = dedup_cooldown_seconds
|
|
107
|
+
@dedup_enabled_at = dedup_enabled_at
|
|
108
|
+
@dedup_disabled_at = dedup_disabled_at
|
|
109
|
+
@error = error
|
|
110
|
+
@started_at = started_at
|
|
111
|
+
@finished_at = finished_at
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# True if state is Running but the heartbeat (updated_at) is older than
|
|
115
|
+
# STALE_THRESHOLD_SEC. Callers should surface state as 'Stale' in that case.
|
|
116
|
+
def stale?
|
|
117
|
+
return false unless @state == 'Running'
|
|
118
|
+
return false unless @updated_at
|
|
119
|
+
age_nsec = Time.now.to_nsec_from_epoch - @updated_at.to_i
|
|
120
|
+
age_nsec > STALE_THRESHOLD_SEC * 1_000_000_000
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def as_json(*_a)
|
|
124
|
+
{
|
|
125
|
+
'name' => @name,
|
|
126
|
+
'state' => stale? ? 'Stale' : @state,
|
|
127
|
+
'files' => @files,
|
|
128
|
+
'bucket' => @bucket,
|
|
129
|
+
'path' => @path,
|
|
130
|
+
'table_names' => @table_names,
|
|
131
|
+
'target_version' => @target_version,
|
|
132
|
+
'versions_used' => @versions_used,
|
|
133
|
+
'warnings' => @warnings,
|
|
134
|
+
'progress_phase' => @progress_phase,
|
|
135
|
+
'progress_current' => @progress_current,
|
|
136
|
+
'progress_total' => @progress_total,
|
|
137
|
+
'packets_written' => @packets_written,
|
|
138
|
+
'dedup_enabled_by_us' => @dedup_enabled_by_us,
|
|
139
|
+
'dedup_preexisting' => @dedup_preexisting,
|
|
140
|
+
'dedup_disabled_tables' => @dedup_disabled_tables,
|
|
141
|
+
'dedup_cooldown_seconds' => @dedup_cooldown_seconds,
|
|
142
|
+
'dedup_enabled_at' => @dedup_enabled_at,
|
|
143
|
+
'dedup_disabled_at' => @dedup_disabled_at,
|
|
144
|
+
'error' => @error,
|
|
145
|
+
'started_at' => @started_at,
|
|
146
|
+
'finished_at' => @finished_at,
|
|
147
|
+
'updated_at' => @updated_at,
|
|
148
|
+
'plugin' => @plugin,
|
|
149
|
+
'scope' => @scope,
|
|
150
|
+
}
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
@@ -389,8 +389,9 @@ module OpenC3
|
|
|
389
389
|
end
|
|
390
390
|
|
|
391
391
|
# Delete the topics we created for the scope
|
|
392
|
-
|
|
393
|
-
Topic.del("#{@scope}
|
|
392
|
+
db_shard = Store.db_shard_for_target('UNKNOWN', scope: @scope)
|
|
393
|
+
Topic.del("#{@scope}__COMMAND__{UNKNOWN}__UNKNOWN", db_shard: db_shard)
|
|
394
|
+
Topic.del("#{@scope}__TELEMETRY__{UNKNOWN}__UNKNOWN", db_shard: db_shard)
|
|
394
395
|
Topic.del("#{@scope}__openc3_targets")
|
|
395
396
|
Topic.del("#{@scope}__CONFIG")
|
|
396
397
|
end
|
|
@@ -66,17 +66,9 @@ module OpenC3
|
|
|
66
66
|
keys = self.store.zrevrange("#{RUNNING_PRIMARY_KEY}__#{scope}__LIST", offset.to_i, offset.to_i + limit.to_i - 1)
|
|
67
67
|
return [] if keys.empty?
|
|
68
68
|
result = []
|
|
69
|
-
|
|
70
|
-
# No pipelining for cluster mode
|
|
71
|
-
# because it requires using the same shard for all keys
|
|
69
|
+
result = self.store.redis_pool.pipelined do
|
|
72
70
|
keys.each do |key|
|
|
73
|
-
|
|
74
|
-
end
|
|
75
|
-
else
|
|
76
|
-
result = self.store.redis_pool.pipelined do
|
|
77
|
-
keys.each do |key|
|
|
78
|
-
self.store.hget("#{RUNNING_PRIMARY_KEY}__#{scope}", key)
|
|
79
|
-
end
|
|
71
|
+
self.store.hget("#{RUNNING_PRIMARY_KEY}__#{scope}", key)
|
|
80
72
|
end
|
|
81
73
|
end
|
|
82
74
|
result = result.map do |r|
|
|
@@ -91,17 +83,9 @@ module OpenC3
|
|
|
91
83
|
keys = self.store.zrevrange("#{COMPLETED_PRIMARY_KEY}__#{scope}__LIST", offset.to_i, offset.to_i + limit.to_i - 1)
|
|
92
84
|
return [] if keys.empty?
|
|
93
85
|
result = []
|
|
94
|
-
|
|
95
|
-
# No pipelining for cluster mode
|
|
96
|
-
# because it requires using the same shard for all keys
|
|
86
|
+
result = self.store.redis_pool.pipelined do
|
|
97
87
|
keys.each do |key|
|
|
98
|
-
|
|
99
|
-
end
|
|
100
|
-
else
|
|
101
|
-
result = self.store.redis_pool.pipelined do
|
|
102
|
-
keys.each do |key|
|
|
103
|
-
self.store.hget("#{COMPLETED_PRIMARY_KEY}__#{scope}", key)
|
|
104
|
-
end
|
|
88
|
+
self.store.hget("#{COMPLETED_PRIMARY_KEY}__#{scope}", key)
|
|
105
89
|
end
|
|
106
90
|
end
|
|
107
91
|
result = result.map do |r|
|