1+ import QuickLRU from '@alloc/quick-lru'
12import type {
23 BaseSearchParamsWithoutQuery ,
34 Hit ,
5+ SearchQuery ,
46 SearchResponse
57} from 'algoliasearch/dist/lite/browser'
68import { liteClient as algoliasearch } from 'algoliasearch/dist/lite/builds/browser'
79import { omit } from 'lodash'
810
911import { components } from '@/types/comfyRegistryTypes'
12+ import { paramsToCacheKey } from '@/utils/formatUtil'
13+
14+ const DEFAULT_MAX_CACHE_SIZE = 64
15+ const DEFAULT_MIN_CHARS_FOR_SUGGESTIONS = 2
1016
1117type SafeNestedProperty <
1218 T ,
@@ -15,6 +21,10 @@ type SafeNestedProperty<
1521> = T [ K1 ] extends undefined | null ? undefined : NonNullable < T [ K1 ] > [ K2 ]
1622
1723type RegistryNodePack = components [ 'schemas' ] [ 'Node' ]
24+ type SearchPacksResult = {
25+ nodePacks : Hit < AlgoliaNodePack > [ ]
26+ querySuggestions : Hit < NodesIndexSuggestion > [ ]
27+ }
1828
1929export interface AlgoliaNodePack {
2030 objectID : RegistryNodePack [ 'id' ]
@@ -91,8 +101,33 @@ type SearchNodePacksParams = BaseSearchParamsWithoutQuery & {
91101 restrictSearchableAttributes : SearchAttribute [ ]
92102}
93103
94- export const useAlgoliaSearchService = ( ) => {
104+ interface AlgoliaSearchServiceOptions {
105+ /**
106+ * Maximum number of search results to store in the cache.
107+ * The cache is automatically cleared when the component is unmounted.
108+ * @default 64
109+ */
110+ maxCacheSize ?: number
111+ /**
112+ * Minimum number of characters for suggestions. An additional query
113+ * will be made to the suggestions/completions index for queries that
114+ * are this length or longer.
115+ * @default 3
116+ */
117+ minCharsForSuggestions ?: number
118+ }
119+
120+ export const useAlgoliaSearchService = (
121+ options : AlgoliaSearchServiceOptions = { }
122+ ) => {
123+ const {
124+ maxCacheSize = DEFAULT_MAX_CACHE_SIZE ,
125+ minCharsForSuggestions = DEFAULT_MIN_CHARS_FOR_SUGGESTIONS
126+ } = options
95127 const searchClient = algoliasearch ( __ALGOLIA_APP_ID__ , __ALGOLIA_API_KEY__ )
128+ const searchPacksCache = new QuickLRU < string , SearchPacksResult > ( {
129+ maxSize : maxCacheSize
130+ } )
96131
97132 const toRegistryLatestVersion = (
98133 algoliaNode : AlgoliaNodePack
@@ -141,34 +176,39 @@ export const useAlgoliaSearchService = () => {
141176 const searchPacks = async (
142177 query : string ,
143178 params : SearchNodePacksParams
144- ) : Promise < {
145- nodePacks : Hit < AlgoliaNodePack > [ ]
146- querySuggestions : Hit < NodesIndexSuggestion > [ ]
147- } > => {
179+ ) : Promise < SearchPacksResult > => {
148180 const { pageSize, pageNumber } = params
149181 const rest = omit ( params , [ 'pageSize' , 'pageNumber' ] )
150182
183+ const requests : SearchQuery [ ] = [
184+ {
185+ query,
186+ indexName : 'nodes_index' ,
187+ attributesToRetrieve : RETRIEVE_ATTRIBUTES ,
188+ ...rest ,
189+ hitsPerPage : pageSize ,
190+ page : pageNumber
191+ }
192+ ]
193+
194+ const shouldQuerySuggestions = query . length >= minCharsForSuggestions
195+
196+ // If the query is long enough, also query the suggestions index
197+ if ( shouldQuerySuggestions ) {
198+ requests . push ( {
199+ indexName : 'nodes_index_query_suggestions' ,
200+ query
201+ } )
202+ }
203+
151204 const { results } = await searchClient . search <
152205 AlgoliaNodePack | NodesIndexSuggestion
153206 > ( {
154- requests : [
155- {
156- query,
157- indexName : 'nodes_index' ,
158- attributesToRetrieve : RETRIEVE_ATTRIBUTES ,
159- ...rest ,
160- hitsPerPage : pageSize ,
161- page : pageNumber
162- } ,
163- {
164- indexName : 'nodes_index_query_suggestions' ,
165- query
166- }
167- ] ,
207+ requests,
168208 strategy : 'none'
169209 } )
170210
171- const [ nodePacks , querySuggestions ] = results as [
211+ const [ nodePacks , querySuggestions = { hits : [ ] } ] = results as [
172212 SearchResponse < AlgoliaNodePack > ,
173213 SearchResponse < NodesIndexSuggestion >
174214 ]
@@ -179,8 +219,27 @@ export const useAlgoliaSearchService = () => {
179219 }
180220 }
181221
222+ const searchPacksCached = async (
223+ query : string ,
224+ params : SearchNodePacksParams
225+ ) : Promise < SearchPacksResult > => {
226+ const cacheKey = paramsToCacheKey ( { query, ...params } )
227+ const cachedResult = searchPacksCache . get ( cacheKey )
228+ if ( cachedResult !== undefined ) return cachedResult
229+
230+ const result = await searchPacks ( query , params )
231+ searchPacksCache . set ( cacheKey , result )
232+ return result
233+ }
234+
235+ const clearSearchPacksCache = ( ) => {
236+ searchPacksCache . clear ( )
237+ }
238+
182239 return {
183240 searchPacks,
184- toRegistryPack
241+ searchPacksCached,
242+ toRegistryPack,
243+ clearSearchPacksCache
185244 }
186245}
0 commit comments