Skip to content
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

fix: Optimize job query with created_at and status indexes #267

Merged
merged 1 commit into from
Dec 20, 2024

Conversation

adityachoudhari26
Copy link
Contributor

@adityachoudhari26 adityachoudhari26 commented Dec 19, 2024

Summary by CodeRabbit

  • New Features

    • Introduced a loading state for job totals in the JobTable component.
    • Added a new counting feature for job triggers.
    • Enhanced job data retrieval methods for improved clarity and performance.
  • Bug Fixes

    • Adjusted conditions for rendering components based on updated data structures.
  • Chores

    • Improved database indexing for the job table to enhance query performance.
    • Streamlined code structure for better readability and maintainability.

Copy link
Contributor

coderabbitai bot commented Dec 19, 2024

Walkthrough

The pull request introduces modifications across multiple files in the web service and database layers. The changes primarily focus on refactoring job-related data fetching, counting, and rendering logic. Key updates include replacing job trigger queries with count-based queries, updating index structures in the database, and streamlining data handling in components like JobTable and ReleaseSequencingNode. The modifications aim to improve data retrieval efficiency and code clarity across the application's job management functionality.

Changes

File Change Summary
apps/webservice/src/app/[workspaceSlug]/(app)/(job)/jobs/JobTable.tsx - Replaced job triggers query with count query
- Added loading state for total job count
- Updated total count display using nFormatter
apps/webservice/src/app/[workspaceSlug]/(app)/(job)/jobs/page.tsx - Modified job triggers API call limit
- Updated condition for checking job triggers existence
apps/webservice/src/app/[workspaceSlug]/(app)/systems/.../TableDeployments.tsx - Simplified releaseJobTriggers assignment
- Removed conditional items variable
apps/webservice/src/app/[workspaceSlug]/(app)/systems/.../ReleaseSequencingNode.tsx - Updated job status checks using length instead of total
packages/api/src/router/job.ts - Added new count procedure
- Changed job triggers ordering
- Refactored list query
packages/db/drizzle/0046_little_warstar.sql - Added indexes for job table on created_at and status columns
packages/db/src/schema/job.ts - Added index definitions for job table

Possibly related PRs

Suggested reviewers

  • jsbroks

Poem

🐰 Hopping through code with glee,
Job triggers dance, now light and free!
Indexes bloom, queries refine,
Performance leaps, line by line!
A rabbit's code review, oh so fine! 🚀

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (5)
apps/webservice/src/app/[workspaceSlug]/(app)/(job)/jobs/JobTable.tsx (2)

76-85: Consider adding aria-label for accessibility.

The total count badge should have an aria-label for screen readers.

 <Badge
   variant="outline"
+  aria-label={`Total jobs: ${total ?? 0}`}
   className="rounded-full border-neutral-800 text-inherit"
 >

Line range hint 107-122: Consider adding virtual scrolling for large datasets.

The table might benefit from virtual scrolling if the dataset grows large, as rendering 100 rows at once could impact performance.

Consider using a virtualized table library like react-virtual or react-window if performance becomes an issue with large datasets.

apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/TableDeployments.tsx (1)

112-118: LGTM! Clean simplification of the null handling logic.

The change improves type safety by ensuring releaseJobTriggers is always an array. Consider using a const assertion for the empty array to make it even more type-safe.

-      : [];
+      : [] as const;
packages/db/src/schema/job.ts (1)

99-102: LGTM! Well-chosen indexes for query optimization.

The addition of indexes on createdAt and status columns is a good optimization for:

  • Sorting operations using created_at (commonly used in ORDER BY clauses)
  • Filtering operations using status (commonly used in WHERE clauses)

Consider monitoring the index usage patterns using PostgreSQL's pg_stat_user_indexes view to ensure these indexes are being utilized effectively.

packages/api/src/router/job.ts (1)

Line range hint 189-241: Consider extracting common query structure.

