11// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22// SPDX-License-Identifier: Apache-2.0
3- import { useEffect , useState } from 'react' ;
3+ import { useEffect , useState , useCallback , useRef } from 'react' ;
44import { generateClient } from 'aws-amplify/api' ;
55import { ConsoleLogger } from 'aws-amplify/utils' ;
66
@@ -24,21 +24,26 @@ const useGraphQlApi = ({ initialPeriodsToLoad = DOCUMENT_LIST_SHARDS_PER_DAY * 2
2424 const [ documents , setDocuments ] = useState ( [ ] ) ;
2525 const { setErrorMessage } = useAppContext ( ) ;
2626
27- const setDocumentsDeduped = ( documentValues ) => {
27+ const subscriptionsRef = useRef ( { onCreate : null , onUpdate : null } ) ;
28+
29+ const setDocumentsDeduped = useCallback ( ( documentValues ) => {
30+ logger . debug ( 'setDocumentsDeduped called with:' , documentValues ) ;
2831 setDocuments ( ( currentDocuments ) => {
2932 const documentValuesdocumentIds = documentValues . map ( ( c ) => c . ObjectKey ) ;
30- return [
33+ const updatedDocuments = [
3134 ...currentDocuments . filter ( ( c ) => ! documentValuesdocumentIds . includes ( c . ObjectKey ) ) ,
3235 ...documentValues . map ( ( document ) => ( {
3336 ...document ,
3437 ListPK : document . ListPK || currentDocuments . find ( ( c ) => c . ObjectKey === document . ObjectKey ) ?. ListPK ,
3538 ListSK : document . ListSK || currentDocuments . find ( ( c ) => c . ObjectKey === document . ObjectKey ) ?. ListSK ,
3639 } ) ) ,
3740 ] ;
41+ logger . debug ( 'Documents state updated, new count:' , updatedDocuments . length ) ;
42+ return updatedDocuments ;
3843 } ) ;
39- } ;
44+ } , [ ] ) ;
4045
41- const getDocumentDetailsFromIds = async ( objectKeys ) => {
46+ const getDocumentDetailsFromIds = useCallback ( async ( objectKeys ) => {
4247 // prettier-ignore
4348 logger . debug ( 'getDocumentDetailsFromIds' , objectKeys ) ;
4449 const getDocumentPromises = objectKeys . map ( ( objectKey ) =>
@@ -55,46 +60,80 @@ const useGraphQlApi = ({ initialPeriodsToLoad = DOCUMENT_LIST_SHARDS_PER_DAY * 2
5560 . map ( ( r ) => r . value ?. data ?. getDocument ) ;
5661
5762 return documentValues ;
58- } ;
63+ } , [ setErrorMessage ] ) ;
5964
6065 useEffect ( ( ) => {
66+ if ( subscriptionsRef . current . onCreate ) {
67+ logger . debug ( 'onCreateDocument subscription already exists, skipping' ) ;
68+ return ;
69+ }
70+
6171 logger . debug ( 'onCreateDocument subscription' ) ;
6272 const subscription = client . graphql ( { query : onCreateDocument } ) . subscribe ( {
63- next : async ( { provider, value } ) => {
64- logger . debug ( 'document list subscription update' , { provider, value } ) ;
65- const objectKey = value ?. data ?. onCreateDocument . ObjectKey || '' ;
73+ next : async ( subscriptionData ) => {
74+ logger . debug ( 'document list subscription update' , subscriptionData ) ;
75+ const data = subscriptionData ?. data ;
76+ const objectKey = data ?. onCreateDocument ?. ObjectKey || '' ;
6677 if ( objectKey ) {
67- const documentValues = await getDocumentDetailsFromIds ( [ objectKey ] ) ;
68- setDocumentsDeduped ( documentValues ) ;
78+ try {
79+ const documentValues = await getDocumentDetailsFromIds ( [ objectKey ] ) ;
80+ if ( documentValues && documentValues . length > 0 ) {
81+ setDocumentsDeduped ( documentValues ) ;
82+ }
83+ } catch ( error ) {
84+ logger . error ( 'Error processing onCreateDocument subscription:' , error ) ;
85+ }
6986 }
7087 } ,
7188 error : ( error ) => {
72- logger . error ( error ) ;
89+ logger . error ( 'onCreateDocument subscription error:' , error ) ;
7390 setErrorMessage ( 'document list network subscription failed - please reload the page' ) ;
7491 } ,
7592 } ) ;
7693
77- return ( ) => subscription . unsubscribe ( ) ;
78- } , [ ] ) ;
94+ subscriptionsRef . current . onCreate = subscription ;
95+
96+ return ( ) => {
97+ logger . debug ( 'onCreateDocument subscription cleanup' ) ;
98+ if ( subscriptionsRef . current . onCreate ) {
99+ subscriptionsRef . current . onCreate . unsubscribe ( ) ;
100+ subscriptionsRef . current . onCreate = null ;
101+ }
102+ } ;
103+ } , [ getDocumentDetailsFromIds , setDocumentsDeduped , setErrorMessage ] ) ;
79104
80105 useEffect ( ( ) => {
81- logger . debug ( 'onUpdateDocument subscription' ) ;
106+ if ( subscriptionsRef . current . onUpdate ) {
107+ logger . debug ( 'onUpdateDocument subscription already exists, skipping' ) ;
108+ return ;
109+ }
110+
111+ logger . debug ( 'onUpdateDocument subscription setup' ) ;
82112 const subscription = client . graphql ( { query : onUpdateDocument } ) . subscribe ( {
83- next : async ( { provider, value } ) => {
84- logger . debug ( 'document update' , { provider, value } ) ;
85- const documentUpdateEvent = value ?. data ?. onUpdateDocument ;
113+ next : async ( subscriptionData ) => {
114+ logger . debug ( 'document update subscription received' , subscriptionData ) ;
115+ const data = subscriptionData ?. data ;
116+ const documentUpdateEvent = data ?. onUpdateDocument ;
86117 if ( documentUpdateEvent ?. ObjectKey ) {
87118 setDocumentsDeduped ( [ documentUpdateEvent ] ) ;
88119 }
89120 } ,
90121 error : ( error ) => {
91- logger . error ( error ) ;
122+ logger . error ( 'onUpdateDocument subscription error:' , error ) ;
92123 setErrorMessage ( 'document update network request failed - please reload the page' ) ;
93124 } ,
94125 } ) ;
95126
96- return ( ) => subscription . unsubscribe ( ) ;
97- } , [ ] ) ;
127+ subscriptionsRef . current . onUpdate = subscription ;
128+
129+ return ( ) => {
130+ logger . debug ( 'onUpdateDocument subscription cleanup' ) ;
131+ if ( subscriptionsRef . current . onUpdate ) {
132+ subscriptionsRef . current . onUpdate . unsubscribe ( ) ;
133+ subscriptionsRef . current . onUpdate = null ;
134+ }
135+ } ;
136+ } , [ setDocumentsDeduped , setErrorMessage , getDocumentDetailsFromIds ] ) ;
98137
99138 const listDocumentIdsByDateShards = async ( { date, shards } ) => {
100139 const listDocumentsDateShardPromises = shards . map ( ( i ) => {
0 commit comments