()
| 39 | }; |
| 40 | |
| 41 | function DMOpsQueueHandler(): React.Node { |
| 42 | const dispatch = useDispatch(); |
| 43 | |
| 44 | const prune = React.useCallback(() => { |
| 45 | const now = Date.now(); |
| 46 | dispatch({ |
| 47 | type: pruneDMOpsQueueActionType, |
| 48 | payload: { |
| 49 | pruneMaxTimestamp: now - QUEUED_OPERATION_TTL, |
| 50 | }, |
| 51 | }); |
| 52 | }, [dispatch]); |
| 53 | |
| 54 | React.useEffect(() => { |
| 55 | const timeoutID = setTimeout(prune, FIRST_PRUNING_DELAY); |
| 56 | const intervalID = setInterval(prune, PRUNING_FREQUENCY); |
| 57 | |
| 58 | return () => { |
| 59 | clearTimeout(timeoutID); |
| 60 | clearInterval(intervalID); |
| 61 | }; |
| 62 | }, [prune]); |
| 63 | |
| 64 | const threadInfos = useSelector(threadInfoSelector); |
| 65 | |
| 66 | const queuedThreadOperations = useSelector( |
| 67 | state => state.queuedDMOperations.threadQueue, |
| 68 | ); |
| 69 | |
| 70 | const processDMOperation = useProcessDMOperation(); |
| 71 | |
| 72 | const processItem = React.useCallback( |
| 73 | async (item: QueueItem) => { |
| 74 | if (item.type === 'operation') { |
| 75 | await processDMOperation({ |
| 76 | // This is `INBOUND` because we assume that when generating |
| 77 | // `dmOperationSpecificationTypes.OUBOUND` it should be possible |
| 78 | // to be processed and never queued up. |
| 79 | type: dmOperationSpecificationTypes.INBOUND, |
| 80 | op: item.operation, |
| 81 | // There is no metadata, because messages were confirmed when |
| 82 | // adding to the queue. |
| 83 | metadata: null, |
| 84 | }); |
| 85 | } else if (item.type === 'action') { |
| 86 | dispatch(item.action); |
| 87 | } else { |
| 88 | item.itemFunction(); |
| 89 | } |
| 90 | }, |
| 91 | [dispatch, processDMOperation], |
| 92 | ); |
| 93 | |
| 94 | const { enqueue } = useActionsQueue(processItem); |
| 95 | |
| 96 | const runningThreadOperations = React.useRef<Set<string>>(new Set()); |
| 97 | |
| 98 | React.useEffect(() => { |
nothing calls this directly
no test coverage detected