Throttle re-renders for rapidly-updating messages
This commit is contained in:
		
					parent
					
						
							
								9206b9984b
							
						
					
				
			
			
				commit
				
					
						0da867a0ef
					
				
			
		
					 1 changed files with 47 additions and 22 deletions
				
			
		|  | @ -2,6 +2,8 @@ | ||||||
| // SPDX-License-Identifier: AGPL-3.0-only
 | // SPDX-License-Identifier: AGPL-3.0-only
 | ||||||
| 
 | 
 | ||||||
| import cloneDeep from 'lodash/cloneDeep'; | import cloneDeep from 'lodash/cloneDeep'; | ||||||
|  | import { throttle } from 'lodash'; | ||||||
|  | import LRU from 'lru-cache'; | ||||||
| import type { MessageAttributesType } from '../model-types.d'; | import type { MessageAttributesType } from '../model-types.d'; | ||||||
| import type { MessageModel } from '../models/messages'; | import type { MessageModel } from '../models/messages'; | ||||||
| import * as Errors from '../types/errors'; | import * as Errors from '../types/errors'; | ||||||
|  | @ -17,6 +19,7 @@ import { softAssert, strictAssert } from '../util/assert'; | ||||||
| import { isStory } from '../messages/helpers'; | import { isStory } from '../messages/helpers'; | ||||||
| import { getStoryDataFromMessageAttributes } from './storyLoader'; | import { getStoryDataFromMessageAttributes } from './storyLoader'; | ||||||
| 
 | 
 | ||||||
|  | const MAX_THROTTLED_REDUX_UPDATERS = 200; | ||||||
| export class MessageCache { | export class MessageCache { | ||||||
|   private state = { |   private state = { | ||||||
|     messages: new Map<string, MessageAttributesType>(), |     messages: new Map<string, MessageAttributesType>(), | ||||||
|  | @ -198,28 +201,7 @@ export class MessageCache { | ||||||
| 
 | 
 | ||||||
|     this.markModelStale(nextMessageAttributes); |     this.markModelStale(nextMessageAttributes); | ||||||
| 
 | 
 | ||||||
|     if (window.reduxActions) { |     this.throttledUpdateRedux(nextMessageAttributes); | ||||||
|       if (isStory(nextMessageAttributes)) { |  | ||||||
|         const storyData = getStoryDataFromMessageAttributes({ |  | ||||||
|           ...nextMessageAttributes, |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|         if (!storyData) { |  | ||||||
|           return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         window.reduxActions.stories.storyChanged(storyData); |  | ||||||
| 
 |  | ||||||
|         // We don't want messageChanged to run
 |  | ||||||
|         return; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       window.reduxActions.conversations.messageChanged( |  | ||||||
|         messageId, |  | ||||||
|         nextMessageAttributes.conversationId, |  | ||||||
|         nextMessageAttributes |  | ||||||
|       ); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (skipSaveToDatabase) { |     if (skipSaveToDatabase) { | ||||||
|       return; |       return; | ||||||
|  | @ -231,6 +213,49 @@ export class MessageCache { | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   private throttledReduxUpdaters = new LRU<string, typeof this.updateRedux>({ | ||||||
|  |     max: MAX_THROTTLED_REDUX_UPDATERS, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   private throttledUpdateRedux(attributes: MessageAttributesType) { | ||||||
|  |     let updater = this.throttledReduxUpdaters.get(attributes.id); | ||||||
|  |     if (!updater) { | ||||||
|  |       updater = throttle(this.updateRedux.bind(this), 200, { | ||||||
|  |         leading: true, | ||||||
|  |         trailing: true, | ||||||
|  |       }); | ||||||
|  |       this.throttledReduxUpdaters.set(attributes.id, updater); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     updater(attributes); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   private updateRedux(attributes: MessageAttributesType) { | ||||||
|  |     if (!window.reduxActions) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     if (isStory(attributes)) { | ||||||
|  |       const storyData = getStoryDataFromMessageAttributes({ | ||||||
|  |         ...attributes, | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       if (!storyData) { | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       window.reduxActions.stories.storyChanged(storyData); | ||||||
|  | 
 | ||||||
|  |       // We don't want messageChanged to run
 | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     window.reduxActions.conversations.messageChanged( | ||||||
|  |       attributes.id, | ||||||
|  |       attributes.conversationId, | ||||||
|  |       attributes | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   // When you already have the message attributes from the db and want to
 |   // When you already have the message attributes from the db and want to
 | ||||||
|   // ensure that they're added to the cache. The latest attributes from cache
 |   // ensure that they're added to the cache. The latest attributes from cache
 | ||||||
|   // are returned if they exist, if not the attributes passed in are returned.
 |   // are returned if they exist, if not the attributes passed in are returned.
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 trevor-signal
				trevor-signal