mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-01-26 19:09:52 +00:00
feat: optimize empty search to use cached /nodes endpoint (#8159)
## Summary Optimizes the Manager dialog to use the cached `GET /nodes` endpoint instead of `GET /nodes/search` for empty search queries (when the dialog first opens). This significantly reduces Algolia usage since empty searches account for the majority of search requests. ## Changes - **registrySearchProvider.ts**: Modified `searchPacks()` to detect empty queries and route them to `listAllPacks()` instead of `search()` - **registrySearchProvider.test.ts**: Added 5 new test cases covering empty query behavior - Cache clearing now clears both `search` and `listAllPacks` caches ## Technical Details **Empty Query Flow (NEW):** - Query: `""` or whitespace - Endpoint: `GET /nodes?limit=X&page=Y` - Cache: Server-side cached (via omitting `latest` parameter) - Result: Fast, cached node pack list **Non-Empty Query Flow (UNCHANGED):** - Query: Any non-empty string - Endpoint: `GET /nodes/search?search=X` or `comfy_node_search=X` - Result: Search results as before ## Testing ```bash pnpm test:unit -- src/services/providers/registrySearchProvider.test.ts pnpm typecheck ```
This commit is contained in:
committed by
GitHub
parent
b0d7a7f0f4
commit
0d0576faab
@@ -11,6 +11,8 @@ vi.mock('@/stores/comfyRegistryStore', () => ({
|
||||
describe('useComfyRegistrySearchProvider', () => {
|
||||
const mockSearchCall = vi.fn()
|
||||
const mockSearchClear = vi.fn()
|
||||
const mockListAllPacksCall = vi.fn()
|
||||
const mockListAllPacksClear = vi.fn()
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
@@ -20,6 +22,10 @@ describe('useComfyRegistrySearchProvider', () => {
|
||||
search: {
|
||||
call: mockSearchCall,
|
||||
clear: mockSearchClear
|
||||
},
|
||||
listAllPacks: {
|
||||
call: mockListAllPacksCall,
|
||||
clear: mockListAllPacksClear
|
||||
}
|
||||
} as any)
|
||||
})
|
||||
@@ -111,14 +117,85 @@ describe('useComfyRegistrySearchProvider', () => {
|
||||
expect(result.nodePacks).toEqual([])
|
||||
expect(result.querySuggestions).toEqual([])
|
||||
})
|
||||
|
||||
it('should use listAllPacks for empty query', async () => {
|
||||
const mockResults = {
|
||||
nodes: [
|
||||
{ id: '1', name: 'Pack 1' },
|
||||
{ id: '2', name: 'Pack 2' }
|
||||
]
|
||||
}
|
||||
mockListAllPacksCall.mockResolvedValue(mockResults)
|
||||
|
||||
const provider = useComfyRegistrySearchProvider()
|
||||
const result = await provider.searchPacks('', {
|
||||
pageSize: 20,
|
||||
pageNumber: 0
|
||||
})
|
||||
|
||||
expect(mockListAllPacksCall).toHaveBeenCalledWith({
|
||||
limit: 20,
|
||||
page: 1
|
||||
})
|
||||
expect(mockSearchCall).not.toHaveBeenCalled()
|
||||
expect(result.nodePacks).toEqual(mockResults.nodes)
|
||||
expect(result.querySuggestions).toEqual([])
|
||||
})
|
||||
|
||||
it('should use listAllPacks for whitespace-only query', async () => {
|
||||
const mockResults = {
|
||||
nodes: [{ id: '1', name: 'Pack 1' }]
|
||||
}
|
||||
mockListAllPacksCall.mockResolvedValue(mockResults)
|
||||
|
||||
const provider = useComfyRegistrySearchProvider()
|
||||
const result = await provider.searchPacks(' ', {
|
||||
pageSize: 10,
|
||||
pageNumber: 0
|
||||
})
|
||||
|
||||
expect(mockListAllPacksCall).toHaveBeenCalledWith({
|
||||
limit: 10,
|
||||
page: 1
|
||||
})
|
||||
expect(mockSearchCall).not.toHaveBeenCalled()
|
||||
expect(result.nodePacks).toEqual(mockResults.nodes)
|
||||
})
|
||||
|
||||
it('should handle empty results from listAllPacks', async () => {
|
||||
mockListAllPacksCall.mockResolvedValue({ nodes: [] })
|
||||
|
||||
const provider = useComfyRegistrySearchProvider()
|
||||
const result = await provider.searchPacks('', {
|
||||
pageSize: 10,
|
||||
pageNumber: 0
|
||||
})
|
||||
|
||||
expect(result.nodePacks).toEqual([])
|
||||
expect(result.querySuggestions).toEqual([])
|
||||
})
|
||||
|
||||
it('should handle null results from listAllPacks', async () => {
|
||||
mockListAllPacksCall.mockResolvedValue(null)
|
||||
|
||||
const provider = useComfyRegistrySearchProvider()
|
||||
const result = await provider.searchPacks('', {
|
||||
pageSize: 10,
|
||||
pageNumber: 0
|
||||
})
|
||||
|
||||
expect(result.nodePacks).toEqual([])
|
||||
expect(result.querySuggestions).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe('clearSearchCache', () => {
|
||||
it('should delegate to store search.clear', () => {
|
||||
it('should clear both search and listAllPacks caches', () => {
|
||||
const provider = useComfyRegistrySearchProvider()
|
||||
provider.clearSearchCache()
|
||||
|
||||
expect(mockSearchClear).toHaveBeenCalled()
|
||||
expect(mockListAllPacksClear).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -25,33 +25,45 @@ export const useComfyRegistrySearchProvider = (): NodePackSearchProvider => {
|
||||
): Promise<SearchPacksResult> => {
|
||||
const { pageSize, pageNumber, restrictSearchableAttributes } = params
|
||||
|
||||
// Determine search mode based on searchable attributes
|
||||
// For empty queries, use the cached listAllPacks endpoint instead of search
|
||||
if (!query || query.trim() === '') {
|
||||
const listParams = {
|
||||
limit: pageSize,
|
||||
page: pageNumber + 1 // Registry API uses 1-based pagination
|
||||
// Note: omitting 'latest' parameter defaults to cached result
|
||||
}
|
||||
|
||||
const listResult = await registryStore.listAllPacks.call(listParams)
|
||||
const nodePacks = listResult?.nodes ?? []
|
||||
|
||||
return {
|
||||
nodePacks,
|
||||
querySuggestions: []
|
||||
}
|
||||
}
|
||||
|
||||
// For non-empty queries, use the search endpoint
|
||||
const isNodeSearch = restrictSearchableAttributes?.includes('comfy_nodes')
|
||||
|
||||
const searchParams = {
|
||||
search: isNodeSearch ? undefined : query,
|
||||
comfy_node_search: isNodeSearch ? query : undefined,
|
||||
limit: pageSize,
|
||||
page: pageNumber + 1 // Registry API uses 1-based pagination
|
||||
page: pageNumber + 1
|
||||
}
|
||||
|
||||
const searchResult = await registryStore.search.call(searchParams)
|
||||
|
||||
if (!searchResult || !searchResult.nodes) {
|
||||
return {
|
||||
nodePacks: [],
|
||||
querySuggestions: []
|
||||
}
|
||||
}
|
||||
const nodePacks = searchResult?.nodes ?? []
|
||||
|
||||
return {
|
||||
nodePacks: searchResult.nodes,
|
||||
nodePacks,
|
||||
querySuggestions: [] // Registry doesn't support query suggestions
|
||||
}
|
||||
}
|
||||
|
||||
const clearSearchCache = () => {
|
||||
registryStore.search.clear()
|
||||
registryStore.listAllPacks.clear()
|
||||
}
|
||||
|
||||
const getSortValue = (
|
||||
|
||||
Reference in New Issue
Block a user