Skip to content

Commit 2bfdaae

Browse files
committed
feat: redefine how subject and customer lifecycles interact
1 parent a16cb4e commit 2bfdaae

File tree

16 files changed

+398
-414
lines changed

16 files changed

+398
-414
lines changed

app/common/customer.go

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -88,27 +88,6 @@ func NewCustomerSubjectServiceHook(
8888
return h, nil
8989
}
9090

91-
type CustomerSubjectValidatorHook customerservicehooks.SubjectValidatorHook
92-
93-
func NewCustomerSubjectValidatorServiceHook(
94-
logger *slog.Logger,
95-
subjectService subject.Service,
96-
customerService customer.Service,
97-
) (CustomerSubjectValidatorHook, error) {
98-
// Initialize the customer subject validator hook and register it for Subject service
99-
h, err := customerservicehooks.NewSubjectValidatorHook(customerservicehooks.SubjectValidatorHookConfig{
100-
Customer: customerService,
101-
Logger: logger,
102-
})
103-
if err != nil {
104-
return nil, fmt.Errorf("failed to create customer subject validator hook: %w", err)
105-
}
106-
107-
subjectService.RegisterHooks(h)
108-
109-
return h, nil
110-
}
111-
11291
type CustomerEntitlementValidatorHook customerservicehooks.EntitlementValidatorHook
11392

