Skip to content

Conversation

@adityachoudhari26
Copy link
Contributor

@adityachoudhari26 adityachoudhari26 commented Apr 13, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a worker for updating deployments and environments efficiently.
    • Added new tables for computed deployment and environment resources to enhance resource management.
    • Expanded export options to include new selectors for improved data querying.
  • Refactor

    • Streamlined resource matching and release target updates into consolidated, efficient operations.
  • Chores

    • Updated database schema with new tables to support computed resource associations.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 13, 2025

Walkthrough

This pull request integrates new worker functions and enhanced database schema elements to manage resource selectors more dynamically across deployments and environments. It introduces new SQL tables for computed resource selectors and updates various TypeScript modules with builder classes that facilitate query construction. New enum values and corresponding channel mappings are added for deployment updates. Additionally, the control flow in worker functions and API endpoints is modified to recompute resource selectors through asynchronous calls, centralizing resource matching logic and eliminating redundant helper functions.

Changes

File(s) Change Summary
apps/event-worker/src/workers/index.ts, apps/event-worker/src/workers/update-deployment.ts, apps/event-worker/src/workers/update-environment.ts, apps/event-worker/src/utils/upsert-release-targets.ts Added a new updateDeploymentWorker, updated updateEnvironmentWorker to compute resource selectors, and removed the obsolete getReleaseTargetInsertsForSystem function in favor of a consolidated query.
packages/db/src/index.ts, packages/db/src/schema/deployment.ts, packages/db/src/schema/environment.ts, packages/db/drizzle/0089_robust_diamondback.sql, packages/db/drizzle/meta/_journal.json Introduced new table definitions (computedDeploymentResource, computedEnvironmentResource), corresponding SQL migration script, and updated module exports to include selectors.
packages/events/src/types.ts Extended the Channel enum with UpdateDeployment and updated the ChannelMap type to support deployment updates.
packages/db/src/selectors/** Added multiple selector files and builder classes (e.g., ComputeBuilder, InitialBuilder, QueryBuilder, ReplaceBuilder, and associated query helpers) to facilitate dynamic resource selector computation and query construction.
apps/pty-proxy/src/controller/agent-socket.ts, apps/webservice/src/app/api/v1/resources/route.ts, packages/job-dispatch/src/resource/handle-provider-scan.ts Enhanced resource update logic by integrating asynchronous recomputation of environment and deployment selectors via updated selector functions.

Sequence Diagram(s)

sequenceDiagram
    actor Event as Event Source
    participant UDW as UpdateDeploymentWorker
    participant Sel as Selector Function
    participant DB as Database
    Event->>UDW: Trigger UpdateDeployment event (includes oldSelector & resourceSelector)
    UDW->>UDW: Compare selectors using _.isEqual
    alt Selectors are equal
        UDW-->>Event: Exit early (no action)
    else Selectors differ
        UDW->>Sel: Compute deployment resource selectors
        Sel->>DB: Query and update computed resources
        DB-->>Sel: Return updated resource data
        Sel-->>UDW: Return computed results
        UDW-->>Event: Proceed with deployment update
    end
Loading
sequenceDiagram
    actor Event as Event Source
    participant UEW as UpdateEnvironmentWorker
    participant Sel as Selector Function
    participant DB as Database
    Event->>UEW: Trigger UpdateEnvironment event (with workspaceId)
    UEW->>Sel: Compute environment resource selectors
    Sel->>DB: Query and update computed selectors for environments
    DB-->>Sel: Return updated data
    Sel-->>UEW: Return computed results
    UEW-->>Event: Continue with resource matching operations
Loading

Possibly related PRs

  • feat: init computed resource selector tables #485: The changes in the main PR involve adding the updateDeploymentWorker to handle deployment updates, related to modifications in deployment resource handling through new functions and tables.
  • feat: Deployment worker #446: The changes modify the workers object in apps/event-worker/src/workers/index.ts, adding new worker functions associated with different channels, similar to the enhancements in this PR.

Poem

Hey, I'm a rabbit with a coding twist,
Hopping through changes with a joyful list.
New workers and tables, all shiny and bright,
Recomputing selectors deep into the night.
From schema to queries, our logic's renewed,
With ASCII carrots and code, my heart’s all imbued!
🐰 Hop on, let’s debug in this springtime mood!

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @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: 0

🧹 Nitpick comments (5)
packages/db/src/schema/deployment.ts (1)

116-129: Consider using stricter constraints or a composite primary key.
Currently, deploymentId and resourceId are not explicitly marked notNull(). If the relationship is mandatory, marking them as non-null can prevent accidental null inserts. Additionally, you could enforce uniqueness by making (deploymentId, resourceId) a composite primary key (and remove the id column), if you want to simplify the schema.

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

135-148: Consider non-null ID references or a composite primary key.
Similar to your deploymentSelectorComputedResource table, you may want to mark environmentId and resourceId as non-null if they're always required. You could also consider using (environmentId, resourceId) as a composite primary key instead of a separate id field, which might simplify the schema.

packages/db/src/resources/selector-diff.ts (1)

1-63: Well-structured resource selector diff logic.
The function is clear and maintains readability. As a nice-to-have, consider adding unit tests or integration tests with edge cases (e.g., both selectors empty, large sets) to ensure future reliability.

apps/event-worker/src/workers/update-deployment.ts (1)

6-35: Optimize insert handling for empty arrays.
The updateDeploymentSelectorComputedResources function is well-structured. For a slight optimization, you can skip the insert statement when matchedResourceIds is empty, reducing an unnecessary DB call.

apps/event-worker/src/workers/update-environment.ts (1)

129-158: Consider wrapping these operations in a transaction for atomic updates.
Deleting unmatched resources followed by inserting newly/unchanged matched ones in separate statements can introduce race conditions if multiple updates occur concurrently. Executing them in a single transaction can prevent partial updates and maintain stronger data consistency.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4869689 and 0ccc639.

📒 Files selected for processing (9)
  • apps/event-worker/src/workers/index.ts (2 hunks)
  • apps/event-worker/src/workers/update-deployment.ts (1 hunks)
  • apps/event-worker/src/workers/update-environment.ts (3 hunks)
  • packages/db/src/index.ts (1 hunks)
  • packages/db/src/resources/index.ts (1 hunks)
  • packages/db/src/resources/selector-diff.ts (1 hunks)
  • packages/db/src/schema/deployment.ts (2 hunks)
  • packages/db/src/schema/environment.ts (2 hunks)
  • packages/events/src/types.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{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...

**/*.{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/index.ts
  • packages/db/src/resources/index.ts
  • apps/event-worker/src/workers/index.ts
  • packages/db/src/schema/deployment.ts
  • packages/events/src/types.ts
  • packages/db/src/schema/environment.ts
  • apps/event-worker/src/workers/update-environment.ts
  • packages/db/src/resources/selector-diff.ts
  • apps/event-worker/src/workers/update-deployment.ts
🧬 Code Graph Analysis (6)
apps/event-worker/src/workers/index.ts (1)
apps/event-worker/src/workers/update-deployment.ts (1)
  • updateDeploymentWorker (37-65)
packages/db/src/schema/deployment.ts (1)
packages/db/src/schema/resource.ts (1)
  • resource (59-87)
packages/events/src/types.ts (2)
packages/db/src/schema/deployment.ts (1)
  • Deployment (103-103)
packages/validators/src/resources/conditions/resource-condition.ts (1)
  • ResourceCondition (29-39)
packages/db/src/schema/environment.ts (1)
packages/db/src/schema/resource.ts (1)
  • resource (59-87)
apps/event-worker/src/workers/update-environment.ts (3)
packages/db/src/client.ts (1)
  • db (14-14)
packages/db/src/resources/selector-diff.ts (1)
  • getResourceSelectorDiff (20-63)
packages/db/src/schema/environment.ts (1)
  • environment (58-83)
apps/event-worker/src/workers/update-deployment.ts (5)
packages/db/src/client.ts (1)
  • db (14-14)
packages/events/src/index.ts (1)
  • createWorker (10-25)
packages/db/src/schema/job.ts (1)
  • job (74-106)
packages/db/src/schema/deployment.ts (1)
  • deployment (67-91)
packages/db/src/resources/selector-diff.ts (1)
  • getResourceSelectorDiff (20-63)
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: Typecheck
  • GitHub Check: build (linux/amd64)
  • GitHub Check: Lint
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
🔇 Additional comments (11)
packages/db/src/resources/index.ts (1)

1-1: Clean export of selector-diff module

This export makes the functionality from selector-diff.js accessible through the resources index, which is a good practice for modular code organization.

packages/db/src/index.ts (1)

12-12: Good re-export pattern for resources

The addition of this export line correctly exposes the resources module (including the new selector-diff functionality) to consumers of the DB package.

packages/events/src/types.ts (2)

23-23: Well-named event channel for deployment updates

The new UpdateDeployment channel follows the existing naming convention pattern in the Channel enum.


47-49: Properly structured channel data type

The data structure for the UpdateDeployment channel correctly includes the deployment data and an oldSelector property, which is necessary for computing differences between old and new selectors.

This matches the pattern used for UpdateEnvironment (lines 44-46), maintaining consistency across similar operations.

apps/event-worker/src/workers/index.ts (2)

13-13: Clean import of the new worker

The import follows the established pattern for worker imports in this file.


27-27: Proper registration of the deployment update worker

The worker is correctly registered to handle the UpdateDeployment channel events, maintaining the pattern established for other workers.

This registration enables the system to process deployment update events through the defined worker, completing the event processing pipeline.

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

24-24: Import looks good.
No concerns with this additional import; it correctly brings in the resource schema for reference.

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

35-35: Import looks good.
The new import aligns the file with the references to the resource schema.

apps/event-worker/src/workers/update-deployment.ts (1)

37-65: Deployment update worker logic is solid.
Your approach cleanly handles old vs. new selectors and updates the computed resource table accordingly. The use of onConflictDoNothing() reduces potential concurrency conflicts.

apps/event-worker/src/workers/update-environment.ts (2)

6-12: All set on the new imports.
They appear consistent with the rest of the file and align with existing usage of @ctrlplane/db helpers.


200-212: Good use of getResourceSelectorDiff results to update computed resources.
Merging newly matched and unchanged resources into one list for insertion ensures that the table reflects the final, correct state of environment-resource associations.

resourceId: uuid("resource_id").references(() => resource.id, {
onDelete: "cascade",
}),
},
Copy link
Member

