Skip to content

Commit e9cb761

Browse files
committed
fix: update retry policy handling to respect re-initialization
1 parent de5ed49 commit e9cb761

File tree

3 files changed

+77
-9
lines changed

3 files changed

+77
-9
lines changed

android/src/main/java/com/iterable/reactnative/RNIterableAPIModuleImpl.java

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.iterable.iterableapi.IterableActionContext;
2525
import com.iterable.iterableapi.IterableApi;
2626
import com.iterable.iterableapi.IterableAuthHandler;
27+
import com.iterable.iterableapi.IterableAuthManager;
2728
import com.iterable.iterableapi.IterableConfig;
2829
import com.iterable.iterableapi.IterableCustomActionHandler;
2930
import com.iterable.iterableapi.IterableAttributionInfo;
@@ -88,7 +89,34 @@ public void initializeWithApiKey(String apiKey, ReadableMap configReadableMap, S
8889
configBuilder.setAuthHandler(this);
8990
}
9091

91-
IterableApi.initialize(reactContext, apiKey, configBuilder.build());
92+
IterableConfig config = configBuilder.build();
93+
IterableApi.initialize(reactContext, apiKey, config);
94+
95+
// Update retry policy on existing authManager if it was already created
96+
// This fixes the issue where retryInterval is not respected after re-initialization
97+
try {
98+
// Use reflection to access package-private fields and methods
99+
java.lang.reflect.Field configRetryPolicyField = config.getClass().getDeclaredField("retryPolicy");
100+
configRetryPolicyField.setAccessible(true);
101+
Object retryPolicy = configRetryPolicyField.get(config);
102+
103+
if (retryPolicy != null) {
104+
java.lang.reflect.Method getAuthManagerMethod = IterableApi.getInstance().getClass().getDeclaredMethod("getAuthManager");
105+
getAuthManagerMethod.setAccessible(true);
106+
IterableAuthManager authManager = (IterableAuthManager) getAuthManagerMethod.invoke(IterableApi.getInstance());
107+
108+
if (authManager != null) {
109+
// Update the retry policy field on the authManager
110+
java.lang.reflect.Field authRetryPolicyField = authManager.getClass().getDeclaredField("authRetryPolicy");
111+
authRetryPolicyField.setAccessible(true);
112+
authRetryPolicyField.set(authManager, retryPolicy);
113+
IterableLogger.d(TAG, "Updated retry policy on existing authManager");
114+
}
115+
}
116+
} catch (Exception e) {
117+
IterableLogger.e(TAG, "Failed to update retry policy: " + e.getMessage());
118+
}
119+
92120
IterableApi.getInstance().setDeviceAttribute("reactNativeSDKVersion", version);
93121

