Skip to content

Conversation

@adityachoudhari26
Copy link
Contributor

@adityachoudhari26 adityachoudhari26 commented Apr 5, 2025

Summary by CodeRabbit

  • New Features

    • Improved release workflow now ensures that every deployment target generates its respective release reliably.
    • Enhanced policy matching capabilities provide more accurate retrieval and validation of release data.
    • Consolidated release management utilities streamline the creation and integration of releases for a smoother operational experience.
    • New function to find all releases matching a specified policy has been introduced.
    • New utilities for creating releases have been added, enhancing the release management process.
    • A new parameter for workspace ID has been added to the release targets creation process.
  • Bug Fixes

    • Improved error handling for missing resources during release creation operations.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 5, 2025

Walkthrough

This pull request introduces asynchronous release creation within the deployment worker and expands release management functionality in the rule engine. The event worker now maps over inserted release targets to create releases concurrently, while the rule engine gains a new method and function for fetching policy-matching releases. Additionally, exports in the module have been reorganized, and new utility functions for creating releases have been added with proper error handling and documentation updates.

Changes

File(s) Change Summary
apps/event-worker/src/.../new-deployment-version.ts Added asynchronous operation in newDeploymentVersionWorker which maps over release targets, verifies resources, and concurrently calls createRelease using Promise.all.
packages/rule-engine/src/index.ts Removed the export for merge-policies.js and added an export for utils/index.js, altering the module's export set for utilities.
packages/rule-engine/src/repositories/db-release-repository.ts
packages/rule-engine/src/repositories/get-releases.ts
Introduced a new asynchronous findAllPolicyMatchingReleases method (and function) to fetch releases matching a given policy; updated documentation for findMatchingReleases.
packages/rule-engine/src/utils/create-release.ts Added a new file defining getDesiredVersionId and createRelease functions, which include DB queries, validation, and upsert logic for creating and validating a release.
packages/rule-engine/src/utils/index.ts Added a new index file that re-exports entities from create-release.js and merge-policies.js, consolidating utility exports.
apps/event-worker/src/.../env-selector-update.ts Updated createReleaseTargets function to include workspaceId, modifying logic to create release targets using createRelease function and awaiting promises collectively.
apps/event-worker/src/.../update-deployment-variable.ts Enhanced updateDeploymentVariableWorker to manage resources related to release targets, incorporating createRelease functionality and error handling.
apps/event-worker/src/.../update-resource-variable.ts Modified updateResourceVariableWorker to include resource management, destructuring query results, and implementing error handling for resource retrieval.

Sequence Diagram(s)

sequenceDiagram
    participant Worker as newDeploymentVersionWorker
    participant DB as Database
    participant Resource as Resource Lookup
    participant ReleaseUtil as createRelease
    Worker->>DB: Insert release targets
    Worker->>Worker: Map over releaseTargets to build promises
    loop For each releaseTarget
        Worker->>DB: Query for resource by ID
        alt Resource found
            Worker->>ReleaseUtil: Call createRelease(db, releaseTarget, workspaceId)
        else Resource not found
            Worker-->>Worker: Throw error
        end
    end
    Worker->>Worker: Await Promise.all(createReleasePromises)
Loading
sequenceDiagram
    participant Caller as Release Creator
    participant DB as Database (Tx)
    participant Repo as Repository
    participant ReleaseUtil as createRelease
    Caller->>DB: Call createRelease(db, releaseTarget, workspaceId, versionId?)
    DB->>DB: Query for release target
    alt Release target exists
         ReleaseUtil->>Repo: Get repository instance
         ReleaseUtil->>Repo: Call getDesiredVersionId(db, repo, versionId)
         alt Version ID found
              ReleaseUtil->>DB: Upsert new release with latest variables
              DB->>Repo: Validate against policy-matching releases
              ReleaseUtil->>Repo: Set new release as desired release
         else Version ID missing
              ReleaseUtil-->>Caller: Throw error (missing version)
         end
    else
         ReleaseUtil-->>Caller: Throw error (release target not found)
    end
Loading

