Skip to content

Remove mobx from quotas page#2174

Open
jvorcak wants to merge 13 commits intomasterfrom
refactor/remove-mobx-from-quotas-page
Open

Remove mobx from quotas page#2174
jvorcak wants to merge 13 commits intomasterfrom
refactor/remove-mobx-from-quotas-page

Conversation

@jvorcak
Copy link
Collaborator

@jvorcak jvorcak commented Jan 23, 2026

No description provided.

@jvorcak jvorcak force-pushed the refactor/remove-mobx-from-quotas-page branch from 123ce0c to 9f3f8dd Compare January 23, 2026 09:17
@redpanda-data redpanda-data deleted a comment from blacksmith-sh bot Jan 23, 2026
@blacksmith-sh
Copy link

blacksmith-sh bot commented Jan 23, 2026

Found 1 test failure on Blacksmith runners:

Failure

Test View Logs
[chromium] › quotas/
pagination.spec.ts:9:7 › Quotas - Display 50 quotas › should create 50 quotas and verif
y all are visible on the page › Verify all 50 quotas are visible on the page
View Logs

Fix in Cursor

@jvorcak jvorcak force-pushed the refactor/remove-mobx-from-quotas-page branch from d6907a0 to 48cd773 Compare January 23, 2026 11:44
@jvorcak jvorcak force-pushed the refactor/remove-mobx-from-quotas-page branch from f180b54 to 3b49d7c Compare January 23, 2026 13:09
@jvorcak jvorcak force-pushed the refactor/remove-mobx-from-quotas-page branch from 3b49d7c to e99d002 Compare January 23, 2026 13:17
@jvorcak jvorcak force-pushed the refactor/remove-mobx-from-quotas-page branch from 4275d70 to bb4001b Compare January 24, 2026 20:16
@jvorcak jvorcak marked this pull request as ready for review January 26, 2026 16:31
@jvorcak jvorcak force-pushed the refactor/remove-mobx-from-quotas-page branch from 68210c4 to 37c9237 Compare January 26, 2026 18:35
@jvorcak jvorcak force-pushed the refactor/remove-mobx-from-quotas-page branch from 9d48946 to e104821 Compare February 3, 2026 14:28
@jvorcak jvorcak force-pushed the refactor/remove-mobx-from-quotas-page branch from 7bac1c4 to d463bdf Compare February 3, 2026 16:51
@jvorcak
Copy link
Collaborator Author

jvorcak commented Feb 3, 2026

@malinskibeniamin I've addressed all your comments

Comment on lines +88 to 95
// Transform REST API settings to protobuf Value format
const values: Quota_Value[] = item.settings.map(
(setting: QuotaResponseSetting): Quota_Value => ({
valueType: mapValueTypeToProto(setting.key),
value: setting.value,
$typeName: 'redpanda.api.dataplane.v1.Quota.Value',
})
);
Copy link
Contributor

@malinskibeniamin malinskibeniamin Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like we should be doing this inside the hook like useListQuotas

Also having $typeName here feels awkward, should we try to create connect query key or similar to keep REST/gRPC calls use the same cache