Choose a reason for hiding this comment

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

notNull?

Copy link
Member

Choose a reason for hiding this comment

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

use composite primary key

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 (1)
packages/db/src/resources/deployment-computed-resources.ts (1)

6-44: Consider adding logging for better observability.

While the implementation is solid, consider adding logging at key points (function entry, after deletion, after insertion) to improve observability, especially during debugging or troubleshooting scenarios.

import { and, eq } from "drizzle-orm";

import { Tx } from "../common";
import * as SCHEMA from "../schema/index.js";
+// Import logging utility if available in your project
+// import { logger } from "../utils/logger";

export const computeDeploymentComputedResources = async (
  db: Tx,
  deploymentId: string,
) => {
+  // logger.debug(`Computing resources for deployment: ${deploymentId}`);
  
  const deployment = await db.query.deployment.findFirst({
    where: eq(SCHEMA.deployment.id, deploymentId),
    with: { system: true },
  });
  if (deployment == null)
    throw new Error(`Deployment not found: ${deploymentId}`);

  const { system } = deployment;
  const { workspaceId } = system;

+  // logger.debug(`Deleting existing computed resources for deployment: ${deploymentId}`);
  await db
    .delete(SCHEMA.deploymentSelectorComputedResource)
    .where(
      eq(SCHEMA.deploymentSelectorComputedResource.deploymentId, deploymentId),
    );

+  // logger.debug(`Computing and inserting new resources for deployment: ${deploymentId}`);
  await db
    .insert(SCHEMA.deploymentSelectorComputedResource)
    .select(
      db
        .select({
          deploymentId: SCHEMA.deployment.id,
          resourceId: SCHEMA.resource.id,
        })
        .from(SCHEMA.resource)
        .innerJoin(SCHEMA.deployment, eq(SCHEMA.deployment.id, deploymentId))
        .where(
          and(
            eq(SCHEMA.resource.workspaceId, workspaceId),
            SCHEMA.resourceMatchesMetadata(db, deployment.resourceSelector),
          ),
        ),
    )
    .onConflictDoNothing();
+  // logger.debug(`Completed computing resources for deployment: ${deploymentId}`);
};
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0ccc639 and 0580ffe.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • apps/event-worker/src/workers/update-deployment.ts (1 hunks)
  • packages/db/package.json (1 hunks)
  • packages/db/src/resources/deployment-computed-resources.ts (1 hunks)
  • packages/db/src/resources/env-computed-resources.ts (1 hunks)
  • packages/db/src/resources/index.ts (1 hunks)
  • packages/events/src/types.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/db/src/resources/index.ts
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{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...

**/*.{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/event-worker/src/workers/update-deployment.ts
  • packages/events/src/types.ts
  • packages/db/src/resources/deployment-computed-resources.ts
  • packages/db/src/resources/env-computed-resources.ts
🧬 Code Graph Analysis (3)
apps/event-worker/src/workers/update-deployment.ts (3)
packages/events/src/index.ts (1)
  • createWorker (10-25)
packages/db/src/client.ts (1)
  • db (14-14)
packages/db/src/resources/deployment-computed-resources.ts (1)
  • computeDeploymentComputedResources (6-44)
packages/db/src/resources/deployment-computed-resources.ts (2)
packages/db/src/client.ts (1)
  • db (14-14)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/resources/env-computed-resources.ts (3)
packages/db/src/client.ts (1)
  • db (14-14)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/schema/environment.ts (1)
  • environment (58-83)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Lint
  • GitHub Check: Typecheck
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
🔇 Additional comments (11)
apps/event-worker/src/workers/update-deployment.ts (1)

5-11: Well-structured worker implementation.

The worker correctly uses database transactions when computing deployment resources, ensuring atomicity and data consistency. The implementation is concise and appropriately handles the deployment update event.

packages/events/src/types.ts (2)

28-29: LGTM! Well-structured enum additions.

The new channel enum values follow the existing naming convention and structure.


49-50: LGTM! Type definitions are correctly structured.

The ChannelMap entries properly define the expected payload structure for the new channels, maintaining type safety.

packages/db/src/resources/env-computed-resources.ts (1)

6-47: Well-implemented database transaction function.

The function correctly:

  1. Queries for the environment and handles the not-found case
  2. Deletes existing computed resources
  3. Inserts new resources based on the selector criteria
  4. Uses onConflictDoNothing for idempotency

The implementation maintains transactional integrity by using the provided transaction object throughout.

Verify that SCHEMA.resourceMatchesMetadata correctly handles the case when environment.resourceSelector is null, as the schema indicates this field can be null.

packages/db/src/resources/deployment-computed-resources.ts (7)

1-5: Imports look good.

The imports are clean and appropriate for the file's functionality. Using named imports from drizzle-orm for specific SQL operations is a good practice.


6-9: Function signature appropriately uses transaction object.

The function is properly exported and uses the Tx type for transaction handling, which is a good practice for ensuring database operations can be part of larger transactions.


10-15: Error handling for missing deployment is well implemented.

The code correctly checks if the deployment exists and throws a descriptive error if not found. The query also efficiently includes the related system information in a single database call.


17-19: Clean data extraction with destructuring.

Good use of destructuring to extract the required information from the deployment object. This makes the code more readable.


20-24: Appropriate cleanup of existing resources before recalculation.

The code correctly deletes existing computed resources for the deployment before inserting new ones. This ensures a clean slate for the computation results.


26-43: Well-structured query for computing resources.

The insertion query is well-structured with appropriate joins and filtering. Using innerJoin ensures only valid deployments are processed, and the combination of workspace filtering with metadata matching provides proper scoping of resources.


43-44: Good conflict handling strategy.

Using onConflictDoNothing() is appropriate for this use case, ensuring idempotency if the function is called multiple times with the same data.

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: 0

🧹 Nitpick comments (4)
packages/db/src/resources/env-computed-resources.ts (2)

10-19: Consider using domain-specific errors for better clarity.
Throwing a plain Error makes debugging more challenging. If possible, introduce a custom error or include error codes for improved error handling.


31-48: Be mindful of potential concurrency issues.
If multiple transactions invoke this function concurrently for the same environmentId, there could be unintended race conditions during the delete-and-insert operations. Ensure higher-level transaction or locking mechanisms handle concurrent calls to guarantee consistent state.

packages/db/src/resources/deployment-computed-resources.ts (1)

6-16: Consider adding a short docstring for clarity.
Adding a concise description above computeDeploymentSelectorResources can improve readability by clarifying the function’s intent and expected side effects, especially for contributors discovering this code.

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

117-128: New table definition is appropriate.
Defining a composite primary key for (deploymentId, resourceId) suits the context. Should queries often filter by deploymentId alone, consider adding a dedicated index on deploymentId for improved performance.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b990052 and e9fc77e.

📒 Files selected for processing (4)
  • packages/db/src/resources/deployment-computed-resources.ts (1 hunks)
  • packages/db/src/resources/env-computed-resources.ts (1 hunks)
  • packages/db/src/schema/deployment.ts (3 hunks)
  • packages/db/src/schema/environment.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/db/src/schema/environment.ts
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{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...

**/*.{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/deployment.ts
  • packages/db/src/resources/env-computed-resources.ts
  • packages/db/src/resources/deployment-computed-resources.ts
🧬 Code Graph Analysis (2)
packages/db/src/schema/deployment.ts (1)
packages/db/src/schema/resource.ts (1)
  • resource (59-87)
packages/db/src/resources/deployment-computed-resources.ts (3)
packages/db/src/client.ts (1)
  • db (14-14)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/schema/deployment.ts (1)
  • deployment (68-92)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: Typecheck
  • GitHub Check: build (linux/amd64)
  • GitHub Check: Lint
🔇 Additional comments (5)
packages/db/src/resources/env-computed-resources.ts (2)

6-9: Function definition looks good.
This async function signature is consistent with the overall naming and type usage.


20-29: Logic for deletion and early return is solid.
Clearing old records before insertion and skipping when resourceSelector is null seems correct.

packages/db/src/resources/deployment-computed-resources.ts (2)

20-25: Double-check the delete approach.
Deleting all existing computed resources for the given deployment before re-inserting is suitable if you always want to rebuild them from scratch. Ensure this aligns with your business rules (e.g., partial updates vs. full regeneration).


28-44: Insertion logic looks solid.
Using INSERT ... SELECT with onConflictDoNothing() is a good approach to prevent duplicates. Make sure an appropriate primary or unique key exists on the target table (which you defined in deploymentSelectorComputedResource) so the conflict resolution works as expected.

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

25-25: Import statement aligns with usage.
The resource import is necessary for referencing in the new table definition. No issues here.

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: 0

🧹 Nitpick comments (7)
packages/db/src/resources/deployment-computed-resources.ts (5)

1-2: Remove unused import sql
sql is imported but not used anywhere in this file. Removing it will help keep the code clean.

Apply this diff if sql is truly unused:

- import { and, eq, sql } from "drizzle-orm";
+ import { and, eq } from "drizzle-orm";

6-9: Consider adding JSDoc comments
Documenting parameters and the purpose of computeDeploymentSelectorResources can help future collaborators quickly understand its functionality and expected inputs.


10-15: Handle the case when no workspace is found
If the query returns no rows for the provided deployment ID, takeFirst might return undefined, leading to a TypeError when destructuring. Consider verifying the result and throwing an error or handling it gracefully if no matching record is found.


23-23: Early return ensures no resources are stored if selector is null
Make sure to test the scenario where resourceSelector is null or undefined, confirming this short-circuit logic works as intended.

Would you like help generating a targeted test for this scenario?


40-44: Evaluate onConflictDoNothing() usage
This prevents duplicate entries when inserting. If you eventually need to update existing records in case of changes, consider onConflictDoUpdate() or a different approach. Otherwise, this usage looks correct for skipping duplicates.

packages/db/src/resources/env-computed-resources.ts (2)

38-41: Consider batch processing for large resource sets.

The current implementation processes all matching resources at once. For systems with a large number of resources, consider implementing batch processing to avoid memory issues or database constraints on bulk operations.

- const inserts = resourceIds.map((r) => ({
-   environmentId: environment.id,
-   resourceId: r.resourceId,
- }));
- 
- await db
-   .insert(SCHEMA.environmentSelectorComputedResource)
-   .values(inserts)
-   .onConflictDoNothing();

+ // Process in batches of 1000 resources
+ const batchSize = 1000;
+ for (let i = 0; i < resourceIds.length; i += batchSize) {
+   const batch = resourceIds.slice(i, i + batchSize).map((r) => ({
+     environmentId: environment.id,
+     resourceId: r.resourceId,
+   }));
+   
+   if (batch.length > 0) {
+     await db
+       .insert(SCHEMA.environmentSelectorComputedResource)
+       .values(batch)
+       .onConflictDoNothing();
+   }
+ }

1-47: Consider adding error handling and logging.

The function doesn't include explicit error handling. Consider adding try/catch blocks with appropriate error logging, especially since this appears to be part of a worker system that processes events.

export const computeEnvironmentSelectorResources = async (
  db: Tx,
  environment: Pick<SCHEMA.Environment, "id" | "resourceSelector">,
) => {
+  try {
    const { workspaceId } = await db
      .select({ workspaceId: SCHEMA.system.workspaceId })
      .from(SCHEMA.environment)
      .innerJoin(SCHEMA.system, eq(SCHEMA.environment.systemId, SCHEMA.system.id))
      .where(eq(SCHEMA.environment.id, environment.id))
      .then(takeFirst);

    await db
      .delete(SCHEMA.environmentSelectorComputedResource)
      .where(
        eq(
          SCHEMA.environmentSelectorComputedResource.environmentId,
          environment.id,
        ),
      );

    if (environment.resourceSelector == null) return;

    const resourceIds = await db
      .select({ resourceId: SCHEMA.resource.id })
      .from(SCHEMA.resource)
      .where(
        and(
          eq(SCHEMA.resource.workspaceId, workspaceId),
          SCHEMA.resourceMatchesMetadata(db, environment.resourceSelector),
        ),
      );

    const inserts = resourceIds.map((r) => ({
      environmentId: environment.id,
      resourceId: r.resourceId,
    }));

    await db
      .insert(SCHEMA.environmentSelectorComputedResource)
      .values(inserts)
      .onConflictDoNothing();
+  } catch (error) {
+    console.error(`Error computing environment selector resources for environment ${environment.id}:`, error);
+    throw error;
+  }
};
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ebd247b and 2b2df83.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • apps/event-worker/src/workers/update-deployment.ts (1 hunks)
  • apps/event-worker/src/workers/update-environment.ts (2 hunks)
  • packages/db/src/resources/deployment-computed-resources.ts (1 hunks)
  • packages/db/src/resources/env-computed-resources.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/event-worker/src/workers/update-environment.ts
  • apps/event-worker/src/workers/update-deployment.ts
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{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...

**/*.{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/resources/deployment-computed-resources.ts
  • packages/db/src/resources/env-computed-resources.ts
🧬 Code Graph Analysis (1)
packages/db/src/resources/env-computed-resources.ts (2)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/schema/environment.ts (2)
  • environment (59-84)
  • Environment (86-86)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: Typecheck
  • GitHub Check: Format
  • GitHub Check: Lint
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
🔇 Additional comments (10)
packages/db/src/resources/deployment-computed-resources.ts (4)

3-5: Imports from local modules look good
The import statements for takeFirst, Tx, and the SCHEMA index are precise and align with the usage in this file.


17-21: Potential concurrency considerations
If multiple transactions call this function simultaneously for the same deployment, the process of deleting and then re-inserting could momentarily leave the table empty or cause race conditions. Verify synchronization needs or wrap this process in a transaction at the caller level to ensure consistency.


25-33: Verify the logic of SCHEMA.resourceMatchesMetadata
The function uses SCHEMA.resourceMatchesMetadata to filter resources by metadata. Confirm that the criteria in this helper method correctly represent the desired matching logic and that all necessary keys are checked. If additional verification or custom logic is needed, update accordingly.


35-38: Straightforward record mapping
Creating insertion objects by mapping the found resource IDs to (deploymentId, resourceId) pairs is a clean and readable approach.

packages/db/src/resources/env-computed-resources.ts (6)

6-9: Well-designed function signature with proper type definitions.

The function signature is clear and uses appropriate types, making good use of TypeScript's Pick utility to specify exactly which properties of the Environment type are needed.


10-15: Code correctly retrieves the workspace ID for the environment.

The database query joins the necessary tables and uses takeFirst appropriately to get a single result. This is a clean approach to get the required context for the resource computation.


26-26: Good early return pattern for null selector.

The early return pattern when the resourceSelector is null is efficient and clear, avoiding unnecessary processing when there's nothing to compute.


43-47: Good use of onConflictDoNothing.

Using onConflictDoNothing() is a good approach to handle potential duplicate inserts without causing errors.


17-24:

✅ Verification successful

Consider using a transaction for delete and insert operations.

The code deletes existing resources before computing new ones. This is a good pattern to ensure clean data, but make sure the calling code wraps this in a transaction to avoid potential data integrity issues if a failure occurs between delete and insert operations.


🏁 Script executed:

#!/bin/bash
# Check if the function is called within transactions in other files
rg -A 3 -B 3 "computeEnvironmentSelectorResources" --glob "*.ts"

Length of output: 1636


Transaction already in use for delete/insert operations

The function computeEnvironmentSelectorResources is consistently invoked within a transaction (e.g., as seen in apps/event-worker/src/workers/update-environment.ts), ensuring atomicity for the delete and insert operations. No further changes are needed at the moment.


28-36:

❓ Verification inconclusive

Verify the behavior of resourceMatchesMetadata.

The code uses SCHEMA.resourceMatchesMetadata(db, environment.resourceSelector) to filter resources, but the implementation of this function isn't visible in the current context. Make sure it handles all edge cases correctly, especially with complex selectors.


🏁 Script executed:

#!/bin/bash
# Check the implementation of resourceMatchesMetadata
rg -A 10 "resourceMatchesMetadata.*=" --glob "*.ts"

Length of output: 53


Action Required: Manual Verification of resourceMatchesMetadata Implementation

It appears that our initial search did not reveal the implementation details of resourceMatchesMetadata. As a result, we cannot currently confirm whether it handles all edge cases (especially with complex selectors) as expected. Please perform a manual verification of the function to ensure its behavior is correct.

  • Verify that resourceMatchesMetadata properly handles complex selectors and edge cases.
  • Confirm that its implementation (whether defined in another module or dynamically) is correct and appropriately tested.

To further assist, you may run the following broader search command:

#!/bin/bash
# Search for any occurrences of resourceMatchesMetadata across the repository
rg "resourceMatchesMetadata" -n

This should help locate its definition or any related comments for deeper context.

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: 0

🧹 Nitpick comments (2)
apps/event-worker/src/utils/upsert-release-targets.ts (2)

6-6: Unused import detected.

The takeFirstOrNull function is imported but never used in this file. Consider removing unused imports to keep the codebase clean.

-import { and, eq, takeFirstOrNull } from "@ctrlplane/db";
+import { and, eq } from "@ctrlplane/db";

21-65: Consider adding explanatory comments.

While the code is well-structured, adding comments explaining the purpose of the filtering logic would improve readability, especially for other developers who might not be familiar with the selector matching criteria.

 const targets = rows
   .filter(
     (r) =>
+      // Include targets where either:
+      // 1. The deployment has no resource selector (applies to all resources), or
+      // 2. The deployment has a matching computed resource for this specific resource
       r.deployment.resourceSelector == null ||
       r.deployment_selector_computed_resource != null,
   )
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0aeb944 and b06d977.

📒 Files selected for processing (2)
  • apps/event-worker/src/utils/upsert-release-targets.ts (1 hunks)
  • packages/db/drizzle/meta/_journal.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/db/drizzle/meta/_journal.json
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{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...

**/*.{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/event-worker/src/utils/upsert-release-targets.ts
🧬 Code Graph Analysis (1)
apps/event-worker/src/utils/upsert-release-targets.ts (4)
apps/event-worker/src/workers/updated-resources/span.ts (1)
  • withSpan (6-6)
apps/event-worker/src/utils/spans.ts (1)
  • makeWithSpan (28-49)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/schema/resource.ts (1)
  • resource (59-87)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Lint
  • GitHub Check: Typecheck
  • GitHub Check: build (linux/amd64)
🔇 Additional comments (3)
apps/event-worker/src/utils/upsert-release-targets.ts (3)

21-47: Good database query structure with appropriate joins.

The query efficiently retrieves data by:

  1. Selecting from environmentSelectorComputedResource
  2. Inner joining with related tables
  3. Left joining with deploymentSelectorComputedResource
  4. Filtering by the resource ID

The structure is well-organized and handles the relationship between environments, deployments, and computed resources correctly.


49-59: Clear filtering logic with explicit mapping.

The filtering logic properly handles the case where either:

  • The deployment doesn't specify a resource selector, OR
  • The deployment has a matching computed resource

The mapping to create targets with the necessary IDs is concise and appropriate.


61-65: Good optimization with early return.

The early return when no targets are found avoids an unnecessary database operation. The values insertion with the mapped targets is clean and efficient.

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: 0

🧹 Nitpick comments (2)
packages/db/src/resources/env-computed-resources.ts (2)

31-47: Consider adding a comment explaining resource matching logic

The resource matching logic using resourceMatchesMetadata is a key part of this function, but it might not be immediately clear how it works to future developers. Consider adding a brief comment explaining this matching process.


71-71: Consider consistent error message format

The error message uses string interpolation for the workspace ID. Consider using a structured format that might be easier to parse in error handling systems.

- if (workspace == null) throw new Error(`Workspace not found: ${workspaceId}`);
+ if (workspace == null) throw new Error(`Workspace not found: ${workspaceId}`);

This is a minor suggestion, but consistent error formatting can help with logging and monitoring.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b06d977 and ebae0a6.

📒 Files selected for processing (3)
  • apps/event-worker/src/utils/upsert-release-targets.ts (1 hunks)
  • packages/db/src/resources/deployment-computed-resources.ts (1 hunks)
  • packages/db/src/resources/env-computed-resources.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/db/src/resources/deployment-computed-resources.ts
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{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...

**/*.{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/event-worker/src/utils/upsert-release-targets.ts
  • packages/db/src/resources/env-computed-resources.ts
🧬 Code Graph Analysis (2)
apps/event-worker/src/utils/upsert-release-targets.ts (2)
packages/db/src/client.ts (1)
  • db (14-14)
packages/db/src/schema/resource.ts (1)
  • resource (59-87)
packages/db/src/resources/env-computed-resources.ts (2)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/schema/environment.ts (2)
  • environment (59-84)
  • Environment (86-86)
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: Typecheck
  • GitHub Check: Lint
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
🔇 Additional comments (8)
packages/db/src/resources/env-computed-resources.ts (4)

7-53: Well-structured function with clear purpose

The computeEnvironmentSelectorResources function handles the computation of environment selector resources with a clean transaction-based approach. It properly retrieves workspace information, cleans up existing computed resources, and efficiently handles early returns for edge cases.


47-48: Optimize empty check before DB operation

Good check for empty inserts to avoid unnecessary database operations.


55-77: Parallel processing with proper error handling

The recomputeAllEnvSelectorsInWorkspace function efficiently uses Promise.all for parallel processing of environments and has appropriate error handling for missing workspaces.


59-70: Efficient query with nested relationships

The query efficiently retrieves all relevant environments with non-null resource selectors in a single database call, which is good for performance.

apps/event-worker/src/utils/upsert-release-targets.ts (4)

19-45: Complex join query implemented effectively

The join logic correctly connects environment computed resources with deployments, ensuring proper resource targeting. The query structure follows a logical progression from environments to deployments with appropriate conditions.


47-57: Clear filtering logic for target generation

The filtering logic correctly handles cases where either a deployment has no resource selector or has a matching computed resource. The mapping to target objects is concise and captures all necessary information.


59-64: Good optimization for empty targets

The early return for empty targets avoids an unnecessary database operation, which is a good performance optimization.


33-42:

✅ Verification successful

Verify deployment selector join conditions

The left join with deploymentSelectorComputedResource uses two conditions: matching the deployment ID and the resource ID. Ensure this is the intended behavior as it might filter out some deployments if the second condition is too restrictive.


🏁 Script executed:

#!/bin/bash
# Verify if the join conditions for deploymentSelectorComputedResource are correctly implemented
# by checking if there are any potential edge cases being missed

# 1. Check the schema definition
cat packages/db/src/schema/deployment.ts | grep -A 20 "deploymentSelectorComputedResource"

# 2. Check if there are any other usages of this table with different join conditions
rg "deploymentSelectorComputedResource" --type ts

Length of output: 1795


Verified: Deployment Selector Join Conditions Are Correct

The left join in apps/event-worker/src/utils/upsert-release-targets.ts has been inspected. The join conditions—matching the deployment ID and the resource ID—are consistent with the schema defined in packages/db/src/schema/deployment.ts and align with other usages in the codebase (e.g., in deployment-computed-resources.ts). The composite primary key on these columns confirms that filtering by both fields is intentional. No adjustments are needed.

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: 2

🧹 Nitpick comments (4)
packages/db/src/selectors/compute/compute.ts (2)

1-4: Ensure imports are complete and properly arranged.

The import statements look correct but seem incomplete. Consider adding imports for any operations you plan to use in the commented-out code blocks, such as eq from Drizzle ORM, which appears to be needed for the commented query conditions.


1-63: Add type annotations and documentation to improve code clarity.

Consider enhancing the code with:

  1. Return type annotations for methods
  2. JSDoc comments explaining the purpose of each class and method
  3. A brief file-level comment explaining the overall purpose of this module

This will improve maintainability and help future developers understand the code more easily.

Example for improved type annotations:

- async insert() {
+ async insert(): Promise<void | InsertResult> {
  const vals = await this.values();
  if (vals.length === 0) return;
  return this.tx.insert(this.table).values(vals);
}

- resourceSelector() {
+ resourceSelector(): InsertBuilder<typeof resource> {

Example for documentation:

/**
 * Handles building and executing computed resource operations for environment selectors.
 * This module provides classes to manage the relationship between resources and 
 * environment/deployment selectors in the database.
 */

/**
 * Generic builder for database insert operations.
 * Only performs insert if values are present.
 */
class InsertBuilder<T extends PgTableWithColumns<any>> {
  // ...
}
packages/db/src/selectors/query/builder.ts (1)

10-10: Implement or remove the empty deployments() method.
Leaving this method empty might lead to confusion. If it is not ready to be implemented, consider adding a TODO comment or removing it until you are ready to implement deployments-related query building.

packages/db/src/selectors/query/environments-selector.ts (1)

17-88: Consider reducing repetitive logic in buildMetadataCondition.
Each if block repeats the environment ID matching and key check, which could be unified or handled via a switch statement to reduce verbosity.

Example of a possible switch-based approach for clarity:

- if (cond.operator === MetadataOperator.StartsWith)
-   return exists( ... ilike(environmentMetadata.value, `${cond.value}%`) ... );
- if (cond.operator === MetadataOperator.EndsWith)
-   return exists( ... ilike(environmentMetadata.value, `%${cond.value}`) ... );

+ switch (cond.operator) {
+   case MetadataOperator.StartsWith:
+     return exists(
+       tx.select({ value: sql<number>`1` })
+         .from(environmentMetadata)
+         .where(
+           and(
+             eq(environmentMetadata.environmentId, environment.id),
+             eq(environmentMetadata.key, cond.key),
+             ilike(environmentMetadata.value, `${cond.value}%`),
+           ),
+         ),
+     );
+   // ... other cases ...
+ }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ebae0a6 and 1ced035.

📒 Files selected for processing (5)
  • packages/db/src/selectors/compute/compute.ts (1 hunks)
  • packages/db/src/selectors/index.ts (1 hunks)
  • packages/db/src/selectors/query/builder-types.ts (1 hunks)
  • packages/db/src/selectors/query/builder.ts (1 hunks)
  • packages/db/src/selectors/query/environments-selector.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{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...

**/*.{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/selectors/query/builder.ts
  • packages/db/src/selectors/index.ts
  • packages/db/src/selectors/query/builder-types.ts
  • packages/db/src/selectors/query/environments-selector.ts
  • packages/db/src/selectors/compute/compute.ts
🧬 Code Graph Analysis (4)
packages/db/src/selectors/query/builder.ts (4)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/selectors/query/builder-types.ts (1)
  • WhereBuilder (20-29)
packages/validators/src/environments/environment-condition.ts (1)
  • EnvironmentCondition (19-25)
packages/db/src/selectors/query/environments-selector.ts (1)
  • EnvironmentOutputBuilder (120-131)
packages/db/src/selectors/index.ts (4)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/selectors/compute/compute.ts (1)
  • ComputeBuilder (52-62)
packages/db/src/selectors/query/builder.ts (1)
  • QueryBuilder (8-18)
packages/db/src/client.ts (1)
  • db (14-14)
packages/db/src/selectors/query/environments-selector.ts (4)
packages/db/src/common.ts (2)
  • Tx (22-22)
  • ColumnOperatorFn (54-65)
packages/validators/src/conditions/metadata-condition.ts (1)
  • MetadataCondition (56-56)
packages/db/src/schema/environment.ts (2)
  • environmentMetadata (123-134)
  • environment (59-84)
packages/validators/src/environments/environment-condition.ts (1)
  • EnvironmentCondition (19-25)
packages/db/src/selectors/compute/compute.ts (2)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/schema/resource.ts (1)
  • resource (59-87)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: Lint
  • GitHub Check: build (linux/amd64)
🔇 Additional comments (8)
packages/db/src/selectors/compute/compute.ts (2)

6-18: LGTM! Generic insert builder is well-designed.

The InsertBuilder class is well-structured with a generic type parameter that allows it to work with any table. The implementation avoids unnecessary database operations when there are no values to insert, which is efficient.


52-62: LGTM! Factory pattern implementation looks good.

The ComputeBuilder class effectively serves as a factory for creating instances of WorkspaceEnvironmentBuilder and EnvironmentBuilder with the appropriate transaction context.

packages/db/src/selectors/query/builder.ts (1)

12-17: Return type consistency check.
The environments() method returns a WhereBuilder instance, which is consistent with the approach of building queries. Everything else looks good for the new environments query builder.

packages/db/src/selectors/index.ts (1)

6-16:

❓ Verification inconclusive

Ensure clarity on the default transaction usage.
When no tx is provided, the code falls back to the global db. Confirm that this fallback aligns with the desired transactional boundaries, especially when multiple operations share the same default context.

Would you like to verify whether the fallback database usage introduces any unintentional shared state?


🏁 Script executed:

#!/bin/bash
# This script searches for all calls to the `selector` function,
# checking if they're passed with or without a transaction argument.
rg -A 3 "selector\(.*\)"

Length of output: 26


Verify Fallback Mechanism for Global DB Usage

The code in packages/db/src/selectors/index.ts (lines 6–16) creates builder instances by passing a tx instance. The current design expects that when no explicit tx is provided, a fallback to the global db is used. Although our initial search for calls to the selector function did not yield any output, this result is inconclusive. Please manually verify that the fallback to the global db does not inadvertently introduce shared state between operations, especially in scenarios involving concurrent operations or operations spanning multiple transactional boundaries.

  • Action Needed: Manually confirm that when tx is undefined, the fallback to the global db behaves as intended without causing shared state issues.
  • Location for Attention: packages/db/src/selectors/index.ts (lines 6–16).
packages/db/src/selectors/query/builder-types.ts (2)

9-13: Solid union type for SelectorCondition.
The union type properly covers resource, version, deployment, and environment conditions. This is a good pattern for building flexible queries.


21-29: Clear separation of concerns with WhereBuilder.
Instantiating a new output builder via the provided class is straightforward. No issues found.

packages/db/src/selectors/query/environments-selector.ts (2)

90-119: Comprehensive handling of environment conditions in buildCondition.
The logic covers name, directory, system, metadata, and composite conditions, which should meet your varied querying needs. Nice job.


120-131: EnvironmentOutputBuilder integrates well with WhereBuilder.
This class neatly wraps condition building while deferring to buildCondition. It’s good that unspecified conditions return undefined.

Comment on lines 36 to 50
class WorkspaceEnvironmentBuilder {
constructor(
private readonly tx: Tx,
private readonly workspaceId: string,
) {}

resourceSelectors() {
return new InsertBuilder(this.tx, resource, async () => {
// return this.tx
// .select()
// .from(resource)
// .where(eq(resource.workspaceId, this.workspaceId));
});
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Implement or remove commented-out code in resourceSelectors().

Similar to the EnvironmentBuilder, the resourceSelectors() method contains commented-out code that doesn't return any values, causing the InsertBuilder to always receive an empty array. This means no inserts will ever be performed.

resourceSelectors() {
  return new InsertBuilder(this.tx, resource, async () => {
-    // return this.tx
-    //   .select()
-    //   .from(resource)
-    //   .where(eq(resource.workspaceId, this.workspaceId));
+    // TODO: Implement resource selection logic using this.workspaceId
+    return [];
  });
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class WorkspaceEnvironmentBuilder {
constructor(
private readonly tx: Tx,
private readonly workspaceId: string,
) {}
resourceSelectors() {
return new InsertBuilder(this.tx, resource, async () => {
// return this.tx
// .select()
// .from(resource)
// .where(eq(resource.workspaceId, this.workspaceId));
});
}
}
class WorkspaceEnvironmentBuilder {
constructor(
private readonly tx: Tx,
private readonly workspaceId: string,
) {}
resourceSelectors() {
return new InsertBuilder(this.tx, resource, async () => {
// TODO: Implement resource selection logic using this.workspaceId
return [];
});
}
}

Comment on lines 20 to 34
class EnvironmentBuilder {
constructor(
private readonly tx: Tx,
private readonly ids: string[],
) {}

resourceSelector() {
return new InsertBuilder(this.tx, resource, async () => {
// return this.tx
// .select()
// .from(resource)
// .where(eq(resource.workspaceId, this.workspaceId));
});
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Implement or remove commented-out code in resourceSelector().

The resourceSelector() method contains commented-out code that doesn't return any values, causing the InsertBuilder to always receive an empty array. This means no inserts will ever be performed.

Additionally, the ids parameter in the constructor isn't used in any active code.

resourceSelector() {
  return new InsertBuilder(this.tx, resource, async () => {
-    // return this.tx
-    //   .select()
-    //   .from(resource)
-    //   .where(eq(resource.workspaceId, this.workspaceId));
+    // TODO: Implement resource selection logic using this.ids
+    return [];
  });
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class EnvironmentBuilder {
constructor(
private readonly tx: Tx,
private readonly ids: string[],
) {}
resourceSelector() {
return new InsertBuilder(this.tx, resource, async () => {
// return this.tx
// .select()
// .from(resource)
// .where(eq(resource.workspaceId, this.workspaceId));
});
}
}
class EnvironmentBuilder {
constructor(
private readonly tx: Tx,
private readonly ids: string[],
) {}
resourceSelector() {
return new InsertBuilder(this.tx, resource, async () => {
// TODO: Implement resource selection logic using this.ids
return [];
});
}
}

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: 2

🧹 Nitpick comments (6)
packages/db/src/selectors/query/builder.ts (1)

11-14: Unimplemented deployments method.

Currently, the deployments() method is an empty placeholder. If a future implementation is planned, consider adding a TODO comment to clarify its purpose, or remove it if it’s not needed.

packages/db/src/selectors/query/resource-selector.ts (2)

39-115: Consider refactoring repetitive subquery patterns in buildMetadataCondition().

Although the logic is correct, each metadata operator (StartsWith, EndsWith, Contains, etc.) uses a similar exists(...) pattern. If more operators are introduced, you may want to unify or generalize these checks to reduce code repetition.


117-135: Unify date-based condition builders if desired.

buildCreatedAtCondition() and buildLastSyncCondition() perform nearly identical comparisons on different columns (createdAt vs. updatedAt). Merging or sharing logic could help maintainability if more date-based fields are introduced.

apps/event-worker/src/workers/update-deployment.ts (1)

1-17: Consider adding logging similar to the environment worker

The implementation is clean and follows the same pattern as the environment worker. However, unlike the environment worker, this one doesn't include any logging.

Consider adding some basic logging for better observability:

import _ from "lodash";

-import { selector } from "@ctrlplane/db";
+import { selector } from "@ctrlplane/db";
+import { logger } from "@ctrlplane/logger";
import { Channel, createWorker } from "@ctrlplane/events";

+const log = logger.child({
+  module: "deployment-selector-update",
+  function: "updateDeploymentWorker",
+});

export const updateDeploymentWorker = createWorker(
  Channel.UpdateDeployment,
  async ({ data }) => {
    const { oldSelector, resourceSelector } = data;
-    if (_.isEqual(oldSelector, resourceSelector)) return;
+    if (_.isEqual(oldSelector, resourceSelector)) {
+      log.info("No change in deployment selector", { deploymentId: data.id });
+      return;
+    }
+    log.info("Computing resource selectors for deployment", { deploymentId: data.id });
    await selector()
      .compute()
      .deployments([data.id])
      .resourceSelectors()
      .replace();
+    log.info("Completed computing resource selectors for deployment", { deploymentId: data.id });
  },
);
packages/db/src/selectors/compute/deployment-builder.ts (1)

17-58: Consider performance implications of large batch operations.
If the deployments or resources arrays grow large, the map operation (line 37) followed by Promise.all() (line 54) may cause high memory usage. You might consider chunking or paging through resources to avoid potential performance bottlenecks.

packages/db/src/selectors/compute/environment-builder.ts (1)

17-58: Consider performance implications of large batch operations.
Similar to DeploymentBuilder, the combined size of envs (line 32) and resources (line 41) could become quite large. If so, you might encounter high memory usage in the mapped promises. Consider chunking or lazy-loading results for efficiency.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1ced035 and 547211b.

📒 Files selected for processing (12)
  • apps/event-worker/src/workers/update-deployment.ts (1 hunks)
  • apps/event-worker/src/workers/update-environment.ts (2 hunks)
  • apps/pty-proxy/src/controller/agent-socket.ts (2 hunks)
  • apps/webservice/src/app/api/v1/resources/route.ts (2 hunks)
  • packages/db/src/index.ts (1 hunks)
  • packages/db/src/selectors/compute/compute.ts (1 hunks)
  • packages/db/src/selectors/compute/deployment-builder.ts (1 hunks)
  • packages/db/src/selectors/compute/environment-builder.ts (1 hunks)
  • packages/db/src/selectors/compute/replace-builder.ts (1 hunks)
  • packages/db/src/selectors/query/builder.ts (1 hunks)
  • packages/db/src/selectors/query/resource-selector.ts (1 hunks)
  • packages/job-dispatch/src/resource/handle-provider-scan.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/webservice/src/app/api/v1/resources/route.ts
  • packages/db/src/index.ts
  • apps/pty-proxy/src/controller/agent-socket.ts
  • packages/job-dispatch/src/resource/handle-provider-scan.ts
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{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...

**/*.{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/event-worker/src/workers/update-environment.ts
  • apps/event-worker/src/workers/update-deployment.ts
  • packages/db/src/selectors/compute/replace-builder.ts
  • packages/db/src/selectors/query/builder.ts
  • packages/db/src/selectors/compute/compute.ts
  • packages/db/src/selectors/compute/deployment-builder.ts
  • packages/db/src/selectors/compute/environment-builder.ts
  • packages/db/src/selectors/query/resource-selector.ts
🧬 Code Graph Analysis (7)
apps/event-worker/src/workers/update-environment.ts (3)
packages/db/src/selectors/index.ts (1)
  • selector (18-18)
packages/db/src/client.ts (1)
  • db (14-14)
packages/db/src/schema/environment.ts (1)
  • environment (59-84)
apps/event-worker/src/workers/update-deployment.ts (2)
packages/events/src/index.ts (1)
  • createWorker (10-25)
packages/db/src/selectors/index.ts (1)
  • selector (18-18)
packages/db/src/selectors/compute/replace-builder.ts (1)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/selectors/query/builder.ts (6)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/selectors/query/builder-types.ts (1)
  • WhereBuilder (20-29)
packages/validators/src/environments/environment-condition.ts (1)
  • EnvironmentCondition (19-25)
packages/db/src/selectors/query/environments-selector.ts (1)
  • EnvironmentOutputBuilder (120-131)
packages/validators/src/resources/conditions/resource-condition.ts (1)
  • ResourceCondition (29-39)
packages/db/src/selectors/query/resource-selector.ts (1)
  • ResourceOutputBuilder (165-176)
packages/db/src/selectors/compute/compute.ts (3)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/selectors/compute/environment-builder.ts (2)
  • WorkspaceEnvironmentBuilder (78-121)
  • EnvironmentBuilder (8-59)
packages/db/src/selectors/compute/deployment-builder.ts (2)
  • WorkspaceDeploymentBuilder (78-127)
  • DeploymentBuilder (8-59)
packages/db/src/selectors/compute/environment-builder.ts (4)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/selectors/query/builder.ts (2)
  • QueryBuilder (11-28)
  • resources (22-27)
packages/db/src/selectors/compute/replace-builder.ts (1)
  • ReplaceBuilder (6-26)
packages/db/src/schema/workspace.ts (1)
  • workspace (18-27)
packages/db/src/selectors/query/resource-selector.ts (6)
packages/db/src/common.ts (2)
  • Tx (22-22)
  • ColumnOperatorFn (54-65)
packages/validators/src/conditions/metadata-condition.ts (1)
  • MetadataCondition (56-56)
packages/db/src/schema/resource.ts (2)
  • resourceMetadata (155-166)
  • resource (59-87)
packages/validators/src/conditions/date-condition.ts (1)
  • CreatedAtCondition (37-37)
packages/validators/src/resources/conditions/last-sync-condition.ts (1)
  • LastSyncCondition (11-11)
packages/validators/src/resources/conditions/resource-condition.ts (1)
  • ResourceCondition (29-39)
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: Typecheck
  • GitHub Check: Lint
🔇 Additional comments (10)
packages/db/src/selectors/query/builder.ts (3)

1-9: Imports look good.

The imported types and utilities (EnvironmentCondition, ResourceCondition, Tx, etc.) are consistent with their usage in this file. No issues detected.


15-20: environments builder is well-structured.

The environments() method correctly returns a WhereBuilder specialized for EnvironmentCondition and Environment. This approach keeps the query-building logic clean and consistent.


22-27: resources builder is coherent.

Similar to environments(), the resources() method cleanly returns a WhereBuilder for ResourceCondition and Resource. Implementation is straightforward and adheres to the established pattern.

packages/db/src/selectors/query/resource-selector.ts (2)

137-163: Comprehensive condition handling.

The buildCondition() function covers a wide array of resource conditions (kind, name, provider, etc.). This thorough approach to combining multiple conditions via AND, OR, and optional negation looks well-structured, with no apparent logical errors.


165-176: ResourceOutputBuilder implementation is sound.

Using buildCondition() inside the sql() method effectively delegates the condition-building logic. Returning undefined for null or empty conditions is a clean approach that can simplify upstream usage.

apps/event-worker/src/workers/update-environment.ts (1)

203-207: LGTM: Good addition of resource selector computation

The addition of the selector computation step here ensures that environment resource selectors are up-to-date before proceeding with the resource matching logic. This is a logical enhancement that maintains the flow of the worker function.

packages/db/src/selectors/compute/replace-builder.ts (1)

1-26: Well-structured generic builder class for database operations

This ReplaceBuilder class follows a good pattern for transaction management and provides a clean API for replacing records. The implementation correctly handles:

  1. Transactional operations
  2. Early return when no values are present
  3. Conflict handling with onConflictDoNothing

The generic type parameter ensures type safety across different table operations.

packages/db/src/selectors/compute/compute.ts (1)

1-29: LGTM: Well-designed builder pattern implementation

The ComputeBuilder class provides a clean API for creating different types of builders. The implementation is:

  1. Consistent in its patterns
  2. Well-organized with clear separation of concerns
  3. Type-safe with proper imports

This builder pattern will make the code more maintainable and easier to use.

packages/db/src/selectors/compute/deployment-builder.ts (1)

61-76: Validate existence of systems in getDeploymentsInWorkspace.
This function throws an error if the workspace is not found, but if the workspace is present with zero or mismatched systems, the result will simply be an empty array. If this is expected behavior, it’s fine; otherwise, consider validating that workspace.systems is not empty to catch unexpected data inconsistencies.

packages/db/src/selectors/compute/environment-builder.ts (1)

61-76: Validate zero-systems scenario in getEnvsInWorkspace.
While an error is thrown if no workspace is found (line 74), having an existing workspace with no systems or no valid environments will produce an empty array (line 75). If this is intentional, no change is needed; otherwise, consider additional validation.

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

♻️ Duplicate comments (1)
packages/db/src/selectors/compute/environment-builder.ts (1)

41-46: ⚠️ Potential issue

Use the local transaction parameter for query consistency

The resource query is using this.tx instead of the local tx parameter passed to the callback. This could lead to transaction isolation issues.

-          const resources = await this.tx.query.resource.findMany({
+          const resources = await tx.query.resource.findMany({
             where: and(
               eq(SCHEMA.resource.workspaceId, workspaceId),
               this._queryBuilder.resources().where(env.resourceSelector).sql(),
             ),
           });
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 547211b and 6f94ae3.

📒 Files selected for processing (2)
  • packages/db/src/selectors/compute/deployment-builder.ts (1 hunks)
  • packages/db/src/selectors/compute/environment-builder.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{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...

**/*.{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/selectors/compute/deployment-builder.ts
  • packages/db/src/selectors/compute/environment-builder.ts
🧬 Code Graph Analysis (2)
packages/db/src/selectors/compute/deployment-builder.ts (3)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/selectors/query/builder.ts (3)
  • QueryBuilder (11-28)
  • deployments (13-13)
  • resources (22-27)
packages/db/src/selectors/compute/replace-builder.ts (1)
  • ReplaceBuilder (6-26)
packages/db/src/selectors/compute/environment-builder.ts (4)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/selectors/query/builder.ts (2)
  • QueryBuilder (11-28)
  • resources (22-27)
packages/db/src/selectors/compute/replace-builder.ts (1)
  • ReplaceBuilder (6-26)
packages/db/src/schema/workspace.ts (1)
  • workspace (18-27)
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: Typecheck
  • GitHub Check: Lint
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: build (linux/amd64)
🔇 Additional comments (5)
packages/db/src/selectors/compute/deployment-builder.ts (3)

8-59: LGTM: Well-structured DeploymentBuilder implementation

This class provides a clean implementation for managing deployment resource selectors. The transaction context is properly maintained throughout the operations.


61-76: LGTM: Well-implemented helper function

The getDeploymentsInWorkspace function properly fetches deployments with non-null resource selectors from a specified workspace, with appropriate error handling when the workspace isn't found.


78-127: LGTM: WorkspaceDeploymentBuilder is properly implemented

The WorkspaceDeploymentBuilder class provides workspace-scoped deployment resource selector computation. Nice job consistently using the local transaction parameter (tx) in the callbacks to ensure proper transaction scoping.

packages/db/src/selectors/compute/environment-builder.ts (2)

61-76: LGTM: Well-implemented helper function

The getEnvsInWorkspace function correctly fetches environments with non-null resource selectors from a specified workspace and includes appropriate error handling.


78-121: LGTM: WorkspaceEnvironmentBuilder correctly uses the transaction parameter

The WorkspaceEnvironmentBuilder implementation correctly uses the local transaction parameter in all database operations, ensuring proper transaction isolation.

Comment on lines 8 to 59
export class EnvironmentBuilder {
private readonly _queryBuilder;
constructor(
private readonly tx: Tx,
private readonly ids: string[],
) {
this._queryBuilder = new QueryBuilder(tx);
}

resourceSelectors() {
return new ReplaceBuilder(
this.tx,
SCHEMA.environmentSelectorComputedResource,
async (tx) => {
await tx
.delete(SCHEMA.environmentSelectorComputedResource)
.where(
inArray(
SCHEMA.environmentSelectorComputedResource.environmentId,
this.ids,
),
);
},
async (tx) => {
const envs = await tx.query.environment.findMany({
where: inArray(SCHEMA.environment.id, this.ids),
with: { system: true },
});

const promises = envs.map(async (env) => {
const { system } = env;
const { workspaceId } = system;

const resources = await this.tx.query.resource.findMany({
where: and(
eq(SCHEMA.resource.workspaceId, workspaceId),
this._queryBuilder.resources().where(env.resourceSelector).sql(),
),
});

return resources.map((r) => ({
environmentId: env.id,
resourceId: r.id,
}));
});

const fulfilled = await Promise.all(promises);
return fulfilled.flat();
},
);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Overall implementation of EnvironmentBuilder is sound

Apart from the transaction inconsistency noted above, the class is well-structured and follows a clean pattern for computing resource selectors for environments.

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: 0

♻️ Duplicate comments (2)
packages/db/src/selectors/compute/environment-builder.ts (2)

17-55: ⚠️ Potential issue

The EnvironmentBuilder's resourceSelectors method looks well-structured but has a transaction inconsistency.

The resourceSelectors method properly implements a pattern for computing and replacing resource selectors for environments. However, there's an issue with transaction scope.

On line 38, you're using this.tx rather than the local transaction parameter tx that was passed to the callback:

-          const resources = await this.tx.query.resource.findMany({
+          const resources = await tx.query.resource.findMany({
             where: and(
               eq(SCHEMA.resource.workspaceId, workspaceId),
               this._queryBuilder.resources().where(env.resourceSelector).sql(),
             ),
           });

This inconsistency can cause transaction isolation issues since other operations in this method use the local transaction parameter.


84-117: ⚠️ Potential issue

WorkspaceEnvironmentBuilder's resourceSelectors has the same transaction inconsistency issue.

Similar to the first builder class, the resourceSelectors method has a transaction inconsistency issue.

On line 103, you're using this._queryBuilder (initialized with this.tx) rather than the local transaction parameter:

-              this._queryBuilder.resources().where(env.resourceSelector).sql(),
+              new QueryBuilder(tx).resources().where(env.resourceSelector).sql(),

Both builder classes have this same issue, which breaks proper transaction isolation. All database operations within the callback should use the same transaction context.

🧹 Nitpick comments (1)
packages/db/drizzle/0090_organic_sinister_six.sql (1)

1-14: Table schema looks good but consider creating an index for query performance.

The creation of the computed resource selector tables with composite primary keys is well-structured. The dropping of the old tables indicates this is a replacement of an existing feature.

Consider adding an index on the foreign key columns to improve query performance, especially if you'll be frequently querying by just the resource_id:

CREATE TABLE IF NOT EXISTS "computed_deployment_resource" (
	"deployment_id" uuid NOT NULL,
	"resource_id" uuid NOT NULL,
	CONSTRAINT "computed_deployment_resource_deployment_id_resource_id_pk" PRIMARY KEY("deployment_id","resource_id")
);
+CREATE INDEX IF NOT EXISTS "computed_deployment_resource_resource_id_idx" ON "computed_deployment_resource" ("resource_id");

CREATE TABLE IF NOT EXISTS "computed_environment_resource" (
	"environment_id" uuid NOT NULL,
	"resource_id" uuid NOT NULL,
	CONSTRAINT "computed_environment_resource_environment_id_resource_id_pk" PRIMARY KEY("environment_id","resource_id")
);
+CREATE INDEX IF NOT EXISTS "computed_environment_resource_resource_id_idx" ON "computed_environment_resource" ("resource_id");
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6f94ae3 and c35f40c.

📒 Files selected for processing (8)
  • apps/event-worker/src/utils/upsert-release-targets.ts (1 hunks)
  • packages/db/drizzle/0090_organic_sinister_six.sql (1 hunks)
  • packages/db/drizzle/meta/_journal.json (1 hunks)
  • packages/db/src/schema/deployment.ts (3 hunks)
  • packages/db/src/schema/environment.ts (3 hunks)
  • packages/db/src/selectors/compute/deployment-builder.ts (1 hunks)
  • packages/db/src/selectors/compute/environment-builder.ts (1 hunks)
  • packages/db/src/selectors/query/builder.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/db/drizzle/meta/_journal.json
  • packages/db/src/selectors/query/builder.ts
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{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...

**/*.{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/deployment.ts
  • apps/event-worker/src/utils/upsert-release-targets.ts
  • packages/db/src/schema/environment.ts
  • packages/db/src/selectors/compute/deployment-builder.ts
  • packages/db/src/selectors/compute/environment-builder.ts
🧬 Code Graph Analysis (5)
packages/db/src/schema/deployment.ts (1)
packages/db/src/schema/resource.ts (1)
  • resource (59-87)
apps/event-worker/src/utils/upsert-release-targets.ts (2)
packages/db/src/client.ts (1)
  • db (14-14)
packages/db/src/schema/resource.ts (1)
  • resource (59-87)
packages/db/src/schema/environment.ts (1)
packages/db/src/schema/resource.ts (1)
  • resource (59-87)
packages/db/src/selectors/compute/deployment-builder.ts (5)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/selectors/query/builder.ts (3)
  • QueryBuilder (10-27)
  • deployments (12-12)
  • resources (21-26)
packages/db/src/selectors/compute/replace-builder.ts (1)
  • ReplaceBuilder (6-26)
packages/db/src/selectors/compute/compute.ts (1)
  • deployments (26-28)
packages/db/src/schema/workspace.ts (1)
  • workspace (18-27)
packages/db/src/selectors/compute/environment-builder.ts (4)
packages/db/src/common.ts (1)
  • Tx (22-22)
packages/db/src/selectors/query/builder.ts (2)
  • QueryBuilder (10-27)
  • resources (21-26)
packages/db/src/selectors/compute/replace-builder.ts (1)
  • ReplaceBuilder (6-26)
packages/db/src/schema/workspace.ts (1)
  • workspace (18-27)
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: build (linux/amd64)
  • GitHub Check: Typecheck
  • GitHub Check: build (linux/amd64)
  • GitHub Check: Lint
  • GitHub Check: build (linux/amd64)
🔇 Additional comments (10)
packages/db/src/schema/environment.ts (1)

136-147: The composite primary key implementation looks good.

The computedEnvironmentResource table structure is well-defined with appropriate foreign key references and cascading delete behavior. Using a composite primary key on both columns is an excellent approach for this many-to-many relationship.

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

117-128: Proper implementation of the computed relationship table.

The computedDeploymentResource table follows the same pattern as the environment counterpart, with appropriate foreign key references and a composite primary key. This consistent approach will ensure referential integrity and efficient query patterns.

apps/event-worker/src/utils/upsert-release-targets.ts (1)

19-57: Query optimization looks great!

The refactored implementation leverages the new computed relationship tables to simplify the resource matching process. This approach is more efficient as it:

  1. Eliminates the need for complex client-side filtering
  2. Pushes the filtering logic to the database layer
  3. Reduces the amount of data transferred between DB and application

The query structure with appropriate inner and left joins shows good understanding of the data relationships.

packages/db/src/selectors/compute/deployment-builder.ts (3)

8-56: Well-structured builder pattern for deployment resources.

The DeploymentBuilder class effectively encapsulates the logic for managing computed resources for specific deployments. The transaction handling and resource selection approach are appropriate. The pattern of using a ReplaceBuilder for the atomic delete-then-insert operation ensures data consistency.


58-73: Good separation of concerns with the workspace deployment helper.

The getDeploymentsInWorkspace function provides a clean abstraction for fetching deployments within a workspace context. The error handling for non-existent workspaces is appropriate, ensuring that callers receive clear feedback.


75-124: Consistent transaction handling in workspace deployment builder.

The WorkspaceDeploymentBuilder implementation follows the same pattern as the DeploymentBuilder, maintaining consistency across the codebase. Good job on using the passed transaction object consistently in both callbacks, which ensures proper transactional integrity.

packages/db/src/selectors/compute/environment-builder.ts (2)

58-73: Helper function is well-implemented and includes proper error handling.

The getEnvsInWorkspace helper function properly:

  1. Queries for the workspace with its related systems and environments
  2. Filters for environments with non-null resource selectors
  3. Includes appropriate error handling when a workspace isn't found

75-83: WorkspaceEnvironmentBuilder's constructor is well-designed.

The constructor properly initializes the query builder and stores the necessary parameters.

packages/db/drizzle/0090_organic_sinister_six.sql (2)

15-37: Well-structured foreign key constraints with proper cascade behavior.

The foreign key constraints are properly defined with:

  1. CASCADE delete behavior - ensures referential integrity when parent records are deleted
  2. Exception handling for duplicate objects - makes the migration script idempotent

The exception handling is particularly important in migration scripts as it allows the script to be run multiple times without errors, which is useful in development and deployment scenarios.


1-37:

❓ Verification inconclusive

Verify data migration strategy between old and new tables.

You're dropping existing tables (deployment_selector_computed_resource and environment_selector_computed_resource) and creating new ones with similar names. Make sure you have a strategy to migrate any existing data or recompute it.


🏁 Script executed:

#!/bin/bash
# Check if the old tables had records that need migration
echo "Checking how many records might need migration..."
cat << 'EOF' > check_tables.sql
SELECT 'deployment_selector_computed_resource' as table_name, count(*) FROM information_schema.tables WHERE table_name = 'deployment_selector_computed_resource';
SELECT 'environment_selector_computed_resource' as table_name, count(*) FROM information_schema.tables WHERE table_name = 'environment_selector_computed_resource';
EOF

# This would need to be run in a PostgreSQL environment
echo "Note: This script needs to be run in an environment with PostgreSQL access"
echo "In an actual production environment, you'd need to run this script against your database."

Length of output: 465


Data Migration Strategy Verification

The script output confirms that the checks were only echoed rather than executed against an actual PostgreSQL instance, so there's no evidence that a data migration is occurring. Since the code is dropping the old tables (deployment_selector_computed_resource and environment_selector_computed_resource) and creating new ones without an embedded migration step, please ensure you have a robust plan in place to migrate or recompute any data from the old tables.

  • Verify that a data migration procedure is implemented (or scheduled) during the deployment process.
  • Confirm that records from the old tables are either preserved or recomputed in the new table structures in a production environment.
  • Update the migration documentation if necessary.

@adityachoudhari26 adityachoudhari26 merged commit 509f538 into main Apr 14, 2025
9 of 10 checks passed
@adityachoudhari26 adityachoudhari26 deleted the selector-computed-resources branch April 14, 2025 06:42
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.

3 participants