AnnouncementsStorage.swift 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import Foundation
  2. import SwiftDate
  3. import Swinject
  4. protocol AnnouncementsStorage {
  5. func storeAnnouncements(_ announcements: [Announcement], enacted: Bool)
  6. func syncDate() -> Date
  7. func recent() -> Announcement?
  8. func validate() -> [Announcement]
  9. }
  10. final class BaseAnnouncementsStorage: AnnouncementsStorage, Injectable {
  11. enum Config {
  12. static let recentInterval = 10.minutes.timeInterval
  13. }
  14. private let processQueue = DispatchQueue(label: "BaseAnnouncementsStorage.processQueue")
  15. @Injected() private var storage: FileStorage!
  16. init(resolver: Resolver) {
  17. injectServices(resolver)
  18. }
  19. func storeAnnouncements(_ announcements: [Announcement], enacted: Bool) {
  20. processQueue.sync {
  21. let file = enacted ? OpenAPS.FreeAPS.announcementsEnacted : OpenAPS.FreeAPS.announcements
  22. self.storage.transaction { storage in
  23. storage.append(announcements, to: file, uniqBy: \.createdAt)
  24. let uniqEvents = storage.retrieve(file, as: [Announcement].self)?
  25. .filter { $0.createdAt.addingTimeInterval(1.days.timeInterval) > Date() }
  26. .sorted { $0.createdAt > $1.createdAt } ?? []
  27. storage.save(Array(uniqEvents), as: file)
  28. }
  29. }
  30. }
  31. func syncDate() -> Date {
  32. guard let events = storage.retrieve(OpenAPS.FreeAPS.announcementsEnacted, as: [Announcement].self),
  33. let recentEnacted = events.filter({ $0.enteredBy == Announcement.remote }).first
  34. else {
  35. return Date().addingTimeInterval(-Config.recentInterval)
  36. }
  37. return recentEnacted.createdAt.addingTimeInterval(Config.recentInterval)
  38. }
  39. func recent() -> Announcement? {
  40. guard let events = storage.retrieve(OpenAPS.FreeAPS.announcements, as: [Announcement].self)
  41. else {
  42. return nil
  43. }
  44. guard let recent = events
  45. .filter({
  46. $0.enteredBy == Announcement.remote && $0.createdAt.addingTimeInterval(Config.recentInterval) > Date()
  47. })
  48. .first
  49. else {
  50. return nil
  51. }
  52. guard let enactedEvents = storage.retrieve(OpenAPS.FreeAPS.announcementsEnacted, as: [Announcement].self)
  53. else {
  54. return recent
  55. }
  56. guard enactedEvents.first(where: { $0.createdAt == recent.createdAt }) == nil
  57. else {
  58. return nil
  59. }
  60. return recent
  61. }
  62. func validate() -> [Announcement] {
  63. guard let enactedEvents = storage.retrieve(OpenAPS.FreeAPS.announcementsEnacted, as: [Announcement].self)?.reversed()
  64. else {
  65. return []
  66. }
  67. let validate = enactedEvents
  68. .filter({ $0.enteredBy == Announcement.remote })
  69. return validate
  70. }
  71. }