diff --git a/projects/plugins/protect/changelog/update-protect-optimistically-scanning b/projects/plugins/protect/changelog/update-protect-optimistically-scanning new file mode 100644 index 0000000000000..35a9a6afb5f74 --- /dev/null +++ b/projects/plugins/protect/changelog/update-protect-optimistically-scanning @@ -0,0 +1,4 @@ +Significance: minor +Type: changed + +Improves optimistic scanning diff --git a/projects/plugins/protect/src/js/data/scan/use-scan-status-query.ts b/projects/plugins/protect/src/js/data/scan/use-scan-status-query.ts index e01d5fcfb1213..848b4395e6baf 100644 --- a/projects/plugins/protect/src/js/data/scan/use-scan-status-query.ts +++ b/projects/plugins/protect/src/js/data/scan/use-scan-status-query.ts @@ -1,5 +1,5 @@ import { useConnection } from '@automattic/jetpack-connection'; -import { useQuery, UseQueryResult } from '@tanstack/react-query'; +import { useQuery, UseQueryResult, useQueryClient } from '@tanstack/react-query'; import camelize from 'camelize'; import API from '../../api'; import { @@ -10,6 +10,31 @@ import { import { ScanStatus } from '../../types/scans'; import { QUERY_SCAN_STATUS_KEY } from './../../constants'; +export const isRequestedScanNotStarted = ( status: ScanStatus ) => { + if ( status.status !== 'idle' ) { + return false; + } + + const lastRequestedScanTimestamp = Number( localStorage.getItem( 'last_requested_scan' ) ); + + if ( ! lastRequestedScanTimestamp ) { + return false; + } + + if ( lastRequestedScanTimestamp < Date.now() - 5 * 60 * 1000 ) { + return false; + } + + const lastCheckedTimestamp = new Date( status.lastChecked + ' UTC' ).getTime(); + + const isScanCompleted = lastCheckedTimestamp > lastRequestedScanTimestamp; + if ( isScanCompleted ) { + return false; + } + + return true; +}; + export const isScanInProgress = ( status: ScanStatus ) => { // If there has never been a scan, and the scan status is idle or unavailable, then we must still be getting set up. const scanIsInitializing = @@ -32,6 +57,7 @@ export const isScanInProgress = ( status: ScanStatus ) => { export default function useScanStatusQuery( { usePolling, }: { usePolling?: boolean } = {} ): UseQueryResult< ScanStatus > { + const queryClient = useQueryClient(); const { isRegistered } = useConnection( { autoTrigger: false, from: 'protect', @@ -41,7 +67,18 @@ export default function useScanStatusQuery( { return useQuery( { queryKey: [ QUERY_SCAN_STATUS_KEY ], - queryFn: API.getScanStatus, + queryFn: async () => { + // Fetch scan status data from the API + const data = await API.getScanStatus(); + + // Return cached data if conditions are met + if ( isRequestedScanNotStarted( data ) ) { + return queryClient.getQueryData( [ QUERY_SCAN_STATUS_KEY ] ); + } + + // If cached data is not applicable or expired, return the fresh API data + return data; + }, initialData: camelize( window?.jetpackProtectInitialState?.status ), enabled: isRegistered, refetchInterval( query ) { diff --git a/projects/plugins/protect/src/js/data/scan/use-start-scan-mutation.ts b/projects/plugins/protect/src/js/data/scan/use-start-scan-mutation.ts index 8f65b0410f83d..ba2433e99620f 100644 --- a/projects/plugins/protect/src/js/data/scan/use-start-scan-mutation.ts +++ b/projects/plugins/protect/src/js/data/scan/use-start-scan-mutation.ts @@ -24,6 +24,8 @@ export default function useStartScanMutation(): UseMutationResult { ...currentStatus, status: SCAN_STATUS_OPTIMISTICALLY_SCANNING, } ) ); + + localStorage.setItem( 'last_requested_scan', Date.now().toString() ); }, onError() { // The scan failed to enqueue, invalidate the scan status query to reset the current status.