retention.hpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. #pragma once
  2. #include <nlohmann/json.hpp>
  3. #include <optional>
  4. #include <string>
  5. namespace smartbotic::storage {
  6. // How long a workflow's data is kept: its own documents, the files it stores,
  7. // and its execution records, so a run's history and the files that history
  8. // points at go together rather than one outliving the other.
  9. //
  10. // Settings shape, on both a project and a workflow:
  11. //
  12. // "retention": { "ttlSeconds": 604800 }
  13. //
  14. // **Absent is not the same as zero.** Absent (or null) on a workflow means
  15. // inherit the project's; an explicit 0 means keep for ever, which is a choice
  16. // somebody made and must not be re-read as "unset". A plain
  17. // value("ttlSeconds", 0) collapses the two, so nothing reads it that way.
  18. inline constexpr const char* kRetentionKey = "retention";
  19. inline constexpr const char* kTtlSecondsKey = "ttlSeconds";
  20. inline std::optional<int64_t> declaredTtlSeconds(const nlohmann::json& settings) {
  21. if (!settings.is_object() || !settings.contains(kRetentionKey)) return std::nullopt;
  22. const auto& retention = settings[kRetentionKey];
  23. if (!retention.is_object() || !retention.contains(kTtlSecondsKey)) return std::nullopt;
  24. const auto& ttl = retention[kTtlSecondsKey];
  25. if (!ttl.is_number_integer()) return std::nullopt; // null, or a string somebody typed
  26. const auto seconds = ttl.get<int64_t>();
  27. return seconds < 0 ? std::nullopt : std::optional<int64_t>{seconds};
  28. }
  29. struct Retention {
  30. int64_t ttl_seconds = 0; // 0 = keep for ever
  31. bool inherited = false; // true when it came from the project
  32. [[nodiscard]] bool keepsForever() const { return ttl_seconds == 0; }
  33. [[nodiscard]] int64_t ttlMs() const { return ttl_seconds * 1000; }
  34. };
  35. // Nothing at all is a third answer, distinct from "keep for ever": an
  36. // installation from before retention existed has made no choice, and each
  37. // caller applies its own historical default rather than having one invented
  38. // here. Executions have always aged out after a week; documents never have.
  39. // Collapsing those into a single "0" would either start deleting documents
  40. // nobody agreed to lose or stop executions ageing out at all.
  41. inline std::optional<Retention> declaredRetention(const nlohmann::json& workflow_settings,
  42. const nlohmann::json& project_settings) {
  43. if (const auto own = declaredTtlSeconds(workflow_settings)) {
  44. return Retention{*own, false};
  45. }
  46. if (const auto from_project = declaredTtlSeconds(project_settings)) {
  47. return Retention{*from_project, true};
  48. }
  49. return std::nullopt;
  50. }
  51. } // namespace smartbotic::storage