Skip to content

Commit bd6e02a

Browse files
authored
chore: kickoff release
2 parents af4a5f7 + 6e2a881 commit bd6e02a

File tree

4 files changed

+88
-113
lines changed

4 files changed

+88
-113
lines changed

.github/workflows/unit_test.yml

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ concurrency:
4141
cancel-in-progress: ${{ github.ref_name != 'main'}}
4242

4343
jobs:
44-
unit-tests-without-coverage:
44+
targets-without-coverage:
4545
name: ${{ matrix.scheme }} Unit Tests
4646
strategy:
4747
fail-fast: false
@@ -54,7 +54,7 @@ jobs:
5454
scheme: ${{ matrix.scheme }}
5555
generate_coverage_report: false
5656

57-
unit-tests-with-coverage:
57+
targets-with-coverage:
5858
name: ${{ matrix.scheme }} Unit Tests
5959
strategy:
6060
fail-fast: false
@@ -76,40 +76,41 @@ jobs:
7676
uses: ./.github/workflows/run_unit_tests_platforms.yml
7777
with:
7878
scheme: ${{ matrix.scheme }}
79-
generate_coverage_report: true
79+
generate_coverage_report: ${{ vars.DISABLE_COVERAGE_REPORT != 'true' }}
8080

81-
# report-coverage:
82-
# name: ${{ matrix.file.scheme }} Unit Tests
83-
# needs: [unit-tests-with-coverage]
84-
# strategy:
85-
# fail-fast: false
86-
# matrix:
87-
# file: [
88-
# { scheme: Amplify, flags: 'Amplify,unit_tests' },
89-
# { scheme: AWSPluginsCore, flags: 'AWSPluginsCore,unit_tests' },
90-
# { scheme: AWSAPIPlugin, flags: 'API_plugin_unit_test,unit_tests' },
91-
# { scheme: AWSCloudWatchLoggingPlugin, flags: 'Logging_plugin_unit_test,unit_tests' },
92-
# { scheme: AWSCognitoAuthPlugin, flags: 'Auth_plugin_unit_test,unit_tests' },
93-
# { scheme: AWSDataStorePlugin, flags: 'DataStore_plugin_unit_test,unit_tests' },
94-
# { scheme: AWSLocationGeoPlugin, flags: 'Geo_plugin_unit_test,unit_tests' },
95-
# { scheme: AWSPredictionsPlugin, flags: 'Predictions_plugin_unit_test,unit_tests' },
96-
# { scheme: AWSPinpointAnalyticsPlugin, flags: 'Analytics_plugin_unit_test,unit_tests' },
97-
# { scheme: AWSPinpointPushNotificationsPlugin, flags: 'PushNotifications_plugin_unit_test,unit_tests' },
98-
# { scheme: AWSS3StoragePlugin, flags: 'Storage_plugin_unit_test,unit_tests' },
99-
# { scheme: CoreMLPredictionsPlugin, flags: 'CoreMLPredictions_plugin_unit_test,unit_tests' }
100-
# ]
101-
# uses: ./.github/workflows/upload_coverage_report.yml
102-
# with:
103-
# scheme: ${{ matrix.file.scheme }}
104-
# flags: ${{ matrix.file.flags }}
81+
report-coverage:
82+
if: ${{ vars.DISABLE_COVERAGE_REPORT != 'true' }}
83+
name: ${{ matrix.file.scheme }} Unit Tests
84+
needs: [targets-with-coverage]
85+
strategy:
86+
fail-fast: false
87+
matrix:
88+
file: [
89+
{ scheme: Amplify, flags: 'Amplify,unit_tests' },
90+
{ scheme: AWSPluginsCore, flags: 'AWSPluginsCore,unit_tests' },
91+
{ scheme: AWSAPIPlugin, flags: 'API_plugin_unit_test,unit_tests' },
92+
{ scheme: AWSCloudWatchLoggingPlugin, flags: 'Logging_plugin_unit_test,unit_tests' },
93+
{ scheme: AWSCognitoAuthPlugin, flags: 'Auth_plugin_unit_test,unit_tests' },
94+
{ scheme: AWSDataStorePlugin, flags: 'DataStore_plugin_unit_test,unit_tests' },
95+
{ scheme: AWSLocationGeoPlugin, flags: 'Geo_plugin_unit_test,unit_tests' },
96+
{ scheme: AWSPredictionsPlugin, flags: 'Predictions_plugin_unit_test,unit_tests' },
97+
{ scheme: AWSPinpointAnalyticsPlugin, flags: 'Analytics_plugin_unit_test,unit_tests' },
98+
{ scheme: AWSPinpointPushNotificationsPlugin, flags: 'PushNotifications_plugin_unit_test,unit_tests' },
99+
{ scheme: AWSS3StoragePlugin, flags: 'Storage_plugin_unit_test,unit_tests' },
100+
{ scheme: CoreMLPredictionsPlugin, flags: 'CoreMLPredictions_plugin_unit_test,unit_tests' }
101+
]
102+
uses: ./.github/workflows/upload_coverage_report.yml
103+
with:
104+
scheme: ${{ matrix.file.scheme }}
105+
flags: ${{ matrix.file.flags }}
105106

