|
7 | 7 | } from "@dafthunk/types"; |
8 | 8 | import * as crypto from "crypto"; |
9 | 9 | import { and, desc, eq, inArray, SQL, sql } from "drizzle-orm"; |
| 10 | +import { alias } from "drizzle-orm/sqlite-core"; |
10 | 11 | import { v7 as uuidv7 } from "uuid"; |
11 | 12 |
|
12 | 13 | import { |
@@ -682,85 +683,70 @@ export async function getDeploymentsGroupedByWorkflow( |
682 | 683 | db: ReturnType<typeof createDatabase>, |
683 | 684 | organizationIdOrHandle: string |
684 | 685 | ): Promise<WorkflowDeployment[]> { |
685 | | - // First, get the latest deployment per workflow |
686 | | - const latestDeploymentsSubquery = db |
687 | | - .select({ |
688 | | - workflowId: deployments.workflowId, |
689 | | - maxCreatedAt: sql<string>`MAX(${deployments.createdAt})`.as( |
690 | | - "maxCreatedAt" |
691 | | - ), |
692 | | - }) |
693 | | - .from(deployments) |
694 | | - .innerJoin( |
695 | | - organizations, |
696 | | - and( |
697 | | - eq(deployments.organizationId, organizations.id), |
698 | | - getOrganizationCondition(organizationIdOrHandle) |
699 | | - ) |
700 | | - ) |
701 | | - .groupBy(deployments.workflowId) |
702 | | - .as("latest"); |
| 686 | + const workflowDeploymentAggregates = db |
| 687 | + .$with("workflow_deployment_aggregates") |
| 688 | + .as( |
| 689 | + db |
| 690 | + .select({ |
| 691 | + workflowId: deployments.workflowId, |
| 692 | + maxVersion: sql<number>`MAX(${deployments.version})`.mapWith(Number).as("max_version"), |
| 693 | + deploymentCount: sql<number>`COUNT(${deployments.id})`.mapWith(Number).as("deployment_count"), |
| 694 | + }) |
| 695 | + .from(deployments) |
| 696 | + .innerJoin( |
| 697 | + organizations, |
| 698 | + and( |
| 699 | + eq(deployments.organizationId, organizations.id), |
| 700 | + getOrganizationCondition(organizationIdOrHandle) |
| 701 | + ) |
| 702 | + ) |
| 703 | + .groupBy(deployments.workflowId) |
| 704 | + ); |
703 | 705 |
|
704 | | - // Get deployment counts per workflow |
705 | | - const deploymentCountsSubquery = db |
706 | | - .select({ |
707 | | - workflowId: deployments.workflowId, |
708 | | - count: sql<number>`COUNT(*)`.as("count"), |
709 | | - }) |
710 | | - .from(deployments) |
711 | | - .innerJoin( |
712 | | - organizations, |
713 | | - and( |
714 | | - eq(deployments.organizationId, organizations.id), |
715 | | - getOrganizationCondition(organizationIdOrHandle) |
716 | | - ) |
717 | | - ) |
718 | | - .groupBy(deployments.workflowId) |
719 | | - .as("counts"); |
| 706 | + // Alias the deployments table to clearly refer to the specific deployment record |
| 707 | + // that corresponds to the maxVersion. This is not strictly necessary if Drizzle handles |
| 708 | + // self-joins well without it, but can improve clarity. |
| 709 | + // Using a different alias name if 'latest_deployment' was used before or is confusing. |
| 710 | + const actualLatestDeployment = alias(deployments, "actual_latest_deployment"); |
720 | 711 |
|
721 | | - // Main query to get workflow details with latest deployment info |
722 | 712 | const results = await db |
| 713 | + .with(workflowDeploymentAggregates) |
723 | 714 | .select({ |
724 | 715 | workflowId: workflows.id, |
725 | 716 | workflowName: workflows.name, |
726 | | - deploymentId: deployments.id, |
727 | | - version: deployments.version, |
728 | | - createdAt: deployments.createdAt, |
729 | | - deploymentCount: deploymentCountsSubquery.count, |
| 717 | + latestDeploymentId: actualLatestDeployment.id, |
| 718 | + latestVersion: workflowDeploymentAggregates.maxVersion, |
| 719 | + deploymentCount: workflowDeploymentAggregates.deploymentCount, |
| 720 | + latestCreatedAt: actualLatestDeployment.createdAt, |
730 | 721 | }) |
731 | 722 | .from(workflows) |
732 | 723 | .innerJoin( |
733 | | - latestDeploymentsSubquery, |
734 | | - eq(workflows.id, latestDeploymentsSubquery.workflowId) |
| 724 | + workflowDeploymentAggregates, |
| 725 | + eq(workflows.id, workflowDeploymentAggregates.workflowId) |
735 | 726 | ) |
736 | 727 | .innerJoin( |
737 | | - deployments, |
| 728 | + actualLatestDeployment, |
738 | 729 | and( |
739 | | - eq(deployments.workflowId, latestDeploymentsSubquery.workflowId), |
740 | | - eq(deployments.createdAt, latestDeploymentsSubquery.maxCreatedAt) |
| 730 | + eq(actualLatestDeployment.workflowId, workflowDeploymentAggregates.workflowId), |
| 731 | + eq(actualLatestDeployment.version, workflowDeploymentAggregates.maxVersion) |
741 | 732 | ) |
742 | 733 | ) |
743 | | - .innerJoin( |
744 | | - deploymentCountsSubquery, |
745 | | - eq(workflows.id, deploymentCountsSubquery.workflowId) |
746 | | - ) |
747 | | - .innerJoin( |
| 734 | + .innerJoin( // Ensure workflows themselves are filtered by the organization |
748 | 735 | organizations, |
749 | 736 | and( |
750 | 737 | eq(workflows.organizationId, organizations.id), |
751 | 738 | getOrganizationCondition(organizationIdOrHandle) |
752 | 739 | ) |
753 | 740 | ) |
754 | | - // Sort by the latest deployment date (most recent first) |
755 | | - .orderBy(desc(latestDeploymentsSubquery.maxCreatedAt)); |
| 741 | + .orderBy(desc(actualLatestDeployment.createdAt)); // Order by the actual latest deployment's creation time |
756 | 742 |
|
757 | 743 | return results.map((row) => ({ |
758 | 744 | workflowId: row.workflowId, |
759 | 745 | workflowName: row.workflowName, |
760 | | - latestDeploymentId: row.deploymentId, |
761 | | - latestVersion: row.version, |
| 746 | + latestDeploymentId: row.latestDeploymentId, |
| 747 | + latestVersion: row.latestVersion, |
762 | 748 | deploymentCount: row.deploymentCount, |
763 | | - latestCreatedAt: row.createdAt, |
| 749 | + latestCreatedAt: row.latestCreatedAt, |
764 | 750 | })); |
765 | 751 | } |
766 | 752 |
|
@@ -1078,3 +1064,4 @@ export async function getExecutionWithVisibility( |
1078 | 1064 |
|
1079 | 1065 | return execution; |
1080 | 1066 | } |
| 1067 | + |
0 commit comments