1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

AWSAppSyncClientの処理をRxでラップする

Posted at

やったこと

AWSAppSyncClientで頻出のfetch, mutate, subscribe処理をRxでラップして、
SingleObservableなどのオペレータで扱えるようにしました。

AWSAppSyncClientでは内部でApolloClientをラップしているので、
AWSサービスなどを使わずにApolloをGraphQLしてRxで扱うケースと同じようなコードになるかなと思います。

コード

AWSAppSyncClient+Rx.swift
import Foundation
import AWSAppSync
import RxSwift
import SwiftyBeaver

let log = SwiftyBeaver.self

enum AppSyncError: Error {
    case gqlErrors([GraphQLError])
    case noData
    case unknowned
}

extension AWSAppSyncClient: ReactiveCompatible {}

extension Reactive where Base: AWSAppSyncClient {
    
    public func fetch<Query: GraphQLQuery>(
        query: Query,
        cachePolicy: CachePolicy = .returnCacheDataElseFetch,
        queue: DispatchQueue = DispatchQueue.main
    ) -> Single<Query.Data> {
        return Single.create { [weak base] observer in
            log.debug("query did called - query: \(query)")
            let cancellable = base?.fetch(query: query, cachePolicy: cachePolicy, queue: queue) {(result, error) in
                if let error = error {
                    log.error("client connection error - error: \(error)")
                    observer(.error(error))
                }
                switch result {
                case .none:
                    log.error("fetched result is nil")
                    observer(.error(AppSyncError.noData))
                case .some(let result):
                    if let errors = result.errors {
                        log.error("GraphQL fetch error - errors: \(errors.map { $0.description } )")
                        observer(.error(AppSyncError.gqlErrors(errors)))
                    } else if let data = result.data {
                        observer(.success(data))
                    } else {
                        log.error("Unknowned error. result and error, both values ​​are nil")
                        observer(.error(AppSyncError.unknowned))
                    }
                }
            }
            return Disposables.create {
                cancellable?.cancel()
            }
        }
    }

    public func perform<Mutation: GraphQLMutation>(
        mutation: Mutation,
        queue: DispatchQueue = .main
    ) -> Single<Mutation.Data> {
        return Single.create { [weak base] observer in
            log.debug("mutation did called - mutation: \(mutation)")
            let cancellable = base?.perform(mutation: mutation, queue: queue, optimisticUpdate: nil, conflictResolutionBlock: nil, resultHandler: { (result, error) in
                if let error = error {
                    log.error("client connection error - error: \(error)")
                    observer(.error(error))
                }
                switch result {
                case .none:
                    assertionFailure("Unexpected error - in case result is nil, should return error before evaluating result value")
                    observer(.error(AppSyncError.resultIsNil)) // 一応エラーを返しておく
                case .some(let result):
                    if let errors = result.errors {
                        log.error("GraphQL perform error - errors: \(errors.map { $0.description } )")
                        observer(.error(AppSyncError.gqlErrors(errors)))
                    } else if let data = result.data {
                        observer(.success(data))
                    } else {
                        log.error("perform unknowned error. result and error, both values ​​are nil")
                        observer(.error(AppSyncError.unknowned))
                    }
                }
            })
            return Disposables.create {
                cancellable?.cancel()
            }
        }
    }

    public func subscribe<Subscription: GraphQLSubscription>(
      subscription: Subscription,
      queue: DispatchQueue = .main
    ) -> Observable<Subscription.Data> {
        return Observable.create { [weak base] observer in
            log.debug("subscription did called - subscription: \(subscription)")
            var cancellable: Cancellable?
            do {
                cancellable = try base?.subscribe(subscription: subscription, queue: queue, statusChangeHandler: nil, resultHandler: { (result, _, error) in
                    if let error = error {
                        log.error("client connection error - error: \(error)")
                        observer.onError(error)
                    }
                    switch result {
                    case .none:
                        assertionFailure("Unexpected error - in case result is nil, should return error before evaluating result value")
                        observer.onError(AppSyncError.resultIsNil) // 一応エラーを返しておく
                    case .some(let result):
                        if let data = result.data {
                            log.debug("subscribed data: - \(data)")
                            observer.onNext(data)
                        } else if let errors = result.errors {
                            log.error("GraphQL subscribe error - errors: \(errors.map { $0.description } )")
                            observer.onError(AppSyncError.gqlErrors(errors))
                        }
                    }
                })
            } catch {
                log.error("subscribe configurations error")
                observer.onError(AppSyncError.unknowned) // base?.subscribe内でthrowされるがどんなerrorが投げられているのかは不明
                cancellable?.cancel()
            }
            return Disposables.create {
                cancellable?.cancel()
            }
        }
    }
}

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?