@@ -51,25 +51,33 @@ import {
5151} from './appsyncUrl' ;
5252import { awsRealTimeHeaderBasedAuth } from './authHeaders' ;
5353
54- // Platform-safe AsyncStorage import
55- let AsyncStorage : Pick < KeyValueStorageInterface , 'setItem' | 'getItem' > | null ;
54+ // Storage key for persistent keep-alive tracking
55+ const KEEP_ALIVE_STORAGE_KEY = 'AWS_AMPLIFY_LAST_KEEP_ALIVE' ;
56+
57+ // Platform-safe storage implementation
58+ let platformStorage : Pick <
59+ KeyValueStorageInterface ,
60+ 'setItem' | 'getItem'
61+ > | null = null ;
62+
5663try {
5764 // Try to import AsyncStorage for React Native (optional dependency)
58- // eslint-disable-next-line import/no-extraneous-dependencies
59- AsyncStorage = require ( '@react-native-async-storage/async-storage' ) . default ;
65+ const AsyncStorage =
66+ // eslint-disable-next-line import/no-extraneous-dependencies
67+ require ( '@react-native-async-storage/async-storage' ) . default ;
68+ platformStorage = AsyncStorage ;
6069} catch ( e ) {
6170 // Fallback for web/other platforms - use localStorage if available
62- AsyncStorage =
63- typeof localStorage !== 'undefined'
64- ? {
65- setItem : ( key : string , value : string ) => {
66- localStorage . setItem ( key , value ) ;
71+ if ( typeof localStorage !== 'undefined' ) {
72+ platformStorage = {
73+ setItem : ( key : string , value : string ) => {
74+ localStorage . setItem ( key , value ) ;
6775
68- return Promise . resolve ( ) ;
69- } ,
70- getItem : ( key : string ) => Promise . resolve ( localStorage . getItem ( key ) ) ,
71- }
72- : null ;
76+ return Promise . resolve ( ) ;
77+ } ,
78+ getItem : ( key : string ) => Promise . resolve ( localStorage . getItem ( key ) ) ,
79+ } ;
80+ }
7381}
7482
7583const dispatchApiEvent = ( payload : HubPayload ) => {
@@ -706,13 +714,12 @@ export abstract class AWSWebSocketProvider {
706714 this . maintainKeepAlive ( ) ;
707715
708716 // Persist keep-alive timestamp for cross-session tracking
709- if ( AsyncStorage ) {
710- AsyncStorage . setItem (
711- 'AWS_AMPLIFY_LAST_KEEP_ALIVE' ,
712- `${ Date . now ( ) } ` ,
713- ) . catch ( error => {
714- this . logger . warn ( 'Failed to persist keep-alive timestamp:' , error ) ;
715- } ) ;
717+ if ( platformStorage ) {
718+ platformStorage
719+ . setItem ( KEEP_ALIVE_STORAGE_KEY , `${ Date . now ( ) } ` )
720+ . catch ( error => {
721+ this . logger . warn ( 'Failed to persist keep-alive timestamp:' , error ) ;
722+ } ) ;
716723 }
717724
718725 return ;
@@ -1066,18 +1073,14 @@ export abstract class AWSWebSocketProvider {
10661073 * Get current WebSocket health state
10671074 */
10681075 getConnectionHealth ( ) : WebSocketHealthState {
1069- const timeSinceLastKeepAlive = this . keepAliveTimestamp
1070- ? Date . now ( ) - this . keepAliveTimestamp
1071- : undefined ;
1076+ const timeSinceLastKeepAlive = Date . now ( ) - this . keepAliveTimestamp ;
10721077
10731078 const isHealthy =
10741079 this . connectionState === ConnectionState . Connected &&
1075- this . keepAliveTimestamp &&
1076- timeSinceLastKeepAlive !== undefined &&
1077- timeSinceLastKeepAlive < 65000 ; // 65 second threshold
1080+ timeSinceLastKeepAlive < DEFAULT_KEEP_ALIVE_ALERT_TIMEOUT ;
10781081
10791082 return {
1080- isHealthy : Boolean ( isHealthy ) ,
1083+ isHealthy,
10811084 connectionState : this . connectionState || ConnectionState . Disconnected ,
10821085 lastKeepAliveTime : this . keepAliveTimestamp ,
10831086 timeSinceLastKeepAlive,
@@ -1088,16 +1091,16 @@ export abstract class AWSWebSocketProvider {
10881091 * Get persistent WebSocket health state (survives app restarts)
10891092 */
10901093 async getPersistentConnectionHealth ( ) : Promise < WebSocketHealthState > {
1091- let persistentKeepAliveTime : number | undefined ;
1094+ let persistentKeepAliveTime = 0 ;
10921095
10931096 // Try to get persistent keep-alive timestamp
1094- if ( AsyncStorage ) {
1097+ if ( platformStorage ) {
10951098 try {
1096- const persistentKeepAlive = await AsyncStorage . getItem (
1097- 'AWS_AMPLIFY_LAST_KEEP_ALIVE' ,
1099+ const persistentKeepAlive = await platformStorage . getItem (
1100+ KEEP_ALIVE_STORAGE_KEY ,
10981101 ) ;
10991102 if ( persistentKeepAlive ) {
1100- persistentKeepAliveTime = Number ( persistentKeepAlive ) ;
1103+ persistentKeepAliveTime = Number ( persistentKeepAlive ) || 0 ;
11011104 }
11021105 } catch ( error ) {
11031106 this . logger . warn (
@@ -1108,26 +1111,25 @@ export abstract class AWSWebSocketProvider {
11081111 }
11091112
11101113 // Use the more recent timestamp (in-memory vs persistent)
1111- const lastKeepAliveTime =
1112- Math . max ( this . keepAliveTimestamp || 0 , persistentKeepAliveTime || 0 ) ||
1113- undefined ;
1114+ const lastKeepAliveTime = Math . max (
1115+ this . keepAliveTimestamp ,
1116+ persistentKeepAliveTime ,
1117+ ) ;
11141118
1115- const timeSinceLastKeepAlive = lastKeepAliveTime
1116- ? Date . now ( ) - lastKeepAliveTime
1117- : undefined ;
1119+ const timeSinceLastKeepAlive =
1120+ lastKeepAliveTime > 0 ? Date . now ( ) - lastKeepAliveTime : Infinity ; // If no keep-alive has been received, treat as unhealthy
11181121
11191122 // Health check includes persistent data
11201123 const isHealthy =
11211124 this . connectionState === ConnectionState . Connected &&
1122- lastKeepAliveTime &&
1123- timeSinceLastKeepAlive !== undefined &&
1124- timeSinceLastKeepAlive < 65000 ; // 65 second threshold
1125+ timeSinceLastKeepAlive < DEFAULT_KEEP_ALIVE_ALERT_TIMEOUT ;
11251126
11261127 return {
1127- isHealthy : Boolean ( isHealthy ) ,
1128+ isHealthy,
11281129 connectionState : this . connectionState || ConnectionState . Disconnected ,
1129- lastKeepAliveTime,
1130- timeSinceLastKeepAlive,
1130+ lastKeepAliveTime : lastKeepAliveTime > 0 ? lastKeepAliveTime : undefined ,
1131+ timeSinceLastKeepAlive :
1132+ lastKeepAliveTime > 0 ? timeSinceLastKeepAlive : undefined ,
11311133 } ;
11321134 }
11331135
0 commit comments