106107
unit-test-pass-confirmation:
107108
runs-on: ubuntu-latest
108109
name: Confirm Passing Unit Tests
109110
if: ${{ !cancelled() }}
110111
needs: [
111-
unit-tests-with-coverage,
112-
unit-tests-without-coverage
112+
targets-with-coverage,
113+
targets-without-coverage
113114
]
114115
env:
115116
EXIT_CODE: ${{ contains(needs.*.result, 'failure') && 1 || 0 }}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
import Combine
9+
10+
class CancellableAsyncStream<Element>: AsyncSequence {
11+
12+
typealias AsyncIterator = AsyncStream<Element>.AsyncIterator
13+
private let asyncStream: AsyncStream<Element>
14+
private let cancellable: AnyCancellable?
15+
16+
deinit {
17+
cancel()
18+
}
19+
20+
init(asyncStream: AsyncStream<Element>, cancellable: AnyCancellable?) {
21+
self.asyncStream = asyncStream
22+
self.cancellable = cancellable
23+
}
24+
25+
convenience init(with publisher: AnyPublisher<Element, Never>) {
26+
var cancellable: AnyCancellable?
27+
self.init(asyncStream: AsyncStream { continuation in
28+
cancellable = publisher.sink { _ in
29+
continuation.finish()
30+
} receiveValue: {
31+
continuation.yield($0)
32+
}
33+
}, cancellable: cancellable)
34+
}
35+
36+
func makeAsyncIterator() -> AsyncStream<Element>.AsyncIterator {
37+
asyncStream.makeAsyncIterator()
38+
}
39+
40+
func cancel() {
41+
cancellable?.cancel()
42+
}
43+
}

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/hierarchical-state-machine-swift/StateAsyncSequence.swift

Lines changed: 0 additions & 36 deletions
This file was deleted.

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/hierarchical-state-machine-swift/StateMachine.swift

Lines changed: 15 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,7 @@
55
// SPDX-License-Identifier: Apache-2.0
66
//
77

8-
import Foundation
9-
10-
/// Captures a weak reference to the value
11-
class WeakWrapper<T> where T: AnyObject {
12-
private(set) weak var value: T?
13-
init(_ value: T) {
14-
self.value = value
15-
}
16-
}
8+
import Combine
179

1810
/// Models, evolves, and processes effects for a system.
1911
///
@@ -31,15 +23,18 @@ actor StateMachine<
3123
EnvironmentType: Environment
3224
> where StateType: State {
3325

34-
/// AsyncSequences are invoked a minimum of one time: Each sequence receives the current
35-
/// state as soon as `listen()` is invoked, and will receive each subsequent state change.
36-
typealias StateChangeSequence = StateAsyncSequence<StateType>
37-
3826
private let environment: EnvironmentType
3927
private let resolver: AnyResolver<StateType>
4028

41-
private(set) var currentState: StateType
42-
private var subscribers: [WeakWrapper<StateAsyncSequence<StateType>>]
29+
public var currentState: StateType {
30+
currentStateSubject.value
31+
}
32+
33+
private let currentStateSubject: CurrentValueSubject<StateType, Never>
34+
35+
deinit {
36+
currentStateSubject.send(completion: .finished)
37+
}
4338

4439
init<ResolverType>(
4540
resolver: ResolverType,
@@ -48,22 +43,16 @@ actor StateMachine<
4843
) where ResolverType: StateMachineResolver, ResolverType.StateType == StateType {
4944
self.resolver = resolver.eraseToAnyResolver()
5045
self.environment = environment
51-
self.currentState = initialState ?? resolver.defaultState
52-
53-
self.subscribers = []
46+
self.currentStateSubject = CurrentValueSubject(initialState ?? resolver.defaultState)
5447
}
5548

5649
/// Start listening to state change updates. The current state and all subsequent state changes will be sent to the sequence.
5750
///
5851
/// - Returns: An async sequence that get states asynchronously
59-
func listen() -> StateChangeSequence {
60-
let sequence = StateAsyncSequence<StateType>()
61-
let currentState = self.currentState
62-
let wrappedSequence = WeakWrapper(sequence)
63-
subscribers.append(wrappedSequence)
64-
sequence.send(currentState)
65-
return sequence
52+
func listen() -> CancellableAsyncStream<StateType> {
53+
CancellableAsyncStream(with: currentStateSubject.eraseToAnyPublisher())
6654
}
55+
6756
}
6857

6958
extension StateMachine: EventDispatcher {
@@ -88,33 +77,11 @@ extension StateMachine: EventDispatcher {
8877
)
8978

9079
if currentState != resolution.newState {
91-
currentState = resolution.newState
92-
subscribers.removeAll { item in
93-
!notify(subscriberElement: item, about: resolution.newState)
94-
}
80+
currentStateSubject.send(resolution.newState)
9581
}
9682
execute(resolution.actions)
9783
}
9884

99-
/// - Parameters:
100-
/// - subscriberElement: A weak wrapped async sequence
101-
/// - newState: The new state to be sent
102-
/// - Returns: true if the subscriber was notified, false if the wrapper reference was nil or a cancellation was pending
103-
private func notify(
104-
subscriberElement: WeakWrapper<StateChangeSequence>,
105-
about newState: StateType
106-
) -> Bool {
107-
108-
// If weak reference has become nil, do not process, and return false so caller can remove
109-
// the subscription from the subscribers list
110-
guard let sequence = subscriberElement.value else {
111-
return false
112-
}
113-
114-
sequence.send(newState)
115-
return true
116-
}
117-
11885
private func execute(_ actions: [Action]) {
11986
guard !actions.isEmpty else {
12087
return

0 commit comments

Comments
 (0)