The new count procedure duplicates much of the join and where clause logic from the list procedure. Consider extracting this into a shared base query function to improve maintainability.

+const baseJobQuery = (tx: Tx, workspaceId: string, filter?: JobCondition) =>
+  tx
+    .from(schema.releaseJobTrigger)
+    .innerJoin(schema.job, eq(schema.releaseJobTrigger.jobId, schema.job.id))
+    .innerJoin(schema.resource, eq(schema.releaseJobTrigger.resourceId, schema.resource.id))
+    .innerJoin(schema.release, eq(schema.releaseJobTrigger.releaseId, schema.release.id))
+    .innerJoin(schema.deployment, eq(schema.release.deploymentId, schema.deployment.id))
+    .innerJoin(schema.environment, eq(schema.releaseJobTrigger.environmentId, schema.environment.id))
+    .innerJoin(schema.system, eq(schema.environment.systemId, schema.system.id))
+    .where(
+      and(
+        eq(schema.system.workspaceId, workspaceId),
+        isNull(schema.resource.deletedAt),
+        schema.releaseJobMatchesCondition(tx, filter),
+      ),
+    );

 count: protectedProcedure
   .input(
     z.object({
       workspaceId: z.string().uuid(),
       filter: jobCondition.optional(),
     }),
   )
   .meta({
     authorizationCheck: ({ canUser, input }) =>
       canUser
         .perform(Permission.JobList)
         .on({ type: "workspace", id: input.workspaceId }),
   })
   .query(({ ctx, input }) =>
-    ctx.db
+    baseJobQuery(ctx.db, input.workspaceId, input.filter)
       .select({
         count: countDistinct(schema.releaseJobTrigger.id),
       })
-      .from(schema.releaseJobTrigger)
-      .innerJoin(...)  // Remove duplicated joins
-      .where(...)      // Remove duplicated where clause
       .then(takeFirst)
       .then((t) => t.count),
   ),
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 567d31a and cbfc4b4.

📒 Files selected for processing (8)
  • apps/webservice/src/app/[workspaceSlug]/(app)/(job)/jobs/JobTable.tsx (5 hunks)
  • apps/webservice/src/app/[workspaceSlug]/(app)/(job)/jobs/page.tsx (1 hunks)
  • apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/TableDeployments.tsx (1 hunks)
  • apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/ReleaseSequencingNode.tsx (1 hunks)
  • packages/api/src/router/job.ts (4 hunks)
  • packages/db/drizzle/0046_little_warstar.sql (1 hunks)
  • packages/db/drizzle/meta/_journal.json (1 hunks)
  • packages/db/src/schema/job.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/webservice/src/app/[workspaceSlug]/(app)/(job)/jobs/page.tsx (1)

Pattern **/*.{ts,tsx}: Note on Error Handling:
Avoid strict enforcement of try/catch blocks. Code may use early returns, Promise chains (.then().catch()), or other patterns for error handling. These are acceptable as long as they maintain clarity and predictability.

packages/db/src/schema/job.ts (1)

Pattern **/*.{ts,tsx}: Note on Error Handling:
Avoid strict enforcement of try/catch blocks. Code may use early returns, Promise chains (.then().catch()), or other patterns for error handling. These are acceptable as long as they maintain clarity and predictability.

apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/TableDeployments.tsx (1)

Pattern **/*.{ts,tsx}: Note on Error Handling:
Avoid strict enforcement of try/catch blocks. Code may use early returns, Promise chains (.then().catch()), or other patterns for error handling. These are acceptable as long as they maintain clarity and predictability.

apps/webservice/src/app/[workspaceSlug]/(app)/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/ReleaseSequencingNode.tsx (1)

Pattern **/*.{ts,tsx}: Note on Error Handling:
Avoid strict enforcement of try/catch blocks. Code may use early returns, Promise chains (.then().catch()), or other patterns for error handling. These are acceptable as long as they maintain clarity and predictability.

