PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
routing_types.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2021-2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
18#pragma once
19
21
22#include <chrono>
23#include <functional>
24#include <optional>
25#include <string>
26#include <string_view>
27#include <vector>
28
29namespace kcenon::pacs::client {
30
31// =============================================================================
32// Routing Condition Field
33// =============================================================================
34
53
59[[nodiscard]] constexpr const char* to_string(routing_field field) noexcept {
60 switch (field) {
61 case routing_field::modality: return "modality";
62 case routing_field::station_ae: return "station_ae";
63 case routing_field::institution: return "institution";
64 case routing_field::department: return "department";
65 case routing_field::referring_physician: return "referring_physician";
66 case routing_field::study_description: return "study_description";
67 case routing_field::series_description: return "series_description";
68 case routing_field::body_part: return "body_part";
69 case routing_field::patient_id_pattern: return "patient_id_pattern";
70 case routing_field::sop_class_uid: return "sop_class_uid";
71 default: return "unknown";
72 }
73}
74
81 std::string_view str) noexcept {
82 if (str == "modality") return routing_field::modality;
83 if (str == "station_ae") return routing_field::station_ae;
84 if (str == "institution") return routing_field::institution;
85 if (str == "department") return routing_field::department;
86 if (str == "referring_physician") return routing_field::referring_physician;
87 if (str == "study_description") return routing_field::study_description;
88 if (str == "series_description") return routing_field::series_description;
89 if (str == "body_part") return routing_field::body_part;
90 if (str == "patient_id_pattern") return routing_field::patient_id_pattern;
91 if (str == "sop_class_uid") return routing_field::sop_class_uid;
93}
94
95// =============================================================================
96// Routing Condition
97// =============================================================================
98
107 std::string pattern;
108 bool case_sensitive{false};
109 bool negate{false};
110
114 routing_condition() = default;
115
123 routing_condition(routing_field field, std::string pat,
124 bool case_sens = false, bool neg = false)
125 : match_field(field)
126 , pattern(std::move(pat))
127 , case_sensitive(case_sens)
128 , negate(neg) {}
129};
130
131// =============================================================================
132// Routing Action
133// =============================================================================
134
143 std::chrono::minutes delay{0};
144 bool delete_after_send{false};
145 bool notify_on_failure{true};
146
150 routing_action() = default;
151
158 routing_action(std::string dest_node_id,
160 std::chrono::minutes del = std::chrono::minutes{0})
161 : destination_node_id(std::move(dest_node_id))
162 , priority(prio)
163 , delay(del) {}
164};
165
166// =============================================================================
167// Routing Rule
168// =============================================================================
169
177 // =========================================================================
178 // Identification
179 // =========================================================================
180
181 std::string rule_id;
182 std::string name;
183 std::string description;
184
185 // =========================================================================
186 // Rule State
187 // =========================================================================
188
189 bool enabled{true};
190 int priority{0};
191
192 // =========================================================================
193 // Matching Configuration
194 // =========================================================================
195
196 std::vector<routing_condition> conditions;
197 std::vector<routing_action> actions;
198
199 // =========================================================================
200 // Schedule (Optional)
201 // =========================================================================
202
203 std::optional<std::string> schedule_cron;
204 std::optional<std::chrono::system_clock::time_point> effective_from;
205 std::optional<std::chrono::system_clock::time_point> effective_until;
206
207 // =========================================================================
208 // Statistics
209 // =========================================================================
210
211 size_t triggered_count{0};
212 size_t success_count{0};
213 size_t failure_count{0};
214 std::chrono::system_clock::time_point last_triggered;
215 std::chrono::system_clock::time_point created_at;
216 std::chrono::system_clock::time_point updated_at;
217
218 // =========================================================================
219 // Database Fields
220 // =========================================================================
221
222 int64_t pk{0};
223
224 // =========================================================================
225 // Convenience Methods
226 // =========================================================================
227
232 [[nodiscard]] bool is_effective_now() const noexcept {
233 if (!enabled) return false;
234
235 auto now = std::chrono::system_clock::now();
236
237 if (effective_from.has_value() && now < effective_from.value()) {
238 return false;
239 }
240
241 if (effective_until.has_value() && now > effective_until.value()) {
242 return false;
243 }
244
245 return true;
246 }
247};
248
249// =============================================================================
250// Routing Event Callback
251// =============================================================================
252
260using routing_event_callback = std::function<void(
261 const std::string& rule_id,
262 const std::string& instance_uid,
263 const std::vector<routing_action>& triggered_actions)>;
264
265// =============================================================================
266// Routing Manager Configuration
267// =============================================================================
268
273 bool enabled{true};
274 size_t max_rules{100};
275 std::chrono::seconds evaluation_timeout{5};
276};
277
278// =============================================================================
279// Routing Statistics
280// =============================================================================
281
286 size_t total_evaluated{0};
287 size_t total_matched{0};
288 size_t total_forwarded{0};
289 size_t total_failed{0};
290};
291
292// =============================================================================
293// Test Result
294// =============================================================================
295
300 bool matched{false};
301 std::string matched_rule_id;
302 std::vector<routing_action> actions;
303};
304
305} // namespace kcenon::pacs::client
Job types and structures for asynchronous DICOM operations.
routing_field
DICOM field to match in routing conditions.
@ series_description
(0008,103E) Series Description
@ department
(0008,1040) Institutional Department Name
@ body_part
(0018,0015) Body Part Examined
@ study_description
(0008,1030) Study Description
@ modality
(0008,0060) Modality - CT, MR, US, etc.
@ sop_class_uid
(0008,0016) SOP Class UID
@ institution
(0008,0080) Institution Name
@ station_ae
(0008,1010) Station Name or calling AE
@ patient_id_pattern
(0010,0020) Patient ID (pattern matching)
@ referring_physician
(0008,0090) Referring Physician's Name
job_priority
Priority level for job execution.
Definition job_types.h:154
constexpr const char * to_string(job_type type) noexcept
Convert job_type to string representation.
Definition job_types.h:54
std::function< void( const std::string &rule_id, const std::string &instance_uid, const std::vector< routing_action > &triggered_actions)> routing_event_callback
Callback type for routing events.
routing_field routing_field_from_string(std::string_view str) noexcept
Parse routing_field from string.
Action to perform when a routing rule matches.
std::string destination_node_id
Target remote node ID.
std::chrono::minutes delay
Delay before forwarding.
bool notify_on_failure
Generate notification on failure.
job_priority priority
Job priority for forwarding.
routing_action(std::string dest_node_id, job_priority prio=job_priority::normal, std::chrono::minutes del=std::chrono::minutes{0})
Construct with destination.
bool delete_after_send
Delete local copy after successful send.
routing_action()=default
Default constructor.
A single condition for routing rule evaluation.
std::string pattern
Pattern to match (supports wildcards: *, ?)
routing_field match_field
The DICOM field to match.
routing_condition()=default
Default constructor.
bool negate
Invert the match result.
routing_condition(routing_field field, std::string pat, bool case_sens=false, bool neg=false)
Construct with field and pattern.
bool case_sensitive
Whether matching is case-sensitive.
Configuration for the routing manager.
std::chrono::seconds evaluation_timeout
Timeout for rule evaluation.
size_t max_rules
Maximum number of rules.
A complete routing rule with conditions and actions.
size_t success_count
Successful forwarding count.
std::string name
Human-readable name.
std::optional< std::string > schedule_cron
Cron expression for scheduling.
std::optional< std::chrono::system_clock::time_point > effective_until
std::optional< std::chrono::system_clock::time_point > effective_from
std::chrono::system_clock::time_point updated_at
std::string rule_id
Unique rule identifier.
bool enabled
Whether the rule is active.
std::chrono::system_clock::time_point created_at
std::vector< routing_condition > conditions
Conditions (AND logic)
std::chrono::system_clock::time_point last_triggered
std::string description
Detailed description.
size_t triggered_count
Number of times the rule was triggered.
int64_t pk
Primary key (0 if not persisted)
size_t failure_count
Failed forwarding count.
std::vector< routing_action > actions
Actions to execute on match.
bool is_effective_now() const noexcept
Check if the rule is currently effective based on schedule.
int priority
Evaluation priority (higher = first)
Statistics for routing operations.
size_t total_matched
Total instances that matched a rule.
size_t total_evaluated
Total instances evaluated.
size_t total_failed
Total failed forwards.
size_t total_forwarded
Total successful forwards.
Result of testing rules against a dataset (dry run)
std::string matched_rule_id
ID of the matched rule.
bool matched
Whether any rule matched.
std::vector< routing_action > actions
Actions that would execute.