AsyncStorage.swift 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import Foundation
  2. import Dispatch
  3. /// Manipulate storage in a "all async" manner.
  4. /// The completion closure will be called when operation completes.
  5. public class AsyncStorage<T> {
  6. public let innerStorage: HybridStorage<T>
  7. public let serialQueue: DispatchQueue
  8. public init(storage: HybridStorage<T>, serialQueue: DispatchQueue) {
  9. self.innerStorage = storage
  10. self.serialQueue = serialQueue
  11. }
  12. }
  13. extension AsyncStorage {
  14. public func entry(forKey key: String, completion: @escaping (Result<Entry<T>>) -> Void) {
  15. serialQueue.async { [weak self] in
  16. guard let `self` = self else {
  17. completion(Result.error(StorageError.deallocated))
  18. return
  19. }
  20. do {
  21. let anEntry = try self.innerStorage.entry(forKey: key)
  22. completion(Result.value(anEntry))
  23. } catch {
  24. completion(Result.error(error))
  25. }
  26. }
  27. }
  28. public func removeObject(forKey key: String, completion: @escaping (Result<()>) -> Void) {
  29. serialQueue.async { [weak self] in
  30. guard let `self` = self else {
  31. completion(Result.error(StorageError.deallocated))
  32. return
  33. }
  34. do {
  35. try self.innerStorage.removeObject(forKey: key)
  36. completion(Result.value(()))
  37. } catch {
  38. completion(Result.error(error))
  39. }
  40. }
  41. }
  42. public func setObject(
  43. _ object: T,
  44. forKey key: String,
  45. expiry: Expiry? = nil,
  46. completion: @escaping (Result<()>) -> Void) {
  47. serialQueue.async { [weak self] in
  48. guard let `self` = self else {
  49. completion(Result.error(StorageError.deallocated))
  50. return
  51. }
  52. do {
  53. try self.innerStorage.setObject(object, forKey: key, expiry: expiry)
  54. completion(Result.value(()))
  55. } catch {
  56. completion(Result.error(error))
  57. }
  58. }
  59. }
  60. public func removeAll(completion: @escaping (Result<()>) -> Void) {
  61. serialQueue.async { [weak self] in
  62. guard let `self` = self else {
  63. completion(Result.error(StorageError.deallocated))
  64. return
  65. }
  66. do {
  67. try self.innerStorage.removeAll()
  68. completion(Result.value(()))
  69. } catch {
  70. completion(Result.error(error))
  71. }
  72. }
  73. }
  74. public func removeExpiredObjects(completion: @escaping (Result<()>) -> Void) {
  75. serialQueue.async { [weak self] in
  76. guard let `self` = self else {
  77. completion(Result.error(StorageError.deallocated))
  78. return
  79. }
  80. do {
  81. try self.innerStorage.removeExpiredObjects()
  82. completion(Result.value(()))
  83. } catch {
  84. completion(Result.error(error))
  85. }
  86. }
  87. }
  88. public func object(forKey key: String, completion: @escaping (Result<T>) -> Void) {
  89. entry(forKey: key, completion: { (result: Result<Entry<T>>) in
  90. completion(result.map({ entry in
  91. return entry.object
  92. }))
  93. })
  94. }
  95. public func existsObject(
  96. forKey key: String,
  97. completion: @escaping (Result<Bool>) -> Void) {
  98. object(forKey: key, completion: { (result: Result<T>) in
  99. completion(result.map({ _ in
  100. return true
  101. }))
  102. })
  103. }
  104. }
  105. public extension AsyncStorage {
  106. func transform<U>(transformer: Transformer<U>) -> AsyncStorage<U> {
  107. let storage = AsyncStorage<U>(
  108. storage: innerStorage.transform(transformer: transformer),
  109. serialQueue: serialQueue
  110. )
  111. return storage
  112. }
  113. }