1- import {
2- createContext ,
3- useCallback ,
4- useContext ,
5- useMemo ,
6- useRef ,
7- type PropsWithChildren ,
8- } from "react"
9- import { useDatabrowserStore } from "@/store"
1+ import { createContext , useContext , useMemo , type PropsWithChildren } from "react"
2+ import { useDatabrowser , useDatabrowserStore } from "@/store"
3+ import type { DataType , RedisKey } from "@/types"
104import { useInfiniteQuery , type UseInfiniteQueryResult } from "@tanstack/react-query"
115
12- import { useFetchKeyType } from "./use-fetch-key-type"
13- import { useFetchKeys , type RedisKey } from "./use-fetch-keys"
14-
156const KeysContext = createContext <
167 | {
178 keys : RedisKey [ ]
189 query : UseInfiniteQueryResult
19- refetch : ( ) => void
2010 }
2111 | undefined
2212> ( undefined )
2313
2414export const FETCH_KEYS_QUERY_KEY = "use-fetch-keys"
2515
16+ const SCAN_COUNT = 100
17+
2618export const KeysProvider = ( { children } : PropsWithChildren ) => {
2719 const { search } = useDatabrowserStore ( )
28- const cleanSearchKey = search . key . replace ( "*" , "" )
2920
30- const { data : exactMatchType , isFetching, isLoading } = useFetchKeyType ( cleanSearchKey )
31-
32- const { fetchKeys, resetCache } = useFetchKeys ( search )
33- const pageRef = useRef ( 0 )
21+ const { redisNoPipeline : redis } = useDatabrowser ( )
3422
3523 const query = useInfiniteQuery ( {
3624 queryKey : [ FETCH_KEYS_QUERY_KEY , search ] ,
3725
38- initialPageParam : 0 ,
39- queryFn : async ( { pageParam : page } ) => {
26+ initialPageParam : "0" ,
27+ queryFn : async ( { pageParam : lastCursor } ) => {
4028 // We should reset the cache when the pagination is reset
41- if ( pageRef . current >= page ) resetCache ( )
42- pageRef . current = page
4329
44- return await fetchKeys ( )
30+ const args = [ lastCursor ]
31+
32+ if ( search . key ) {
33+ args . push ( "MATCH" , search . key )
34+ }
35+
36+ if ( search . type ) {
37+ args . push ( "TYPE" , search . type )
38+ }
39+
40+ args . push ( "COUNT" , SCAN_COUNT . toString ( ) )
41+
42+ if ( ! search . type ) args . push ( "WITHTYPE" )
43+
44+ const [ cursor , values ] = await redis . exec < [ string , string [ ] ] > ( [ "SCAN" , ...args ] )
45+ const keys : RedisKey [ ] = [ ]
46+
47+ let index = 0
48+ while ( true ) {
49+ if ( search . type ) {
50+ if ( index >= values . length ) break
51+ keys . push ( [ values [ index ] , search . type as DataType ] )
52+ index += 1
53+ } else {
54+ if ( index + 1 >= values . length ) break
55+ keys . push ( [ values [ index ] , values [ index + 1 ] as DataType ] )
56+ index += 2
57+ }
58+ }
59+
60+ return {
61+ cursor : cursor === "0" ? undefined : cursor ,
62+ keys,
63+ hasNextPage : cursor !== "0" ,
64+ }
4565 } ,
4666 select : ( data ) => data ,
47- getNextPageParam : ( lastPage , __ , lastPageIndex ) => {
48- return lastPage . hasNextPage ? lastPageIndex + 1 : undefined
49- } ,
50- enabled : ! isFetching ,
67+ getNextPageParam : ( { cursor } ) => cursor ,
5168 refetchOnMount : false ,
5269 } )
5370
54- const refetch = useCallback ( ( ) => {
55- resetCache ( )
56- query . refetch ( )
57- } , [ query , resetCache ] )
58-
5971 const keys = useMemo ( ( ) => {
6072 const keys = query . data ?. pages . flatMap ( ( page ) => page . keys ) ?? [ ]
6173
62- // Include the exact match if it exists before SCAN returns
63- if (
64- exactMatchType &&
65- exactMatchType !== "none" &&
66- ( search . type === undefined || search . type === exactMatchType )
67- ) {
68- keys . push ( [ cleanSearchKey , exactMatchType ] )
69- }
70-
7174 // deduplication
7275 const keysSet = new Set < string > ( )
7376 const dedupedKeys : RedisKey [ ] = [ ]
@@ -79,19 +82,13 @@ export const KeysProvider = ({ children }: PropsWithChildren) => {
7982 dedupedKeys . push ( key )
8083 }
8184 return dedupedKeys
82- } , [ query . data , cleanSearchKey , exactMatchType ] )
85+ } , [ query . data ] )
8386
8487 return (
8588 < KeysContext . Provider
8689 value = { {
8790 keys,
88- // @ts -expect-error Ignore the error with spread syntax
89- query : {
90- ...query ,
91- isLoading : isLoading || query . isLoading ,
92- isFetching : isFetching || query . isFetching ,
93- } ,
94- refetch,
91+ query,
9592 } }
9693 >
9794 { children }
0 commit comments