Skip to content

Commit e5cc7e8

Browse files
committed
Use upcoming invoice
1 parent 1cd0fbf commit e5cc7e8

File tree

13 files changed

+443
-299
lines changed

13 files changed

+443
-299
lines changed

components/server/ee/src/billing/billing-service.ts

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
import { CostCenterDB } from "@gitpod/gitpod-db/lib";
88
import { User } from "@gitpod/gitpod-protocol";
99
import { AttributionId } from "@gitpod/gitpod-protocol/lib/attribution";
10-
import { BillableSession, BillableSessionRequest, SortOrder } from "@gitpod/gitpod-protocol/lib/usage";
1110
import { log } from "@gitpod/gitpod-protocol/lib/util/logging";
12-
import { CachingUsageServiceClientProvider, UsageService } from "@gitpod/usage-api/lib/usage/v1/sugar";
13-
import { Timestamp } from "google-protobuf/google/protobuf/timestamp_pb";
11+
import { GetUpcomingInvoiceResponse } from "@gitpod/usage-api/lib/usage/v1/billing_pb";
12+
import {
13+
CachingUsageServiceClientProvider,
14+
CachingBillingServiceClientProvider,
15+
} from "@gitpod/usage-api/lib/usage/v1/sugar";
1416
import { inject, injectable } from "inversify";
1517
import { UserService } from "../../../src/user/user-service";
1618

