-
Notifications
You must be signed in to change notification settings - Fork 49
Refactor/graphql batching and optimisations #1850
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThis pull request introduces two new GraphQL-related dependencies to the project's Changes
Sequence DiagramsequenceDiagram
participant Client
participant GraphqlBatcher
participant BatchExecutor
participant GraphQLServer
Client->>GraphqlBatcher: Initiate Multiple Queries
GraphqlBatcher->>BatchExecutor: Batch Queries
BatchExecutor->>GraphQLServer: Send Batched Request
GraphQLServer-->>BatchExecutor: Return Batched Results
BatchExecutor-->>GraphqlBatcher: Processed Results
GraphqlBatcher-->>Client: Deliver Query Results
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (8)
web/src/hooks/queries/useAllCasesQuery.ts (1)
5-5
: Consider enhancing the query configuration.While adding
staleTime
is good for optimization, consider these improvements:
- Make the
queryKey
more specific by including version/type information- Add error boundaries to handle failed queries gracefully
return useQuery({ - queryKey: [`allCasesQuery`], + queryKey: ['cases', 'all', 'v1'], staleTime: STALE_TIME, queryFn: async () => await graphqlBatcher.fetch({ id: crypto.randomUUID(), document: allCasesQuery, variables: {} }), + retry: 2, + onError: (error) => { + console.error('Failed to fetch cases:', error); + }, });Also applies to: 24-24
web/src/hooks/queries/useCourtDetails.ts (1)
3-3
: Consider implementing field-level caching for court details.While adding
staleTime
helps with query-level caching, the court details query fetches multiple fields that might have different freshness requirements. Consider:
- Implementing field-level caching for slowly-changing data like
policy
,minStake
,alpha
- Using shorter stale times only for frequently-changing fields like
numberDisputes
,numberVotes
This can be achieved using type policies in Apollo Client's cache. Would you like me to provide an example implementation?
Also applies to: 39-39
web/src/hooks/queries/useDisputeMaintenanceQuery.ts (1)
5-5
: Enhance type safety and caching strategy for dispute maintenance.The current implementation has room for improvement:
- The ID conversion to string could be more type-safe
- The complex nested data structure might benefit from a more granular caching strategy
return useQuery<DisputeMaintenanceQuery>({ - queryKey: [`disputeMaintenanceQuery-${id}`], + queryKey: ['dispute', 'maintenance', id], enabled: isEnabled, staleTime: STALE_TIME, queryFn: async () => { + const disputeId = id?.toString() ?? ''; + if (!disputeId) throw new Error('Invalid dispute ID'); await graphqlBatcher.fetch({ id: crypto.randomUUID(), document: disputeMaintenance, - variables: { disputeId: id?.toString(), disputeIdAsString: id?.toString() }, + variables: { disputeId, disputeIdAsString: disputeId }, }), } });Also applies to: 44-44
web/src/hooks/queries/useCourtTree.ts (2)
5-5
: Fix inconsistent import path.The import path
src/consts
differs from other files that useconsts/index
. Maintain consistency across the codebase.-import { STALE_TIME } from "src/consts"; +import { STALE_TIME } from "consts/index";
43-43
: Consider longer stale time for court tree data.Since court hierarchy rarely changes, consider using a longer
staleTime
for this query to reduce unnecessary refetches.web/src/hooks/queries/useVotingHistory.ts (1)
62-62
: Consider dynamic stale time based on voting period.For voting history, a static
staleTime
might not be optimal. Consider adjusting the stale time dynamically based on:
- Active voting period (shorter stale time)
- Completed disputes (longer stale time)
Example approach:
const getStaleTime = (dispute?: VotingHistoryQuery['dispute']) => { if (!dispute) return STALE_TIME; return dispute.ruled ? STALE_TIME * 10 : STALE_TIME; };web/src/hooks/queries/useClassicAppealQuery.ts (1)
3-3
: Consider a more flexible stale time configuration.The current implementation uses a single
STALE_TIME
constant across different types of queries. Consider:
- Creating different stale time constants for different data types (e.g.,
COURT_STALE_TIME
,VOTING_STALE_TIME
)- Implementing a configuration system that allows fine-tuning stale times based on data type and context
Example approach:
// src/consts/staleTime.ts export const STALE_TIMES = { COURT_TREE: 1000 * 60 * 60, // 1 hour VOTING_HISTORY: 1000 * 30, // 30 seconds DISPUTE_DETAILS: 1000 * 60, // 1 minute APPEAL: 1000 * 15, // 15 seconds } as const;web/src/consts/index.ts (1)
10-10
: Consider increasing STALE_TIME and adding documentation.A stale time of 1 second might be too aggressive and could lead to unnecessary refetches. Consider:
- Increasing the value based on your data freshness requirements
- Adding documentation explaining the chosen value
+// Duration (in ms) for which the query data is considered fresh. +// Set to 1 second to balance data freshness with performance. export const STALE_TIME = 1000;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
yarn.lock
is excluded by!**/yarn.lock
,!**/*.lock
📒 Files selected for processing (12)
web/package.json
(1 hunks)web/src/consts/index.ts
(2 hunks)web/src/context/GraphqlBatcher.tsx
(2 hunks)web/src/hooks/queries/useAllCasesQuery.ts
(2 hunks)web/src/hooks/queries/useClassicAppealQuery.ts
(2 hunks)web/src/hooks/queries/useCourtDetails.ts
(2 hunks)web/src/hooks/queries/useCourtTree.ts
(2 hunks)web/src/hooks/queries/useDisputeDetailsQuery.ts
(2 hunks)web/src/hooks/queries/useDisputeMaintenanceQuery.ts
(2 hunks)web/src/hooks/queries/useJurorStakeDetailsQuery.ts
(2 hunks)web/src/hooks/queries/useUser.ts
(2 hunks)web/src/hooks/queries/useVotingHistory.ts
(2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: contracts-testing
- GitHub Check: SonarCloud
- GitHub Check: Analyze (javascript)
- GitHub Check: dependency-review
🔇 Additional comments (6)
web/src/hooks/queries/useJurorStakeDetailsQuery.ts (1)
3-3
: Verify the relationship betweenstaleTime
andrefetchInterval
.The query uses both
staleTime
andrefetchInterval
. This combination might lead to unnecessary refetches ifrefetchInterval
is shorter thanstaleTime
. Consider:
- Ensuring
REFETCH_INTERVAL > STALE_TIME
to prevent wasted requests- Documenting why both intervals are needed
Also applies to: 32-32
✅ Verification successful
The timing configuration is correct and well-designed
The relationship between the constants is properly configured:
STALE_TIME
(1s) <REFETCH_INTERVAL
(5s)- This allows for efficient caching while maintaining data freshness:
- Data is considered stale after 1 second, enabling manual refreshes when needed
- Automatic background refetches occur every 5 seconds to minimize unnecessary requests
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check the values of both constants echo "Checking timing constants..." rg "export const (REFETCH_INTERVAL|STALE_TIME)" "src/consts"Length of output: 178
Script:
#!/bin/bash # Check the values of both constants and their usage echo "Checking timing constants in web/src..." rg "export const (REFETCH_INTERVAL|STALE_TIME)" "web/src/consts" echo -e "\nChecking usage patterns..." rg "(REFETCH_INTERVAL|STALE_TIME)" "web/src" -A 2 -B 2Length of output: 17753
web/src/hooks/queries/useDisputeDetailsQuery.ts (1)
3-3
: Consider the relationship between STALE_TIME and REFETCH_INTERVAL.The combination of
staleTime
andrefetchInterval
needs careful consideration for dispute details:
- If
STALE_TIME
is greater thanREFETCH_INTERVAL
, the refetch might not trigger as expected- For dispute details that require fresh data (e.g., ruling status), consider if caching for
STALE_TIME
is appropriateLet's verify the constant values and their relationship:
Also applies to: 51-51
✅ Verification successful
The STALE_TIME and REFETCH_INTERVAL configuration is appropriate ✅
The current setup with
STALE_TIME
(1s) being less thanREFETCH_INTERVAL
(5s) is correct. This configuration ensures that:
- Data is considered stale quickly (after 1s)
- Regular refetching occurs every 5s
- React Query's background refetching works as expected
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check the values of STALE_TIME and REFETCH_INTERVAL echo "Checking constant definitions..." rg "export const (STALE_TIME|REFETCH_INTERVAL)" src/consts/Length of output: 188
Script:
#!/bin/bash # First, find potential const files echo "Finding potential const files..." fd index.ts -t f web/src/consts # Then search for the constants with more flexible pattern echo -e "\nSearching for constant definitions..." rg "export const (STALE_TIME|REFETCH_INTERVAL)" web/srcLength of output: 472
web/src/hooks/queries/useClassicAppealQuery.ts (1)
47-47
: Review caching strategy for time-sensitive appeal data.Appeal-related data (especially fee information) is time-sensitive. The current implementation might cache this data for too long during critical periods.
Consider:
- Does the appeal period status affect how long we should cache?
- Are there any race conditions with fee updates?
Let's verify the appeal period handling:
web/src/context/GraphqlBatcher.tsx (1)
3-4
: LGTM! New dependencies for improved GraphQL batching.The addition of
@graphql-tools
packages enables better batching capabilities.web/src/hooks/queries/useUser.ts (1)
62-62
: LGTM! Consistent stale time implementation.The addition of STALE_TIME to the useQuery options aligns with the PR's optimization goals.
web/package.json (1)
81-82
: LGTM! Dependencies align with batching implementation.The added GraphQL tools dependencies support the new batching functionality.
✅ Deploy Preview for kleros-v2-testnet ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
web/src/context/GraphqlBatcher.tsx (3)
27-31
: Improve type safety by removing @ts-ignore.The @ts-ignore comment suggests potential type mismatches. Consider adding proper type definitions for the
request
function's return type.- // eslint-disable-next-line @typescript-eslint/ban-ts-comment - //@ts-ignore - const result = request(extensions.url, document, variables).then((res) => ({ - data: res, - })) as Promise<ExecutionResult>; + const result = request<ExecutionResult['data']>( + extensions.url, + document, + variables + ).then((res) => ({ + data: res, + }));
35-35
: Replace console.error with proper logging.Consider using a proper logging service for better error tracking and monitoring in production.
- console.error("Graph error: ", { error }); + // TODO: Replace with proper logging service + logger.error("GraphQL request failed", { + error, + document, + variables + });
44-53
: Improve type safety in data processing.The @ts-ignore comment suggests potential type mismatches in the data processing logic.
const batchdata = await Promise.all( queries.map(({ document, variables, isDisputeTemplate, chainId }) => myBatchExec({ document, variables, extensions: { url: getGraphqlUrl(isDisputeTemplate ?? false, chainId) } }) ) ); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - //@ts-ignore - const processedData = batchdata.map((data, index) => ({ id: queries[index].id, result: data.data })); + const processedData = batchdata.map((data, index) => ({ + id: queries[index].id, + result: (data as ExecutionResult).data + })); return processedData;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
web/src/context/GraphqlBatcher.tsx
(2 hunks)
🧰 Additional context used
📓 Learnings (1)
web/src/context/GraphqlBatcher.tsx (1)
Learnt from: Harman-singh-waraich
PR: kleros/kleros-v2#1850
File: web/src/context/GraphqlBatcher.tsx:25-41
Timestamp: 2025-01-27T11:25:08.246Z
Learning: In GraphQL batch operations using Promise.all, individual request errors should be caught and handled (e.g., returning {data: {}}) rather than thrown, to prevent a single failure from causing the entire batch to fail.
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: SonarCloud
- GitHub Check: Analyze (javascript)
- GitHub Check: contracts-testing
- GitHub Check: dependency-review
🔇 Additional comments (2)
web/src/context/GraphqlBatcher.tsx (2)
3-4
: LGTM! Imports align with batching objectives.The new imports from @graphql-tools provide the necessary functionality for implementing GraphQL request batching.
41-41
: LGTM! Batch executor creation is correct.The batching executor is properly created using the executor function.
✅ Deploy Preview for kleros-v2-university ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
✅ Deploy Preview for kleros-v2-testnet-devtools ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
✅ Deploy Preview for kleros-v2-neo ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
web/src/context/GraphqlBatcher.tsx (2)
25-39
: Improve type safety and logging in the executor.While the error handling approach is correct for batch operations, there are a few improvements to consider:
- The @ts-ignore comment should be addressed
- Console.error should use structured logging
Consider this implementation:
const executor: AsyncExecutor = async ({ document, variables, extensions }) => { try { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - //@ts-ignore + const { url } = extensions as { url: string }; const result = request(extensions.url, document, variables).then((res) => ({ data: res, })) as Promise<ExecutionResult>; return result; } catch (error) { - console.error("Graph error: ", { error }); + // TODO: Replace with structured logging + const errorDetails = error instanceof Error ? { message: error.message, stack: error.stack } : { error }; + console.error("Graph error: ", errorDetails); debounceErrorToast("Graph query error: failed to fetch data."); return { data: {} }; } };
44-53
: Improve type safety in the fetcher implementation.The implementation correctly uses Promise.all for parallel execution, but the type safety can be improved.
Consider this implementation:
const batchdata = await Promise.all( queries.map(({ document, variables, isDisputeTemplate, chainId }) => batchExec({ document, variables, extensions: { url: getGraphqlUrl(isDisputeTemplate ?? false, chainId) } }) ) ); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - //@ts-ignore - const processedData = batchdata.map((data, index) => ({ id: queries[index].id, result: data.data })); + const processedData = batchdata.map((data, index) => ({ + id: queries[index].id, + result: (data as ExecutionResult).data + })); return processedData;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
web/src/context/GraphqlBatcher.tsx
(2 hunks)
🧰 Additional context used
📓 Learnings (1)
web/src/context/GraphqlBatcher.tsx (1)
Learnt from: Harman-singh-waraich
PR: kleros/kleros-v2#1850
File: web/src/context/GraphqlBatcher.tsx:25-41
Timestamp: 2025-01-27T11:25:08.246Z
Learning: In GraphQL batch operations using Promise.all, individual request errors should be caught and handled (e.g., returning {data: {}}) rather than thrown, to prevent a single failure from causing the entire batch to fail.
⏰ Context from checks skipped due to timeout of 90000ms (16)
- GitHub Check: Redirect rules - kleros-v2-testnet
- GitHub Check: Redirect rules - kleros-v2-testnet
- GitHub Check: Header rules - kleros-v2-testnet
- GitHub Check: Header rules - kleros-v2-testnet
- GitHub Check: Pages changed - kleros-v2-testnet
- GitHub Check: Pages changed - kleros-v2-testnet
- GitHub Check: Redirect rules - kleros-v2-neo
- GitHub Check: Redirect rules - kleros-v2-testnet-devtools
- GitHub Check: Header rules - kleros-v2-neo
- GitHub Check: Header rules - kleros-v2-testnet-devtools
- GitHub Check: Pages changed - kleros-v2-neo
- GitHub Check: Pages changed - kleros-v2-testnet-devtools
- GitHub Check: contracts-testing
- GitHub Check: dependency-review
- GitHub Check: SonarCloud
- GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
web/src/context/GraphqlBatcher.tsx (2)
3-4
: LGTM! Necessary imports added for GraphQL batching.The new imports from @graphql-tools provide the required functionality for batch execution and type definitions.
41-41
: LGTM! Batch executor creation is correct.The batching executor is properly created using the custom executor implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Code Climate has analyzed commit 11c8057 and detected 5 issues on this pull request. Here's the issue category breakdown:
View more on Code Climate. |
|
PR-Codex overview
This PR introduces the
@graphql-tools/batch-execute
and@graphql-tools/utils
dependencies and enhances several query hooks by addingstaleTime
for cache management. It also updates theGraphqlBatcher
to use a batching executor for improved performance.Detailed summary
@graphql-tools/batch-execute
and@graphql-tools/utils
topackage.json
.STALE_TIME
constant inweb/src/consts/index.ts
.useClassicAppealQuery
,useAllCasesQuery
, etc.) to includestaleTime
.GraphqlBatcher
with a new executor for batch processing of GraphQL requests.Summary by CodeRabbit
Dependencies
@graphql-tools/batch-execute
and@graphql-tools/utils
to project dependenciesPerformance Improvements
STALE_TIME
constant to optimize query caching across multiple hooksQuery Management