94122
IterableApi.getInstance().getInAppManager().addListener(this);
@@ -122,7 +150,34 @@ public void initialize2WithApiKey(String apiKey, ReadableMap configReadableMap,
122150
// override in the Android SDK. Check with @Ayyanchira and @evantk91 to
123151
// see what the best approach is.
124152

125-
IterableApi.initialize(reactContext, apiKey, configBuilder.build());
153+
IterableConfig config = configBuilder.build();
154+
IterableApi.initialize(reactContext, apiKey, config);
155+
156+
// Update retry policy on existing authManager if it was already created
157+
// This fixes the issue where retryInterval is not respected after re-initialization
158+
try {
159+
// Use reflection to access package-private fields and methods
160+
java.lang.reflect.Field configRetryPolicyField = config.getClass().getDeclaredField("retryPolicy");
161+
configRetryPolicyField.setAccessible(true);
162+
Object retryPolicy = configRetryPolicyField.get(config);
163+
164+
if (retryPolicy != null) {
165+
java.lang.reflect.Method getAuthManagerMethod = IterableApi.getInstance().getClass().getDeclaredMethod("getAuthManager");
166+
getAuthManagerMethod.setAccessible(true);
167+
IterableAuthManager authManager = (IterableAuthManager) getAuthManagerMethod.invoke(IterableApi.getInstance());
168+
169+
if (authManager != null) {
170+
// Update the retry policy field on the authManager
171+
java.lang.reflect.Field authRetryPolicyField = authManager.getClass().getDeclaredField("authRetryPolicy");
172+
authRetryPolicyField.setAccessible(true);
173+
authRetryPolicyField.set(authManager, retryPolicy);
174+
IterableLogger.d(TAG, "Updated retry policy on existing authManager");
175+
}
176+
}
177+
} catch (Exception e) {
178+
IterableLogger.e(TAG, "Failed to update retry policy: " + e.getMessage());
179+
}
180+
126181
IterableApi.getInstance().setDeviceAttribute("reactNativeSDKVersion", version);
127182

128183
IterableApi.getInstance().getInAppManager().addListener(this);

android/src/main/java/com/iterable/reactnative/Serialization.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,13 +226,12 @@ static IterableConfig.Builder getConfigFromReadableMap(ReadableMap iterableConte
226226
// TODO [SDK-197]: Create consistency between Android and iOS
227227
// instead of converting here
228228
// Convert from seconds to milliseconds for Android native SDK
229-
long retryIntervalMs = retryInterval * 1000;
230229
String retryBackoff = retryPolicyJson.getString("retryBackoff");
231230
RetryPolicy.Type retryPolicyType = RetryPolicy.Type.LINEAR;
232231
if (retryBackoff.equals("EXPONENTIAL")) {
233232
retryPolicyType = RetryPolicy.Type.EXPONENTIAL;
234233
}
235-
configBuilder.setAuthRetryPolicy(new RetryPolicy(maxRetry, retryIntervalMs, retryPolicyType));
234+
configBuilder.setAuthRetryPolicy(new RetryPolicy(maxRetry, retryInterval, retryPolicyType));
236235
}
237236

238237
return configBuilder;

example/src/hooks/useIterableApp.tsx

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
8989

9090
const getIsEmail = (id: string) => EMAIL_REGEX.test(id);
9191

92+
let lastTimeStamp = 0;
93+
9294
export const IterableAppProvider: FunctionComponent<
9395
React.PropsWithChildren<unknown>
9496
> = ({ children }) => {
@@ -141,17 +143,15 @@ export const IterableAppProvider: FunctionComponent<
141143

142144
const initialize = useCallback(
143145
(navigation: Navigation) => {
144-
if (getUserId()) {
145-
login();
146-
}
146+
logout();
147147

148148
const config = new IterableConfig();
149149

150150
config.inAppDisplayInterval = 1.0; // Min gap between in-apps. No need to set this in production.
151151

152152
config.retryPolicy = {
153153
maxRetry: 5,
154-
retryInterval: 10,
154+
retryInterval:2,
155155
retryBackoff: IterableRetryBackoff.linear,
156156
};
157157

@@ -199,8 +199,16 @@ export const IterableAppProvider: FunctionComponent<
199199
process.env.ITBL_JWT_SECRET
200200
) {
201201
config.authHandler = async () => {
202+
console.group('authHandler');
203+
const now = Date.now();
204+
if (lastTimeStamp !== 0) {
205+
console.log('Time since last call:', now - lastTimeStamp);
206+
}
207+
lastTimeStamp = now;
208+
console.groupEnd();
209+
210+
// return 'InvalidToken'; // Uncomment this to test the failure callback
202211
const token = await getJwtToken();
203-
// return 'SomethingNotValid'; // Uncomment this to test the failure callback
204212
return token;
205213
};
206214
}
@@ -219,6 +227,10 @@ export const IterableAppProvider: FunctionComponent<
219227
.then((isSuccessful) => {
220228
setIsInitialized(isSuccessful);
221229

230+
if (isSuccessful && getUserId()) {
231+
return login();
232+
}
233+
222234
if (!isSuccessful) {
223235
return Promise.reject('`Iterable.initialize` failed');
224236
}
@@ -242,6 +254,8 @@ export const IterableAppProvider: FunctionComponent<
242254
const logout = useCallback(() => {
243255
Iterable.setEmail(null);
244256
Iterable.setUserId(null);
257+
Iterable.logout();
258+
lastTimeStamp = 0;
245259
setIsLoggedIn(false);
246260
}, []);
247261

0 commit comments

Comments
 (0)