diff --git a/context/ue.go b/context/ue.go index 9002e93..63cec58 100644 --- a/context/ue.go +++ b/context/ue.go @@ -11,6 +11,7 @@ import ( "reflect" "strconv" "strings" + "sync" "github.com/omec-project/openapi/v2/models" "github.com/omec-project/pcf/logger" @@ -20,7 +21,8 @@ import ( // key is supi type UeContext struct { // Udr Ref - UdrUri string + UdrUri string + UdrUriMu sync.RWMutex // SMPolicy SmPolicyData map[string]*UeSmPolicyData // use smPolicyId(ue.Supi-pduSessionId) as key // App Session Related diff --git a/producer/ampolicy.go b/producer/ampolicy.go index 4210e4b..14cd8c1 100644 --- a/producer/ampolicy.go +++ b/producer/ampolicy.go @@ -179,7 +179,7 @@ func UpdatePostPoliciesPolAssoIdProcedure(polAssoId string, // HandlePostPolicies Create AM Policy func HandlePostPolicies(request *httpwrapper.Request) *httpwrapper.Response { - logger.AMpolicylog.Infoln("handle AM Policy Create Request") + logger.AMpolicylog.Debugln("handle AM Policy Create Request") polAssoId := request.Params["polAssoId"] policyAssociationRequest := request.Body.(models.PolicyAssociationRequest) @@ -224,7 +224,6 @@ func PostPoliciesProcedure(polAssoId string, logger.AMpolicylog.Errorf("Ue[%s] is not supported in PCF", ue.Supi) return nil, "", problemDetail } - ue.UdrUri = udrUri var reqCopy models.PolicyAssociationRequest if err := util.DeepCopyViaJSON(policyAssociationRequest, &reqCopy); err != nil { @@ -321,7 +320,21 @@ func PostPoliciesProcedure(polAssoId string, return &response, locationHeader, nil } -// returns UDR Uri of Ue, if ue.UdrUri dose not exist, query NRF to get supported Udr Uri +// returns UDR Uri of Ue, caching it on the UeContext after first discovery func getUdrUri(ue *pcfContext.UeContext) string { - return consumer.SendNFInstancesUDR(pcfContext.PCF_Self().NrfUri, ue.Supi) + ue.UdrUriMu.RLock() + uri := ue.UdrUri + ue.UdrUriMu.RUnlock() + if uri != "" { + return uri + } + uri = consumer.SendNFInstancesUDR(pcfContext.PCF_Self().NrfUri, ue.Supi) + if uri != "" { + ue.UdrUriMu.Lock() + if ue.UdrUri == "" { + ue.UdrUri = uri + } + ue.UdrUriMu.Unlock() + } + return uri } diff --git a/producer/smpolicy.go b/producer/smpolicy.go index d381341..1fdc745 100644 --- a/producer/smpolicy.go +++ b/producer/smpolicy.go @@ -31,7 +31,7 @@ var getSlicePccPolicy = polling.GetSlicePccPolicy // SmPoliciesPost - func HandleCreateSmPolicyRequest(request *httpwrapper.Request) *httpwrapper.Response { - logger.SMpolicylog.Infoln("handle CreateSmPolicy") + logger.SMpolicylog.Debugln("handle CreateSmPolicy") requestDataType := request.Body.(models.SmPolicyContextData) header, response, problemDetails := createSMPolicyProcedure(requestDataType) if response != nil { @@ -223,7 +223,7 @@ func createSMPolicyProcedure(request models.SmPolicyContextData) ( "Location": {locationHeader}, } logger.SMpolicylog.Debugf("SMPolicy PduSessionId[%d] Create", request.PduSessionId) - logger.SMpolicylog.Infof("SM Policy Decision Sent to SMF: %v", decision) + logger.SMpolicylog.Debugf("SM Policy Decision Sent to SMF: %v", decision) return header, decision, nil } diff --git a/util/pcf_util.go b/util/pcf_util.go index 10bb227..780d646 100644 --- a/util/pcf_util.go +++ b/util/pcf_util.go @@ -15,6 +15,7 @@ import ( "slices" "sort" "strings" + "sync" "github.com/omec-project/openapi/v2/Nudr_DR" "github.com/omec-project/openapi/v2/models" @@ -53,15 +54,36 @@ var ( } ) +var ( + nudrClientMu sync.RWMutex + cachedNudrClient *Nudr_DR.APIClient + cachedNudrUri string +) + func GetNudrClient(uri string) *Nudr_DR.APIClient { + nudrClientMu.RLock() + if cachedNudrClient != nil && cachedNudrUri == uri { + client := cachedNudrClient + nudrClientMu.RUnlock() + return client + } + nudrClientMu.RUnlock() + + nudrClientMu.Lock() + defer nudrClientMu.Unlock() + // double-checked: another goroutine may have updated the cache between the RUnlock and Lock + if cachedNudrClient != nil && cachedNudrUri == uri { + return cachedNudrClient + } configuration := Nudr_DR.NewConfiguration() serverConfig := &configuration.Servers[0] if apiRootVar, exists := serverConfig.Variables["apiRoot"]; exists { apiRootVar.DefaultValue = uri serverConfig.Variables["apiRoot"] = apiRootVar } - client := Nudr_DR.NewAPIClient(configuration) - return client + cachedNudrClient = Nudr_DR.NewAPIClient(configuration) + cachedNudrUri = uri + return cachedNudrClient } // Return ProblemDetail; errString represents Detail and cause represents Cause. diff --git a/util/pcf_util_test.go b/util/pcf_util_test.go index 9df616f..ab917fb 100644 --- a/util/pcf_util_test.go +++ b/util/pcf_util_test.go @@ -73,3 +73,29 @@ func TestDeepCopyViaJSONPreservesNullableField(t *testing.T) { t.Errorf("Arp.PriorityLevel (NullableInt32) lost in copy: got %v, want 5", v) } } + +func resetNudrClientCache() { + nudrClientMu.Lock() + defer nudrClientMu.Unlock() + cachedNudrClient = nil + cachedNudrUri = "" +} + +func TestGetNudrClientReturnsSamePointerForSameURI(t *testing.T) { + resetNudrClientCache() + const uri = "https://udr.example:29504" + c1 := GetNudrClient(uri) + c2 := GetNudrClient(uri) + if c1 != c2 { + t.Error("expected the same *APIClient pointer for repeated calls with the same URI") + } +} + +func TestGetNudrClientReturnsDifferentPointerForDifferentURI(t *testing.T) { + resetNudrClientCache() + c1 := GetNudrClient("https://udr1.example:29504") + c2 := GetNudrClient("https://udr2.example:29504") + if c1 == c2 { + t.Error("expected a different *APIClient pointer when the URI changes") + } +}