From c2d0970b058855f4b1f0201edbd6640b69e35e08 Mon Sep 17 00:00:00 2001 From: Andrew Farries Date: Thu, 1 Sep 2022 13:57:31 +0000 Subject: [PATCH 1/3] Add LastUsageReconcilationTime rpc --- components/usage-api/go/v1/usage.pb.go | 216 ++++++++++--- components/usage-api/go/v1/usage_grpc.pb.go | 38 +++ .../src/usage/v1/usage_grpc_pb.d.ts | 17 + .../typescript/src/usage/v1/usage_grpc_pb.js | 34 ++ .../typescript/src/usage/v1/usage_pb.d.ts | 40 +++ .../typescript/src/usage/v1/usage_pb.js | 296 ++++++++++++++++++ components/usage-api/usage/v1/usage.proto | 10 + 7 files changed, 608 insertions(+), 43 deletions(-) diff --git a/components/usage-api/go/v1/usage.pb.go b/components/usage-api/go/v1/usage.pb.go index 4d784645719c9e..a8162c3338d197 100644 --- a/components/usage-api/go/v1/usage.pb.go +++ b/components/usage-api/go/v1/usage.pb.go @@ -742,6 +742,91 @@ func (x *CostCenter) GetSpendingLimit() int32 { return 0 } +type LastUsageReconcilationTimeRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *LastUsageReconcilationTimeRequest) Reset() { + *x = LastUsageReconcilationTimeRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_usage_v1_usage_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LastUsageReconcilationTimeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LastUsageReconcilationTimeRequest) ProtoMessage() {} + +func (x *LastUsageReconcilationTimeRequest) ProtoReflect() protoreflect.Message { + mi := &file_usage_v1_usage_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LastUsageReconcilationTimeRequest.ProtoReflect.Descriptor instead. +func (*LastUsageReconcilationTimeRequest) Descriptor() ([]byte, []int) { + return file_usage_v1_usage_proto_rawDescGZIP(), []int{10} +} + +type LastUsageReconcilationTimeResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` +} + +func (x *LastUsageReconcilationTimeResponse) Reset() { + *x = LastUsageReconcilationTimeResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_usage_v1_usage_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LastUsageReconcilationTimeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LastUsageReconcilationTimeResponse) ProtoMessage() {} + +func (x *LastUsageReconcilationTimeResponse) ProtoReflect() protoreflect.Message { + mi := &file_usage_v1_usage_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LastUsageReconcilationTimeResponse.ProtoReflect.Descriptor instead. +func (*LastUsageReconcilationTimeResponse) Descriptor() ([]byte, []int) { + return file_usage_v1_usage_proto_rawDescGZIP(), []int{11} +} + +func (x *LastUsageReconcilationTimeResponse) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.Timestamp + } + return nil +} + var File_usage_v1_usage_proto protoreflect.FileDescriptor var file_usage_v1_usage_proto_rawDesc = []byte{ @@ -854,18 +939,34 @@ var file_usage_v1_usage_proto_rawDesc = []byte{ 0x09, 0x52, 0x0d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x32, 0x93, 0x02, 0x0a, 0x0c, 0x55, 0x73, 0x61, 0x67, - 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, - 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, 0x2e, 0x75, 0x73, - 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, - 0x64, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, - 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x69, 0x6c, - 0x6c, 0x65, 0x64, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x55, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x65, 0x55, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, + 0x6e, 0x67, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x23, 0x0a, 0x21, 0x4c, 0x61, 0x73, 0x74, 0x55, + 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x5e, 0x0a, 0x22, + 0x4c, 0x61, 0x73, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x32, 0x8e, 0x03, 0x0a, + 0x0c, 0x55, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x58, 0x0a, + 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x55, 0x73, 0x61, 0x67, 0x65, + 0x12, 0x20, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x55, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x6f, 0x6e, + 0x63, 0x69, 0x6c, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x2e, 0x75, 0x73, 0x61, 0x67, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x65, 0x55, 0x73, + 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x75, 0x73, 0x61, + 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x65, 0x55, + 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x79, + 0x0a, 0x1a, 0x4c, 0x61, 0x73, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x6e, + 0x63, 0x69, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x2b, 0x2e, 0x75, + 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x73, 0x74, 0x55, 0x73, 0x61, 0x67, + 0x65, 0x52, 0x65, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, + 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x75, 0x73, 0x61, 0x67, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x73, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x52, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x73, 0x74, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x73, 0x74, 0x43, 0x65, 0x6e, @@ -891,45 +992,50 @@ func file_usage_v1_usage_proto_rawDescGZIP() []byte { } var file_usage_v1_usage_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_usage_v1_usage_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_usage_v1_usage_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_usage_v1_usage_proto_goTypes = []interface{}{ - (ListBilledUsageRequest_Ordering)(0), // 0: usage.v1.ListBilledUsageRequest.Ordering - (*ListBilledUsageRequest)(nil), // 1: usage.v1.ListBilledUsageRequest - (*PaginatedRequest)(nil), // 2: usage.v1.PaginatedRequest - (*ListBilledUsageResponse)(nil), // 3: usage.v1.ListBilledUsageResponse - (*PaginatedResponse)(nil), // 4: usage.v1.PaginatedResponse - (*BilledSession)(nil), // 5: usage.v1.BilledSession - (*ReconcileUsageRequest)(nil), // 6: usage.v1.ReconcileUsageRequest - (*ReconcileUsageResponse)(nil), // 7: usage.v1.ReconcileUsageResponse - (*GetCostCenterRequest)(nil), // 8: usage.v1.GetCostCenterRequest - (*GetCostCenterResponse)(nil), // 9: usage.v1.GetCostCenterResponse - (*CostCenter)(nil), // 10: usage.v1.CostCenter - (*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp + (ListBilledUsageRequest_Ordering)(0), // 0: usage.v1.ListBilledUsageRequest.Ordering + (*ListBilledUsageRequest)(nil), // 1: usage.v1.ListBilledUsageRequest + (*PaginatedRequest)(nil), // 2: usage.v1.PaginatedRequest + (*ListBilledUsageResponse)(nil), // 3: usage.v1.ListBilledUsageResponse + (*PaginatedResponse)(nil), // 4: usage.v1.PaginatedResponse + (*BilledSession)(nil), // 5: usage.v1.BilledSession + (*ReconcileUsageRequest)(nil), // 6: usage.v1.ReconcileUsageRequest + (*ReconcileUsageResponse)(nil), // 7: usage.v1.ReconcileUsageResponse + (*GetCostCenterRequest)(nil), // 8: usage.v1.GetCostCenterRequest + (*GetCostCenterResponse)(nil), // 9: usage.v1.GetCostCenterResponse + (*CostCenter)(nil), // 10: usage.v1.CostCenter + (*LastUsageReconcilationTimeRequest)(nil), // 11: usage.v1.LastUsageReconcilationTimeRequest + (*LastUsageReconcilationTimeResponse)(nil), // 12: usage.v1.LastUsageReconcilationTimeResponse + (*timestamppb.Timestamp)(nil), // 13: google.protobuf.Timestamp } var file_usage_v1_usage_proto_depIdxs = []int32{ - 11, // 0: usage.v1.ListBilledUsageRequest.from:type_name -> google.protobuf.Timestamp - 11, // 1: usage.v1.ListBilledUsageRequest.to:type_name -> google.protobuf.Timestamp + 13, // 0: usage.v1.ListBilledUsageRequest.from:type_name -> google.protobuf.Timestamp + 13, // 1: usage.v1.ListBilledUsageRequest.to:type_name -> google.protobuf.Timestamp 0, // 2: usage.v1.ListBilledUsageRequest.order:type_name -> usage.v1.ListBilledUsageRequest.Ordering 2, // 3: usage.v1.ListBilledUsageRequest.pagination:type_name -> usage.v1.PaginatedRequest 5, // 4: usage.v1.ListBilledUsageResponse.sessions:type_name -> usage.v1.BilledSession 4, // 5: usage.v1.ListBilledUsageResponse.pagination:type_name -> usage.v1.PaginatedResponse - 11, // 6: usage.v1.BilledSession.start_time:type_name -> google.protobuf.Timestamp - 11, // 7: usage.v1.BilledSession.end_time:type_name -> google.protobuf.Timestamp - 11, // 8: usage.v1.ReconcileUsageRequest.start_time:type_name -> google.protobuf.Timestamp - 11, // 9: usage.v1.ReconcileUsageRequest.end_time:type_name -> google.protobuf.Timestamp + 13, // 6: usage.v1.BilledSession.start_time:type_name -> google.protobuf.Timestamp + 13, // 7: usage.v1.BilledSession.end_time:type_name -> google.protobuf.Timestamp + 13, // 8: usage.v1.ReconcileUsageRequest.start_time:type_name -> google.protobuf.Timestamp + 13, // 9: usage.v1.ReconcileUsageRequest.end_time:type_name -> google.protobuf.Timestamp 5, // 10: usage.v1.ReconcileUsageResponse.sessions:type_name -> usage.v1.BilledSession 10, // 11: usage.v1.GetCostCenterResponse.cost_center:type_name -> usage.v1.CostCenter - 1, // 12: usage.v1.UsageService.ListBilledUsage:input_type -> usage.v1.ListBilledUsageRequest - 6, // 13: usage.v1.UsageService.ReconcileUsage:input_type -> usage.v1.ReconcileUsageRequest - 8, // 14: usage.v1.UsageService.GetCostCenter:input_type -> usage.v1.GetCostCenterRequest - 3, // 15: usage.v1.UsageService.ListBilledUsage:output_type -> usage.v1.ListBilledUsageResponse - 7, // 16: usage.v1.UsageService.ReconcileUsage:output_type -> usage.v1.ReconcileUsageResponse - 9, // 17: usage.v1.UsageService.GetCostCenter:output_type -> usage.v1.GetCostCenterResponse - 15, // [15:18] is the sub-list for method output_type - 12, // [12:15] is the sub-list for method input_type - 12, // [12:12] is the sub-list for extension type_name - 12, // [12:12] is the sub-list for extension extendee - 0, // [0:12] is the sub-list for field type_name + 13, // 12: usage.v1.LastUsageReconcilationTimeResponse.timestamp:type_name -> google.protobuf.Timestamp + 1, // 13: usage.v1.UsageService.ListBilledUsage:input_type -> usage.v1.ListBilledUsageRequest + 6, // 14: usage.v1.UsageService.ReconcileUsage:input_type -> usage.v1.ReconcileUsageRequest + 11, // 15: usage.v1.UsageService.LastUsageReconcilationTime:input_type -> usage.v1.LastUsageReconcilationTimeRequest + 8, // 16: usage.v1.UsageService.GetCostCenter:input_type -> usage.v1.GetCostCenterRequest + 3, // 17: usage.v1.UsageService.ListBilledUsage:output_type -> usage.v1.ListBilledUsageResponse + 7, // 18: usage.v1.UsageService.ReconcileUsage:output_type -> usage.v1.ReconcileUsageResponse + 12, // 19: usage.v1.UsageService.LastUsageReconcilationTime:output_type -> usage.v1.LastUsageReconcilationTimeResponse + 9, // 20: usage.v1.UsageService.GetCostCenter:output_type -> usage.v1.GetCostCenterResponse + 17, // [17:21] is the sub-list for method output_type + 13, // [13:17] is the sub-list for method input_type + 13, // [13:13] is the sub-list for extension type_name + 13, // [13:13] is the sub-list for extension extendee + 0, // [0:13] is the sub-list for field type_name } func init() { file_usage_v1_usage_proto_init() } @@ -1058,6 +1164,30 @@ func file_usage_v1_usage_proto_init() { return nil } } + file_usage_v1_usage_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LastUsageReconcilationTimeRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_usage_v1_usage_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LastUsageReconcilationTimeResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1065,7 +1195,7 @@ func file_usage_v1_usage_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_usage_v1_usage_proto_rawDesc, NumEnums: 1, - NumMessages: 10, + NumMessages: 12, NumExtensions: 0, NumServices: 1, }, diff --git a/components/usage-api/go/v1/usage_grpc.pb.go b/components/usage-api/go/v1/usage_grpc.pb.go index e874edfc7e26ce..7b30069ed17372 100644 --- a/components/usage-api/go/v1/usage_grpc.pb.go +++ b/components/usage-api/go/v1/usage_grpc.pb.go @@ -30,6 +30,8 @@ type UsageServiceClient interface { ListBilledUsage(ctx context.Context, in *ListBilledUsageRequest, opts ...grpc.CallOption) (*ListBilledUsageResponse, error) // ReconcileUsage collects usage for the specified time period, and stores the usage records in the database, returning the records. ReconcileUsage(ctx context.Context, in *ReconcileUsageRequest, opts ...grpc.CallOption) (*ReconcileUsageResponse, error) + // LastUsageReconcilationTime returns the last time the usage reconciler ran. + LastUsageReconcilationTime(ctx context.Context, in *LastUsageReconcilationTimeRequest, opts ...grpc.CallOption) (*LastUsageReconcilationTimeResponse, error) // GetCostCenter retrieves the spending limit with its associated attributionID GetCostCenter(ctx context.Context, in *GetCostCenterRequest, opts ...grpc.CallOption) (*GetCostCenterResponse, error) } @@ -60,6 +62,15 @@ func (c *usageServiceClient) ReconcileUsage(ctx context.Context, in *ReconcileUs return out, nil } +func (c *usageServiceClient) LastUsageReconcilationTime(ctx context.Context, in *LastUsageReconcilationTimeRequest, opts ...grpc.CallOption) (*LastUsageReconcilationTimeResponse, error) { + out := new(LastUsageReconcilationTimeResponse) + err := c.cc.Invoke(ctx, "/usage.v1.UsageService/LastUsageReconcilationTime", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *usageServiceClient) GetCostCenter(ctx context.Context, in *GetCostCenterRequest, opts ...grpc.CallOption) (*GetCostCenterResponse, error) { out := new(GetCostCenterResponse) err := c.cc.Invoke(ctx, "/usage.v1.UsageService/GetCostCenter", in, out, opts...) @@ -77,6 +88,8 @@ type UsageServiceServer interface { ListBilledUsage(context.Context, *ListBilledUsageRequest) (*ListBilledUsageResponse, error) // ReconcileUsage collects usage for the specified time period, and stores the usage records in the database, returning the records. ReconcileUsage(context.Context, *ReconcileUsageRequest) (*ReconcileUsageResponse, error) + // LastUsageReconcilationTime returns the last time the usage reconciler ran. + LastUsageReconcilationTime(context.Context, *LastUsageReconcilationTimeRequest) (*LastUsageReconcilationTimeResponse, error) // GetCostCenter retrieves the spending limit with its associated attributionID GetCostCenter(context.Context, *GetCostCenterRequest) (*GetCostCenterResponse, error) mustEmbedUnimplementedUsageServiceServer() @@ -92,6 +105,9 @@ func (UnimplementedUsageServiceServer) ListBilledUsage(context.Context, *ListBil func (UnimplementedUsageServiceServer) ReconcileUsage(context.Context, *ReconcileUsageRequest) (*ReconcileUsageResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ReconcileUsage not implemented") } +func (UnimplementedUsageServiceServer) LastUsageReconcilationTime(context.Context, *LastUsageReconcilationTimeRequest) (*LastUsageReconcilationTimeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method LastUsageReconcilationTime not implemented") +} func (UnimplementedUsageServiceServer) GetCostCenter(context.Context, *GetCostCenterRequest) (*GetCostCenterResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetCostCenter not implemented") } @@ -144,6 +160,24 @@ func _UsageService_ReconcileUsage_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } +func _UsageService_LastUsageReconcilationTime_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LastUsageReconcilationTimeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UsageServiceServer).LastUsageReconcilationTime(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/usage.v1.UsageService/LastUsageReconcilationTime", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UsageServiceServer).LastUsageReconcilationTime(ctx, req.(*LastUsageReconcilationTimeRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _UsageService_GetCostCenter_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetCostCenterRequest) if err := dec(in); err != nil { @@ -177,6 +211,10 @@ var UsageService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ReconcileUsage", Handler: _UsageService_ReconcileUsage_Handler, }, + { + MethodName: "LastUsageReconcilationTime", + Handler: _UsageService_LastUsageReconcilationTime_Handler, + }, { MethodName: "GetCostCenter", Handler: _UsageService_GetCostCenter_Handler, diff --git a/components/usage-api/typescript/src/usage/v1/usage_grpc_pb.d.ts b/components/usage-api/typescript/src/usage/v1/usage_grpc_pb.d.ts index 07376264290a50..eb3c92ca460fb7 100644 --- a/components/usage-api/typescript/src/usage/v1/usage_grpc_pb.d.ts +++ b/components/usage-api/typescript/src/usage/v1/usage_grpc_pb.d.ts @@ -17,6 +17,7 @@ import * as google_protobuf_timestamp_pb from "google-protobuf/google/protobuf/t interface IUsageServiceService extends grpc.ServiceDefinition { listBilledUsage: IUsageServiceService_IListBilledUsage; reconcileUsage: IUsageServiceService_IReconcileUsage; + lastUsageReconcilationTime: IUsageServiceService_ILastUsageReconcilationTime; getCostCenter: IUsageServiceService_IGetCostCenter; } @@ -38,6 +39,15 @@ interface IUsageServiceService_IReconcileUsage extends grpc.MethodDefinition; responseDeserialize: grpc.deserialize; } +interface IUsageServiceService_ILastUsageReconcilationTime extends grpc.MethodDefinition { + path: "/usage.v1.UsageService/LastUsageReconcilationTime"; + requestStream: false; + responseStream: false; + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; +} interface IUsageServiceService_IGetCostCenter extends grpc.MethodDefinition { path: "/usage.v1.UsageService/GetCostCenter"; requestStream: false; @@ -53,6 +63,7 @@ export const UsageServiceService: IUsageServiceService; export interface IUsageServiceServer extends grpc.UntypedServiceImplementation { listBilledUsage: grpc.handleUnaryCall; reconcileUsage: grpc.handleUnaryCall; + lastUsageReconcilationTime: grpc.handleUnaryCall; getCostCenter: grpc.handleUnaryCall; } @@ -63,6 +74,9 @@ export interface IUsageServiceClient { reconcileUsage(request: usage_v1_usage_pb.ReconcileUsageRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.ReconcileUsageResponse) => void): grpc.ClientUnaryCall; reconcileUsage(request: usage_v1_usage_pb.ReconcileUsageRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.ReconcileUsageResponse) => void): grpc.ClientUnaryCall; reconcileUsage(request: usage_v1_usage_pb.ReconcileUsageRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.ReconcileUsageResponse) => void): grpc.ClientUnaryCall; + lastUsageReconcilationTime(request: usage_v1_usage_pb.LastUsageReconcilationTimeRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.LastUsageReconcilationTimeResponse) => void): grpc.ClientUnaryCall; + lastUsageReconcilationTime(request: usage_v1_usage_pb.LastUsageReconcilationTimeRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.LastUsageReconcilationTimeResponse) => void): grpc.ClientUnaryCall; + lastUsageReconcilationTime(request: usage_v1_usage_pb.LastUsageReconcilationTimeRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.LastUsageReconcilationTimeResponse) => void): grpc.ClientUnaryCall; getCostCenter(request: usage_v1_usage_pb.GetCostCenterRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.GetCostCenterResponse) => void): grpc.ClientUnaryCall; getCostCenter(request: usage_v1_usage_pb.GetCostCenterRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.GetCostCenterResponse) => void): grpc.ClientUnaryCall; getCostCenter(request: usage_v1_usage_pb.GetCostCenterRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.GetCostCenterResponse) => void): grpc.ClientUnaryCall; @@ -76,6 +90,9 @@ export class UsageServiceClient extends grpc.Client implements IUsageServiceClie public reconcileUsage(request: usage_v1_usage_pb.ReconcileUsageRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.ReconcileUsageResponse) => void): grpc.ClientUnaryCall; public reconcileUsage(request: usage_v1_usage_pb.ReconcileUsageRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.ReconcileUsageResponse) => void): grpc.ClientUnaryCall; public reconcileUsage(request: usage_v1_usage_pb.ReconcileUsageRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.ReconcileUsageResponse) => void): grpc.ClientUnaryCall; + public lastUsageReconcilationTime(request: usage_v1_usage_pb.LastUsageReconcilationTimeRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.LastUsageReconcilationTimeResponse) => void): grpc.ClientUnaryCall; + public lastUsageReconcilationTime(request: usage_v1_usage_pb.LastUsageReconcilationTimeRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.LastUsageReconcilationTimeResponse) => void): grpc.ClientUnaryCall; + public lastUsageReconcilationTime(request: usage_v1_usage_pb.LastUsageReconcilationTimeRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.LastUsageReconcilationTimeResponse) => void): grpc.ClientUnaryCall; public getCostCenter(request: usage_v1_usage_pb.GetCostCenterRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.GetCostCenterResponse) => void): grpc.ClientUnaryCall; public getCostCenter(request: usage_v1_usage_pb.GetCostCenterRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.GetCostCenterResponse) => void): grpc.ClientUnaryCall; public getCostCenter(request: usage_v1_usage_pb.GetCostCenterRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: usage_v1_usage_pb.GetCostCenterResponse) => void): grpc.ClientUnaryCall; diff --git a/components/usage-api/typescript/src/usage/v1/usage_grpc_pb.js b/components/usage-api/typescript/src/usage/v1/usage_grpc_pb.js index 1af57caf172eb2..63c7209eeb8f70 100644 --- a/components/usage-api/typescript/src/usage/v1/usage_grpc_pb.js +++ b/components/usage-api/typescript/src/usage/v1/usage_grpc_pb.js @@ -33,6 +33,28 @@ function deserialize_usage_v1_GetCostCenterResponse(buffer_arg) { return usage_v1_usage_pb.GetCostCenterResponse.deserializeBinary(new Uint8Array(buffer_arg)); } +function serialize_usage_v1_LastUsageReconcilationTimeRequest(arg) { + if (!(arg instanceof usage_v1_usage_pb.LastUsageReconcilationTimeRequest)) { + throw new Error('Expected argument of type usage.v1.LastUsageReconcilationTimeRequest'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_usage_v1_LastUsageReconcilationTimeRequest(buffer_arg) { + return usage_v1_usage_pb.LastUsageReconcilationTimeRequest.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_usage_v1_LastUsageReconcilationTimeResponse(arg) { + if (!(arg instanceof usage_v1_usage_pb.LastUsageReconcilationTimeResponse)) { + throw new Error('Expected argument of type usage.v1.LastUsageReconcilationTimeResponse'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_usage_v1_LastUsageReconcilationTimeResponse(buffer_arg) { + return usage_v1_usage_pb.LastUsageReconcilationTimeResponse.deserializeBinary(new Uint8Array(buffer_arg)); +} + function serialize_usage_v1_ListBilledUsageRequest(arg) { if (!(arg instanceof usage_v1_usage_pb.ListBilledUsageRequest)) { throw new Error('Expected argument of type usage.v1.ListBilledUsageRequest'); @@ -103,6 +125,18 @@ reconcileUsage: { responseSerialize: serialize_usage_v1_ReconcileUsageResponse, responseDeserialize: deserialize_usage_v1_ReconcileUsageResponse, }, + // LastUsageReconcilationTime returns the last time the usage reconciler ran. +lastUsageReconcilationTime: { + path: '/usage.v1.UsageService/LastUsageReconcilationTime', + requestStream: false, + responseStream: false, + requestType: usage_v1_usage_pb.LastUsageReconcilationTimeRequest, + responseType: usage_v1_usage_pb.LastUsageReconcilationTimeResponse, + requestSerialize: serialize_usage_v1_LastUsageReconcilationTimeRequest, + requestDeserialize: deserialize_usage_v1_LastUsageReconcilationTimeRequest, + responseSerialize: serialize_usage_v1_LastUsageReconcilationTimeResponse, + responseDeserialize: deserialize_usage_v1_LastUsageReconcilationTimeResponse, + }, // GetCostCenter retrieves the spending limit with its associated attributionID getCostCenter: { path: '/usage.v1.UsageService/GetCostCenter', diff --git a/components/usage-api/typescript/src/usage/v1/usage_pb.d.ts b/components/usage-api/typescript/src/usage/v1/usage_pb.d.ts index 28dd34ada8db40..be1de19dd47647 100644 --- a/components/usage-api/typescript/src/usage/v1/usage_pb.d.ts +++ b/components/usage-api/typescript/src/usage/v1/usage_pb.d.ts @@ -321,3 +321,43 @@ export namespace CostCenter { spendingLimit: number, } } + +export class LastUsageReconcilationTimeRequest extends jspb.Message { + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): LastUsageReconcilationTimeRequest.AsObject; + static toObject(includeInstance: boolean, msg: LastUsageReconcilationTimeRequest): LastUsageReconcilationTimeRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: LastUsageReconcilationTimeRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): LastUsageReconcilationTimeRequest; + static deserializeBinaryFromReader(message: LastUsageReconcilationTimeRequest, reader: jspb.BinaryReader): LastUsageReconcilationTimeRequest; +} + +export namespace LastUsageReconcilationTimeRequest { + export type AsObject = { + } +} + +export class LastUsageReconcilationTimeResponse extends jspb.Message { + + hasTimestamp(): boolean; + clearTimestamp(): void; + getTimestamp(): google_protobuf_timestamp_pb.Timestamp | undefined; + setTimestamp(value?: google_protobuf_timestamp_pb.Timestamp): LastUsageReconcilationTimeResponse; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): LastUsageReconcilationTimeResponse.AsObject; + static toObject(includeInstance: boolean, msg: LastUsageReconcilationTimeResponse): LastUsageReconcilationTimeResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: LastUsageReconcilationTimeResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): LastUsageReconcilationTimeResponse; + static deserializeBinaryFromReader(message: LastUsageReconcilationTimeResponse, reader: jspb.BinaryReader): LastUsageReconcilationTimeResponse; +} + +export namespace LastUsageReconcilationTimeResponse { + export type AsObject = { + timestamp?: google_protobuf_timestamp_pb.Timestamp.AsObject, + } +} diff --git a/components/usage-api/typescript/src/usage/v1/usage_pb.js b/components/usage-api/typescript/src/usage/v1/usage_pb.js index 066105cc0e8bc1..f64c900b3ee5eb 100644 --- a/components/usage-api/typescript/src/usage/v1/usage_pb.js +++ b/components/usage-api/typescript/src/usage/v1/usage_pb.js @@ -27,6 +27,8 @@ goog.exportSymbol('proto.usage.v1.BilledSession', null, global); goog.exportSymbol('proto.usage.v1.CostCenter', null, global); goog.exportSymbol('proto.usage.v1.GetCostCenterRequest', null, global); goog.exportSymbol('proto.usage.v1.GetCostCenterResponse', null, global); +goog.exportSymbol('proto.usage.v1.LastUsageReconcilationTimeRequest', null, global); +goog.exportSymbol('proto.usage.v1.LastUsageReconcilationTimeResponse', null, global); goog.exportSymbol('proto.usage.v1.ListBilledUsageRequest', null, global); goog.exportSymbol('proto.usage.v1.ListBilledUsageRequest.Ordering', null, global); goog.exportSymbol('proto.usage.v1.ListBilledUsageResponse', null, global); @@ -244,6 +246,48 @@ if (goog.DEBUG && !COMPILED) { */ proto.usage.v1.CostCenter.displayName = 'proto.usage.v1.CostCenter'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.usage.v1.LastUsageReconcilationTimeRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.usage.v1.LastUsageReconcilationTimeRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.usage.v1.LastUsageReconcilationTimeRequest.displayName = 'proto.usage.v1.LastUsageReconcilationTimeRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.usage.v1.LastUsageReconcilationTimeResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.usage.v1.LastUsageReconcilationTimeResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.usage.v1.LastUsageReconcilationTimeResponse.displayName = 'proto.usage.v1.LastUsageReconcilationTimeResponse'; +} @@ -2521,4 +2565,256 @@ proto.usage.v1.CostCenter.prototype.setSpendingLimit = function(value) { }; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.usage.v1.LastUsageReconcilationTimeRequest.prototype.toObject = function(opt_includeInstance) { + return proto.usage.v1.LastUsageReconcilationTimeRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.usage.v1.LastUsageReconcilationTimeRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.usage.v1.LastUsageReconcilationTimeRequest.toObject = function(includeInstance, msg) { + var f, obj = { + + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.usage.v1.LastUsageReconcilationTimeRequest} + */ +proto.usage.v1.LastUsageReconcilationTimeRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.usage.v1.LastUsageReconcilationTimeRequest; + return proto.usage.v1.LastUsageReconcilationTimeRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.usage.v1.LastUsageReconcilationTimeRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.usage.v1.LastUsageReconcilationTimeRequest} + */ +proto.usage.v1.LastUsageReconcilationTimeRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.usage.v1.LastUsageReconcilationTimeRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.usage.v1.LastUsageReconcilationTimeRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.usage.v1.LastUsageReconcilationTimeRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.usage.v1.LastUsageReconcilationTimeRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.usage.v1.LastUsageReconcilationTimeResponse.prototype.toObject = function(opt_includeInstance) { + return proto.usage.v1.LastUsageReconcilationTimeResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.usage.v1.LastUsageReconcilationTimeResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.usage.v1.LastUsageReconcilationTimeResponse.toObject = function(includeInstance, msg) { + var f, obj = { + timestamp: (f = msg.getTimestamp()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.usage.v1.LastUsageReconcilationTimeResponse} + */ +proto.usage.v1.LastUsageReconcilationTimeResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.usage.v1.LastUsageReconcilationTimeResponse; + return proto.usage.v1.LastUsageReconcilationTimeResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.usage.v1.LastUsageReconcilationTimeResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.usage.v1.LastUsageReconcilationTimeResponse} + */ +proto.usage.v1.LastUsageReconcilationTimeResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new google_protobuf_timestamp_pb.Timestamp; + reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader); + msg.setTimestamp(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.usage.v1.LastUsageReconcilationTimeResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.usage.v1.LastUsageReconcilationTimeResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.usage.v1.LastUsageReconcilationTimeResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.usage.v1.LastUsageReconcilationTimeResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getTimestamp(); + if (f != null) { + writer.writeMessage( + 1, + f, + google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter + ); + } +}; + + +/** + * optional google.protobuf.Timestamp timestamp = 1; + * @return {?proto.google.protobuf.Timestamp} + */ +proto.usage.v1.LastUsageReconcilationTimeResponse.prototype.getTimestamp = function() { + return /** @type{?proto.google.protobuf.Timestamp} */ ( + jspb.Message.getWrapperField(this, google_protobuf_timestamp_pb.Timestamp, 1)); +}; + + +/** + * @param {?proto.google.protobuf.Timestamp|undefined} value + * @return {!proto.usage.v1.LastUsageReconcilationTimeResponse} returns this +*/ +proto.usage.v1.LastUsageReconcilationTimeResponse.prototype.setTimestamp = function(value) { + return jspb.Message.setWrapperField(this, 1, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.usage.v1.LastUsageReconcilationTimeResponse} returns this + */ +proto.usage.v1.LastUsageReconcilationTimeResponse.prototype.clearTimestamp = function() { + return this.setTimestamp(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.usage.v1.LastUsageReconcilationTimeResponse.prototype.hasTimestamp = function() { + return jspb.Message.getField(this, 1) != null; +}; + + goog.object.extend(exports, proto.usage.v1); diff --git a/components/usage-api/usage/v1/usage.proto b/components/usage-api/usage/v1/usage.proto index 09e0db9db9908d..fd7315a0036f2c 100644 --- a/components/usage-api/usage/v1/usage.proto +++ b/components/usage-api/usage/v1/usage.proto @@ -13,6 +13,9 @@ service UsageService { // ReconcileUsage collects usage for the specified time period, and stores the usage records in the database, returning the records. rpc ReconcileUsage(ReconcileUsageRequest) returns (ReconcileUsageResponse) {} + // LastUsageReconcilationTime returns the last time the usage reconciler ran. + rpc LastUsageReconcilationTime(LastUsageReconcilationTimeRequest) returns (LastUsageReconcilationTimeResponse) {} + // GetCostCenter retrieves the spending limit with its associated attributionID rpc GetCostCenter(GetCostCenterRequest) returns (GetCostCenterResponse) {} } @@ -98,3 +101,10 @@ message CostCenter { string attribution_id = 1; int32 spending_limit = 2; } + +message LastUsageReconcilationTimeRequest { +} + +message LastUsageReconcilationTimeResponse { + google.protobuf.Timestamp timestamp = 1; +} From 554553432cd9f41f208e5061a7faf755310cdd72 Mon Sep 17 00:00:00 2001 From: Andrew Farries Date: Thu, 1 Sep 2022 14:00:41 +0000 Subject: [PATCH 2/3] LastUsageReconcilationTime implementation --- components/usage/pkg/apiv1/usage.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/components/usage/pkg/apiv1/usage.go b/components/usage/pkg/apiv1/usage.go index d704ddc810519a..ea95d45d4a0ca2 100644 --- a/components/usage/pkg/apiv1/usage.go +++ b/components/usage/pkg/apiv1/usage.go @@ -32,6 +32,8 @@ type UsageService struct { reportGenerator *ReportGenerator + lastReconciliation time.Time + v1.UnimplementedUsageServiceServer } @@ -126,6 +128,7 @@ func (s *UsageService) ReconcileUsage(ctx context.Context, req *v1.ReconcileUsag return nil, status.Errorf(codes.InvalidArgument, "End time must be after start time") } + s.lastReconciliation = time.Now() report, err := s.reportGenerator.GenerateUsageReport(ctx, from, to) if err != nil { log.Log.WithError(err).Error("Failed to reconcile time range.") @@ -148,7 +151,6 @@ func (s *UsageService) ReconcileUsage(ctx context.Context, req *v1.ReconcileUsag return &v1.ReconcileUsageResponse{ ReportId: filename, }, nil - } func (s *UsageService) GetCostCenter(ctx context.Context, in *v1.GetCostCenterRequest) (*v1.GetCostCenterResponse, error) { @@ -220,3 +222,9 @@ func instancesToUsageRecords(instances []db.WorkspaceInstanceForUsage, pricer *W return usageRecords } + +func (s *UsageService) LastUsageReconcilationTime(ctx context.Context, in *v1.LastUsageReconcilationTimeRequest) (*v1.LastUsageReconcilationTimeResponse, error) { + return &v1.LastUsageReconcilationTimeResponse{ + Timestamp: timestamppb.New(s.lastReconciliation), + }, nil +} From 92229977efb6b336d1625890531a7a3de8242056 Mon Sep 17 00:00:00 2001 From: Andrew Farries Date: Fri, 2 Sep 2022 10:37:16 +0000 Subject: [PATCH 3/3] Add test for LastUsageReconcilationTime RPC Ensure that the timestamps returned by the method are always increasing. --- components/usage/pkg/apiv1/usage_test.go | 42 ++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/components/usage/pkg/apiv1/usage_test.go b/components/usage/pkg/apiv1/usage_test.go index e219c54b281334..df247e6e4acd3d 100644 --- a/components/usage/pkg/apiv1/usage_test.go +++ b/components/usage/pkg/apiv1/usage_test.go @@ -563,3 +563,45 @@ func TestReportGenerator_GenerateUsageReportTable(t *testing.T) { }) } } + +func TestUsageService_LastUsageReconcilationTimeIsIncreasing(t *testing.T) { + ctx := context.Background() + dbconn := dbtest.ConnectForTests(t) + + srv := baseserver.NewForTests(t, + baseserver.WithGRPC(baseserver.MustUseRandomLocalAddress(t)), + ) + + generator := NewReportGenerator(dbconn, DefaultWorkspacePricer) + v1.RegisterUsageServiceServer(srv.GRPC(), NewUsageService(dbconn, generator, &stubContentService{})) + baseserver.StartServerForTests(t, srv) + + conn, err := grpc.Dial(srv.GRPCAddress(), grpc.WithTransportCredentials(insecure.NewCredentials())) + require.NoError(t, err) + + client := v1.NewUsageServiceClient(conn) + + resp, err := client.LastUsageReconcilationTime(ctx, &v1.LastUsageReconcilationTimeRequest{}) + require.NoError(t, err) + for i := 0; i < 10; i++ { + previousTimestamp := resp.GetTimestamp() + _, err = client.ReconcileUsage(ctx, &v1.ReconcileUsageRequest{ + StartTime: timestamppb.New(time.Now().Add(-1 * time.Hour)), + EndTime: timestamppb.New(time.Now()), + }) + require.NoError(t, err) + resp, err = client.LastUsageReconcilationTime(ctx, &v1.LastUsageReconcilationTimeRequest{}) + require.NoError(t, err) + require.Truef(t, resp.GetTimestamp().AsTime().After(previousTimestamp.AsTime()), "timestamp of last usage reconciliation was not monotonically increasing") + } +} + +type stubContentService struct{} + +func (c *stubContentService) UploadUsageReport(ctx context.Context, filename string, report contentservice.UsageReport) error { + return nil +} + +func (c *stubContentService) DownloadUsageReport(ctx context.Context, filename string) (contentservice.UsageReport, error) { + return contentservice.UsageReport{}, nil +}