PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
sync_repository.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
22#pragma once
23
25
26#include <kcenon/common/patterns/result.h>
27
28#include <memory>
29#include <optional>
30#include <string>
31#include <string_view>
32#include <vector>
33
34#ifdef PACS_WITH_DATABASE_SYSTEM
35
37
38namespace kcenon::pacs::storage {
39
41template <typename T>
43
45using VoidResult = kcenon::common::VoidResult;
46
79class sync_repository {
80public:
81 // =========================================================================
82 // Construction / Destruction
83 // =========================================================================
84
90 explicit sync_repository(std::shared_ptr<pacs_database_adapter> db);
91
96
97 // Non-copyable, movable
98 sync_repository(const sync_repository&) = delete;
99 auto operator=(const sync_repository&) -> sync_repository& = delete;
101 auto operator=(sync_repository&&) noexcept -> sync_repository&;
102
103 // =========================================================================
104 // Config Operations
105 // =========================================================================
106
116 [[nodiscard]] auto save_config(const client::sync_config& config) -> VoidResult;
117
124 [[nodiscard]] auto find_config(std::string_view config_id) const
125 -> std::optional<client::sync_config>;
126
132 [[nodiscard]] auto list_configs() const -> std::vector<client::sync_config>;
133
139 [[nodiscard]] auto list_enabled_configs() const -> std::vector<client::sync_config>;
140
147 [[nodiscard]] auto remove_config(std::string_view config_id) -> VoidResult;
148
157 [[nodiscard]] auto update_config_stats(
158 std::string_view config_id,
159 bool success,
160 size_t studies_synced) -> VoidResult;
161
162 // =========================================================================
163 // Conflict Operations
164 // =========================================================================
165
174 [[nodiscard]] auto save_conflict(const client::sync_conflict& conflict) -> VoidResult;
175
182 [[nodiscard]] auto find_conflict(std::string_view study_uid) const
183 -> std::optional<client::sync_conflict>;
184
191 [[nodiscard]] auto list_conflicts(std::string_view config_id) const
192 -> std::vector<client::sync_conflict>;
193
199 [[nodiscard]] auto list_unresolved_conflicts() const
200 -> std::vector<client::sync_conflict>;
201
209 [[nodiscard]] auto resolve_conflict(
210 std::string_view study_uid,
211 client::conflict_resolution resolution) -> VoidResult;
212
219 [[nodiscard]] auto cleanup_old_conflicts(std::chrono::hours max_age)
220 -> Result<size_t>;
221
222 // =========================================================================
223 // History Operations
224 // =========================================================================
225
232 [[nodiscard]] auto save_history(const client::sync_history& history) -> VoidResult;
233
241 [[nodiscard]] auto list_history(std::string_view config_id, size_t limit = 100) const
242 -> std::vector<client::sync_history>;
243
250 [[nodiscard]] auto get_last_history(std::string_view config_id) const
251 -> std::optional<client::sync_history>;
252
259 [[nodiscard]] auto cleanup_old_history(std::chrono::hours max_age)
260 -> Result<size_t>;
261
262 // =========================================================================
263 // Statistics
264 // =========================================================================
265
271 [[nodiscard]] auto count_configs() const -> size_t;
272
278 [[nodiscard]] auto count_unresolved_conflicts() const -> size_t;
279
285 [[nodiscard]] auto count_syncs_today() const -> size_t;
286
287 // =========================================================================
288 // Database Information
289 // =========================================================================
290
296 [[nodiscard]] auto is_valid() const noexcept -> bool;
297
298private:
299 // =========================================================================
300 // Private Implementation
301 // =========================================================================
302
306 [[nodiscard]] auto map_row_to_config(const database_row& row) const
307 -> client::sync_config;
308
312 [[nodiscard]] auto map_row_to_conflict(const database_row& row) const
313 -> client::sync_conflict;
314
318 [[nodiscard]] auto map_row_to_history(const database_row& row) const
319 -> client::sync_history;
320
324 [[nodiscard]] static auto serialize_vector(
325 const std::vector<std::string>& vec) -> std::string;
326
330 [[nodiscard]] static auto deserialize_vector(
331 std::string_view json) -> std::vector<std::string>;
332
336 [[nodiscard]] auto parse_timestamp(const std::string& str) const
337 -> std::chrono::system_clock::time_point;
338
342 [[nodiscard]] auto format_timestamp(
343 std::chrono::system_clock::time_point tp) const -> std::string;
344
346 std::shared_ptr<pacs_database_adapter> db_;
347};
348
349} // namespace kcenon::pacs::storage
350
351#else // !PACS_WITH_DATABASE_SYSTEM
352
353// =============================================================================
354// Legacy SQLite Interface
355// =============================================================================
356
357struct sqlite3;
358
359namespace kcenon::pacs::storage {
360
362template <typename T>
364
366using VoidResult = kcenon::common::VoidResult;
367
376public:
377 explicit sync_repository(sqlite3* db);
379
381 auto operator=(const sync_repository&) -> sync_repository& = delete;
383 auto operator=(sync_repository&&) noexcept -> sync_repository&;
384
385 // Config Operations
386 [[nodiscard]] auto save_config(const client::sync_config& config) -> VoidResult;
387 [[nodiscard]] auto find_config(std::string_view config_id) const
388 -> std::optional<client::sync_config>;
389 [[nodiscard]] auto list_configs() const -> std::vector<client::sync_config>;
390 [[nodiscard]] auto list_enabled_configs() const -> std::vector<client::sync_config>;
391 [[nodiscard]] auto remove_config(std::string_view config_id) -> VoidResult;
392 [[nodiscard]] auto update_config_stats(
393 std::string_view config_id, bool success, size_t studies_synced) -> VoidResult;
394
395 // Conflict Operations
396 [[nodiscard]] auto save_conflict(const client::sync_conflict& conflict) -> VoidResult;
397 [[nodiscard]] auto find_conflict(std::string_view study_uid) const
398 -> std::optional<client::sync_conflict>;
399 [[nodiscard]] auto list_conflicts(std::string_view config_id) const
400 -> std::vector<client::sync_conflict>;
401 [[nodiscard]] auto list_unresolved_conflicts() const
402 -> std::vector<client::sync_conflict>;
403 [[nodiscard]] auto resolve_conflict(
404 std::string_view study_uid, client::conflict_resolution resolution) -> VoidResult;
405 [[nodiscard]] auto cleanup_old_conflicts(std::chrono::hours max_age)
406 -> Result<size_t>;
407
408 // History Operations
409 [[nodiscard]] auto save_history(const client::sync_history& history) -> VoidResult;
410 [[nodiscard]] auto list_history(std::string_view config_id, size_t limit = 100) const
411 -> std::vector<client::sync_history>;
412 [[nodiscard]] auto get_last_history(std::string_view config_id) const
413 -> std::optional<client::sync_history>;
414 [[nodiscard]] auto cleanup_old_history(std::chrono::hours max_age)
415 -> Result<size_t>;
416
417 // Statistics
418 [[nodiscard]] auto count_configs() const -> size_t;
419 [[nodiscard]] auto count_unresolved_conflicts() const -> size_t;
420 [[nodiscard]] auto count_syncs_today() const -> size_t;
421
422 // Database Information
423 [[nodiscard]] auto is_valid() const noexcept -> bool;
424
425private:
426 [[nodiscard]] auto parse_config_row(void* stmt) const -> client::sync_config;
427 [[nodiscard]] auto parse_conflict_row(void* stmt) const -> client::sync_conflict;
428 [[nodiscard]] auto parse_history_row(void* stmt) const -> client::sync_history;
429 [[nodiscard]] static auto serialize_vector(
430 const std::vector<std::string>& vec) -> std::string;
431 [[nodiscard]] static auto deserialize_vector(
432 std::string_view json) -> std::vector<std::string>;
433
434 sqlite3* db_{nullptr};
435};
436
437} // namespace kcenon::pacs::storage
438
439#endif // PACS_WITH_DATABASE_SYSTEM
Repository for sync persistence (legacy SQLite interface)
auto find_config(std::string_view config_id) const -> std::optional< client::sync_config >
auto list_unresolved_conflicts() const -> std::vector< client::sync_conflict >
auto save_config(const client::sync_config &config) -> VoidResult
auto remove_config(std::string_view config_id) -> VoidResult
sync_repository(sync_repository &&) noexcept
auto count_unresolved_conflicts() const -> size_t
static auto serialize_vector(const std::vector< std::string > &vec) -> std::string
auto get_last_history(std::string_view config_id) const -> std::optional< client::sync_history >
auto save_history(const client::sync_history &history) -> VoidResult
auto list_enabled_configs() const -> std::vector< client::sync_config >
auto parse_config_row(void *stmt) const -> client::sync_config
sync_repository(const sync_repository &)=delete
auto find_conflict(std::string_view study_uid) const -> std::optional< client::sync_conflict >
auto resolve_conflict(std::string_view study_uid, client::conflict_resolution resolution) -> VoidResult
auto list_configs() const -> std::vector< client::sync_config >
auto cleanup_old_history(std::chrono::hours max_age) -> Result< size_t >
auto parse_conflict_row(void *stmt) const -> client::sync_conflict
static auto deserialize_vector(std::string_view json) -> std::vector< std::string >
auto is_valid() const noexcept -> bool
auto update_config_stats(std::string_view config_id, bool success, size_t studies_synced) -> VoidResult
auto operator=(const sync_repository &) -> sync_repository &=delete
auto list_conflicts(std::string_view config_id) const -> std::vector< client::sync_conflict >
auto parse_history_row(void *stmt) const -> client::sync_history
auto list_history(std::string_view config_id, size_t limit=100) const -> std::vector< client::sync_history >
auto save_conflict(const client::sync_conflict &conflict) -> VoidResult
auto cleanup_old_conflicts(std::chrono::hours max_age) -> Result< size_t >
kcenon::common::Result< T > Result
Result type alias for operations returning a value.
Unified database adapter for PACS system.
Types and structures for bidirectional DICOM synchronization.