11493
func NewCustomerEntitlementValidatorServiceHook(

app/common/subject.go

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99

1010
"github.com/openmeterio/openmeter/openmeter/customer"
1111
entdb "github.com/openmeterio/openmeter/openmeter/ent/db"
12-
"github.com/openmeterio/openmeter/openmeter/registry"
1312
"github.com/openmeterio/openmeter/openmeter/subject"
1413
"github.com/openmeterio/openmeter/openmeter/subject/adapter"
1514
"github.com/openmeterio/openmeter/openmeter/subject/service"
@@ -52,20 +51,3 @@ func NewSubjectCustomerHook(
5251

5352
return h, nil
5453
}
55-
56-
func NewSubjectEntitlementValidatorHook(
57-
logger *slog.Logger,
58-
entitlementRegistry *registry.Entitlement,
59-
subjectService subject.Service,
60-
) (subjecthooks.EntitlementValidatorHook, error) {
61-
h, err := subjecthooks.NewEntitlementValidatorHook(subjecthooks.EntitlementValidatorHookConfig{
62-
EntitlementService: entitlementRegistry.Entitlement,
63-
})
64-
if err != nil {
65-
return nil, fmt.Errorf("failed to create subject entitlement validator hook: %w", err)
66-
}
67-
68-
subjectService.RegisterHooks(h)
69-
70-
return h, nil
71-
}

cmd/server/wire.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ type Application struct {
4848
AppRegistry common.AppRegistry
4949
Customer customer.Service
5050
CustomerSubjectHook common.CustomerSubjectHook
51-
CustomerSubjectValidatorHook common.CustomerSubjectValidatorHook
5251
CustomerEntitlementValidatorHook common.CustomerEntitlementValidatorHook
5352
Billing billing.Service
5453
EntClient *db.Client
@@ -77,7 +76,6 @@ type Application struct {
7776
Secret secret.Service
7877
SubjectService subject.Service
7978
SubjectCustomerHook subjecthooks.CustomerSubjectHook
80-
SubjectEntitlementValidatorHook subjecthooks.EntitlementValidatorHook
8179
Subscription common.SubscriptionServiceWithWorkflow
8280
StreamingConnector streaming.Connector
8381
TelemetryServer common.TelemetryServer
@@ -95,7 +93,6 @@ func initializeApplication(ctx context.Context, conf config.Configuration) (Appl
9593
common.Config,
9694
common.Customer,
9795
common.NewCustomerSubjectServiceHook,
98-
common.NewCustomerSubjectValidatorServiceHook,
9996
common.NewCustomerEntitlementValidatorServiceHook,
10097
common.Database,
10198
common.Entitlement,
@@ -125,7 +122,6 @@ func initializeApplication(ctx context.Context, conf config.Configuration) (Appl
125122
common.ServerProvisionTopics,
126123
common.Subject,
127124
common.NewSubjectCustomerHook,
128-
common.NewSubjectEntitlementValidatorHook,
129125
common.Telemetry,
130126
common.TelemetryLoggerNoAdditionalMiddlewares,
131127
common.NewTerminationChecker,

cmd/server/wire_gen.go

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

openmeter/customer/customer.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,21 @@ type Customer struct {
5252
ActiveSubscriptionIDs mo.Option[[]string]
5353
}
5454

55+
// AsCustomerMutate returns a CustomerMutate from the Customer
56+
func (c Customer) AsCustomerMutate() CustomerMutate {
57+
return CustomerMutate{
58+
Key: c.Key,
59+
Name: c.Name,
60+
Description: c.Description,
61+
UsageAttribution: c.UsageAttribution,
62+
PrimaryEmail: c.PrimaryEmail,
63+
Currency: c.Currency,
64+
BillingAddress: c.BillingAddress,
65+
Metadata: c.Metadata,
66+
Annotation: c.Annotation,
67+
}
68+
}
69+
5570
// GetUsageAttribution returns the customer usage attribution
5671
// implementing the streaming.CustomerUsageAttribution interface
5772
func (c Customer) GetUsageAttribution() streaming.CustomerUsageAttribution {

openmeter/customer/service/hooks/subjectcustomer.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"slices"
1111
"strconv"
1212
"strings"
13+
"time"
1314

1415
"github.com/samber/lo"
1516
"go.opentelemetry.io/otel/attribute"
@@ -22,6 +23,7 @@ import (
2223
"github.com/openmeterio/openmeter/openmeter/customer"
2324
"github.com/openmeterio/openmeter/openmeter/subject"
2425
subjectservicehooks "github.com/openmeterio/openmeter/openmeter/subject/service/hooks"
26+
"github.com/openmeterio/openmeter/pkg/clock"
2527
"github.com/openmeterio/openmeter/pkg/models"
2628
)
2729

@@ -57,6 +59,79 @@ func (s subjectCustomerHook) provision(ctx context.Context, sub *subject.Subject
5759
return nil
5860
}
5961

62+
func (s subjectCustomerHook) PostDelete(ctx context.Context, sub *subject.Subject) error {
63+
ctx, span := s.tracer.Start(ctx, "subject_customer_hook.post_delete", trace.WithAttributes(
64+
attribute.String("subject.id", sub.Id),
65+
attribute.String("subject.key", sub.Key),
66+
))
67+
defer span.End()
68+
69+
// Let's get the customer by usage attribution
70+
cus, err := s.provisioner.customer.GetCustomerByUsageAttribution(ctx, customer.GetCustomerByUsageAttributionInput{
71+
Namespace: sub.Namespace,
72+
SubjectKey: sub.Key,
73+
})
74+
if err != nil {
75+
if models.IsGenericNotFoundError(err) {
76+
span.AddEvent("customer not found by usage attribution", trace.WithAttributes(
77+
attribute.String("error", err.Error()),
78+
))
79+
80+
return nil
81+
}
82+
83+
return err
84+
}
85+
86+
if cus == nil {
87+
span.AddEvent("customer not found by usage attribution")
88+
89+
return nil
90+
}
91+
92+
if cus.DeletedAt != nil && cus.DeletedAt.Before(clock.Now()) {
93+
span.AddEvent("customer is deleted", trace.WithAttributes(
94+
attribute.String("customer.id", cus.ID),
95+
attribute.String("customer.deleted_at", cus.DeletedAt.Format(time.RFC3339)),
96+
))
97+
98+
return nil
99+
}
100+
101+
// Let's update the customer usage attribution
102+
cus, err = s.provisioner.customer.UpdateCustomer(ctx, customer.UpdateCustomerInput{
103+
CustomerID: customer.CustomerID{
104+
Namespace: cus.Namespace,
105+
ID: cus.ID,
106+
},
107+
CustomerMutate: func() customer.CustomerMutate {
108+
mut := cus.AsCustomerMutate()
109+
110+
mut.UsageAttribution.SubjectKeys = lo.Filter(mut.UsageAttribution.SubjectKeys, func(key string, _ int) bool {
111+
return key != sub.Key
112+
})
113+
114+
return mut
115+
}(),
116+
})
117+
118+
if cus != nil {
119+
span.AddEvent("updated customer usage attribution", trace.WithAttributes(
120+
attribute.String("customer.usage_attribution.subject_keys", strings.Join(cus.UsageAttribution.SubjectKeys, ", ")),
121+
))
122+
}
123+
124+
if err != nil {
125+
span.AddEvent("failed to update customer usage attribution", trace.WithAttributes(
126+
attribute.String("error", err.Error()),
127+
))
128+
129+
return err
130+
}
131+
132+
return nil
133+
}
134+
60135
func (s subjectCustomerHook) PostCreate(ctx context.Context, sub *subject.Subject) error {
61136
ctx, span := s.tracer.Start(ctx, "subject_customer_hook.post_create")
62137
defer span.End()

openmeter/customer/service/hooks/subjectvalidator.go

Lines changed: 0 additions & 84 deletions
This file was deleted.

0 commit comments

Comments
 (0)