Possibly related PRs

  • fix: Typecheck on var change #438: The changes in the main PR are related to the createRelease function, which is also utilized in the retrieved PR's context of managing resource releases.
  • feat: Init new worker format #444: The changes in the main PR are related to the createRelease function, which is also referenced in the retrieved PR's context, indicating a direct connection at the code level.
  • fix: Target variables #170: The changes in the main PR are related to the createRelease function, which is also modified in the retrieved PR, indicating a direct connection at the code level.

Suggested reviewers

  • jsbroks

Poem

I hopped through lines of code in flight,
New asynchronous bounds set things right.
With releases created in a joyful race,
And exports organized with style and grace.
I'm a rabbit coding under the moonlight –
Celebrating changes with a bounce so light! 🐇✨


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between adb9063 and 1ba926c.

📒 Files selected for processing (6)
  • apps/event-worker/src/workers/env-selector-update.ts (4 hunks)
  • apps/event-worker/src/workers/new-deployment-version.ts (2 hunks)
  • apps/event-worker/src/workers/update-deployment-variable.ts (2 hunks)
  • apps/event-worker/src/workers/update-resource-variable.ts (3 hunks)
  • packages/rule-engine/src/repositories/db-release-repository.ts (4 hunks)
  • packages/rule-engine/src/utils/create-release.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/rule-engine/src/repositories/db-release-repository.ts
  • apps/event-worker/src/workers/new-deployment-version.ts
  • packages/rule-engine/src/utils/create-release.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-variable.ts
  • apps/event-worker/src/workers/env-selector-update.ts
  • apps/event-worker/src/workers/update-resource-variable.ts
🧬 Code Definitions (3)
apps/event-worker/src/workers/update-deployment-variable.ts (1)
packages/rule-engine/src/utils/create-release.ts (1)
  • createRelease (30-69)
apps/event-worker/src/workers/env-selector-update.ts (1)
packages/rule-engine/src/utils/create-release.ts (1)
  • createRelease (30-69)
apps/event-worker/src/workers/update-resource-variable.ts (1)
packages/rule-engine/src/utils/create-release.ts (1)
  • createRelease (30-69)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Typecheck
  • GitHub Check: build (linux/amd64)
  • GitHub Check: Lint
🔇 Additional comments (13)
apps/event-worker/src/workers/update-resource-variable.ts (4)

5-5: New import for release functionality

Added import for createRelease function from the rule engine module, which will be used to create releases for each release target.


12-36: Improved data structure for query results

The code now destructures deploymentIds and resource from the database query results, replacing the previous single variable structure. This change makes the relationship between data pieces clearer and enables resource-specific operations.


38-38: Proper null check for resource

Good defensive programming - the added null check ensures the code fails fast if the resource is not found.


47-50: Asynchronous release creation implementation

The new code implements concurrent release creation for all release targets before adding jobs to the evaluation queue. This pattern ensures all releases exist before evaluation begins.

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

1-1: Updated imports for enhanced functionality

Added inArray import to support efficient batch querying of resources.


5-5: New import for release functionality

Added import for createRelease function which centralizes release creation logic across workers.


29-34: Efficient batch resource fetching

Good implementation of batch fetching resources for all release targets in a single query using inArray, which is more efficient than individual queries.


36-42: Proper resource-to-release target mapping

The implementation correctly maps each release target to its corresponding resource, with appropriate error handling if a resource is not found.


43-43: Concurrent release creation

Using Promise.all to wait for all release creations to complete before proceeding ensures data consistency before adding to the queue.

apps/event-worker/src/workers/env-selector-update.ts (4)

11-11: New import for release functionality

Added import for createRelease function to support the enhanced release target creation process.


65-65: Function parameter addition

Added required workspaceId parameter to createReleaseTargets function to support the new release creation functionality.


83-95: Enhanced release target creation with release creation

The function now not only creates release targets but also creates corresponding releases concurrently using Promise.all. This ensures all releases exist before adding jobs to the evaluation queue.


214-214: Updated function call with workspaceId

Correctly passes the workspaceId parameter to the updated createReleaseTargets function.

✨ 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: 1

🧹 Nitpick comments (6)
packages/rule-engine/src/repositories/get-releases.ts (1)

146-160: LGTM: Well-implemented function for policy-matching releases

The new findAllPolicyMatchingReleases function follows the established patterns of the codebase, logically extending the existing functionality from findLatestPolicyMatchingRelease to return all matching releases instead of just the latest one.

