@@ -28,8 +28,7 @@ import {
28
28
InputRTCMediaStats ,
29
29
InputRTCMediaTrackClosed ,
30
30
InputRTCExternalPeerAttached ,
31
- InputRuleEvent ,
32
- TimingEvents
31
+ InputRuleEvent
33
32
} from '../../types' ;
34
33
35
34
import { lazyObservablePromise } from '../../util/observable' ;
@@ -114,9 +113,11 @@ type EventType =
114
113
| MockttpEventType
115
114
| MockRTCEventType ;
116
115
117
- export type QueuedEvent = ( {
118
- [ T in EventType ] : { type : T , event : EventTypesMap [ T ] }
119
- } [ EventType ] ) ;
116
+ export type QueuedEvent =
117
+ | ( { // Received Mockttp event data:
118
+ [ T in EventType ] : { type : T , event : EventTypesMap [ T ] }
119
+ } [ EventType ] )
120
+ | { type : 'queued-callback' , cb : ( ) => void } // Or a callback to run after data is processed
120
121
121
122
type OrphanableQueuedEvent < T extends
122
123
| 'response'
@@ -137,6 +138,8 @@ type OrphanableQueuedEvent<T extends
137
138
| 'tls-passthrough-closed'
138
139
> = { type : T , event : EventTypesMap [ T ] } ;
139
140
141
+ const LARGE_QUEUE_BATCH_SIZE = 1033 ; // Off by 33 for a new ticking UI effect
142
+
140
143
export class EventsStore {
141
144
142
145
constructor (
@@ -204,8 +207,18 @@ export class EventsStore {
204
207
// on request animation frame, so batches get larger and cheaper if
205
208
// the frame rate starts to drop.
206
209
207
- this . eventQueue . forEach ( this . updateFromQueuedEvent ) ;
208
- this . eventQueue = [ ] ;
210
+ if ( this . eventQueue . length > LARGE_QUEUE_BATCH_SIZE ) {
211
+ // If there's a lot of events in the queue (only ever likely to happen
212
+ // in an import of a large file) we break it up to keep the UI responsive.
213
+ this . eventQueue . slice ( 0 , LARGE_QUEUE_BATCH_SIZE ) . forEach ( this . updateFromQueuedEvent ) ;
214
+ this . eventQueue = this . eventQueue . slice ( LARGE_QUEUE_BATCH_SIZE ) ;
215
+ setTimeout ( ( ) => {
216
+ this . queueEventFlush ( ) ;
217
+ } , 10 ) ;
218
+ } else {
219
+ this . eventQueue . forEach ( this . updateFromQueuedEvent ) ;
220
+ this . eventQueue = [ ] ;
221
+ }
209
222
}
210
223
211
224
private updateFromQueuedEvent = ( queuedEvent : QueuedEvent ) => {
@@ -263,6 +276,10 @@ export class EventsStore {
263
276
return this . addRTCMediaTrackStats ( queuedEvent . event ) ;
264
277
case 'media-track-closed' :
265
278
return this . markRTCMediaTrackClosed ( queuedEvent . event ) ;
279
+
280
+ case 'queued-callback' :
281
+ queuedEvent . cb ( ) ;
282
+ return ;
266
283
}
267
284
} catch ( e ) {
268
285
// It's possible we might fail to parse an input event. This shouldn't happen, but if it
@@ -643,31 +660,18 @@ export class EventsStore {
643
660
644
661
// We now take each of these input items, and put them on the queue to be added
645
662
// to the UI like any other seen request data. Arguably we could call addRequest &
646
- // setResponse etc directly, but this is nicer if the UI thread is already under strain.
647
-
648
- // First, we run through the request & TLS error events together, in order, since these
649
- // define the initial event ordering
650
- const [ initialEvents , updateEvents ] = _ . partition ( events , ( { type } ) =>
651
- type === 'request' ||
652
- type === 'websocket-request' ||
653
- type === 'tls-client-error'
654
- ) ;
655
- this . eventQueue . push ( ..._ . sortBy ( initialEvents , ( e ) =>
656
- ( e . event as { timingEvents : TimingEvents } ) . timingEvents . startTime
657
- ) ) ;
663
+ // setResponse etc directly, but this is nicer in case the UI thread is already under strain.
664
+ this . eventQueue . push ( ...events ) ;
658
665
659
- // Then we add everything else (responses & aborts). They just update, so order doesn't matter:
660
- this . eventQueue . push ( ...updateEvents ) ;
666
+ // After all events are handled, set the required pins:
667
+ this . eventQueue . push ( {
668
+ type : 'queued-callback' ,
669
+ cb : action ( ( ) => pinnedIds . forEach ( ( id ) => {
670
+ this . events . find ( e => e . id === id ) ! . pinned = true ;
671
+ } ) )
672
+ } ) ;
661
673
662
674
this . queueEventFlush ( ) ;
663
-
664
- if ( pinnedIds . length ) {
665
- // This rAF will be scheduled after the queued flush, so the event should
666
- // always be fully imported by this stage:
667
- requestAnimationFrame ( action ( ( ) => pinnedIds . forEach ( ( id ) => {
668
- this . events . find ( e => e . id === id ) ! . pinned = true ;
669
- } ) ) ) ;
670
- }
671
675
}
672
676
673
677
@action
0 commit comments