openc3 5.0.6
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 +7 -0
- data/Gemfile +18 -0
- data/Guardfile +35 -0
- data/LICENSE.txt +727 -0
- data/README.md +37 -0
- data/Rakefile +131 -0
- data/bin/cstol_converter +1178 -0
- data/bin/openc3cli +531 -0
- data/bin/rubysloc +139 -0
- data/data/config/_array_params.yaml +23 -0
- data/data/config/_id_items.yaml +24 -0
- data/data/config/_id_params.yaml +58 -0
- data/data/config/_interfaces.yaml +214 -0
- data/data/config/_interfaces.yaml.err +1017 -0
- data/data/config/_items.yaml +20 -0
- data/data/config/_params.yaml +60 -0
- data/data/config/cmd_tlm_server.yaml +136 -0
- data/data/config/command.yaml +44 -0
- data/data/config/command_modifiers.yaml +160 -0
- data/data/config/command_telemetry.yaml +3 -0
- data/data/config/interface_modifiers.yaml +104 -0
- data/data/config/item_modifiers.yaml +221 -0
- data/data/config/microservice.yaml +78 -0
- data/data/config/param_item_modifiers.yaml +52 -0
- data/data/config/parameter_modifiers.yaml +200 -0
- data/data/config/plugins.yaml +80 -0
- data/data/config/protocols.yaml +290 -0
- data/data/config/screen.yaml +147 -0
- data/data/config/table_manager.yaml +89 -0
- data/data/config/table_parameter_modifiers.yaml +9 -0
- data/data/config/target.yaml +142 -0
- data/data/config/target_config.yaml +94 -0
- data/data/config/telemetry.yaml +87 -0
- data/data/config/telemetry_modifiers.yaml +159 -0
- data/data/config/tool.yaml +63 -0
- data/data/config/unknown.yaml +3 -0
- data/data/config/widgets.yaml +1505 -0
- data/ext/mkrf_conf.rb +49 -0
- data/ext/openc3/ext/array/array.c +122 -0
- data/ext/openc3/ext/array/extconf.rb +13 -0
- data/ext/openc3/ext/buffered_file/buffered_file.c +198 -0
- data/ext/openc3/ext/buffered_file/extconf.rb +13 -0
- data/ext/openc3/ext/config_parser/config_parser.c +280 -0
- data/ext/openc3/ext/config_parser/extconf.rb +13 -0
- data/ext/openc3/ext/crc/crc.c +351 -0
- data/ext/openc3/ext/crc/extconf.rb +13 -0
- data/ext/openc3/ext/openc3_io/extconf.rb +13 -0
- data/ext/openc3/ext/openc3_io/openc3_io.c +158 -0
- data/ext/openc3/ext/packet/extconf.rb +13 -0
- data/ext/openc3/ext/packet/packet.c +318 -0
- data/ext/openc3/ext/platform/extconf.rb +13 -0
- data/ext/openc3/ext/platform/platform.c +134 -0
- data/ext/openc3/ext/polynomial_conversion/extconf.rb +13 -0
- data/ext/openc3/ext/polynomial_conversion/polynomial_conversion.c +79 -0
- data/ext/openc3/ext/string/extconf.rb +13 -0
- data/ext/openc3/ext/string/string.c +63 -0
- data/ext/openc3/ext/structure/structure.c +1719 -0
- data/ext/openc3/ext/tabbed_plots_config/extconf.rb +13 -0
- data/ext/openc3/ext/tabbed_plots_config/tabbed_plots_config.c +62 -0
- data/ext/openc3/ext/telemetry/extconf.rb +13 -0
- data/ext/openc3/ext/telemetry/telemetry.c +336 -0
- data/lib/cosmos.rb +20 -0
- data/lib/cosmosc2.rb +20 -0
- data/lib/openc3/api/api.rb +39 -0
- data/lib/openc3/api/authorized_api.rb +30 -0
- data/lib/openc3/api/cmd_api.rb +451 -0
- data/lib/openc3/api/config_api.rb +58 -0
- data/lib/openc3/api/interface_api.rb +117 -0
- data/lib/openc3/api/limits_api.rb +375 -0
- data/lib/openc3/api/router_api.rb +117 -0
- data/lib/openc3/api/settings_api.rb +70 -0
- data/lib/openc3/api/target_api.rb +78 -0
- data/lib/openc3/api/tlm_api.rb +455 -0
- data/lib/openc3/bridge/bridge.rb +54 -0
- data/lib/openc3/bridge/bridge_config.rb +167 -0
- data/lib/openc3/bridge/bridge_interface_thread.rb +42 -0
- data/lib/openc3/bridge/bridge_router_thread.rb +42 -0
- data/lib/openc3/ccsds/ccsds_packet.rb +68 -0
- data/lib/openc3/ccsds/ccsds_parser.rb +148 -0
- data/lib/openc3/config/config_parser.rb +549 -0
- data/lib/openc3/config/meta_config_parser.rb +74 -0
- data/lib/openc3/conversions/conversion.rb +70 -0
- data/lib/openc3/conversions/generic_conversion.rb +83 -0
- data/lib/openc3/conversions/packet_time_formatted_conversion.rb +43 -0
- data/lib/openc3/conversions/packet_time_seconds_conversion.rb +43 -0
- data/lib/openc3/conversions/polynomial_conversion.rb +87 -0
- data/lib/openc3/conversions/processor_conversion.rb +70 -0
- data/lib/openc3/conversions/received_count_conversion.rb +38 -0
- data/lib/openc3/conversions/received_time_formatted_conversion.rb +42 -0
- data/lib/openc3/conversions/received_time_seconds_conversion.rb +42 -0
- data/lib/openc3/conversions/segmented_polynomial_conversion.rb +171 -0
- data/lib/openc3/conversions/unix_time_conversion.rb +68 -0
- data/lib/openc3/conversions/unix_time_formatted_conversion.rb +49 -0
- data/lib/openc3/conversions/unix_time_seconds_conversion.rb +49 -0
- data/lib/openc3/conversions.rb +34 -0
- data/lib/openc3/core_ext/array.rb +416 -0
- data/lib/openc3/core_ext/binding.rb +29 -0
- data/lib/openc3/core_ext/class.rb +72 -0
- data/lib/openc3/core_ext/exception.rb +61 -0
- data/lib/openc3/core_ext/file.rb +83 -0
- data/lib/openc3/core_ext/hash.rb +37 -0
- data/lib/openc3/core_ext/io.rb +134 -0
- data/lib/openc3/core_ext/kernel.rb +42 -0
- data/lib/openc3/core_ext/math.rb +128 -0
- data/lib/openc3/core_ext/matrix.rb +156 -0
- data/lib/openc3/core_ext/objectspace.rb +36 -0
- data/lib/openc3/core_ext/openc3_io.rb +57 -0
- data/lib/openc3/core_ext/range.rb +27 -0
- data/lib/openc3/core_ext/socket.rb +38 -0
- data/lib/openc3/core_ext/string.rb +389 -0
- data/lib/openc3/core_ext/stringio.rb +33 -0
- data/lib/openc3/core_ext/time.rb +508 -0
- data/lib/openc3/core_ext.rb +36 -0
- data/lib/openc3/interfaces/interface.rb +498 -0
- data/lib/openc3/interfaces/linc_interface.rb +475 -0
- data/lib/openc3/interfaces/protocols/burst_protocol.rb +192 -0
- data/lib/openc3/interfaces/protocols/crc_protocol.rb +193 -0
- data/lib/openc3/interfaces/protocols/fixed_protocol.rb +155 -0
- data/lib/openc3/interfaces/protocols/ignore_packet_protocol.rb +56 -0
- data/lib/openc3/interfaces/protocols/length_protocol.rb +165 -0
- data/lib/openc3/interfaces/protocols/override_protocol.rb +60 -0
- data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +206 -0
- data/lib/openc3/interfaces/protocols/protocol.rb +82 -0
- data/lib/openc3/interfaces/protocols/template_protocol.rb +261 -0
- data/lib/openc3/interfaces/protocols/terminated_protocol.rb +93 -0
- data/lib/openc3/interfaces/serial_interface.rb +94 -0
- data/lib/openc3/interfaces/simulated_target_interface.rb +168 -0
- data/lib/openc3/interfaces/stream_interface.rb +81 -0
- data/lib/openc3/interfaces/tcpip_client_interface.rb +69 -0
- data/lib/openc3/interfaces/tcpip_server_interface.rb +629 -0
- data/lib/openc3/interfaces/udp_interface.rb +169 -0
- data/lib/openc3/interfaces.rb +44 -0
- data/lib/openc3/io/buffered_file.rb +109 -0
- data/lib/openc3/io/io_multiplexer.rb +80 -0
- data/lib/openc3/io/json_api_object.rb +208 -0
- data/lib/openc3/io/json_drb.rb +335 -0
- data/lib/openc3/io/json_drb_object.rb +114 -0
- data/lib/openc3/io/json_drb_rack.rb +84 -0
- data/lib/openc3/io/json_rpc.rb +420 -0
- data/lib/openc3/io/openc3_snmp.rb +58 -0
- data/lib/openc3/io/posix_serial_driver.rb +156 -0
- data/lib/openc3/io/raw_logger.rb +167 -0
- data/lib/openc3/io/raw_logger_pair.rb +77 -0
- data/lib/openc3/io/serial_driver.rb +105 -0
- data/lib/openc3/io/stderr.rb +43 -0
- data/lib/openc3/io/stdout.rb +43 -0
- data/lib/openc3/io/udp_sockets.rb +194 -0
- data/lib/openc3/io/win32_serial_driver.rb +196 -0
- data/lib/openc3/logs/log_writer.rb +302 -0
- data/lib/openc3/logs/packet_log_constants.rb +62 -0
- data/lib/openc3/logs/packet_log_reader.rb +345 -0
- data/lib/openc3/logs/packet_log_writer.rb +299 -0
- data/lib/openc3/logs/text_log_writer.rb +68 -0
- data/lib/openc3/logs.rb +25 -0
- data/lib/openc3/microservices/cleanup_microservice.rb +68 -0
- data/lib/openc3/microservices/decom_microservice.rb +136 -0
- data/lib/openc3/microservices/interface_microservice.rb +532 -0
- data/lib/openc3/microservices/log_microservice.rb +108 -0
- data/lib/openc3/microservices/microservice.rb +204 -0
- data/lib/openc3/microservices/plugin_microservice.rb +43 -0
- data/lib/openc3/microservices/reaction_microservice.rb +541 -0
- data/lib/openc3/microservices/reducer_microservice.rb +313 -0
- data/lib/openc3/microservices/router_microservice.rb +44 -0
- data/lib/openc3/microservices/text_log_microservice.rb +84 -0
- data/lib/openc3/microservices/timeline_microservice.rb +363 -0
- data/lib/openc3/microservices/trigger_group_microservice.rb +638 -0
- data/lib/openc3/models/activity_model.rb +319 -0
- data/lib/openc3/models/auth_model.rb +65 -0
- data/lib/openc3/models/cvt_model.rb +185 -0
- data/lib/openc3/models/environment_model.rb +58 -0
- data/lib/openc3/models/gem_model.rb +137 -0
- data/lib/openc3/models/info_model.rb +31 -0
- data/lib/openc3/models/interface_model.rb +281 -0
- data/lib/openc3/models/interface_status_model.rb +117 -0
- data/lib/openc3/models/metadata_model.rb +139 -0
- data/lib/openc3/models/metric_model.rb +59 -0
- data/lib/openc3/models/microservice_model.rb +206 -0
- data/lib/openc3/models/microservice_status_model.rb +74 -0
- data/lib/openc3/models/model.rb +204 -0
- data/lib/openc3/models/note_model.rb +122 -0
- data/lib/openc3/models/notification_model.rb +40 -0
- data/lib/openc3/models/ping_model.rb +35 -0
- data/lib/openc3/models/plugin_model.rb +292 -0
- data/lib/openc3/models/process_status_model.rb +76 -0
- data/lib/openc3/models/reaction_model.rb +322 -0
- data/lib/openc3/models/reducer_model.rb +65 -0
- data/lib/openc3/models/router_model.rb +35 -0
- data/lib/openc3/models/router_status_model.rb +27 -0
- data/lib/openc3/models/scope_model.rb +153 -0
- data/lib/openc3/models/settings_model.rb +55 -0
- data/lib/openc3/models/sorted_model.rb +167 -0
- data/lib/openc3/models/target_model.rb +759 -0
- data/lib/openc3/models/timeline_model.rb +154 -0
- data/lib/openc3/models/tool_config_model.rb +38 -0
- data/lib/openc3/models/tool_model.rb +262 -0
- data/lib/openc3/models/trigger_group_model.rb +186 -0
- data/lib/openc3/models/trigger_model.rb +330 -0
- data/lib/openc3/models/widget_model.rb +138 -0
- data/lib/openc3/operators/microservice_operator.rb +128 -0
- data/lib/openc3/operators/operator.rb +277 -0
- data/lib/openc3/packets/binary_accessor.rb +1207 -0
- data/lib/openc3/packets/commands.rb +373 -0
- data/lib/openc3/packets/json_packet.rb +134 -0
- data/lib/openc3/packets/limits.rb +271 -0
- data/lib/openc3/packets/limits_response.rb +53 -0
- data/lib/openc3/packets/packet.rb +1168 -0
- data/lib/openc3/packets/packet_config.rb +625 -0
- data/lib/openc3/packets/packet_item.rb +586 -0
- data/lib/openc3/packets/packet_item_limits.rb +162 -0
- data/lib/openc3/packets/parsers/format_string_parser.rb +65 -0
- data/lib/openc3/packets/parsers/limits_parser.rb +159 -0
- data/lib/openc3/packets/parsers/limits_response_parser.rb +61 -0
- data/lib/openc3/packets/parsers/packet_item_parser.rb +272 -0
- data/lib/openc3/packets/parsers/packet_parser.rb +134 -0
- data/lib/openc3/packets/parsers/processor_parser.rb +73 -0
- data/lib/openc3/packets/parsers/state_parser.rb +127 -0
- data/lib/openc3/packets/parsers/xtce_converter.rb +442 -0
- data/lib/openc3/packets/parsers/xtce_parser.rb +722 -0
- data/lib/openc3/packets/structure.rb +553 -0
- data/lib/openc3/packets/structure_item.rb +365 -0
- data/lib/openc3/packets/telemetry.rb +487 -0
- data/lib/openc3/processors/processor.rb +86 -0
- data/lib/openc3/processors/statistics_processor.rb +82 -0
- data/lib/openc3/processors/watermark_processor.rb +58 -0
- data/lib/openc3/processors.rb +24 -0
- data/lib/openc3/script/api_shared.rb +828 -0
- data/lib/openc3/script/calendar.rb +89 -0
- data/lib/openc3/script/commands.rb +227 -0
- data/lib/openc3/script/exceptions.rb +29 -0
- data/lib/openc3/script/extract.rb +161 -0
- data/lib/openc3/script/limits.rb +60 -0
- data/lib/openc3/script/script.rb +299 -0
- data/lib/openc3/script/script_runner.rb +238 -0
- data/lib/openc3/script/storage.rb +146 -0
- data/lib/openc3/script/suite.rb +542 -0
- data/lib/openc3/script/suite_results.rb +196 -0
- data/lib/openc3/script/suite_runner.rb +217 -0
- data/lib/openc3/script.rb +21 -0
- data/lib/openc3/streams/serial_stream.rb +167 -0
- data/lib/openc3/streams/stream.rb +63 -0
- data/lib/openc3/streams/tcpip_client_stream.rb +116 -0
- data/lib/openc3/streams/tcpip_socket_stream.rb +195 -0
- data/lib/openc3/system/system.rb +127 -0
- data/lib/openc3/system/system_config.rb +411 -0
- data/lib/openc3/system/target.rb +269 -0
- data/lib/openc3/system.rb +24 -0
- data/lib/openc3/tools/cmd_tlm_server/api.rb +20 -0
- data/lib/openc3/tools/cmd_tlm_server/cmd_tlm_server_config.rb +320 -0
- data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +294 -0
- data/lib/openc3/tools/table_manager/table.rb +77 -0
- data/lib/openc3/tools/table_manager/table_config.rb +273 -0
- data/lib/openc3/tools/table_manager/table_item.rb +90 -0
- data/lib/openc3/tools/table_manager/table_item_parser.rb +66 -0
- data/lib/openc3/tools/table_manager/table_manager_core.rb +333 -0
- data/lib/openc3/tools/table_manager/table_parser.rb +93 -0
- data/lib/openc3/tools/test_runner/test.rb +67 -0
- data/lib/openc3/top_level.rb +595 -0
- data/lib/openc3/topics/autonomic_topic.rb +52 -0
- data/lib/openc3/topics/calendar_topic.rb +44 -0
- data/lib/openc3/topics/command_decom_topic.rb +76 -0
- data/lib/openc3/topics/command_topic.rb +83 -0
- data/lib/openc3/topics/config_topic.rb +68 -0
- data/lib/openc3/topics/interface_topic.rb +73 -0
- data/lib/openc3/topics/limits_event_topic.rb +109 -0
- data/lib/openc3/topics/notifications_topic.rb +28 -0
- data/lib/openc3/topics/router_topic.rb +85 -0
- data/lib/openc3/topics/telemetry_decom_topic.rb +54 -0
- data/lib/openc3/topics/telemetry_topic.rb +36 -0
- data/lib/openc3/topics/timeline_topic.rb +45 -0
- data/lib/openc3/topics/topic.rb +53 -0
- data/lib/openc3/utilities/authentication.rb +141 -0
- data/lib/openc3/utilities/authorization.rb +51 -0
- data/lib/openc3/utilities/crc.rb +278 -0
- data/lib/openc3/utilities/csv.rb +153 -0
- data/lib/openc3/utilities/logger.rb +187 -0
- data/lib/openc3/utilities/message_log.rb +91 -0
- data/lib/openc3/utilities/metric.rb +141 -0
- data/lib/openc3/utilities/process_manager.rb +139 -0
- data/lib/openc3/utilities/quaternion.rb +257 -0
- data/lib/openc3/utilities/ruby_lex_utils.rb +568 -0
- data/lib/openc3/utilities/s3.rb +202 -0
- data/lib/openc3/utilities/s3_autoload.rb +9 -0
- data/lib/openc3/utilities/s3_file_cache.rb +274 -0
- data/lib/openc3/utilities/simulated_target.rb +117 -0
- data/lib/openc3/utilities/sleeper.rb +51 -0
- data/lib/openc3/utilities/store.rb +23 -0
- data/lib/openc3/utilities/store_autoload.rb +237 -0
- data/lib/openc3/utilities/zip.rb +21 -0
- data/lib/openc3/utilities.rb +35 -0
- data/lib/openc3/version.rb +14 -0
- data/lib/openc3/win32/excel.rb +132 -0
- data/lib/openc3/win32/win32.rb +402 -0
- data/lib/openc3/win32/win32_main.rb +333 -0
- data/lib/openc3.rb +49 -0
- data/tasks/gemfile_stats.rake +113 -0
- data/tasks/spec.rake +30 -0
- data/templates/plugin-template/README.md +15 -0
- data/templates/plugin-template/Rakefile +12 -0
- data/templates/plugin-template/plugin.gemspec +23 -0
- data/templates/plugin-template/plugin.txt +9 -0
- data/templates/plugin-template/targets/TARGET/cmd_tlm/cmd.txt +8 -0
- data/templates/plugin-template/targets/TARGET/cmd_tlm/tlm.txt +8 -0
- data/templates/plugin-template/targets/TARGET/lib/target.rb +10 -0
- data/templates/plugin-template/targets/TARGET/procedures/procedure.rb +3 -0
- data/templates/plugin-template/targets/TARGET/screens/status.txt +9 -0
- data/templates/plugin-template/targets/TARGET/target.txt +5 -0
- metadata +849 -0
|
@@ -0,0 +1,638 @@
|
|
|
1
|
+
# encoding: ascii-8bit
|
|
2
|
+
|
|
3
|
+
# Copyright 2022 Ball Aerospace & Technologies Corp.
|
|
4
|
+
# All Rights Reserved.
|
|
5
|
+
#
|
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
|
7
|
+
# under the terms of the GNU Affero General Public License
|
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
|
10
|
+
#
|
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU Affero General Public License for more details.
|
|
15
|
+
|
|
16
|
+
# Modified by OpenC3, Inc.
|
|
17
|
+
# All changes Copyright 2022, OpenC3, Inc.
|
|
18
|
+
# All Rights Reserved
|
|
19
|
+
|
|
20
|
+
require 'openc3/microservices/microservice'
|
|
21
|
+
require 'openc3/models/notification_model'
|
|
22
|
+
require 'openc3/models/trigger_model'
|
|
23
|
+
require 'openc3/topics/autonomic_topic'
|
|
24
|
+
require 'openc3/utilities/authentication'
|
|
25
|
+
|
|
26
|
+
require 'openc3/script'
|
|
27
|
+
|
|
28
|
+
module OpenC3
|
|
29
|
+
|
|
30
|
+
class TriggerLoopError < TriggerError; end
|
|
31
|
+
|
|
32
|
+
# Stored in the TriggerGroupShare this should be a thread safe
|
|
33
|
+
# hash that triggers will be added, updated, and removed from
|
|
34
|
+
class PacketBase
|
|
35
|
+
|
|
36
|
+
def initialize(scope:)
|
|
37
|
+
@scope = scope
|
|
38
|
+
@mutex = Mutex.new
|
|
39
|
+
@packets = Hash.new
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# ["#{@scope}__DECOM__{#{@target}}__#{@packet}"]
|
|
43
|
+
def packet(target:, packet:)
|
|
44
|
+
topic = "#{@scope}__DECOM__{#{target}}__#{packet}"
|
|
45
|
+
@mutex.synchronize do
|
|
46
|
+
return Marshal.load( Marshal.dump(@packets[topic]) )
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def get(topic:)
|
|
51
|
+
@mutex.synchronize do
|
|
52
|
+
return Marshal.load( Marshal.dump(@packets[topic]) )
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def add(topic:, packet:)
|
|
57
|
+
@mutex.synchronize do
|
|
58
|
+
@packets[topic] = packet
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def remove(topic:)
|
|
63
|
+
@mutex.synchronize do
|
|
64
|
+
@packets.delete(topic)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Stored in the TriggerGroupShare this should be a thread safe
|
|
70
|
+
# hash that triggers will be added, updated, and removed from.
|
|
71
|
+
class TriggerBase
|
|
72
|
+
|
|
73
|
+
attr_reader :autonomic_topic
|
|
74
|
+
|
|
75
|
+
def initialize(scope:)
|
|
76
|
+
@scope = scope
|
|
77
|
+
@autonomic_topic = "#{@scope}__openc3_autonomic".freeze
|
|
78
|
+
@triggers_mutex = Mutex.new
|
|
79
|
+
@triggers = Hash.new
|
|
80
|
+
@lookup_mutex = Mutex.new
|
|
81
|
+
@lookup = Hash.new
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Get triggers to evaluate based on the topic. IF the
|
|
85
|
+
# topic is the equal to the autonomic topic it will
|
|
86
|
+
# return only triggers with roots
|
|
87
|
+
def get_triggers(topic:)
|
|
88
|
+
if @autonomic_topic == topic
|
|
89
|
+
return triggers_with_roots()
|
|
90
|
+
else
|
|
91
|
+
return triggers_from(topic: topic)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# update trigger state after evaluated
|
|
96
|
+
# -1 (the value is considered an error used to disable the trigger)
|
|
97
|
+
# 0 (the value is considered as a false value)
|
|
98
|
+
# 1 (the value is considered as a true value)
|
|
99
|
+
def update_state(name:, value:)
|
|
100
|
+
@triggers_mutex.synchronize do
|
|
101
|
+
data = @triggers[name]
|
|
102
|
+
return unless data
|
|
103
|
+
trigger = TriggerModel.from_json(data, name: data['name'], scope: data['scope'])
|
|
104
|
+
if value == -1 && trigger.active
|
|
105
|
+
trigger.deactivate()
|
|
106
|
+
elsif value == 1 && trigger.state == false
|
|
107
|
+
trigger.enable()
|
|
108
|
+
elsif value == 0 && trigger.state == true
|
|
109
|
+
trigger.disable()
|
|
110
|
+
end
|
|
111
|
+
@triggers[name] = trigger.as_json(:allow_nan => true)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# returns a Hash of ALL active Trigger objects
|
|
116
|
+
def triggers
|
|
117
|
+
val = nil
|
|
118
|
+
@triggers_mutex.synchronize do
|
|
119
|
+
val = Marshal.load( Marshal.dump(@triggers) )
|
|
120
|
+
end
|
|
121
|
+
ret = Hash.new
|
|
122
|
+
val.each do | name, data |
|
|
123
|
+
trigger = TriggerModel.from_json(data, name: data['name'], scope: data['scope'])
|
|
124
|
+
ret[name] = trigger if trigger.active
|
|
125
|
+
end
|
|
126
|
+
return ret
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# returns an Array of active Trigger objects that have roots to other triggers
|
|
130
|
+
def triggers_with_roots
|
|
131
|
+
val = nil
|
|
132
|
+
@triggers_mutex.synchronize do
|
|
133
|
+
val = Marshal.load( Marshal.dump(@triggers) )
|
|
134
|
+
end
|
|
135
|
+
ret = []
|
|
136
|
+
val.each do | _name, data |
|
|
137
|
+
trigger = TriggerModel.from_json(data, name: data['name'], scope: data['scope'])
|
|
138
|
+
ret << trigger if trigger.active && ! trigger.roots.empty?
|
|
139
|
+
end
|
|
140
|
+
return ret
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# returns an Array of active Trigger objects that use a topic
|
|
144
|
+
def triggers_from(topic:)
|
|
145
|
+
val = nil
|
|
146
|
+
@lookup_mutex.synchronize do
|
|
147
|
+
val = Marshal.load( Marshal.dump(@lookup[topic]) )
|
|
148
|
+
end
|
|
149
|
+
return [] if val.nil?
|
|
150
|
+
ret = []
|
|
151
|
+
@triggers_mutex.synchronize do
|
|
152
|
+
val.each do | trigger_name, _v |
|
|
153
|
+
data = Marshal.load( Marshal.dump(@triggers[trigger_name]) )
|
|
154
|
+
trigger = TriggerModel.from_json(data, name: data['name'], scope: data['scope'])
|
|
155
|
+
ret << trigger if trigger.active
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
return ret
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# get all topics group is working with
|
|
162
|
+
def topics
|
|
163
|
+
@lookup_mutex.synchronize do
|
|
164
|
+
return Marshal.load( Marshal.dump(@lookup.keys()) )
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# database update of all triggers in the group
|
|
169
|
+
def update(triggers:)
|
|
170
|
+
@triggers_mutex.synchronize do
|
|
171
|
+
@triggers = Marshal.load( Marshal.dump(triggers) )
|
|
172
|
+
end
|
|
173
|
+
@lookup_mutex.synchronize do
|
|
174
|
+
@lookup = {@autonomic_topic => {}}
|
|
175
|
+
triggers.each do | _name, data |
|
|
176
|
+
trigger = TriggerModel.from_json(data, name: data['name'], scope: data['scope'])
|
|
177
|
+
trigger.generate_topics.each do | topic |
|
|
178
|
+
if @lookup[topic].nil?
|
|
179
|
+
@lookup[topic] = { trigger.name => 1 }
|
|
180
|
+
else
|
|
181
|
+
@lookup[topic][trigger.name] = 1
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# add a trigger from TriggerBase
|
|
189
|
+
def add(trigger:)
|
|
190
|
+
@triggers_mutex.synchronize do
|
|
191
|
+
@triggers[trigger['name']] = Marshal.load( Marshal.dump(trigger) )
|
|
192
|
+
end
|
|
193
|
+
t = TriggerModel.from_json(trigger, name: trigger['name'], scope: trigger['scope'])
|
|
194
|
+
@lookup_mutex.synchronize do
|
|
195
|
+
t.generate_topics.each do | topic |
|
|
196
|
+
if @lookup[topic].nil?
|
|
197
|
+
@lookup[topic] = { t.name => 1 }
|
|
198
|
+
else
|
|
199
|
+
@lookup[topic][t.name] = 1
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# remove a trigger from TriggerBase
|
|
206
|
+
def remove(trigger:)
|
|
207
|
+
@triggers_mutex.synchronize do
|
|
208
|
+
@triggers.delete(trigger['name'])
|
|
209
|
+
end
|
|
210
|
+
t = TriggerModel.from_json(trigger, name: trigger['name'], scope: trigger['scope'])
|
|
211
|
+
@lookup_mutex.synchronize do
|
|
212
|
+
t.generate_topics.each do | topic |
|
|
213
|
+
unless @lookup[topic].nil?
|
|
214
|
+
@lookup[topic].delete(t.name)
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Shared between the monitor thread and the manager thread to
|
|
222
|
+
# share the triggers. This should remain a thread
|
|
223
|
+
# safe implamentation.
|
|
224
|
+
class TriggerGroupShare
|
|
225
|
+
|
|
226
|
+
def self.get_group(name:)
|
|
227
|
+
return name.split('__')[2]
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
attr_reader :trigger_base, :packet_base
|
|
231
|
+
|
|
232
|
+
def initialize(scope:)
|
|
233
|
+
@scope = scope
|
|
234
|
+
@trigger_base = TriggerBase.new(scope: scope)
|
|
235
|
+
@packet_base = PacketBase.new(scope: scope)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# The TriggerGroupWorker is a very simple thread pool worker. Once
|
|
240
|
+
# the trigger manager has pushed a packet to the queue one of
|
|
241
|
+
# these workers will evaluate the triggers in the kit and
|
|
242
|
+
# evaluate triggers for that packet.
|
|
243
|
+
class TriggerGroupWorker
|
|
244
|
+
TRIGGER_METRIC_NAME = 'trigger_eval_duration_seconds'.freeze
|
|
245
|
+
|
|
246
|
+
TYPE = 'type'.freeze
|
|
247
|
+
ITEM_RAW = 'raw'.freeze
|
|
248
|
+
ITEM_TARGET = 'target'.freeze
|
|
249
|
+
ITEM_PACKET = 'packet'.freeze
|
|
250
|
+
ITEM_TYPE = 'item'.freeze
|
|
251
|
+
FLOAT_TYPE = 'float'.freeze
|
|
252
|
+
STRING_TYPE = 'string'.freeze
|
|
253
|
+
LIMIT_TYPE = 'limit'.freeze
|
|
254
|
+
TRIGGER_TYPE = 'trigger'.freeze
|
|
255
|
+
|
|
256
|
+
attr_reader :name, :scope, :target, :packet, :group
|
|
257
|
+
|
|
258
|
+
def initialize(name:, scope:, group:, queue:, share:, ident:)
|
|
259
|
+
@name = name
|
|
260
|
+
@scope = scope
|
|
261
|
+
@group = group
|
|
262
|
+
@queue = queue
|
|
263
|
+
@share = share
|
|
264
|
+
@ident = ident
|
|
265
|
+
@metric = Metric.new(microservice: @name, scope: @scope)
|
|
266
|
+
@metric_output_time = 0
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def run
|
|
270
|
+
Logger.info "TriggerGroupWorker-#{@ident} running"
|
|
271
|
+
loop do
|
|
272
|
+
topic = @queue.pop
|
|
273
|
+
break if topic.nil?
|
|
274
|
+
begin
|
|
275
|
+
evaluate_wrapper(topic: topic)
|
|
276
|
+
current_time = Time.now.to_i
|
|
277
|
+
if @metric_output_time < current_time
|
|
278
|
+
@metric.output
|
|
279
|
+
@metric_output_time = current_time + 120
|
|
280
|
+
end
|
|
281
|
+
rescue StandardError => e
|
|
282
|
+
Logger.error "TriggerGroupWorker-#{@ident} failed to evaluate data packet from topic: #{topic}\n#{e.formatted}"
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
Logger.info "TriggerGroupWorker-#{@ident} exiting"
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# time how long each packet takes to eval and produce a metric to public
|
|
289
|
+
def evaluate_wrapper(topic:)
|
|
290
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
291
|
+
evaluate_data_packet(topic: topic, triggers: @share.trigger_base.triggers)
|
|
292
|
+
diff = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start # seconds as a float
|
|
293
|
+
metric_labels = { 'trigger_group' => @group, 'thread' => "worker-#{@ident}" }
|
|
294
|
+
@metric.add_sample(name: TRIGGER_METRIC_NAME, value: diff, labels: metric_labels)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# Each packet will be evaluated to all triggers and use the result to send
|
|
298
|
+
# the results back to the topic to be used by the reaction microservice.
|
|
299
|
+
def evaluate_data_packet(topic:, triggers:)
|
|
300
|
+
visited = Hash.new
|
|
301
|
+
Logger.debug "TriggerGroupWorker-#{@ident} topic: #{topic}"
|
|
302
|
+
triggers_to_eval = @share.trigger_base.get_triggers(topic: topic)
|
|
303
|
+
Logger.debug "TriggerGroupWorker-#{@ident} triggers_to_eval: #{triggers_to_eval}"
|
|
304
|
+
triggers_to_eval.each do | trigger |
|
|
305
|
+
Logger.debug "TriggerGroupWorker-#{@ident} eval head: #{trigger}"
|
|
306
|
+
value = evaluate_trigger(
|
|
307
|
+
head: trigger,
|
|
308
|
+
trigger: trigger,
|
|
309
|
+
visited: visited,
|
|
310
|
+
triggers: triggers
|
|
311
|
+
)
|
|
312
|
+
Logger.debug "TriggerGroupWorker-#{@ident} trigger: #{trigger} value: #{value}"
|
|
313
|
+
# value MUST be -1, 0, or 1
|
|
314
|
+
@share.trigger_base.update_state(name: trigger.name, value: value)
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# extract the value outlined in the operand to get the packet item limit
|
|
319
|
+
# IF operand limit does not include _LOW or _HIGH this will match the
|
|
320
|
+
# COLOR and return COLOR_LOW || COLOR_HIGH
|
|
321
|
+
# operand item: GREEN_LOW == other operand limit: GREEN
|
|
322
|
+
def get_packet_limit(operand:, other:)
|
|
323
|
+
packet = @share.packet_base.packet(
|
|
324
|
+
target: operand[ITEM_TARGET],
|
|
325
|
+
packet: operand[ITEM_PACKET]
|
|
326
|
+
)
|
|
327
|
+
return nil if packet.nil?
|
|
328
|
+
limit = packet["#{operand[ITEM_TYPE]}__L"]
|
|
329
|
+
if limit.nil? == false && limit.include?('_')
|
|
330
|
+
return other[LIMIT_TYPE] if limit.include?(other[LIMIT_TYPE])
|
|
331
|
+
end
|
|
332
|
+
return limit
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# extract the value outlined in the operand to get the packet item value
|
|
336
|
+
# IF raw in operand it will pull the raw value over the converted
|
|
337
|
+
def get_packet_value(operand:)
|
|
338
|
+
packet = @share.packet_base.packet(
|
|
339
|
+
target: operand[ITEM_TARGET],
|
|
340
|
+
packet: operand[ITEM_PACKET]
|
|
341
|
+
)
|
|
342
|
+
return nil if packet.nil?
|
|
343
|
+
|
|
344
|
+
value_type = operand[ITEM_RAW] ? '' : '__C'
|
|
345
|
+
return packet["#{operand[ITEM_TYPE]}#{value_type}"]
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
# extract the value of the operand from the packet
|
|
349
|
+
def operand_value(operand:, other:, visited:)
|
|
350
|
+
if operand[TYPE] == ITEM_TYPE && other[TYPE] == LIMIT_TYPE
|
|
351
|
+
return get_packet_limit(operand: operand, other: other)
|
|
352
|
+
elsif operand[TYPE] == ITEM_TYPE
|
|
353
|
+
return get_packet_value(operand: operand)
|
|
354
|
+
elsif operand[TYPE] == TRIGGER_TYPE
|
|
355
|
+
return visited["#{operand[TRIGGER_TYPE]}__R"] == 1
|
|
356
|
+
else
|
|
357
|
+
return operand[operand[TYPE]]
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
# the base evaluate method used by evaluate_trigger
|
|
362
|
+
# -1 (the value is considered an error used to disable the trigger)
|
|
363
|
+
# 0 (the value is considered as a false value)
|
|
364
|
+
# 1 (the value is considered as a true value)
|
|
365
|
+
#
|
|
366
|
+
def evaluate(left:, operator:, right:)
|
|
367
|
+
Logger.debug "TriggerGroupWorker-#{@ident} evaluate: (#{left} #{operator} #{right})"
|
|
368
|
+
begin
|
|
369
|
+
case operator
|
|
370
|
+
when '>'
|
|
371
|
+
return left > right ? 1 : 0
|
|
372
|
+
when '<'
|
|
373
|
+
return left < right ? 1 : 0
|
|
374
|
+
when '>='
|
|
375
|
+
return left >= right ? 1 : 0
|
|
376
|
+
when '<='
|
|
377
|
+
return left <= right ? 1 : 0
|
|
378
|
+
when '!='
|
|
379
|
+
return left != right ? 1 : 0
|
|
380
|
+
when '=='
|
|
381
|
+
return left == right ? 1 : 0
|
|
382
|
+
when 'AND'
|
|
383
|
+
return left && right ? 1 : 0
|
|
384
|
+
when 'OR'
|
|
385
|
+
return left || right ? 1 : 0
|
|
386
|
+
end
|
|
387
|
+
rescue ArgumentError
|
|
388
|
+
Logger.error "invalid evaluate: (#{left} #{operator} #{right})"
|
|
389
|
+
return -1
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
# This could be confusing... So this is a recursive method for the
|
|
394
|
+
# TriggerGroupWorkers to call. It will use the trigger name and append a
|
|
395
|
+
# __P for path or __R for result. The Path is a Hash that contains
|
|
396
|
+
# a key for each node traveled to get results. When the result has
|
|
397
|
+
# been found it will be stored in the result key __R in the vistied Hash
|
|
398
|
+
# and eval_trigger will return a number.
|
|
399
|
+
# -1 (the value is considered an error used to disable the trigger)
|
|
400
|
+
# 0 (the value is considered as a false value)
|
|
401
|
+
# 1 (the value is considered as a true value)
|
|
402
|
+
#
|
|
403
|
+
# IF an operand is evaluated as nil it will log an error and return -1
|
|
404
|
+
# IF a loop is detected it will log an error and return -1
|
|
405
|
+
def evaluate_trigger(head:, trigger:, visited:, triggers:)
|
|
406
|
+
if visited["#{trigger.name}__R"]
|
|
407
|
+
return visited["#{trigger.name}__R"]
|
|
408
|
+
end
|
|
409
|
+
if visited["#{trigger.name}__P"].nil?
|
|
410
|
+
visited["#{trigger.name}__P"] = Hash.new
|
|
411
|
+
end
|
|
412
|
+
if visited["#{head.name}__P"][trigger.name]
|
|
413
|
+
# Not sure if this is posible as on create it validates that the dependents are already created
|
|
414
|
+
Logger.error "loop detected from #{head} -> #{trigger} path: #{visited["#{head.name}__P"]}"
|
|
415
|
+
return visited["#{trigger.name}__R"] = -1
|
|
416
|
+
end
|
|
417
|
+
trigger.roots.each do | root_trigger_name |
|
|
418
|
+
next if visited["#{root_trigger_name}__R"]
|
|
419
|
+
root_trigger = triggers[root_trigger_name]
|
|
420
|
+
if head.name == root_trigger.name
|
|
421
|
+
Logger.error "loop detected from #{head} -> #{root_trigger} path: #{visited["#{head.name}__P"]}"
|
|
422
|
+
return visited["#{trigger.name}__R"] = -1
|
|
423
|
+
end
|
|
424
|
+
result = evaluate_trigger(
|
|
425
|
+
head: head,
|
|
426
|
+
trigger: root_trigger,
|
|
427
|
+
visited: visited,
|
|
428
|
+
triggers: triggers
|
|
429
|
+
)
|
|
430
|
+
Logger.debug "TriggerGroupWorker-#{@ident} #{root_trigger.name} result: #{result}"
|
|
431
|
+
visited["#{root_trigger.name}__R"] = visited["#{head.name}__P"][root_trigger.name] = result
|
|
432
|
+
end
|
|
433
|
+
left = operand_value(operand: trigger.left, other: trigger.right, visited: visited)
|
|
434
|
+
right = operand_value(operand: trigger.right, other: trigger.left, visited: visited)
|
|
435
|
+
if left.nil? || right.nil?
|
|
436
|
+
return visited["#{trigger.name}__R"] = 0
|
|
437
|
+
end
|
|
438
|
+
result = evaluate(left: left, operator: trigger.operator, right: right)
|
|
439
|
+
return visited["#{trigger.name}__R"] = result
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
# The trigger manager starts a thread pool and subscribes
|
|
445
|
+
# to the telemtry decom topic add the packet to a queue.
|
|
446
|
+
# TriggerGroupManager adds the "packet" to the thread pool queue
|
|
447
|
+
# and the thread will evaluate the "trigger".
|
|
448
|
+
class TriggerGroupManager
|
|
449
|
+
|
|
450
|
+
attr_reader :name, :scope, :share, :group, :topics, :thread_pool
|
|
451
|
+
|
|
452
|
+
def initialize(name:, scope:, group:, share:)
|
|
453
|
+
@name = name
|
|
454
|
+
@scope = scope
|
|
455
|
+
@group = group
|
|
456
|
+
@share = share
|
|
457
|
+
@worker_count = 3
|
|
458
|
+
@queue = Queue.new
|
|
459
|
+
@read_topic = true
|
|
460
|
+
@topics = []
|
|
461
|
+
@thread_pool = nil
|
|
462
|
+
@cancel_thread = false
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def generate_thread_pool()
|
|
466
|
+
thread_pool = []
|
|
467
|
+
@worker_count.times do | i |
|
|
468
|
+
worker = TriggerGroupWorker.new(
|
|
469
|
+
name: @name,
|
|
470
|
+
scope: @scope,
|
|
471
|
+
group: @group,
|
|
472
|
+
queue: @queue,
|
|
473
|
+
share: @share,
|
|
474
|
+
ident: i,
|
|
475
|
+
)
|
|
476
|
+
thread_pool << Thread.new { worker.run }
|
|
477
|
+
end
|
|
478
|
+
return thread_pool
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
def run
|
|
482
|
+
Logger.info "TriggerGroupManager running"
|
|
483
|
+
@thread_pool = generate_thread_pool()
|
|
484
|
+
loop do
|
|
485
|
+
begin
|
|
486
|
+
update_topics()
|
|
487
|
+
rescue StandardError => e
|
|
488
|
+
Logger.error "TriggerGroupManager failed to update topics.\n#{e.formatted}"
|
|
489
|
+
end
|
|
490
|
+
break if @cancel_thread
|
|
491
|
+
|
|
492
|
+
block_for_updates()
|
|
493
|
+
break if @cancel_thread
|
|
494
|
+
end
|
|
495
|
+
Logger.info "TriggerGroupManager exiting"
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
def update_topics
|
|
499
|
+
past_topics = @topics
|
|
500
|
+
@topics = @share.trigger_base.topics()
|
|
501
|
+
Logger.debug "TriggerGroupManager past_topics: #{past_topics} topics: #{@topics}"
|
|
502
|
+
(past_topics - @topics).each do | removed_topic |
|
|
503
|
+
@share.packet_base.remove(topic: removed_topic)
|
|
504
|
+
end
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
def block_for_updates
|
|
508
|
+
@read_topic = true
|
|
509
|
+
while @read_topic
|
|
510
|
+
begin
|
|
511
|
+
Topic.read_topics(@topics) do |topic, _msg_id, msg_hash, _redis|
|
|
512
|
+
Logger.debug "TriggerGroupManager block_for_updates: #{topic} #{msg_hash.to_s}"
|
|
513
|
+
if topic != @share.trigger_base.autonomic_topic
|
|
514
|
+
packet = JSON.parse(msg_hash['json_data'], :allow_nan => true, :create_additions => true)
|
|
515
|
+
@share.packet_base.add(topic: topic, packet: packet)
|
|
516
|
+
end
|
|
517
|
+
@queue << "#{topic}"
|
|
518
|
+
end
|
|
519
|
+
rescue StandardError => e
|
|
520
|
+
Logger.error "TriggerGroupManager failed to read topics #{@topics}\n#{e.formatted}"
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
def refresh
|
|
526
|
+
@read_topic = false
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def shutdown
|
|
530
|
+
@read_topic = false
|
|
531
|
+
@cancel_thread = true
|
|
532
|
+
@worker_count.times do | i |
|
|
533
|
+
@queue << nil
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
# The trigger microservice starts a manager then gets the activities
|
|
539
|
+
# from the sorted set in redis and updates the schedule for the
|
|
540
|
+
# manager. Timeline will then wait for an update on the timeline
|
|
541
|
+
# stream this will trigger an update again to the schedule.
|
|
542
|
+
class TriggerGroupMicroservice < Microservice
|
|
543
|
+
TRIGGER_METRIC_NAME = 'update_triggers_duration_seconds'.freeze
|
|
544
|
+
|
|
545
|
+
attr_reader :name, :scope, :share, :group, :manager, :manager_thread
|
|
546
|
+
|
|
547
|
+
def initialize(*args)
|
|
548
|
+
super(*args)
|
|
549
|
+
@group = TriggerGroupShare.get_group(name: @name)
|
|
550
|
+
@share = TriggerGroupShare.new(scope: @scope)
|
|
551
|
+
@manager = TriggerGroupManager.new(name: @name, scope: @scope, group: @group, share: @share)
|
|
552
|
+
@manager_thread = nil
|
|
553
|
+
@read_topic = true
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
def run
|
|
557
|
+
Logger.info "TriggerGroupMicroservice running"
|
|
558
|
+
@manager_thread = Thread.new { @manager.run }
|
|
559
|
+
loop do
|
|
560
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
561
|
+
triggers = TriggerModel.all(scope: @scope, group: @group)
|
|
562
|
+
@share.trigger_base.update(triggers: triggers)
|
|
563
|
+
diff = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start # seconds as a float
|
|
564
|
+
metric_labels = { 'trigger_group' => @group, 'thread' => 'microservice' }
|
|
565
|
+
@metric.add_sample(name: TRIGGER_METRIC_NAME, value: diff, labels: metric_labels)
|
|
566
|
+
break if @cancel_thread
|
|
567
|
+
|
|
568
|
+
block_for_updates()
|
|
569
|
+
break if @cancel_thread
|
|
570
|
+
end
|
|
571
|
+
Logger.info "TriggerGroupMicroservice exiting"
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
def topic_lookup_functions
|
|
575
|
+
return {
|
|
576
|
+
'created' => :created_trigger_event,
|
|
577
|
+
'updated' => :created_trigger_event,
|
|
578
|
+
'deleted' => :deleted_trigger_event,
|
|
579
|
+
'enabled' => :created_trigger_event,
|
|
580
|
+
'disabled' => :created_trigger_event,
|
|
581
|
+
'activated' => :created_trigger_event,
|
|
582
|
+
'deactivated' => :created_trigger_event,
|
|
583
|
+
}
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
def block_for_updates
|
|
587
|
+
@read_topic = true
|
|
588
|
+
while @read_topic
|
|
589
|
+
begin
|
|
590
|
+
AutonomicTopic.read_topics(@topics) do |_topic, _msg_id, msg_hash, _redis|
|
|
591
|
+
Logger.debug "TriggerGroupMicroservice block_for_updates: #{msg_hash.to_s}"
|
|
592
|
+
if msg_hash['type'] == 'trigger'
|
|
593
|
+
data = JSON.parse(msg_hash['data'], :allow_nan => true, :create_additions => true)
|
|
594
|
+
public_send(topic_lookup_functions[msg_hash['kind']], data)
|
|
595
|
+
end
|
|
596
|
+
end
|
|
597
|
+
rescue StandardError => e
|
|
598
|
+
Logger.error "TriggerGroupMicroservice failed to read topics #{@topics}\n#{e.formatted}"
|
|
599
|
+
end
|
|
600
|
+
end
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
def no_op(data)
|
|
604
|
+
Logger.debug "TriggerGroupMicroservice web socket event: #{data}"
|
|
605
|
+
end
|
|
606
|
+
|
|
607
|
+
def refresh_event(data)
|
|
608
|
+
Logger.debug "TriggerGroupMicroservice web socket schedule refresh: #{data}"
|
|
609
|
+
@read_topic = false
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
# Add the trigger to the share.
|
|
613
|
+
def created_trigger_event(data)
|
|
614
|
+
Logger.debug "TriggerGroupMicroservice created_trigger_event #{data}"
|
|
615
|
+
if data['group'] == @group
|
|
616
|
+
@share.trigger_base.add(trigger: data)
|
|
617
|
+
@manager.refresh()
|
|
618
|
+
end
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
# Remove the trigger from the share.
|
|
622
|
+
def deleted_trigger_event(data)
|
|
623
|
+
Logger.debug "TriggerGroupMicroservice deleted_trigger_event #{data}"
|
|
624
|
+
if data['group'] == @group
|
|
625
|
+
@share.trigger_base.remove(trigger: data)
|
|
626
|
+
@manager.refresh()
|
|
627
|
+
end
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
def shutdown
|
|
631
|
+
@read_topic = false
|
|
632
|
+
@manager.shutdown()
|
|
633
|
+
super
|
|
634
|
+
end
|
|
635
|
+
end
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
OpenC3::TriggerGroupMicroservice.run if __FILE__ == $0
|