apps/webservice/src/app/[workspaceSlug]/(app)/(job)/jobs/JobTable.tsx (1)

Pattern **/*.{ts,tsx}: Note on Error Handling:
Avoid strict enforcement of try/catch blocks. Code may use early returns, Promise chains (.then().catch()), or other patterns for error handling. These are acceptable as long as they maintain clarity and predictability.

packages/api/src/router/job.ts (1)

Pattern **/*.{ts,tsx}: Note on Error Handling:
Avoid strict enforcement of try/catch blocks. Code may use early returns, Promise chains (.then().catch()), or other patterns for error handling. These are acceptable as long as they maintain clarity and predictability.

🔇 Additional comments (7)
packages/db/drizzle/0046_little_warstar.sql (1)

1-2: LGTM! Verify index usage in production queries.

The indexes are well-structured and align with the optimization objective. B-tree is appropriate for both created_at (range queries) and status (equality queries) columns.

Let's verify if these indexes will be used by the queries:

✅ Verification successful

Let me generate additional scripts to find queries that use these indexes:


Based on the search results, I can now generate the final response:

✅ Indexes are well-justified by query patterns

The created indexes will be used by several queries across the codebase:

  • Job status index (job_status_idx):

    • Used in policy checks: eq(schema.job.status, JobStatus.Pending)
    • Used in job filtering: notInArray(job.status, [...])
    • Used in job querying: eq(SCHEMA.job.status, JobStatus.Pending)
    • Used in job cancellation: eq(schema.job.status, JobStatus.Pending)
  • Job created_at index (job_created_at_idx):

    • Used in ordering: orderBy(desc(schema.job.createdAt))
    • Used in date range queries: lt(job.createdAt, date), gt(job.createdAt, date)
    • Used in job analytics: date_trunc('day', schema.releaseJobTrigger.createdAt)

The B-tree indexes will effectively support these equality, range, and ordering operations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find queries that might benefit from these indexes

# Search for job table queries in the codebase
rg -A 5 'FROM.*job.*WHERE.*created_at|status'

# Search for job-related Prisma/Drizzle queries
rg -A 5 'job.*findMany.*where.*createdAt|status'

Length of output: 65878


Script:

#!/bin/bash
# Search for job table queries in SQL files and ORM code
# Look for queries filtering by created_at or status

# Search in SQL files
rg -t sql "job.*where.*created_at|status" 

# Search in TypeScript/JavaScript files for Drizzle/Prisma queries
rg -t ts -t js "from\(.*job.*\).*where.*created_at|status|createdAt"

# Search specifically for job table related code
rg -t ts -t js "table\(.*job.*\)|job.*findMany"

Length of output: 71076

apps/webservice/src/app/[workspaceSlug]/(app)/(job)/jobs/page.tsx (1)

22-22: LGTM! Query optimization looks good.

Good optimization by:

  1. Setting limit to 1 since we only need to check existence
  2. Using length check which is appropriate for the limited result set

Also applies to: 25-25

apps/webservice/src/app/[workspaceSlug]/(app)/(job)/jobs/JobTable.tsx (2)

39-48: LGTM! Efficient implementation of count queries.

Good separation of total counts:

  • One for overall total (unfiltered)
  • One for filtered total
    Both using appropriate refetch intervals and placeholder data for optimal UX.

Line range hint 90-94: LGTM! Good replacement of lodash with native Array.from.

The change from lodash's range to native Array.from improves bundle size and maintainability.

packages/db/drizzle/meta/_journal.json (1)

326-332: LGTM! Migration entry follows the established pattern.

The new migration entry maintains consistency with the existing journal structure and includes all required fields.

packages/api/src/router/job.ts (2)

Line range hint 139-188: LGTM! Query optimization aligns with new index.

The changes effectively utilize the new created_at index by:

  1. Ordering by job.createdAt instead of releaseJobTrigger.createdAt
  2. Simplifying the query structure while maintaining functionality

