feature/flat_map_async_operation_result_type_codable_storage #8

Merged
ivan.smolin merged 5 commits from feature/flat_map_async_operation_result_type_codable_storage into master 2023-06-15 13:30:23 +03:00
Member

SingleValueExpirationStorage<SingleValueStorage>

Класс позволяющий добавить дополнительную функциональность очистки значения по конкретному ключу
если истёк срок действия объекта (например refresh token'а)

struct Token: Codable, Equatable {
    var value: String
    var expiration: Date

    init(value: String, expiration: Date) {
        self.value = value
        self.expiration = expiration
    }
}

extension StorageKey {
    static var accessToken: StorageKey<Token> {
        .init(rawValue: "accessToken")
    }
}

let accessTokenStorage = DefaultSingleValueCodableStorage(storage: keychain,
                                                           storageKey: .accessToken,
                                                           decoder: JSONKeyValueDecoder(),
                                                           encoder: JSONKeyValueEncoder())

let expirationCheckStorage = accessTokenStorage.isExpireCheck { $0.expiration.timeIntervalSinceNow > 0 }

switch expirationCheckStorage.getValue() {
case let .success(token):
    // use token
    break
case let .failure(storageError)
    if .valueNotFound = storageError {
        // token is missing or expired, request new token
    } else {
        // handle storage error
    }
    break
}

Пример использования оператора flatMap у AsyncOperaton

import TISwiftUtils

extension StorageKey {
    static var loyaltyCardNumber: StorageKey<String> {
        .init(rawValue: "loyaltyCardNumber")
    }
}

struct CardService {
    enum Failure: Error {
        case noCardFound
        case cardFetchError
    }

    private let operationQueue = OperationQueue()

    private let asyncStorage = StringValueDefaultsStorage(defaults: .standard, storageKey: .loyaltyCardNumber)
        .async(on: .global())

    func requestCardTitle(cardNumber: String) -> AsyncOperation<String, Failure> {
        .just(success: "Supreme card")
//        .just(failure: .cardFetchError)
    }

    func getSavedCardTitle(completion: @escaping UIParameterClosure<Result<String, Failure>>) -> Cancellable {
        ClosureAsyncOperation { completion in
            asyncStorage.getValue {
                completion($0.mapError { _ in
                    .noCardFound
                })
            }
        }
        .flatMap {
            requestCardTitle(cardNumber: $0)
        }
        .observe(onResult: completion)
        .add(to: operationQueue)
    }
}

let cardService = CardService()

cardService.getSavedCardTitle { result in
    debugPrint(result)
}
### `SingleValueExpirationStorage<SingleValueStorage>` Класс позволяющий добавить дополнительную функциональность очистки значения по конкретному ключу если истёк срок действия объекта (например refresh token'а) ```swift struct Token: Codable, Equatable { var value: String var expiration: Date init(value: String, expiration: Date) { self.value = value self.expiration = expiration } } extension StorageKey { static var accessToken: StorageKey<Token> { .init(rawValue: "accessToken") } } let accessTokenStorage = DefaultSingleValueCodableStorage(storage: keychain, storageKey: .accessToken, decoder: JSONKeyValueDecoder(), encoder: JSONKeyValueEncoder()) let expirationCheckStorage = accessTokenStorage.isExpireCheck { $0.expiration.timeIntervalSinceNow > 0 } switch expirationCheckStorage.getValue() { case let .success(token): // use token break case let .failure(storageError) if .valueNotFound = storageError { // token is missing or expired, request new token } else { // handle storage error } break } ``` ### Пример использования оператора flatMap у AsyncOperaton ```swift import TISwiftUtils extension StorageKey { static var loyaltyCardNumber: StorageKey<String> { .init(rawValue: "loyaltyCardNumber") } } struct CardService { enum Failure: Error { case noCardFound case cardFetchError } private let operationQueue = OperationQueue() private let asyncStorage = StringValueDefaultsStorage(defaults: .standard, storageKey: .loyaltyCardNumber) .async(on: .global()) func requestCardTitle(cardNumber: String) -> AsyncOperation<String, Failure> { .just(success: "Supreme card") // .just(failure: .cardFetchError) } func getSavedCardTitle(completion: @escaping UIParameterClosure<Result<String, Failure>>) -> Cancellable { ClosureAsyncOperation { completion in asyncStorage.getValue { completion($0.mapError { _ in .noCardFound }) } } .flatMap { requestCardTitle(cardNumber: $0) } .observe(onResult: completion) .add(to: operationQueue) } } let cardService = CardService() cardService.getSavedCardTitle { result in debugPrint(result) } ```
ivan.smolin added 4 commits 2023-06-09 15:23:41 +03:00
23c17c9d85 feat: Added flatMap operator for AsyncOperation
CodableKeyValueStorage now returns Swift.Result with typed errors.
SingleValueExpirationStorage for time aware entries (expirable api tokens, etc.)
AsyncOperation variants of process methods in NetworkServices.
ivan.smolin added 1 commit 2023-06-09 16:40:47 +03:00
vladimir.makarov approved these changes 2023-06-14 10:23:05 +03:00
ivan.smolin merged commit 818d4dbe8d into master 2023-06-15 13:30:23 +03:00
ivan.smolin deleted branch feature/flat_map_async_operation_result_type_codable_storage 2023-06-15 13:30:23 +03:00
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: TouchInstinct/LeadKit#8
No description provided.