await createClientIdQuota({
clientId: quotaClientId,
producerByteRate: 6_291_456, // 6MB
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: 6 * ONE_MB (use storage utils)


await createClientIdQuota({
clientId: quotaClientId,
producerByteRate: 5_242_880, // 5MB
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Comment on lines +31 to +36
test('should navigate to next page using pagination controls', async ({ page }) => {
const quotaPage = new QuotaPage(page);
const timestamp = Date.now();
const quotaIds: string[] = [];
const QUOTA_COUNT = 55; // More than one page
const PAGE_SIZE = 20;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe just to make the test faster, make it a page size of 1 and quota count of 2?

});

await test.step('Reload page and verify quota still visible', async () => {
await quotaPage.reloadPage();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need a full page reload?

import { uiState } from '../state/ui-state';

const quotasSearchSchema = z.object({
page: fallback(z.number().int().min(0).optional(), 0),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

page 0 is accurate? Shouldn't it be 1?

@malinskibeniamin
Copy link
Contributor

@claude review

@claude
Copy link

claude bot commented Feb 4, 2026

Claude finished @malinskibeniamin's task in 2m 2s —— View job


Code Review Complete

I've reviewed the PR to remove MobX from the quotas page. Here are my findings:

Architecture & Implementation ✓

The migration from MobX to React Query + TanStack Router is well-executed:

  • Successfully removed MobX observer pattern and replaced with modern React patterns
  • Properly integrated TanStack Router for URL-based pagination state
  • Good separation of concerns with the new useQuotasQuery hook

Issues Found

1. Missing fallback property in route definition

Location: frontend/src/routes/quotas.tsx:22

The page parameter uses fallback() but is optional. According to the review comment, you should add an explicit fallback property.

Current:

page: fallback(z.number().int().min(0).optional(), 0),

This should be addressed per the review comment.

2. Hook location - should move to hooks directory

Location: frontend/src/hooks/use-quotas-query.ts

The file is already in the correct location (frontend/src/hooks/), so this review comment may have been addressed. Good job!

3. Link component usage inconsistency

Location: frontend/src/components/pages/quotas/quotas-list.tsx:15

import { Link } from 'components/redpanda-ui/components/typography';

Issue: Using the legacy Link from typography which wraps react-router-dom. Should use TanStack Router's Link component or the Redpanda UI registry link for consistency.

Current usage (line 147):

<Link href="https://docs.redpanda.com/docs/manage/console/" target="_blank">

Recommendation: For external links, the current usage is actually fine. TanStack Router's Link is for internal navigation. However, for consistency across the codebase as noted in the review, consider using the UI registry link component.

4. Cache key strategy needs alignment

Location: frontend/src/hooks/use-quotas-query.ts:24-28 and frontend/src/components/pages/quotas/quotas-list.tsx:93

Issue: The $typeName property is manually added to transform REST data into proto-like format. This creates inconsistency between REST and gRPC calls.

Current approach:

// Hook creates Connect Query key for REST endpoint
const queryKey = createConnectQueryKey({
  schema: listQuotas,
  input: {},
  cardinality: 'finite',
});

Then in component:

$typeName: 'redpanda.api.dataplane.v1.Quota.Value',

Recommendation: This bridging strategy should be in the hook, not the component. Consider creating a unified cache key strategy or keeping REST/gRPC keys separate until the protobuf endpoint is ready. The manual $typeName injection feels like a leaky abstraction.

5. Test improvements - storage utilities

Locations:

  • frontend/tests/test-variant-console/quotas/quota-pagination.spec.ts:209 - producerByteRate: 5_242_880, // 5MB
  • frontend/tests/test-variant-console/quotas/quota-pagination.spec.ts:284 - producerByteRate: 6_291_456, // 6MB

Issue: Magic numbers for byte values. Should use storage utility constants.

Recommendation:

// Instead of: producerByteRate: 6_291_456
// Use: producerByteRate: 6 * ONE_MB

However, I couldn't find ONE_MB or similar constants in the codebase. If they don't exist, this is fine as-is, or you could define them in the test utilities.

6. Test optimization opportunity

Location: frontend/tests/test-variant-console/quotas/quota-pagination.spec.ts:36

Creating 55 quotas per test may be slow. Consider reducing to minimum needed:

const QUOTA_COUNT = 55; // More than one page
const PAGE_SIZE = 20;

Suggestion: Use pageSize: 1 and QUOTA_COUNT: 2 for faster tests while still validating pagination.

7. Full page reload necessity?

Location: frontend/tests/test-variant-console/quotas/quota-display.spec.ts:153

await quotaPage.reloadPage();

Question: Does the test need a full page reload (page.goto()) or would page.reload() suffice? Full navigation might be slower and unnecessary if just testing data persistence.

8. Page numbering - zero-indexed?

Location: frontend/src/routes/quotas.tsx:22

page: fallback(z.number().int().min(0).optional(), 0),

Question: Is page 0 accurate for the first page? Most UIs use 1-indexed pages for user-facing display. TanStack Table uses 0-indexed internally, but verify this is the intended UX.

What's Good ✓

  1. Comprehensive test coverage - Excellent E2E tests covering display, pagination, edge cases
  2. Type safety - Good use of TypeScript types and Zod schemas
  3. Error handling - Proper permission and error state handling
  4. Code organization - Clean separation of concerns
  5. Pagination implementation - URL-based state management is correct
  6. Test structure - Well-organized test steps with clear cleanup

Minor Notes

  • The .gitignore addition of /playwright/.auth/ is correct and prevents accidental auth file commits
  • The PR has 26 commits - consider squashing before merge for cleaner history
  • Good use of refetchOnMount: 'always' in the query hook for data freshness

Summary

The MobX removal is successful and the new implementation follows modern React patterns. Main concerns are:

  1. Cache strategy alignment (REST vs gRPC)
  2. Link component consistency
  3. Minor test optimizations

Most issues are minor polish items that don't block functionality.


return useQuery<QuotaResponse | null>({
queryKey,
queryFn: async () => {
const response = await config.fetch(`${config.restBasePath}/quotas`, {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should move from REST to grpc if possible

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants