Skip to content

Commit 2e62a03

Browse files
authored
chore: kickoff release
2 parents bdb1567 + 56d5339 commit 2e62a03

File tree

8 files changed

+170
-3
lines changed

8 files changed

+170
-3
lines changed

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/AWSCognitoAuthPlugin+Configure.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,15 @@ extension AWSCognitoAuthPlugin {
102102
configuration.httpClientEngine = .userAgentEngine(for: configuration)
103103
}
104104

105+
if let requestTimeout = networkPreferences?.timeoutIntervalForRequest {
106+
let requestTimeOutMs = requestTimeout * 1_000
107+
configuration.connectTimeoutMs = UInt32(requestTimeOutMs)
108+
}
109+
110+
if let maxRetryUnwrapped = networkPreferences?.maxRetryCount {
111+
configuration.retryStrategyOptions = RetryStrategyOptions(maxRetriesBase: Int(maxRetryUnwrapped))
112+
}
113+
105114
return CognitoIdentityProviderClient(config: configuration)
106115
default:
107116
fatalError()
@@ -116,6 +125,15 @@ extension AWSCognitoAuthPlugin {
116125
)
117126
configuration.httpClientEngine = .userAgentEngine(for: configuration)
118127

128+
if let requestTimeout = networkPreferences?.timeoutIntervalForRequest {
129+
let requestTimeOutMs = requestTimeout * 1_000
130+
configuration.connectTimeoutMs = UInt32(requestTimeOutMs)
131+
}
132+
133+
if let maxRetryUnwrapped = networkPreferences?.maxRetryCount {
134+
configuration.retryStrategyOptions = RetryStrategyOptions(maxRetriesBase: Int(maxRetryUnwrapped))
135+
}
136+
119137
return CognitoIdentityClient(config: configuration)
120138
default:
121139
fatalError()
@@ -129,6 +147,15 @@ extension AWSCognitoAuthPlugin {
129147
private func makeURLSession() -> URLSession {
130148
let configuration = URLSessionConfiguration.default
131149
configuration.urlCache = nil
150+
151+
if let timeoutIntervalForRequest = networkPreferences?.timeoutIntervalForRequest {
152+
configuration.timeoutIntervalForRequest = timeoutIntervalForRequest
153+
}
154+
155+
if let timeoutIntervalForResource = networkPreferences?.timeoutIntervalForResource {
156+
configuration.timeoutIntervalForResource = timeoutIntervalForResource
157+
}
158+
132159
return URLSession(configuration: configuration)
133160
}
134161

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/AWSCognitoAuthPlugin.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ public final class AWSCognitoAuthPlugin: AWSCognitoAuthPluginBehavior {
3232

3333
var httpClientEngineProxy: HttpClientEngineProxy?
3434

35+
/// The user network preferences for timeout and retry
36+
let networkPreferences: AWSCognitoNetworkPreferences?
37+
3538
@_spi(InternalAmplifyConfiguration)
3639
internal(set) public var jsonConfiguration: JSONValue?
3740

@@ -42,5 +45,13 @@ public final class AWSCognitoAuthPlugin: AWSCognitoAuthPluginBehavior {
4245

4346
/// Instantiates an instance of the AWSCognitoAuthPlugin.
4447
public init() {
48+
self.networkPreferences = nil
49+
}
50+
51+
/// Instantiates an instance of the AWSCognitoAuthPlugin with custom network preferences
52+
/// - Parameters:
53+
/// - networkPreferences: network preferences
54+
public init(networkPreferences: AWSCognitoNetworkPreferences) {
55+
self.networkPreferences = networkPreferences
4556
}
4657
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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 Foundation
9+
10+
public struct AWSCognitoNetworkPreferences {
11+
12+
/// The maximum number of retries for failed requests.
13+
public let maxRetryCount: UInt32
14+
15+
/// The timeout interval to use when waiting for additional data.
16+
public let timeoutIntervalForRequest: TimeInterval
17+
18+
/// The maximum amount of time that a resource request should be allowed to take.
19+
///
20+
/// NOTE: This value is only applicable to HostedUI because the underlying Swift SDK does
21+
/// not support resource timeouts
22+
public let timeoutIntervalForResource: TimeInterval?
23+
24+
public init(maxRetryCount: UInt32,
25+
timeoutIntervalForRequest: TimeInterval,
26+
timeoutIntervalForResource: TimeInterval? = nil) {
27+
self.maxRetryCount = maxRetryCount
28+
self.timeoutIntervalForRequest = timeoutIntervalForRequest
29+
self.timeoutIntervalForResource = timeoutIntervalForResource
30+
}
31+
}

AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ConfigurationTests/AWSCognitoAuthPluginConfigTests.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,50 @@ class AWSCognitoAuthPluginConfigTests: XCTestCase {
190190
}
191191
}
192192

193+
/// Test Auth configuration with valid config for user pool and identity pool, with network preferences
194+
///
195+
/// - Given: Given valid config for user pool and identity pool, and network preferences
196+
/// - When:
197+
/// - I configure auth with the given configuration and network preferences
198+
/// - Then:
199+
/// - I should not get any error while configuring auth
200+
///
201+
func testConfigWithUserPoolAndIdentityPoolWithNetworkPreferences() throws {
202+
let plugin = AWSCognitoAuthPlugin(
203+
networkPreferences: .init(
204+
maxRetryCount: 2,
205+
timeoutIntervalForRequest: 60,
206+
timeoutIntervalForResource: 60))
207+
try Amplify.add(plugin: plugin)
208+
209+
let categoryConfig = AuthCategoryConfiguration(plugins: [
210+
"awsCognitoAuthPlugin": [
211+
"CredentialsProvider": ["CognitoIdentity": ["Default":
212+
["PoolId": "xx",
213+
"Region": "us-east-1"]
214+
]],
215+
"CognitoUserPool": ["Default": [
216+
"PoolId": "xx",
217+
"Region": "us-east-1",
218+
"AppClientId": "xx",
219+
"AppClientSecret": "xx"]]
220+
]
221+
])
222+
let amplifyConfig = AmplifyConfiguration(auth: categoryConfig)
223+
do {
224+
try Amplify.configure(amplifyConfig)
225+
226+
let escapeHatch = plugin.getEscapeHatch()
227+
guard case .userPoolAndIdentityPool(let userPoolClient, let identityPoolClient) = escapeHatch else {
228+
XCTFail("Expected .userPool, got \(escapeHatch)")
229+
return
230+
}
231+
XCTAssertNotNil(userPoolClient)
232+
XCTAssertNotNil(identityPoolClient)
233+
234+
} catch {
235+
XCTFail("Should not throw error. \(error)")
236+
}
237+
}
238+
193239
}

AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/PinpointEvent+PinpointClientTypes.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@ import AWSPluginsCore
1010
import Foundation
1111

1212
extension PinpointEvent {
13-
var clientTypeSession: PinpointClientTypes.Session {
13+
var clientTypeSession: PinpointClientTypes.Session? {
14+
#if os(watchOS)
15+
// If the session duration cannot be represented by Int, return a nil session instead.
16+
// This is extremely unlikely to happen since a session's stopTime is set when the app is closed
17+
if let duration = session.duration, duration > Int.max {
18+
return nil
19+
}
20+
#endif
1421
return PinpointClientTypes.Session(duration: Int(session.duration),
1522
id: session.sessionId,
1623
startTimestamp: session.startTime.asISO8601String,
@@ -48,3 +55,12 @@ extension Bundle {
4855
object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? ""
4956
}
5057
}
58+
59+
private extension Int {
60+
init?(_ value: Int64?) {
61+
guard let value = value else {
62+
return nil
63+
}
64+
self.init(value)
65+
}
66+
}

AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/PinpointSession.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@ public class PinpointSession: Codable {
3535
return stopTime != nil
3636
}
3737

38-
var duration: Date.Millisecond {
39-
let endTime = stopTime ?? Date()
38+
var duration: Date.Millisecond? {
39+
/// According to Pinpoint's documentation, `duration` is only required if `stopTime` is not nil.
40+
guard let endTime = stopTime else {
41+
return nil
42+
}
4043
return endTime.millisecondsSince1970 - startTime.millisecondsSince1970
4144
}
4245

AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/EventRecorderTests.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,37 @@ class EventRecorderTests: XCTestCase {
9494
XCTAssertEqual(storage.deleteEventCallCount, 2)
9595
}
9696

97+
/// - Given: a event recorder with events saved in the local storage with active and stopped sessions
98+
/// - When: submitAllEvents is invoked
99+
/// - Then: the input is generated accordingly by including duration only for the stopped session
100+
func testSubmitAllEvents_withActiveAndStoppedSessions_shouldGenerateRightInput() async throws {
101+
let activeSession = PinpointSession(
102+
sessionId: "active",
103+
startTime: Date(),
104+
stopTime: nil
105+
)
106+
let stoppedSession = PinpointSession(
107+
sessionId: "stopped",
108+
startTime: Date().addingTimeInterval(-10),
109+
stopTime: Date()
110+
)
111+
storage.events = [
112+
.init(id: "1", eventType: "eventType1", eventDate: Date(), session: activeSession),
113+
.init(id: "2", eventType: "eventType2", eventDate: Date(), session: stoppedSession)
114+
]
115+
116+
_ = try? await recorder.submitAllEvents()
117+
XCTAssertEqual(pinpointClient.putEventsCount, 1)
118+
let input = try XCTUnwrap(pinpointClient.putEventsLastInput)
119+
let batchItem = try XCTUnwrap(input.eventsRequest?.batchItem?.first?.value as? PinpointClientTypes.EventsBatch)
120+
let events = try XCTUnwrap(batchItem.events)
121+
XCTAssertEqual(events.count, 2)
122+
XCTAssertNotNil(events["1"]?.session, "Expected session for eventType1")
123+
XCTAssertNil(events["1"]?.session?.duration, "Expected nil session duration for eventType")
124+
XCTAssertNotNil(events["2"]?.session, "Expected session for eventType2")
125+
XCTAssertNotNil(events["2"]?.session?.duration, "Expected session duration for eventType2")
126+
}
127+
97128
/// - Given: a event recorder with events saved in the local storage
98129
/// - When: submitAllEvents is invoked and fails with a non-retryable error
99130
/// - Then: the events are marked as dirty

AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockPinpointClient.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,10 @@ class MockPinpointClient: PinpointClientProtocol {
367367

368368
var putEventsCount = 0
369369
var putEventsResult: Result<PutEventsOutput, Error> = .failure(CancellationError())
370+
var putEventsLastInput: PutEventsInput?
370371
func putEvents(input: PutEventsInput) async throws -> PutEventsOutput {
371372
putEventsCount += 1
373+
putEventsLastInput = input
372374
return try putEventsResult.get()
373375
}
374376

0 commit comments

Comments
 (0)