@@ -26,6 +28,8 @@ export class BillingService {
2628
@inject(CostCenterDB) protected readonly costCenterDB: CostCenterDB;
2729
@inject(CachingUsageServiceClientProvider)
2830
protected readonly usageServiceClientProvider: CachingUsageServiceClientProvider;
31+
@inject(CachingBillingServiceClientProvider)
32+
protected readonly billingServiceClientProvider: CachingBillingServiceClientProvider;
2933

3034
async checkSpendingLimitReached(user: User): Promise<SpendingLimitReachedResult> {
3135
const attributionId = await this.userService.getWorkspaceUsageAttributionId(user);
@@ -40,50 +44,39 @@ export class BillingService {
4044
};
4145
}
4246

43-
const allSessions = await this.listBilledUsage({
44-
attributionId: AttributionId.render(attributionId),
45-
startedTimeOrder: SortOrder.Descending,
46-
});
47-
const totalUsage = allSessions.map((s) => s.credits).reduce((a, b) => a + b, 0);
48-
if (totalUsage >= costCenter.spendingLimit) {
47+
const upcomingInvoice = await this.getUpcomingInvoice(attributionId);
48+
const currentInvoiceCredits = upcomingInvoice.getCredits();
49+
if (currentInvoiceCredits >= costCenter.spendingLimit) {
50+
log.info({ userId: user.id }, "Spending limit reached", {
51+
attributionId,
52+
currentInvoiceCredits,
53+
spendingLimit: costCenter.spendingLimit,
54+
});
4955
return {
5056
reached: true,
5157
attributionId,
5258
};
53-
} else if (totalUsage > costCenter.spendingLimit * 0.8) {
59+
} else if (currentInvoiceCredits > costCenter.spendingLimit * 0.8) {
60+
log.info({ userId: user.id }, "Spending limit almost reached", {
61+
attributionId,
62+
currentInvoiceCredits,
63+
spendingLimit: costCenter.spendingLimit,
64+
});
5465
return {
5566
reached: false,
5667
almostReached: true,
5768
attributionId,
5869
};
5970
}
71+
6072
return {
6173
reached: false,
6274
attributionId,
6375
};
6476
}
6577

66-
// TODO (gpl): Replace this with call to stripeService.getInvoice()
67-
async listBilledUsage(req: BillableSessionRequest): Promise<BillableSession[]> {
68-
const { attributionId, startedTimeOrder, from, to } = req;
69-
let timestampFrom;
70-
let timestampTo;
71-
72-
if (from) {
73-
timestampFrom = Timestamp.fromDate(new Date(from));
74-
}
75-
if (to) {
76-
timestampTo = Timestamp.fromDate(new Date(to));
77-
}
78-
const usageClient = this.usageServiceClientProvider.getDefault();
79-
const response = await usageClient.listBilledUsage(
80-
{},
81-
attributionId,
82-
startedTimeOrder as number,
83-
timestampFrom,
84-
timestampTo,
85-
);
86-
const sessions = response.getSessionsList().map((s) => UsageService.mapBilledSession(s));
87-
return sessions;
78+
async getUpcomingInvoice(attributionId: AttributionId): Promise<GetUpcomingInvoiceResponse> {
79+
const response = await this.billingServiceClientProvider.getDefault().getUpcomingInvoice(attributionId);
80+
return response;
8881
}
8982
}

components/usage-api/go/v1/billing.pb.go

Lines changed: 122 additions & 112 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/usage-api/go/v1/billing_grpc.pb.go

Lines changed: 16 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/usage-api/typescript/src/usage/v1/billing_grpc_pb.d.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import * as usage_v1_usage_pb from "../../usage/v1/usage_pb";
1717

1818
interface IBillingServiceService extends grpc.ServiceDefinition<grpc.UntypedServiceImplementation> {
1919
updateInvoices: IBillingServiceService_IUpdateInvoices;
20-
getLatestInvoice: IBillingServiceService_IGetLatestInvoice;
20+
getUpcomingInvoice: IBillingServiceService_IGetUpcomingInvoice;
2121
finalizeInvoice: IBillingServiceService_IFinalizeInvoice;
2222
setBilledSession: IBillingServiceService_ISetBilledSession;
2323
}
@@ -31,14 +31,14 @@ interface IBillingServiceService_IUpdateInvoices extends grpc.MethodDefinition<u
3131
responseSerialize: grpc.serialize<usage_v1_billing_pb.UpdateInvoicesResponse>;
3232
responseDeserialize: grpc.deserialize<usage_v1_billing_pb.UpdateInvoicesResponse>;
3333
}
34-
interface IBillingServiceService_IGetLatestInvoice extends grpc.MethodDefinition<usage_v1_billing_pb.GetLatestInvoiceRequest, usage_v1_billing_pb.GetLatestInvoiceResponse> {
35-
path: "/usage.v1.BillingService/GetLatestInvoice";
34+
interface IBillingServiceService_IGetUpcomingInvoice extends grpc.MethodDefinition<usage_v1_billing_pb.GetUpcomingInvoiceRequest, usage_v1_billing_pb.GetUpcomingInvoiceResponse> {
35+
path: "/usage.v1.BillingService/GetUpcomingInvoice";
3636
requestStream: false;
3737
responseStream: false;
38-
requestSerialize: grpc.serialize<usage_v1_billing_pb.GetLatestInvoiceRequest>;
39-
requestDeserialize: grpc.deserialize<usage_v1_billing_pb.GetLatestInvoiceRequest>;
40-
responseSerialize: grpc.serialize<usage_v1_billing_pb.GetLatestInvoiceResponse>;
41-
responseDeserialize: grpc.deserialize<usage_v1_billing_pb.GetLatestInvoiceResponse>;
38+
requestSerialize: grpc.serialize<usage_v1_billing_pb.GetUpcomingInvoiceRequest>;
39+
requestDeserialize: grpc.deserialize<usage_v1_billing_pb.GetUpcomingInvoiceRequest>;
40+
responseSerialize: grpc.serialize<usage_v1_billing_pb.GetUpcomingInvoiceResponse>;
41+
responseDeserialize: grpc.deserialize<usage_v1_billing_pb.GetUpcomingInvoiceResponse>;
4242
}
4343
interface IBillingServiceService_IFinalizeInvoice extends grpc.MethodDefinition<usage_v1_billing_pb.FinalizeInvoiceRequest, usage_v1_billing_pb.FinalizeInvoiceResponse> {
4444
path: "/usage.v1.BillingService/FinalizeInvoice";
@@ -63,7 +63,7 @@ export const BillingServiceService: IBillingServiceService;
6363

6464
export interface IBillingServiceServer extends grpc.UntypedServiceImplementation {
6565
updateInvoices: grpc.handleUnaryCall<usage_v1_billing_pb.UpdateInvoicesRequest, usage_v1_billing_pb.UpdateInvoicesResponse>;
66-
getLatestInvoice: grpc.handleUnaryCall<usage_v1_billing_pb.GetLatestInvoiceRequest, usage_v1_billing_pb.GetLatestInvoiceResponse>;
66+
getUpcomingInvoice: grpc.handleUnaryCall<usage_v1_billing_pb.GetUpcomingInvoiceRequest, usage_v1_billing_pb.GetUpcomingInvoiceResponse>;
6767
finalizeInvoice: grpc.handleUnaryCall<usage_v1_billing_pb.FinalizeInvoiceRequest, usage_v1_billing_pb.FinalizeInvoiceResponse>;
6868
setBilledSession: grpc.handleUnaryCall<usage_v1_billing_pb.SetBilledSessionRequest, usage_v1_billing_pb.SetBilledSessionResponse>;
6969
}
@@ -72,9 +72,9 @@ export interface IBillingServiceClient {
7272
updateInvoices(request: usage_v1_billing_pb.UpdateInvoicesRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.UpdateInvoicesResponse) => void): grpc.ClientUnaryCall;
7373
updateInvoices(request: usage_v1_billing_pb.UpdateInvoicesRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.UpdateInvoicesResponse) => void): grpc.ClientUnaryCall;
7474
updateInvoices(request: usage_v1_billing_pb.UpdateInvoicesRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.UpdateInvoicesResponse) => void): grpc.ClientUnaryCall;
75-
getLatestInvoice(request: usage_v1_billing_pb.GetLatestInvoiceRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetLatestInvoiceResponse) => void): grpc.ClientUnaryCall;
76-
getLatestInvoice(request: usage_v1_billing_pb.GetLatestInvoiceRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetLatestInvoiceResponse) => void): grpc.ClientUnaryCall;
77-
getLatestInvoice(request: usage_v1_billing_pb.GetLatestInvoiceRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetLatestInvoiceResponse) => void): grpc.ClientUnaryCall;
75+
getUpcomingInvoice(request: usage_v1_billing_pb.GetUpcomingInvoiceRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetUpcomingInvoiceResponse) => void): grpc.ClientUnaryCall;
76+
getUpcomingInvoice(request: usage_v1_billing_pb.GetUpcomingInvoiceRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetUpcomingInvoiceResponse) => void): grpc.ClientUnaryCall;
77+
getUpcomingInvoice(request: usage_v1_billing_pb.GetUpcomingInvoiceRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetUpcomingInvoiceResponse) => void): grpc.ClientUnaryCall;
7878
finalizeInvoice(request: usage_v1_billing_pb.FinalizeInvoiceRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.FinalizeInvoiceResponse) => void): grpc.ClientUnaryCall;
7979
finalizeInvoice(request: usage_v1_billing_pb.FinalizeInvoiceRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.FinalizeInvoiceResponse) => void): grpc.ClientUnaryCall;
8080
finalizeInvoice(request: usage_v1_billing_pb.FinalizeInvoiceRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.FinalizeInvoiceResponse) => void): grpc.ClientUnaryCall;
@@ -88,9 +88,9 @@ export class BillingServiceClient extends grpc.Client implements IBillingService
8888
public updateInvoices(request: usage_v1_billing_pb.UpdateInvoicesRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.UpdateInvoicesResponse) => void): grpc.ClientUnaryCall;
8989
public updateInvoices(request: usage_v1_billing_pb.UpdateInvoicesRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.UpdateInvoicesResponse) => void): grpc.ClientUnaryCall;
9090
public updateInvoices(request: usage_v1_billing_pb.UpdateInvoicesRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.UpdateInvoicesResponse) => void): grpc.ClientUnaryCall;
91-
public getLatestInvoice(request: usage_v1_billing_pb.GetLatestInvoiceRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetLatestInvoiceResponse) => void): grpc.ClientUnaryCall;
92-
public getLatestInvoice(request: usage_v1_billing_pb.GetLatestInvoiceRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetLatestInvoiceResponse) => void): grpc.ClientUnaryCall;
93-
public getLatestInvoice(request: usage_v1_billing_pb.GetLatestInvoiceRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetLatestInvoiceResponse) => void): grpc.ClientUnaryCall;
91+
public getUpcomingInvoice(request: usage_v1_billing_pb.GetUpcomingInvoiceRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetUpcomingInvoiceResponse) => void): grpc.ClientUnaryCall;
92+
public getUpcomingInvoice(request: usage_v1_billing_pb.GetUpcomingInvoiceRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetUpcomingInvoiceResponse) => void): grpc.ClientUnaryCall;
93+
public getUpcomingInvoice(request: usage_v1_billing_pb.GetUpcomingInvoiceRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetUpcomingInvoiceResponse) => void): grpc.ClientUnaryCall;
9494
public finalizeInvoice(request: usage_v1_billing_pb.FinalizeInvoiceRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.FinalizeInvoiceResponse) => void): grpc.ClientUnaryCall;
9595
public finalizeInvoice(request: usage_v1_billing_pb.FinalizeInvoiceRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.FinalizeInvoiceResponse) => void): grpc.ClientUnaryCall;
9696
public finalizeInvoice(request: usage_v1_billing_pb.FinalizeInvoiceRequest, metadata: grpc.Metadata, options: Partial<grpc.CallOptions>, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.FinalizeInvoiceResponse) => void): grpc.ClientUnaryCall;

0 commit comments

Comments
 (0)