One suggestion would be to add JSDoc comments for this function similar to the other functions in this file to maintain consistency and improve code documentation.

+/**
+ * Finds all releases that match the applicable policy for a given release target
+ *
+ * @param tx - Database transaction object for querying
+ * @param policy - The policy to filter releases by
+ * @param releaseTarget - The release target to find matching releases for
+ * @returns Promise resolving to an array of all matching releases
+ */
 export const findAllPolicyMatchingReleases = async (
   tx: Tx,
   policy: Policy | null,
   releaseTarget: { id: string },
 ): Promise<CompleteRelease[]> =>
packages/rule-engine/src/utils/create-release.ts (5)

9-28: Consider adding explicit return type to the function signature.

The getDesiredVersionId function can return either a string or null, but this isn't explicitly defined in the function signature. Adding an explicit return type would improve type safety and make the API more clear.

-const getDesiredVersionId = async (
+const getDesiredVersionId = async (
   db: Tx,
   repo: DatabaseReleaseRepository,
   versionId?: string,
-) => {
+): Promise<string | null> => {

30-35: Add explicit return type to createRelease function.

The createRelease function doesn't specify a return type. Consider adding Promise<void> to make it clear that the function doesn't return any value.

-export const createRelease = async (
+export const createRelease = async (
   db: Tx,
   releaseTarget: ReleaseTargetIdentifier,
   workspaceId: string,
   versionId?: string,
-) => {
+): Promise<void> => {

58-58: Consider returning a more informative result.

The function currently returns early with no value when a release isn't created. Consider returning a more informative result, such as an object indicating whether a release was created and potentially including the release details.

-  if (!created) return;
+  if (!created) return { created: false, release };

And update the return type of the function:

-export const createRelease = async (
+export const createRelease = async (
   db: Tx,
   releaseTarget: ReleaseTargetIdentifier,
   workspaceId: string,
   versionId?: string,
-): Promise<void> => {
+): Promise<{ created: boolean; release?: typeof release }> => {

60-64: Handle both valid and invalid release scenarios.

Currently, the function sets the desired release only if it's valid, but doesn't handle the case when the release is invalid. Consider adding error handling or at least logging for the invalid case.

  const isReleaseValid = allValidIds.includes(release.id);
-  if (isReleaseValid) repo.setDesiredRelease(release.id);
+  if (isReleaseValid) {
+    await repo.setDesiredRelease(release.id);
+    return { created: true, release, valid: true };
+  } else {
+    // Handle the invalid release case - perhaps log or throw an error
+    return { created: true, release, valid: false };
+  }

30-65: Add error handling around repository operations.

The createRelease function has error handling for specific cases but doesn't have a general try/catch to handle unexpected errors that might occur during repository operations. Consider adding comprehensive error handling.

 export const createRelease = async (
   db: Tx,
   releaseTarget: ReleaseTargetIdentifier,
   workspaceId: string,
   versionId?: string,
 ): Promise<void> => {
+  try {
     const rt = await db.query.releaseTarget.findFirst({
       where: and(
         eq(schema.releaseTarget.deploymentId, releaseTarget.deploymentId),
         eq(schema.releaseTarget.environmentId, releaseTarget.environmentId),
         eq(schema.releaseTarget.resourceId, releaseTarget.resourceId),
       ),
     });
 
     if (rt == null) throw new Error("Release target not found");
 
     const repo = await DatabaseReleaseRepository.create({ ...rt, workspaceId });
     const desiredVersionId = await getDesiredVersionId(db, repo, versionId);
     if (desiredVersionId == null)
       throw new Error("Could not find desired version");
     const variables = await repo.getLatestVariables();
 
     const { release, created } = await repo.upsert(
       releaseTarget,
       desiredVersionId,
       variables,
     );
 
     if (!created) return;
 
     const allPolicyMatchingReleases = await repo.findAllPolicyMatchingReleases();
     const allValidIds = allPolicyMatchingReleases.map((r) => r.id);
 
     const isReleaseValid = allValidIds.includes(release.id);
     if (isReleaseValid) repo.setDesiredRelease(release.id);
+  } catch (error) {
+    // Consider more specific error handling or logging
+    throw new Error(`Failed to create release: ${error.message}`);
+  }
 };
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 20efc63 and 07507fc.

📒 Files selected for processing (6)
  • apps/event-worker/src/workers/new-deployment-version.ts (2 hunks)
  • packages/rule-engine/src/index.ts (1 hunks)
  • packages/rule-engine/src/repositories/db-release-repository.ts (3 hunks)
  • packages/rule-engine/src/repositories/get-releases.ts (1 hunks)
  • packages/rule-engine/src/utils/create-release.ts (1 hunks)
  • packages/rule-engine/src/utils/index.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/rule-engine/src/index.ts
  • packages/rule-engine/src/repositories/get-releases.ts
  • packages/rule-engine/src/utils/index.ts
  • packages/rule-engine/src/repositories/db-release-repository.ts
  • apps/event-worker/src/workers/new-deployment-version.ts
  • packages/rule-engine/src/utils/create-release.ts
🧬 Code Definitions (4)
packages/rule-engine/src/repositories/get-releases.ts (2)
packages/rule-engine/src/repositories/db-release-repository.ts (1)
  • findAllPolicyMatchingReleases (118-121)
packages/rule-engine/src/repositories/types.ts (1)
  • CompleteRelease (41-41)
packages/rule-engine/src/repositories/db-release-repository.ts (2)
packages/rule-engine/src/repositories/types.ts (1)
  • CompleteRelease (41-41)
packages/rule-engine/src/repositories/get-releases.ts (1)
  • findAllPolicyMatchingReleases (146-160)
apps/event-worker/src/workers/new-deployment-version.ts (1)
packages/rule-engine/src/utils/create-release.ts (1)
  • createRelease (30-65)
packages/rule-engine/src/utils/create-release.ts (1)
packages/rule-engine/src/repositories/db-release-repository.ts (1)
  • DatabaseReleaseRepository (45-248)
⏰ 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 (7)
packages/rule-engine/src/utils/index.ts (1)

1-2: LGTM: Clean barrel module structure for utility exports

The index file follows the standard barrel pattern for re-exporting utilities, providing a clean and organized access point for both create-release and merge-policies modules.

packages/rule-engine/src/index.ts (1)

6-6: Improved module organization

Replacing the direct export of merge-policies with the utils/index.js export creates a more maintainable structure, providing a single entry point for all utility functions including the new release creation functionality.

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

8-8: LGTM: New import added for release creation functionality

The import for the createRelease function from the rule-engine package is properly added to support the new functionality.

packages/rule-engine/src/repositories/db-release-repository.ts (3)

23-23: Well-organized module import.

The import of findAllPolicyMatchingReleases from the get-releases.js module aligns well with the existing imports and supports the new method being added to the class.


100-100: Documentation improvement enhances clarity.

The updated documentation clarifies that findMatchingReleases specifically retrieves releases between the latest deployed and desired release, which helps distinguish it from the new method being added.


113-121: Good implementation of the new method.

The new findAllPolicyMatchingReleases method follows the established pattern in the class, correctly obtaining the policy before delegating to the imported function. The method is well-documented with appropriate JSDoc comments.

packages/rule-engine/src/utils/create-release.ts (1)

44-44: Good error handling for missing release target.

Properly checking for the existence of the release target and throwing a descriptive error message if not found is a good practice.

Comment on lines 77 to 86
const createReleasePromises = releaseTargets.map(async (rt) => {
const resource = await db.query.resource.findFirst({
where: eq(schema.resource.id, rt.resourceId),
});
if (resource == null) throw new Error("Resource not found");

await createRelease(db, rt, resource.workspaceId);
});
await Promise.all(createReleasePromises);

Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consider optimizing resource queries for better performance

The current implementation queries resources individually for each release target, which could lead to performance issues with many targets. Consider fetching all resources at once and then mapping them to release targets.

-    const createReleasePromises = releaseTargets.map(async (rt) => {
-      const resource = await db.query.resource.findFirst({
-        where: eq(schema.resource.id, rt.resourceId),
-      });
-      if (resource == null) throw new Error("Resource not found");
-
-      await createRelease(db, rt, resource.workspaceId);
-    });
-    await Promise.all(createReleasePromises);
+    // Fetch all resources in a single query
+    const resourceIds = releaseTargets.map(rt => rt.resourceId);
+    const resources = await db.query.resource.findMany({
+      where: eq(schema.resource.id, { in: resourceIds }),
+    });
+    
+    // Create a map for quick lookups
+    const resourceMap = new Map(resources.map(r => [r.id, r]));
+    
+    // Create releases with proper error handling
+    const createReleasePromises = releaseTargets.map(async (rt) => {
+      const resource = resourceMap.get(rt.resourceId);
+      if (resource == null) throw new Error(`Resource not found: ${rt.resourceId}`);
+      
+      await createRelease(db, rt, resource.workspaceId);
+    });
+    await Promise.all(createReleasePromises);

Also consider adding error handling to prevent a single failure from stopping all release creation:

const results = await Promise.allSettled(createReleasePromises);
const failures = results.filter(r => r.status === 'rejected');
if (failures.length > 0) {
  console.error(`Failed to create ${failures.length} releases:`, 
    failures.map(f => f.reason?.message || f.reason));
  // Decide whether to throw or continue
}

Let's verify if the in operator is supported with Drizzle ORM:


🌐 Web query:

Does Drizzle ORM support the `in` operator for filtering multiple IDs?

💡 Result:

Drizzle ORM supports filtering by multiple IDs using the inArray operator, which serves the same purpose as the SQL IN clause. Here's how it works:

Using inArray for Multiple IDs

  • Basic usage: Pass the table column and an array of values to inArray

    import { inArray } from 'drizzle-orm';
    
    const userIds = [1, 2, 3];
    const users = await db
      .select()
      .from(usersTable)
      .where(inArray(usersTable.id, userIds));
  • Combining with other filters: Use and/or operators for complex queries[1][5][8]

    import { and, eq } from 'drizzle-orm';
    
    const result = await db
      .select()
      .from(books)
      .where(and(
        inArray(books.id, [4, 7, 9]),
        eq(books.category, 'fiction')
      ));

Key Details

  1. Type-safe: Works with typed arrays[1][4][8]
  2. SQL Injection protection: Automatically parameterizes values[8]
  3. Cross-dialect support: Works consistently across PostgreSQL, MySQL, and SQLite[1][4]

For cases where you need to check if a value exists in a JSON array column, you might need to use raw SQL expressions with the sql template[6][7], but inArray is preferred for standard ID filtering[8][9].

Example with optional ID list filtering:

const filterByIds = (ids?: number[]) => 
  ids ? inArray(usersTable.id, ids) : undefined;

const users = await db
  .select()
  .from(usersTable)
  .where(and(
    eq(usersTable.active, true),
    filterByIds([101, 202, 303])
  ));
```[5][8]

Citations:

- 1: https://orm.drizzle.team/docs/operators
- 2: https://www.youtube.com/watch?v=R4ZgTB-1wEg
- 3: https://orm.drizzle.team/docs/indexes-constraints
- 4: https://orm.drizzle.team/docs/rqb
- 5: https://www.answeroverflow.com/m/1172728238968156230
- 6: https://frontendmasters.com/blog/introducing-drizzle/
- 7: https://orm.drizzle.team/docs/sql
- 8: https://www.answeroverflow.com/m/1195618774590697493
- 9: https://www.prisma.io/docs/orm/more/comparisons/prisma-and-drizzle
- 10: https://orm.drizzle.team/docs/relations

---



</details>

**Optimize Resource Query & Correct Operator Usage**

The current implementation queries each resource individually. To improve performance, fetch all resources at once and map them to the corresponding release targets. Also, note that Drizzle ORM doesn't support the native `in` operator—instead, use its `inArray` operator for filtering.

**Points to address:**

- **Bulk Querying:** Instead of querying for each release target, extract all resource IDs and perform a single query.
- **Operator Correction:** Replace the invalid `in` filtering syntax with Drizzle ORM’s `inArray` operator.
- **Error Handling:** Consider using `Promise.allSettled` to ensure that a single failure does not disrupt the release creation process.

**Revised Code Snippet Example:**

```diff
-    // Fetch all resources in a single query
-    const resourceIds = releaseTargets.map(rt => rt.resourceId);
-    const resources = await db.query.resource.findMany({
-      where: eq(schema.resource.id, { in: resourceIds }),
-    });
+    import { inArray } from 'drizzle-orm';
+
+    // Fetch all resources in a single query using inArray
+    const resourceIds = releaseTargets.map(rt => rt.resourceId);
+    const resources = await db.query.resource.findMany({
+      where: inArray(schema.resource.id, resourceIds),
+    });
    
-    // Create a map for quick lookups
-    const resourceMap = new Map(resources.map(r => [r.id, r]));
-    
-    // Create releases with proper error handling
-    const createReleasePromises = releaseTargets.map(async (rt) => {
-      const resource = resourceMap.get(rt.resourceId);
-      if (resource == null) throw new Error(`Resource not found: ${rt.resourceId}`);
-      
-      await createRelease(db, rt, resource.workspaceId);
-    });
-    await Promise.all(createReleasePromises);
+    // Create a map for quick lookups
+    const resourceMap = new Map(resources.map(r => [r.id, r]));
+
+    // Create releases with proper error handling
+    const createReleasePromises = releaseTargets.map(async (rt) => {
+      const resource = resourceMap.get(rt.resourceId);
+      if (resource == null) throw new Error(`Resource not found: ${rt.resourceId}`);
+      
+      await createRelease(db, rt, resource.workspaceId);
+    });
+    await Promise.all(createReleasePromises);

Error handling suggestion:

const results = await Promise.allSettled(createReleasePromises);
const failures = results.filter(r => r.status === 'rejected');
if (failures.length > 0) {
  console.error(`Failed to create ${failures.length} releases:`, 
    failures.map(f => f.reason?.message || f.reason));
  // Decide whether to throw or continue with partial success
}

Comment on lines +77 to +83
const createReleasePromises = releaseTargets.map(async (rt) => {
const resource = resources.find((r) => r.id === rt.resourceId);
if (resource == null) throw new Error("Resource not found");

await createRelease(db, rt, resource.workspaceId, version.id);
});
await Promise.all(createReleasePromises);
Copy link
Member

@jsbroks jsbroks Apr 6, 2025

Choose a reason for hiding this comment

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

Suggested change
const createReleasePromises = releaseTargets.map(async (rt) => {
const resource = resources.find((r) => r.id === rt.resourceId);
if (resource == null) throw new Error("Resource not found");
await createRelease(db, rt, resource.workspaceId, version.id);
});
await Promise.all(createReleasePromises);
const releases = releaseTargets.map((rt) => {
const resource = resources.find((r) => r.id === rt.resourceId);
if (resource == null) throw new Error("Resource not found");
return createRelease(db, rt, resource.workspaceId, version.id);
});
await Promise.all(releases);

Comment on lines +151 to +160
tx.query.release.findMany({
where: and(
eq(schema.release.releaseTargetId, releaseTarget.id),
schema.deploymentVersionMatchesCondition(
tx,
policy?.deploymentVersionSelector?.deploymentVersionSelector,
),
),
with: { variables: true, version: { with: { metadata: true } } },
});
Copy link
Member

Choose a reason for hiding this comment

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

You are applying a version selector to a release?

@jsbroks
Copy link
Member

jsbroks commented Apr 6, 2025

rename to update-environment not this weird selector crap

getQueue(Channel.EvaluateReleaseTarget).addBulk(
.then(async (releaseTargets) => {
const createReleasePromises = releaseTargets.map((rt) =>
createRelease(db, rt, workspaceId),
Copy link
Member

Choose a reason for hiding this comment

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

you shouldn't be creating releases in a function that is suppose to createReleaseTargets

Comment on lines +33 to +36
.then((results) => ({
deploymentIds: results.map((result) => result.deployment.id),
resource: results[0]?.resource,
}));
Copy link
Member

Choose a reason for hiding this comment

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

no, make this different, const resource = results.at(0)
You are making this way more complicated

});
};

export const findAllPolicyMatchingReleases = async (
Copy link
Member

Choose a reason for hiding this comment

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

why extract this out?

Comment on lines +67 to +68
const isReleaseValid = allValidIds.includes(release.id);
if (isReleaseValid) repo.setDesiredRelease(release.id);
Copy link
Member

Choose a reason for hiding this comment

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

don't set desired release, the function is called createRelease, yet you are setting desired versions?

Copy link
Member

Choose a reason for hiding this comment

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

don't set the desired release anywhere

@adityachoudhari26 adityachoudhari26 deleted the create-release-util branch May 5, 2025 19:49
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