[backport cloud/1.39] feat: gate node replacement loading on server feature flag (#8941)

Backport of #8750 to `cloud/1.39`

Automatically created by backport workflow.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8941-backport-cloud-1-39-feat-gate-node-replacement-loading-on-server-feature-flag-30a6d73d36508141923bdcbf614dd917)
by [Unito](https://www.unito.io)

Co-authored-by: Christian Byrne <cbyrne@comfy.org>
Co-authored-by: Jin Yi <jin12cc@gmail.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Comfy Org PR Bot
2026-02-18 04:56:52 +09:00
committed by GitHub
parent 4eb8148e81
commit 177f833233
3 changed files with 35 additions and 2 deletions

View File

@@ -20,7 +20,8 @@ export enum ServerFeatureFlag {
ONBOARDING_SURVEY_ENABLED = 'onboarding_survey_enabled',
LINEAR_TOGGLE_ENABLED = 'linear_toggle_enabled',
TEAM_WORKSPACES_ENABLED = 'team_workspaces_enabled',
USER_SECRETS_ENABLED = 'user_secrets_enabled'
USER_SECRETS_ENABLED = 'user_secrets_enabled',
NODE_REPLACEMENTS = 'node_replacements'
}
/**
@@ -96,6 +97,9 @@ export function useFeatureFlags() {
remoteConfig.value.user_secrets_enabled ??
api.getServerFeature(ServerFeatureFlag.USER_SECRETS_ENABLED, false)
)
},
get nodeReplacementsEnabled() {
return api.getServerFeature(ServerFeatureFlag.NODE_REPLACEMENTS, false)
}
})

View File

@@ -15,6 +15,18 @@ vi.mock('./nodeReplacementService', () => ({
fetchNodeReplacements: vi.fn()
}))
const mockNodeReplacementsEnabled = vi.hoisted(() => ({ value: true }))
vi.mock('@/composables/useFeatureFlags', () => ({
useFeatureFlags: vi.fn(() => ({
flags: {
get nodeReplacementsEnabled() {
return mockNodeReplacementsEnabled.value
}
}
}))
}))
function mockSettingStore(enabled: boolean) {
vi.mocked(useSettingStore, { partial: true }).mockReturnValue({
get: vi.fn().mockImplementation((key: string) => {
@@ -27,9 +39,10 @@ function mockSettingStore(enabled: boolean) {
})
}
function createStore(enabled = true) {
function createStore(enabled = true, featureEnabled = true) {
setActivePinia(createPinia())
mockSettingStore(enabled)
mockNodeReplacementsEnabled.value = featureEnabled
return useNodeReplacementStore()
}
@@ -38,6 +51,7 @@ describe('useNodeReplacementStore', () => {
beforeEach(() => {
vi.clearAllMocks()
mockNodeReplacementsEnabled.value = true
store = createStore(true)
})
@@ -257,5 +271,15 @@ describe('useNodeReplacementStore', () => {
expect(fetchNodeReplacements).not.toHaveBeenCalled()
expect(store.isLoaded).toBe(false)
})
it('should not call API when server feature flag is disabled', async () => {
vi.mocked(fetchNodeReplacements).mockResolvedValue(mockReplacements)
store = createStore(true, false)
await store.load()
expect(fetchNodeReplacements).not.toHaveBeenCalled()
expect(store.isLoaded).toBe(false)
})
})
})

View File

@@ -3,6 +3,7 @@ import type { NodeReplacement, NodeReplacementResponse } from './types'
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import { useFeatureFlags } from '@/composables/useFeatureFlags'
import { useSettingStore } from '@/platform/settings/settingStore'
import { fetchNodeReplacements } from './nodeReplacementService'
@@ -14,8 +15,12 @@ export const useNodeReplacementStore = defineStore('nodeReplacement', () => {
settingStore.get('Comfy.NodeReplacement.Enabled')
)
const { flags } = useFeatureFlags()
async function load() {
if (!isEnabled.value || isLoaded.value) return
if (!flags.nodeReplacementsEnabled) return
try {
replacements.value = await fetchNodeReplacements()
isLoaded.value = true