Line range hint 27-38: Verify index usage across all job queries.

The new indexes should improve performance for multiple queries in this file. Let's verify their usage.

✅ Verification successful

Indexes are correctly defined and utilized across job queries

The verification confirms that the job table has appropriate indexes that are being utilized:

  1. job_status_idx on status column is used in multiple queries:

    • Policy checks and filters using job.status
    • Job queue management
    • Release sequencing and dependency checks
  2. job_created_at_idx on createdAt column is used in:

    • Ordering jobs by creation time in release dependency checks
    • Resource-specific job ranking queries
    • Job listing and filtering operations

The indexes are properly defined in packages/db/src/schema/job.ts and are actively used across the codebase in various query patterns, which will help optimize query performance.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all queries that could benefit from the new indexes

# Find queries using job.status in WHERE clauses
echo "Queries potentially using status index:"
rg -A 2 "job\.status.*WHERE" --type ts

# Find queries using job.createdAt in ORDER BY
echo "Queries potentially using createdAt index:"
rg -A 2 "job\.createdAt.*ORDER" --type ts

Length of output: 268


Script:

#!/bin/bash
# Let's try a broader search for job table usage patterns

# Search for job table queries
echo "Queries using job table:"
rg "from.*job|schema\.job" -B 2 -A 2 --type ts

# Search specifically for WHERE clauses with job table
echo -e "\nWHERE clauses with job table:"
rg "where.*job|schema\.job.*where" -B 2 -A 2 --type ts --ignore-case

# Search for ORDER BY clauses with job table
echo -e "\nORDER BY clauses with job table:"
rg "order by.*job|schema\.job.*order" -B 2 -A 2 --type ts --ignore-case

Length of output: 74246


Script:

#!/bin/bash
# Let's search for job table indexes and their usage

# Find index definitions for job table
echo "Job table index definitions:"
rg "createIndex.*job" --type ts

# Search for specific job status and createdAt usage in queries
echo -e "\nQueries using job status or createdAt:"
rg "job.*status|job.*createdAt|schema\.job\.(status|createdAt)" -B 2 -A 2 --type ts

# Look for ORDER BY clauses specifically with job.createdAt
echo -e "\nORDER BY with job.createdAt:"
rg "ORDER BY.*job\.createdAt|ORDER BY.*schema\.job\.createdAt" -B 2 -A 2 --type ts --ignore-case

Length of output: 49673

Comment on lines +135 to +137
pendingJobsQ.data != null && pendingJobsQ.data.length > 0;
const isSeparateReleaseInProgress =
inProgressJobsQ.data != null && inProgressJobsQ.data.total > 0;
inProgressJobsQ.data != null && inProgressJobsQ.data.length > 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Inconsistent array length checks found in job and release queries

The codebase shows mixed usage of .total and .length for checking array sizes. This inconsistency should be addressed as part of the job query optimization efforts.

Key locations requiring attention:

  • useReleaseChannel.ts: Uses data?.total
  • DeploymentPageContent.tsx: Uses data?.total
  • ReleaseSequencingNode.tsx: Contains both patterns - the updated .length check for jobs and .total for releases
  • JobHistoryChart.tsx: Uses data?.total
  • SearchDialog.tsx: Uses data?.total
  • AppSidebarPopoverResources.tsx: Uses both data?.total and data?.items.length
  • ResourcePageContent.tsx: Uses data?.total
🔗 Analysis chain

LGTM! Consistent array length checks.

The change from .total to .length aligns with the job query optimization efforts. The null checks are properly maintained.

Let's verify that this pattern is consistently applied across the codebase:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any remaining uses of .total in job-related queries
rg -A 2 'data\?\.total' --type ts

Length of output: 4174

@adityachoudhari26 adityachoudhari26 merged commit 72d0337 into main Dec 20, 2024
10 checks passed
@adityachoudhari26 adityachoudhari26 deleted the optimize-job-list branch December 20, 2024 01:10
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.

1 participant