Skip to content

Commit 5c67e99

Browse files
waleedlatif1claude
andcommitted
fix(data-drains): dispatcher must short-circuit enterprise check on self-hosted
isOrganizationOnEnterprisePlan returns false on deployments without billing infrastructure, so the dispatcher would silently skip every drain on self-hosted even with DATA_DRAINS_ENABLED=true. Mirror the access.ts pattern: when isBillingEnabled is false, treat all orgs as eligible — the cron route's DATA_DRAINS_ENABLED gate already controls global on/off. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 216c861 commit 5c67e99

2 files changed

Lines changed: 7 additions & 0 deletions

File tree

apps/sim/lib/data-drains/dispatcher.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ vi.mock('@/lib/billing/core/subscription', () => ({
1919
isOrganizationOnEnterprisePlan: mockIsEnterprise,
2020
}))
2121
vi.mock('@/lib/core/async-jobs', () => ({ getJobQueue: mockGetJobQueue }))
22+
vi.mock('@/lib/core/config/feature-flags', () => ({ isBillingEnabled: true }))
2223

2324
import { dispatchDueDrains, reapOrphanedRuns } from '@/lib/data-drains/dispatcher'
2425

apps/sim/lib/data-drains/dispatcher.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { createLogger } from '@sim/logger'
44
import { and, eq, isNull, lt, or } from 'drizzle-orm'
55
import { isOrganizationOnEnterprisePlan } from '@/lib/billing/core/subscription'
66
import { getJobQueue } from '@/lib/core/async-jobs'
7+
import { isBillingEnabled } from '@/lib/core/config/feature-flags'
78

89
const logger = createLogger('DataDrainsDispatcher')
910

@@ -83,8 +84,13 @@ export async function dispatchDueDrains(now: Date = new Date()): Promise<{
8384
}
8485

8586
// Cache enterprise checks per-org since we may have several drains per org.
87+
// Self-hosted (no billing) deployments have no subscription infrastructure,
88+
// so the enterprise predicate would return false for every org and silently
89+
// skip every drain — short-circuit to allow when billing is disabled, and
90+
// let the cron route's `DATA_DRAINS_ENABLED` gate own the global on/off.
8691
const enterpriseCache = new Map<string, boolean>()
8792
const isEnterprise = async (orgId: string): Promise<boolean> => {
93+
if (!isBillingEnabled) return true
8894
const cached = enterpriseCache.get(orgId)
8995
if (cached !== undefined) return cached
9096
const result = await isOrganizationOnEnterprisePlan(orgId)

0 commit comments

Comments
 (0)