Skip to content

Commit 1638f71

Browse files
committed
fix: address review comments on valuation stub replacement
- Return *grpc.ClientConn from buildValuationComponents for proper lifecycle management (defer close in caller) - Remove DefaultConversionMethodId fallback from resolveFromAccountTypes; only exact instrument match in valuation method templates is used - Add pagination documentation to resolveFromAccountTypes
1 parent ed6b0bd commit 1638f71

3 files changed

Lines changed: 22 additions & 16 deletions

File tree

services/reconciliation/cmd/main.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,14 @@ func run(logger *slog.Logger) error {
219219
)
220220

221221
// Wire VarianceValuator with real valuation engine and reference data provider
222-
valuationEngine, refDataProvider := buildValuationComponents(cfg, logger)
222+
valuationEngine, refDataProvider, refDataConn := buildValuationComponents(cfg, logger)
223+
defer func() {
224+
if refDataConn != nil {
225+
if err := refDataConn.Close(); err != nil {
226+
logger.Error("failed to close reference data connection", "error", err)
227+
}
228+
}
229+
}()
223230
valuator := service.NewVarianceValuator(valuationEngine, refDataProvider, varianceRepo, runRepo)
224231
serviceOpts = append(serviceOpts,
225232
service.WithVarianceValuator(valuator.ValueVariances),
@@ -508,7 +515,7 @@ func (h *healthServer) Check(ctx context.Context, _ *grpc_health_v1.HealthCheckR
508515
// When the Reference Data gRPC URL is configured, it creates gRPC clients for instrument
509516
// and account type lookups. Otherwise, it falls back to the identity conversion method
510517
// with default materiality thresholds.
511-
func buildValuationComponents(cfg *config.Config, logger *slog.Logger) (valuation.Engine, service.ReferenceDataProvider) {
518+
func buildValuationComponents(cfg *config.Config, logger *slog.Logger) (valuation.Engine, service.ReferenceDataProvider, *grpc.ClientConn) {
512519
// Create valuation engine runtime components
513520
policyRT, err := valuation.NewPolicyRuntime()
514521
if err != nil {
@@ -538,13 +545,16 @@ func buildValuationComponents(cfg *config.Config, logger *slog.Logger) (valuatio
538545
Logger: logger,
539546
}
540547

548+
var refDataConn *grpc.ClientConn
541549
if cfg.Services.ReferenceDataURL != "" {
542-
refDataConn, connErr := grpc.NewClient(
550+
var connErr error
551+
refDataConn, connErr = grpc.NewClient(
543552
cfg.Services.ReferenceDataURL,
544553
grpc.WithTransportCredentials(insecure.NewCredentials()),
545554
)
546555
if connErr != nil {
547556
logger.Warn("failed to create reference data gRPC client", "error", connErr)
557+
refDataConn = nil
548558
} else {
549559
providerCfg.InstrumentClient = referencedatav1.NewReferenceDataServiceClient(refDataConn)
550560
providerCfg.AccountTypeClient = referencedatav1.NewAccountTypeRegistryServiceClient(refDataConn)
@@ -563,7 +573,7 @@ func buildValuationComponents(cfg *config.Config, logger *slog.Logger) (valuatio
563573
"reference_data_url", cfg.Services.ReferenceDataURL,
564574
)
565575

566-
return adaptedEngine, refDataProvider
576+
return adaptedEngine, refDataProvider, refDataConn
567577
}
568578

569579
// parseLogLevel converts a string log level to slog.Level.

services/reconciliation/service/grpc_reference_data_provider.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ func (p *GRPCReferenceDataProvider) GetMaterialityThreshold(ctx context.Context,
127127

128128
// resolveFromAccountTypes searches active account type definitions for a valuation
129129
// method template matching the given instrument code.
130+
// Note: queries up to 100 active account types. Deployments with more than 100
131+
// active account types should extend this with pagination.
130132
func (p *GRPCReferenceDataProvider) resolveFromAccountTypes(ctx context.Context, instrumentCode string) (uuid.UUID, error) {
131133
resp, err := p.accountTypeClient.ListActive(ctx, &referencedatav1.ListActiveRequest{
132134
PageSize: 100,
@@ -135,6 +137,7 @@ func (p *GRPCReferenceDataProvider) resolveFromAccountTypes(ctx context.Context,
135137
return uuid.Nil, fmt.Errorf("failed to list active account types: %w", err)
136138
}
137139

140+
// First pass: look for an exact instrument match in valuation method templates
138141
for _, def := range resp.GetDefinitions() {
139142
for _, vm := range def.GetValuationMethods() {
140143
if vm.GetInputInstrument() == instrumentCode {
@@ -145,14 +148,6 @@ func (p *GRPCReferenceDataProvider) resolveFromAccountTypes(ctx context.Context,
145148
return methodID, nil
146149
}
147150
}
148-
149-
// Check default conversion method as fallback
150-
if convID := def.GetDefaultConversionMethodId(); convID != "" {
151-
methodID, err := uuid.Parse(convID)
152-
if err == nil {
153-
return methodID, nil
154-
}
155-
}
156151
}
157152

158153
return uuid.Nil, nil

services/reconciliation/service/grpc_reference_data_provider_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,24 +183,25 @@ func TestGRPCReferenceDataProvider_GetValuationMethodID_AccountTypeError_FallsBa
183183
assert.Equal(t, defaultID, result)
184184
}
185185

186-
func TestGRPCReferenceDataProvider_GetValuationMethodID_DefaultConversionFallback(t *testing.T) {
187-
conversionID := uuid.New()
186+
func TestGRPCReferenceDataProvider_GetValuationMethodID_NoMatchFallsToDefault(t *testing.T) {
187+
defaultID := uuid.New()
188188
acctClient := &mockAccountTypeClient{
189189
definitions: []*referencedatav1.AccountTypeDefinition{
190190
{
191191
Code: "CUSTOMER_CURRENT",
192-
DefaultConversionMethodId: conversionID.String(),
192+
DefaultConversionMethodId: uuid.New().String(),
193193
// No ValuationMethods matching "EXOTIC" instrument
194194
},
195195
},
196196
}
197197

198198
provider := NewGRPCReferenceDataProvider(GRPCReferenceDataProviderConfig{
199199
AccountTypeClient: acctClient,
200+
DefaultMethodID: defaultID,
200201
Logger: testLogger(),
201202
})
202203

203204
result, err := provider.GetValuationMethodID(context.Background(), "EXOTIC")
204205
require.NoError(t, err)
205-
assert.Equal(t, conversionID, result)
206+
assert.Equal(t, defaultID, result, "should fall back to default when no instrument match")
206207
}

0 commit comments

Comments
 (0)