mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-05 15:40:10 +00:00
put search provider global state in store
This commit is contained in:
@@ -1,33 +1,19 @@
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { useAlgoliaSearchProvider } from '@/services/providers/algoliaSearchProvider'
|
||||
import { useComfyRegistrySearchProvider } from '@/services/providers/registrySearchProvider'
|
||||
import { useComfyRegistryStore } from '@/stores/comfyRegistryStore'
|
||||
import type { SearchNodePacksParams } from '@/types/algoliaTypes'
|
||||
import type { components } from '@/types/comfyRegistryTypes'
|
||||
import type {
|
||||
NodePackSearchProvider,
|
||||
ProviderState,
|
||||
SearchPacksResult
|
||||
} from '@/types/searchServiceTypes'
|
||||
|
||||
type RegistryNodePack = components['schemas']['Node']
|
||||
|
||||
interface ProviderState {
|
||||
provider: NodePackSearchProvider
|
||||
name: string
|
||||
isHealthy: boolean
|
||||
lastError?: Error
|
||||
lastAttempt?: Date
|
||||
consecutiveFailures: number
|
||||
}
|
||||
|
||||
const CIRCUIT_BREAKER_THRESHOLD = 3 // Number of failures before circuit opens
|
||||
const CIRCUIT_BREAKER_TIMEOUT = 60000 // 1 minute before retry
|
||||
|
||||
// Global state shared across all uses of the gateway
|
||||
const providers: ProviderState[] = []
|
||||
const activeProviderIndex = ref(0)
|
||||
let isInitialized = false
|
||||
|
||||
/**
|
||||
* API Gateway for registry search providers with circuit breaker pattern.
|
||||
* Acts as a single entry point that routes search requests to appropriate providers
|
||||
@@ -39,11 +25,13 @@ let isInitialized = false
|
||||
* - Automatic failover: Cascades through providers on failure
|
||||
*/
|
||||
export const useRegistrySearchGateway = (): NodePackSearchProvider => {
|
||||
const store = useComfyRegistryStore()
|
||||
|
||||
// Initialize providers only once
|
||||
if (!isInitialized) {
|
||||
if (!store.isSearchGatewayInitialized) {
|
||||
// Initialize providers in priority order
|
||||
try {
|
||||
providers.push({
|
||||
store.searchProviders.push({
|
||||
provider: useAlgoliaSearchProvider(),
|
||||
name: 'Algolia',
|
||||
isHealthy: true,
|
||||
@@ -53,14 +41,14 @@ export const useRegistrySearchGateway = (): NodePackSearchProvider => {
|
||||
console.warn('Failed to initialize Algolia provider:', error)
|
||||
}
|
||||
|
||||
providers.push({
|
||||
store.searchProviders.push({
|
||||
provider: useComfyRegistrySearchProvider(),
|
||||
name: 'ComfyRegistry',
|
||||
isHealthy: true,
|
||||
consecutiveFailures: 0
|
||||
})
|
||||
|
||||
isInitialized = true
|
||||
store.isSearchGatewayInitialized = true
|
||||
}
|
||||
|
||||
// TODO: Add an "offline" provider that operates on a local cache of the registry.
|
||||
@@ -118,16 +106,17 @@ export const useRegistrySearchGateway = (): NodePackSearchProvider => {
|
||||
*/
|
||||
const getActiveProvider = (): NodePackSearchProvider => {
|
||||
// First, try to use the current active provider if it's healthy
|
||||
const currentProvider = providers[activeProviderIndex.value]
|
||||
const currentProvider =
|
||||
store.searchProviders[store.activeSearchProviderIndex]
|
||||
if (currentProvider && isCircuitClosed(currentProvider)) {
|
||||
return currentProvider.provider
|
||||
}
|
||||
|
||||
// Otherwise, find the first healthy provider
|
||||
for (let i = 0; i < providers.length; i++) {
|
||||
const providerState = providers[i]
|
||||
for (let i = 0; i < store.searchProviders.length; i++) {
|
||||
const providerState = store.searchProviders[i]
|
||||
if (isCircuitClosed(providerState)) {
|
||||
activeProviderIndex.value = i
|
||||
store.activeSearchProviderIndex = i
|
||||
return providerState.provider
|
||||
}
|
||||
}
|
||||
@@ -140,8 +129,8 @@ export const useRegistrySearchGateway = (): NodePackSearchProvider => {
|
||||
* Move to the next provider if available.
|
||||
*/
|
||||
const updateActiveProviderOnFailure = () => {
|
||||
if (activeProviderIndex.value < providers.length - 1) {
|
||||
activeProviderIndex.value++
|
||||
if (store.activeSearchProviderIndex < store.searchProviders.length - 1) {
|
||||
store.activeSearchProviderIndex++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,17 +144,23 @@ export const useRegistrySearchGateway = (): NodePackSearchProvider => {
|
||||
let lastError: Error | null = null
|
||||
|
||||
// Start with the current active provider
|
||||
for (let attempts = 0; attempts < providers.length; attempts++) {
|
||||
for (
|
||||
let attempts = 0;
|
||||
attempts < store.searchProviders.length;
|
||||
attempts++
|
||||
) {
|
||||
try {
|
||||
const provider = getActiveProvider()
|
||||
const providerState = providers[activeProviderIndex.value]
|
||||
const providerState =
|
||||
store.searchProviders[store.activeSearchProviderIndex]
|
||||
|
||||
const result = await provider.searchPacks(query, params)
|
||||
recordSuccess(providerState)
|
||||
return result
|
||||
} catch (error) {
|
||||
lastError = error as Error
|
||||
const providerState = providers[activeProviderIndex.value]
|
||||
const providerState =
|
||||
store.searchProviders[store.activeSearchProviderIndex]
|
||||
recordFailure(providerState, lastError)
|
||||
console.warn(
|
||||
`${providerState.name} search provider failed (${providerState.consecutiveFailures} failures):`,
|
||||
@@ -187,7 +182,7 @@ export const useRegistrySearchGateway = (): NodePackSearchProvider => {
|
||||
* Clear the search cache for all providers that implement it.
|
||||
*/
|
||||
const clearSearchCache = () => {
|
||||
for (const providerState of providers) {
|
||||
for (const providerState of store.searchProviders) {
|
||||
try {
|
||||
providerState.provider.clearSearchCache()
|
||||
} catch (error) {
|
||||
@@ -229,11 +224,8 @@ export const useRegistrySearchGateway = (): NodePackSearchProvider => {
|
||||
|
||||
/**
|
||||
* Get the filterable fields for the active provider.
|
||||
* This is now a computed property that will react to provider changes.
|
||||
*/
|
||||
const getFilterableFields = () => {
|
||||
// Access activeProviderIndex.value to establish reactivity
|
||||
void activeProviderIndex.value
|
||||
const provider = getActiveProvider()
|
||||
return provider.getFilterableFields()
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import QuickLRU from '@alloc/quick-lru'
|
||||
import { partition } from 'lodash'
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { useCachedRequest } from '@/composables/useCachedRequest'
|
||||
import { useComfyRegistryService } from '@/services/comfyRegistryService'
|
||||
import type { components, operations } from '@/types/comfyRegistryTypes'
|
||||
import type { ProviderState } from '@/types/searchServiceTypes'
|
||||
|
||||
const PACK_LIST_CACHE_SIZE = 20
|
||||
const PACK_BY_ID_CACHE_SIZE = 64
|
||||
@@ -34,6 +36,11 @@ export const useComfyRegistryStore = defineStore('comfyRegistry', () => {
|
||||
maxSize: PACK_BY_ID_CACHE_SIZE
|
||||
})
|
||||
|
||||
// Search gateway state
|
||||
const searchProviders = ref<ProviderState[]>([])
|
||||
const activeSearchProviderIndex = ref(0)
|
||||
const isSearchGatewayInitialized = ref(false)
|
||||
|
||||
/**
|
||||
* Get a list of all node packs from the registry
|
||||
*/
|
||||
@@ -137,6 +144,11 @@ export const useComfyRegistryStore = defineStore('comfyRegistry', () => {
|
||||
cancelRequests,
|
||||
|
||||
isLoading: registryService.isLoading,
|
||||
error: registryService.error
|
||||
error: registryService.error,
|
||||
|
||||
// Search gateway state
|
||||
searchProviders,
|
||||
activeSearchProviderIndex,
|
||||
isSearchGatewayInitialized
|
||||
}
|
||||
})
|
||||
|
||||
@@ -70,3 +70,15 @@ export interface NodePackSearchProvider {
|
||||
*/
|
||||
getFilterableFields(): SearchFilter[]
|
||||
}
|
||||
|
||||
/**
|
||||
* State of a search provider
|
||||
*/
|
||||
export interface ProviderState {
|
||||
provider: NodePackSearchProvider
|
||||
name: string
|
||||
isHealthy: boolean
|
||||
lastError?: Error
|
||||
lastAttempt?: Date
|
||||
consecutiveFailures: number
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user