PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
job_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
20#include <chrono>
21#include <cstddef>
22#include <cstdint>
23#include <functional>
24#include <optional>
25#include <string>
26#include <string_view>
27#include <unordered_map>
28#include <vector>
29
30namespace kcenon::pacs::client {
31
32// =============================================================================
33// Job Type
34// =============================================================================
35
39enum class job_type {
40 query,
41 retrieve,
42 store,
43 export_,
44 import_,
45 prefetch,
46 sync
47};
48
54[[nodiscard]] constexpr const char* to_string(job_type type) noexcept {
55 switch (type) {
56 case job_type::query: return "query";
57 case job_type::retrieve: return "retrieve";
58 case job_type::store: return "store";
59 case job_type::export_: return "export";
60 case job_type::import_: return "import";
61 case job_type::prefetch: return "prefetch";
62 case job_type::sync: return "sync";
63 default: return "unknown";
64 }
65}
66
72[[nodiscard]] inline job_type job_type_from_string(std::string_view str) noexcept {
73 if (str == "query") return job_type::query;
74 if (str == "retrieve") return job_type::retrieve;
75 if (str == "store") return job_type::store;
76 if (str == "export") return job_type::export_;
77 if (str == "import") return job_type::import_;
78 if (str == "prefetch") return job_type::prefetch;
79 if (str == "sync") return job_type::sync;
80 return job_type::query;
81}
82
83// =============================================================================
84// Job Status
85// =============================================================================
86
90enum class job_status {
91 pending,
92 queued,
93 running,
94 completed,
95 failed,
96 cancelled,
97 paused
98};
99
105[[nodiscard]] constexpr const char* to_string(job_status status) noexcept {
106 switch (status) {
107 case job_status::pending: return "pending";
108 case job_status::queued: return "queued";
109 case job_status::running: return "running";
110 case job_status::completed: return "completed";
111 case job_status::failed: return "failed";
112 case job_status::cancelled: return "cancelled";
113 case job_status::paused: return "paused";
114 default: return "unknown";
115 }
116}
117
123[[nodiscard]] inline job_status job_status_from_string(std::string_view str) noexcept {
124 if (str == "pending") return job_status::pending;
125 if (str == "queued") return job_status::queued;
126 if (str == "running") return job_status::running;
127 if (str == "completed") return job_status::completed;
128 if (str == "failed") return job_status::failed;
129 if (str == "cancelled") return job_status::cancelled;
130 if (str == "paused") return job_status::paused;
131 return job_status::pending;
132}
133
139[[nodiscard]] constexpr bool is_terminal_status(job_status status) noexcept {
140 return status == job_status::completed ||
141 status == job_status::failed ||
142 status == job_status::cancelled;
143}
144
145// =============================================================================
146// Job Priority
147// =============================================================================
148
154enum class job_priority {
155 low = 0,
156 normal = 1,
157 high = 2,
158 urgent = 3
159};
160
166[[nodiscard]] constexpr const char* to_string(job_priority priority) noexcept {
167 switch (priority) {
168 case job_priority::low: return "low";
169 case job_priority::normal: return "normal";
170 case job_priority::high: return "high";
171 case job_priority::urgent: return "urgent";
172 default: return "unknown";
173 }
174}
175
181[[nodiscard]] inline job_priority job_priority_from_string(std::string_view str) noexcept {
182 if (str == "low") return job_priority::low;
183 if (str == "normal") return job_priority::normal;
184 if (str == "high") return job_priority::high;
185 if (str == "urgent") return job_priority::urgent;
187}
188
194[[nodiscard]] inline job_priority job_priority_from_int(int value) noexcept {
195 if (value <= 0) return job_priority::low;
196 if (value == 1) return job_priority::normal;
197 if (value == 2) return job_priority::high;
198 if (value >= 3) return job_priority::urgent;
200}
201
202// =============================================================================
203// Job Progress
204// =============================================================================
205
212 size_t total_items{0};
213 size_t completed_items{0};
214 size_t failed_items{0};
215 size_t skipped_items{0};
217
218 float percent_complete{0.0f};
219
220 std::string current_item;
222
223 std::chrono::milliseconds elapsed{0};
224 std::chrono::milliseconds estimated_remaining{0};
225
229 void calculate_percent() noexcept {
230 if (total_items > 0) {
232 / static_cast<float>(total_items) * 100.0f;
233 }
234 }
235
239 [[nodiscard]] bool is_complete() const noexcept {
240 return total_items > 0 &&
242 }
243};
244
245// =============================================================================
246// Job Record
247// =============================================================================
248
256 // =========================================================================
257 // Identification
258 // =========================================================================
259
260 std::string job_id;
264
265 // =========================================================================
266 // Source/Destination
267 // =========================================================================
268
269 std::string source_node_id;
271
272 // =========================================================================
273 // Scope (what to process)
274 // =========================================================================
275
276 std::optional<std::string> patient_id;
277 std::optional<std::string> study_uid;
278 std::optional<std::string> series_uid;
279 std::optional<std::string> sop_instance_uid;
280 std::vector<std::string> instance_uids;
281
282 // =========================================================================
283 // Progress
284 // =========================================================================
285
287
288 // =========================================================================
289 // Timing
290 // =========================================================================
291
292 std::chrono::system_clock::time_point created_at;
293 std::optional<std::chrono::system_clock::time_point> queued_at;
294 std::optional<std::chrono::system_clock::time_point> started_at;
295 std::optional<std::chrono::system_clock::time_point> completed_at;
296
297 // =========================================================================
298 // Error Handling
299 // =========================================================================
300
301 std::string error_message;
302 std::string error_details;
303 int retry_count{0};
304 int max_retries{3};
305
306 // =========================================================================
307 // Metadata
308 // =========================================================================
309
310 std::string created_by;
311 std::unordered_map<std::string, std::string> metadata;
312
313 // =========================================================================
314 // Database Fields
315 // =========================================================================
316
317 int64_t pk{0};
318
319 // =========================================================================
320 // Convenience Methods
321 // =========================================================================
322
326 [[nodiscard]] bool is_finished() const noexcept {
328 }
329
333 [[nodiscard]] bool can_start() const noexcept {
334 return status == job_status::pending ||
337 }
338
342 [[nodiscard]] bool can_cancel() const noexcept {
343 return !is_terminal_status(status);
344 }
345
349 [[nodiscard]] bool can_pause() const noexcept {
350 return status == job_status::running ||
352 }
353
357 [[nodiscard]] bool can_retry() const noexcept {
359 }
360
365 [[nodiscard]] std::chrono::milliseconds duration() const noexcept {
366 if (!started_at.has_value()) {
367 return std::chrono::milliseconds{0};
368 }
369 auto end_time = completed_at.value_or(std::chrono::system_clock::now());
370 return std::chrono::duration_cast<std::chrono::milliseconds>(
371 end_time - started_at.value());
372 }
373};
374
375// =============================================================================
376// Callbacks
377// =============================================================================
378
385using job_progress_callback = std::function<void(
386 const std::string& job_id,
387 const job_progress& progress)>;
388
395using job_completion_callback = std::function<void(
396 const std::string& job_id,
397 const job_record& record)>;
398
399// =============================================================================
400// Job Manager Configuration
401// =============================================================================
402
407 size_t worker_count{4};
408 size_t max_queue_size{1000};
409 std::chrono::seconds job_timeout{3600};
410 bool persist_jobs{true};
411 bool auto_retry_failed{true};
412 std::chrono::seconds retry_delay{60};
413 std::string local_ae_title{"PACS_CLIENT"};
414};
415
416} // namespace kcenon::pacs::client
std::function< void( const std::string &job_id, const job_progress &progress)> job_progress_callback
Callback for job progress updates.
Definition job_types.h:385
std::function< void( const std::string &job_id, const job_record &record)> job_completion_callback
Callback for job completion.
Definition job_types.h:395
constexpr bool is_terminal_status(job_status status) noexcept
Check if job status is a terminal state.
Definition job_types.h:139
job_priority job_priority_from_int(int value) noexcept
Parse job_priority from integer.
Definition job_types.h:194
job_type job_type_from_string(std::string_view str) noexcept
Parse job_type from string.
Definition job_types.h:72
job_type
Type of job operation.
Definition job_types.h:39
@ export_
Export to external system.
@ prefetch
Prefetch prior studies.
@ store
C-STORE operation.
@ retrieve
C-MOVE/C-GET operation.
@ import_
Import from external source.
job_status job_status_from_string(std::string_view str) noexcept
Parse job_status from string.
Definition job_types.h:123
job_priority
Priority level for job execution.
Definition job_types.h:154
@ low
Background operations.
@ high
User-requested operations.
@ urgent
Critical operations.
constexpr const char * to_string(job_type type) noexcept
Convert job_type to string representation.
Definition job_types.h:54
job_status
Current status of a job.
Definition job_types.h:90
@ failed
Job failed with error.
@ cancelled
Job was cancelled by user.
@ running
Job is currently executing.
@ pending
Job created but not yet queued.
@ queued
Job is in the execution queue.
@ completed
Job completed successfully.
job_priority job_priority_from_string(std::string_view str) noexcept
Parse job_priority from string.
Definition job_types.h:181
Configuration for the job manager.
Definition job_types.h:406
std::chrono::seconds job_timeout
Job timeout (1 hour default)
Definition job_types.h:409
size_t max_queue_size
Maximum jobs in queue.
Definition job_types.h:408
bool auto_retry_failed
Auto-retry failed jobs.
Definition job_types.h:411
bool persist_jobs
Persist jobs to database.
Definition job_types.h:410
size_t worker_count
Number of worker threads.
Definition job_types.h:407
std::chrono::seconds retry_delay
Delay between retries.
Definition job_types.h:412
std::string local_ae_title
Local AE title for operations.
Definition job_types.h:413
Progress tracking for a job.
Definition job_types.h:211
std::chrono::milliseconds elapsed
Time elapsed since start.
Definition job_types.h:223
size_t failed_items
Failed items.
Definition job_types.h:214
std::string current_item
Current SOP Instance UID being processed.
Definition job_types.h:220
size_t skipped_items
Skipped items.
Definition job_types.h:215
std::string current_item_description
Human-readable description.
Definition job_types.h:221
bool is_complete() const noexcept
Check if all items have been processed.
Definition job_types.h:239
size_t bytes_transferred
Total bytes transferred.
Definition job_types.h:216
size_t completed_items
Successfully completed items.
Definition job_types.h:213
size_t total_items
Total number of items to process.
Definition job_types.h:212
float percent_complete
Completion percentage (0-100)
Definition job_types.h:218
void calculate_percent() noexcept
Calculate completion percentage from item counts.
Definition job_types.h:229
std::chrono::milliseconds estimated_remaining
Estimated time remaining.
Definition job_types.h:224
Complete job record with all metadata.
Definition job_types.h:255
std::optional< std::chrono::system_clock::time_point > completed_at
Completion time.
Definition job_types.h:295
job_priority priority
Execution priority.
Definition job_types.h:263
bool can_start() const noexcept
Check if job can be started.
Definition job_types.h:333
std::string job_id
Unique job identifier (UUID)
Definition job_types.h:260
std::chrono::system_clock::time_point created_at
Job creation time.
Definition job_types.h:292
bool can_cancel() const noexcept
Check if job can be cancelled.
Definition job_types.h:342
std::chrono::milliseconds duration() const noexcept
Get job duration.
Definition job_types.h:365
std::optional< std::string > study_uid
Study Instance UID.
Definition job_types.h:277
bool can_retry() const noexcept
Check if job can be retried.
Definition job_types.h:357
int retry_count
Number of retry attempts.
Definition job_types.h:303
std::optional< std::chrono::system_clock::time_point > queued_at
Time added to queue.
Definition job_types.h:293
std::optional< std::string > sop_instance_uid
Single SOP Instance UID.
Definition job_types.h:279
bool can_pause() const noexcept
Check if job can be paused.
Definition job_types.h:349
std::unordered_map< std::string, std::string > metadata
Custom key-value pairs.
Definition job_types.h:311
int max_retries
Maximum retry attempts.
Definition job_types.h:304
std::string created_by
User ID who created the job.
Definition job_types.h:310
job_type type
Type of operation.
Definition job_types.h:261
job_progress progress
Current progress.
Definition job_types.h:286
job_status status
Current status.
Definition job_types.h:262
std::optional< std::string > patient_id
Patient ID filter.
Definition job_types.h:276
std::optional< std::string > series_uid
Series Instance UID.
Definition job_types.h:278
bool is_finished() const noexcept
Check if job is in a terminal state.
Definition job_types.h:326
std::string destination_node_id
Destination remote node ID.
Definition job_types.h:270
std::optional< std::chrono::system_clock::time_point > started_at
Execution start time.
Definition job_types.h:294
std::string error_message
Error message if failed.
Definition job_types.h:301
std::string source_node_id
Source remote node ID.
Definition job_types.h:269
std::string error_details
Detailed error information.
Definition job_types.h:302
std::vector< std::string > instance_uids
Batch operation UIDs.
Definition job_types.h:280
int64_t pk
Primary key (0 if not persisted)
Definition job_types.h:317