@@ -2,7 +2,11 @@ import { describe, expect, vi } from "vitest";
22import { setTimeout } from "node:timers/promises" ;
33import { replicationContainerTest } from "@internal/testcontainers" ;
44import { RunsRepository } from "~/services/runsRepository/runsRepository.server" ;
5- import { countQueuedRunsForBillableEnvironment } from "~/v3/services/billingLimit/billingLimitQueuedRuns.server" ;
5+ import {
6+ countBillableQueuedRunsForOrganization ,
7+ countQueuedRunsForBillableEnvironment ,
8+ getBillableEnvironmentsForBillingLimit ,
9+ } from "~/v3/services/billingLimit/billingLimitQueuedRuns.server" ;
610import { setupClickhouseReplication } from "./utils/replicationUtils" ;
711
812vi . setConfig ( { testTimeout : 60_000 } ) ;
@@ -109,4 +113,173 @@ describe("billingLimitQueuedRuns", () => {
109113 expect ( developmentCount ) . toBe ( 1 ) ;
110114 }
111115 ) ;
116+
117+ replicationContainerTest (
118+ "counts queued runs org-wide with a single query, spanning billable environment types only" ,
119+ async ( { clickhouseContainer, redisOptions, postgresContainer, prisma } ) => {
120+ const { clickhouse } = await setupClickhouseReplication ( {
121+ prisma,
122+ databaseUrl : postgresContainer . getConnectionUri ( ) ,
123+ clickhouseUrl : clickhouseContainer . getConnectionUrl ( ) ,
124+ redisOptions,
125+ } ) ;
126+
127+ const organization = await prisma . organization . create ( {
128+ data : { title : "billing-limit-org-count" , slug : "billing-limit-org-count" } ,
129+ } ) ;
130+
131+ const project = await prisma . project . create ( {
132+ data : {
133+ name : "billing-limit-org-count" ,
134+ slug : "billing-limit-org-count" ,
135+ organizationId : organization . id ,
136+ externalRef : "billing-limit-org-count" ,
137+ } ,
138+ } ) ;
139+
140+ const productionEnv = await prisma . runtimeEnvironment . create ( {
141+ data : {
142+ slug : "prod" ,
143+ type : "PRODUCTION" ,
144+ projectId : project . id ,
145+ organizationId : organization . id ,
146+ apiKey : "prod-org-count" ,
147+ pkApiKey : "prod-org-count" ,
148+ shortcode : "prod-org-count" ,
149+ } ,
150+ } ) ;
151+
152+ const developmentEnv = await prisma . runtimeEnvironment . create ( {
153+ data : {
154+ slug : "dev" ,
155+ type : "DEVELOPMENT" ,
156+ projectId : project . id ,
157+ organizationId : organization . id ,
158+ apiKey : "dev-org-count" ,
159+ pkApiKey : "dev-org-count" ,
160+ shortcode : "dev-org-count" ,
161+ } ,
162+ } ) ;
163+
164+ const previewEnv = await prisma . runtimeEnvironment . create ( {
165+ data : {
166+ slug : "preview" ,
167+ type : "PREVIEW" ,
168+ projectId : project . id ,
169+ organizationId : organization . id ,
170+ apiKey : "preview-org-count" ,
171+ pkApiKey : "preview-org-count" ,
172+ shortcode : "preview-org-count" ,
173+ branchName : "feature-branch" ,
174+ archivedAt : new Date ( ) ,
175+ } ,
176+ } ) ;
177+
178+ const runRows = [
179+ {
180+ friendlyId : "run_org_prod_pending" ,
181+ env : productionEnv ,
182+ type : "PRODUCTION" ,
183+ status : "PENDING" ,
184+ } ,
185+ {
186+ friendlyId : "run_org_prod_delayed" ,
187+ env : productionEnv ,
188+ type : "PRODUCTION" ,
189+ status : "DELAYED" ,
190+ } ,
191+ {
192+ friendlyId : "run_org_prod_done" ,
193+ env : productionEnv ,
194+ type : "PRODUCTION" ,
195+ status : "COMPLETED_SUCCESSFULLY" ,
196+ } ,
197+ {
198+ friendlyId : "run_org_dev_pending" ,
199+ env : developmentEnv ,
200+ type : "DEVELOPMENT" ,
201+ status : "PENDING" ,
202+ } ,
203+ {
204+ friendlyId : "run_org_preview_pending" ,
205+ env : previewEnv ,
206+ type : "PREVIEW" ,
207+ status : "PENDING" ,
208+ } ,
209+ ] as const ;
210+
211+ for ( const row of runRows ) {
212+ await prisma . taskRun . create ( {
213+ data : {
214+ friendlyId : row . friendlyId ,
215+ taskIdentifier : "queued-task" ,
216+ status : row . status ,
217+ payload : JSON . stringify ( { } ) ,
218+ traceId : "trace" ,
219+ spanId : "span" ,
220+ queue : "main" ,
221+ runtimeEnvironmentId : row . env . id ,
222+ projectId : project . id ,
223+ organizationId : organization . id ,
224+ environmentType : row . type ,
225+ engine : "V2" ,
226+ } ,
227+ } ) ;
228+ }
229+
230+ await setTimeout ( 1000 ) ;
231+
232+ const count = await countBillableQueuedRunsForOrganization ( organization . id , clickhouse ) ;
233+
234+ expect ( count ) . toBe ( 3 ) ;
235+ }
236+ ) ;
237+
238+ replicationContainerTest (
239+ "excludes archived environments from the billable environment list" ,
240+ async ( { prisma } ) => {
241+ const organization = await prisma . organization . create ( {
242+ data : { title : "billing-limit-archived" , slug : "billing-limit-archived" } ,
243+ } ) ;
244+
245+ const project = await prisma . project . create ( {
246+ data : {
247+ name : "billing-limit-archived" ,
248+ slug : "billing-limit-archived" ,
249+ organizationId : organization . id ,
250+ externalRef : "billing-limit-archived" ,
251+ } ,
252+ } ) ;
253+
254+ const activeEnv = await prisma . runtimeEnvironment . create ( {
255+ data : {
256+ slug : "prod" ,
257+ type : "PRODUCTION" ,
258+ projectId : project . id ,
259+ organizationId : organization . id ,
260+ apiKey : "prod-archived-test" ,
261+ pkApiKey : "prod-archived-test" ,
262+ shortcode : "prod-archived-test" ,
263+ } ,
264+ } ) ;
265+
266+ await prisma . runtimeEnvironment . create ( {
267+ data : {
268+ slug : "preview-archived" ,
269+ type : "PREVIEW" ,
270+ projectId : project . id ,
271+ organizationId : organization . id ,
272+ apiKey : "preview-archived-test" ,
273+ pkApiKey : "preview-archived-test" ,
274+ shortcode : "preview-archived-test" ,
275+ branchName : "old-branch" ,
276+ archivedAt : new Date ( ) ,
277+ } ,
278+ } ) ;
279+
280+ const environments = await getBillableEnvironmentsForBillingLimit ( organization . id , prisma ) ;
281+
282+ expect ( environments ) . toEqual ( [ { id : activeEnv . id , projectId : project . id } ] ) ;
283+ }
284+ ) ;
112285} ) ;
0 commit comments