mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
fix(studio): bump realtime max_concurrent_users soft limit (#50438)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Bump realtime max_concurrent_users soft limit to 300k <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Increased the maximum supported concurrent clients from 50,000 to 300,000 when plan entitlements allow it. * **Bug Fixes** * Improved validation for concurrent-client limits, including clearer handling of entitlement-based and unlimited limits. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
This commit is contained in:
1 parent
babebc959c
commit
c15b0836d8
2 files changed
+84
-14
No files matched your search
@@ -68,19 +68,28 @@ const REALTIME_CONFIG = {
|
||||
suspend: false,
|
||||
} as const satisfies RealtimeConfigurationData
|
||||
|
||||
const REALTIME_ENTITLEMENTS: Entitlement[] = (
|
||||
[
|
||||
['realtime.max_concurrent_users', 50_000],
|
||||
['realtime.max_events_per_second', 50_000],
|
||||
['realtime.max_presence_events_per_second', 5_000],
|
||||
['realtime.max_payload_size_in_kb', 3_000],
|
||||
] satisfies [FeatureKey, number][]
|
||||
).map(([key, value]) => ({
|
||||
config: { enabled: true, unit: '', unlimited: false, value },
|
||||
feature: { key, type: 'numeric' },
|
||||
hasAccess: true,
|
||||
type: 'numeric',
|
||||
}))
|
||||
const buildRealtimeEntitlements = (
|
||||
overrides: Partial<Record<FeatureKey, number | 'unlimited'>> = {}
|
||||
): Entitlement[] =>
|
||||
(
|
||||
[
|
||||
['realtime.max_concurrent_users', 50_000],
|
||||
['realtime.max_events_per_second', 50_000],
|
||||
['realtime.max_presence_events_per_second', 5_000],
|
||||
['realtime.max_payload_size_in_kb', 3_000],
|
||||
] satisfies [FeatureKey, number][]
|
||||
).map(([key, value]) => {
|
||||
const override = overrides[key]
|
||||
const unlimited = override === 'unlimited'
|
||||
return {
|
||||
config: { enabled: true, unit: '', unlimited, value: unlimited ? 0 : (override ?? value) },
|
||||
feature: { key, type: 'numeric' },
|
||||
hasAccess: true,
|
||||
type: 'numeric',
|
||||
}
|
||||
})
|
||||
|
||||
const REALTIME_ENTITLEMENTS: Entitlement[] = buildRealtimeEntitlements()
|
||||
|
||||
describe('RealtimeSettings', () => {
|
||||
beforeEach(() => {
|
||||
@@ -199,4 +208,65 @@ describe('RealtimeSettings', () => {
|
||||
expect(requests).toHaveLength(0)
|
||||
}
|
||||
})
|
||||
|
||||
test.each([
|
||||
{ value: '300000', accepted: true },
|
||||
{ value: '300001', accepted: false },
|
||||
])(
|
||||
'$accepted for max concurrent clients of $value when the entitlement is unlimited',
|
||||
async ({ value, accepted }) => {
|
||||
addAPIMock({
|
||||
method: 'get',
|
||||
path: '/platform/organizations/:slug/entitlements',
|
||||
response: {
|
||||
entitlements: buildRealtimeEntitlements({ 'realtime.max_concurrent_users': 'unlimited' }),
|
||||
},
|
||||
})
|
||||
|
||||
const requests: unknown[] = []
|
||||
addAPIMock({
|
||||
method: 'patch',
|
||||
path: '/platform/projects/:ref/config/realtime',
|
||||
response: async ({ request }) => {
|
||||
requests.push(await request.json())
|
||||
return new HttpResponse(null, { status: 204 })
|
||||
},
|
||||
})
|
||||
|
||||
customRender(<RealtimeSettings />)
|
||||
|
||||
const maxConcurrentUsersInput = await screen.findByLabelText('Max concurrent clients')
|
||||
await userEvent.clear(maxConcurrentUsersInput)
|
||||
await userEvent.type(maxConcurrentUsersInput, value)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Save changes' }))
|
||||
|
||||
if (accepted) {
|
||||
const dialog = await screen.findByRole('dialog')
|
||||
fireEvent.click(within(dialog).getByRole('button', { name: 'Save changes' }))
|
||||
|
||||
await waitFor(() => expect(requests).toHaveLength(1))
|
||||
expect(requests[0]).toMatchObject({ max_concurrent_users: Number(value) })
|
||||
} else {
|
||||
expect(
|
||||
await screen.findByText('Cannot exceed 300,000 concurrent clients')
|
||||
).toBeInTheDocument()
|
||||
expect(screen.queryByRole('dialog')).not.toBeInTheDocument()
|
||||
expect(requests).toHaveLength(0)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
test('rejects max concurrent clients above the entitlement when it is below the soft limit', async () => {
|
||||
customRender(<RealtimeSettings />)
|
||||
|
||||
const maxConcurrentUsersInput = await screen.findByLabelText('Max concurrent clients')
|
||||
await userEvent.clear(maxConcurrentUsersInput)
|
||||
await userEvent.type(maxConcurrentUsersInput, '50001')
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Save changes' }))
|
||||
|
||||
expect(await screen.findByText('Cannot exceed 50,000 concurrent clients')).toBeInTheDocument()
|
||||
expect(screen.queryByRole('dialog')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
@@ -44,7 +44,7 @@ import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
|
||||
const formId = 'realtime-configuration-form'
|
||||
|
||||
const REALTIME_SOFT_LIMITS = {
|
||||
max_concurrent_users: 50_000,
|
||||
max_concurrent_users: 300_000,
|
||||
max_events_per_second: 50_000,
|
||||
max_presence_events_per_second: 5_000,
|
||||
max_payload_size_in_kb: 3_000,
|
||||
|
||||
Reference in new issue
Block a user