Skip to content

Commit

Permalink
Update RemoteSyncEngine to adopt a StateMachine to allow for easier c…
Browse files Browse the repository at this point in the history
…ontrol of start/stop/retry
  • Loading branch information
wooj2 committed Feb 20, 2020
1 parent c6b902b commit bd82f59
Show file tree
Hide file tree
Showing 9 changed files with 328 additions and 90 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// Copyright 2018-2020 Amazon.com,
// Inc. or its affiliates. All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Amplify
import Combine

@available(iOS 13.0, *)
extension RemoteSyncEngine {

/// Actions are declarative, they say what I just did
enum Action {
// Startup/config actions
case receivedStart

case pausedSubscriptions
case pausedMutationQueue(APICategoryGraphQLBehavior, StorageEngineAdapter)
case initializedSubscriptions
case performedInitialSync
case activatedCloudSubscriptions(APICategoryGraphQLBehavior, MutationEventPublisher)
case activatedMutationQueue
case notifiedSyncStarted

// Terminal actions
case receivedCancel
case errored(AmplifyError)

var displayName: String {
switch self {
case .receivedStart:
return "receivedStart"
case .pausedSubscriptions:
return "pausedSubscriptions"
case .pausedMutationQueue:
return "pausedMutationQueue"
case .initializedSubscriptions:
return "initializedSubscriptions"
case .performedInitialSync:
return "performedInitialSync"
case .activatedCloudSubscriptions:
return "activatedCloudSubscriptions"
case .activatedMutationQueue:
return "activatedMutationQueue"
case .notifiedSyncStarted:
return "notifiedSyncStarted"
case .receivedCancel:
return "receivedCancel"
case .errored:
return "errored"
}

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// Copyright 2018-2020 Amazon.com,
// Inc. or its affiliates. All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Amplify
import Combine
import Foundation

@available(iOS 13.0, *)
extension RemoteSyncEngine {
@available(iOS 13.0, *)
func onReceiveCompletion(receiveCompletion: Subscribers.Completion<DataStoreError>) {
if case .failure(let error) = receiveCompletion {
remoteSyncTopicPublisher.send(completion: .failure(error))
}
if case .finished = receiveCompletion {
let unexpectedFinishError = DataStoreError.unknown("ReconcilationQueue sent .finished message",
AmplifyErrorMessages.shouldNotHappenReportBugToAWS(),
nil)
remoteSyncTopicPublisher.send(completion: .failure(unexpectedFinishError))
}
}

@available(iOS 13.0, *)
func onReceive(receiveValue: IncomingEventReconciliationQueueEvent) {
switch receiveValue {
case .started:
remoteSyncTopicPublisher.send(.subscriptionsActivated)
if let api = self.api {
stateMachine.notify(action: .activatedCloudSubscriptions(api, mutationEventPublisher))
}
case .paused:
remoteSyncTopicPublisher.send(.subscriptionsPaused)
case .mutationEvent(let mutationEvent):
remoteSyncTopicPublisher.send(.mutationEvent(mutationEvent))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// Copyright 2018-2020 Amazon.com,
// Inc. or its affiliates. All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Amplify
import Combine

@available(iOS 13.0, *)
extension RemoteSyncEngine {
struct Resolver {
static func resolve(currentState: State, action: Action) -> State {
switch (currentState, action) {
case (.notStarted, .receivedStart):
return .pauseSubscriptions

case (.pauseSubscriptions, .pausedSubscriptions):
return .pauseMutationQueue

case (.pauseMutationQueue, .pausedMutationQueue(let api, let storageEngineAdapter)):
return .initializeSubscriptions(api, storageEngineAdapter)

case (.initializeSubscriptions, .initializedSubscriptions):
return .performInitialSync

case (.performInitialSync, .performedInitialSync):
return .activateCloudSubscriptions
case (.performInitialSync, .errored(let error)):
return .cleanup(error)

case (.activateCloudSubscriptions, .activatedCloudSubscriptions(let api, let mutationEventPublisher)):
return .activateMutationQueue(api, mutationEventPublisher)
case (.activateCloudSubscriptions, .errored(let error)):
return .cleanup(error)

case (.activateMutationQueue, .activatedMutationQueue):
return .notifySyncStarted
case (.activateMutationQueue, .errored(let error)):
return .cleanup(error)

case (.notifySyncStarted, .notifiedSyncStarted):
return .syncEngineActive

default:
log.warn("Unexpected state transition. In \(currentState.displayName), got \(action.displayName)")
log.verbose("Unexpected state transition. In \(currentState), got \(action)")
return currentState
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// Copyright 2018-2020 Amazon.com,
// Inc. or its affiliates. All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Amplify
import Combine
@available(iOS 13.0, *)
extension RemoteSyncEngine {

/// States are descriptive, they say what is happening in the system right now
enum State {
case notStarted

case pauseSubscriptions
case pauseMutationQueue
case initializeSubscriptions(APICategoryGraphQLBehavior, StorageEngineAdapter)
case performInitialSync
case activateCloudSubscriptions
case activateMutationQueue(APICategoryGraphQLBehavior, MutationEventPublisher)
case notifySyncStarted

case syncEngineActive

case cleanup(AmplifyError)
var displayName: String {
switch self {
case .notStarted:
return "notStarted"
case .pauseSubscriptions:
return "pauseCloudSubscriptions"
case .pauseMutationQueue:
return "pauseMutationQueue"
case .initializeSubscriptions:
return "initializeSubscriptions"
case .performInitialSync:
return "performInitialSync"
case .activateCloudSubscriptions:
return "activateCloudSubscriptions"
case .activateMutationQueue:
return "activateMutationQueue"
case .notifySyncStarted:
return "notifySyncStarted"
case .syncEngineActive:
return "syncEngineActive"
case .cleanup:
return "cleanup"
}
}
}
}
Loading

0 comments on commit bd82f59

Please sign in to comment.