[VOL-5594] Reduce the number of kvstore clients

Change-Id: I7747b0d5729dabf97764432592c5984e5b941bfe
Signed-off-by: Abhay Kumar <abhay.kumar@radisys.com>
diff --git a/VERSION b/VERSION
index 521bb4f..7c66fca 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-4.6.26
+4.7.1
diff --git a/go.mod b/go.mod
index 49626c5..3a2a902 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,7 @@
 	github.com/cenkalti/backoff/v3 v3.1.1
 	github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
 	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
-	github.com/opencord/voltha-lib-go/v7 v7.8.4
+	github.com/opencord/voltha-lib-go/v7 v7.9.1
 	github.com/opencord/voltha-protos/v5 v5.7.3
 	github.com/prometheus/client_golang v1.23.2
 	github.com/stretchr/testify v1.11.1
diff --git a/go.sum b/go.sum
index 62d719a..d72db36 100644
--- a/go.sum
+++ b/go.sum
@@ -158,8 +158,8 @@
 github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
 github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
 github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
-github.com/opencord/voltha-lib-go/v7 v7.8.4 h1:RDxyjtoiCk67mx+fTJohB33VEqQLtnExuMb89RWuyAQ=
-github.com/opencord/voltha-lib-go/v7 v7.8.4/go.mod h1:UELc2f28A2tGsZRu5+XVIWSdEYffACLjWycLlf1o/iI=
+github.com/opencord/voltha-lib-go/v7 v7.9.1 h1:qr/LsU1CRtRrN2xPRgNixONqq9kxS+/ji3YDFVeBLA4=
+github.com/opencord/voltha-lib-go/v7 v7.9.1/go.mod h1:UELc2f28A2tGsZRu5+XVIWSdEYffACLjWycLlf1o/iI=
 github.com/opencord/voltha-protos/v5 v5.7.3 h1:fE4IwjYQzZ/QdfwUKDCIxirua0++zqu2JgbkKwXm6No=
 github.com/opencord/voltha-protos/v5 v5.7.3/go.mod h1:SoKoF6xSY0+v9A//7y2sAX3YgX2Wy4IeBgyMX5n7eOs=
 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index 858aa6a..a040099 100755
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -228,7 +228,9 @@
 	dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
 	dh.childAdapterClients = make(map[string]*vgrpc.Client)
 	dh.cfg = cfg
-	dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, dh.cm.Backend.PathPrefix)
+	// kvStore backend is shared across the flows, groups and resource manager to store the allocated resources and other relevant information.
+	// The kvstore is initialized with a unique path prefix for each device to avoid any conflict with other devices.
+	dh.kvStore = db.NewBackend(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, rsrcMgr.KvstoreTimeout, fmt.Sprintf(rsrcMgr.BasePathKvStore, dh.cm.Backend.PathPrefix, dh.device.Id))
 	if dh.kvStore == nil {
 		logger.Error(ctx, "Failed to setup KV store")
 		return nil
@@ -252,55 +254,23 @@
 	return &dh
 }
 
-func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
-	logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
-	switch storeType {
-	case "etcd":
-		return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
-	case "redis":
-		return kvstore.NewRedisClient(address, timeout, false)
-	case "redis-sentinel":
-		return kvstore.NewRedisClient(address, timeout, true)
-	}
-	return nil, errors.New("unsupported-kv-store")
-}
-
-// SetKVClient sets the KV client and return a kv backend
-func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
-	kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
-	if err != nil {
-		logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
-		return nil
-	}
-	kvbackend := &db.Backend{
-		Client:     kvClient,
-		StoreType:  backend,
-		Address:    addr,
-		Timeout:    rsrcMgr.KvstoreTimeout,
-		PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
-
-	return kvbackend
-}
-
-// CloseKVClient closes open KV clients
-// This method is thread-safe and can be called concurrently
+// CloseKVClient closes the KV client used by this device handler.
+// The kvStore backend is created once in NewDeviceHandler and shared across all
+// per-PON-interface resource managers (dh.resourceMgr) and flow managers
+// (dh.flowMgr). Since they all point to the same underlying KV client, it must
+// be closed exactly once here. Iterating over each resource/flow manager and
+// closing the client per PON interface would double-close the shared client.
 func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
-	// Acquire read lock to safely iterate over resourceMgr and flowMgr slices
-	// Use RLock since we're only reading the slices, not modifying them
-	dh.lockDevice.RLock()
-	defer dh.lockDevice.RUnlock()
-
+	if dh.kvStore != nil && dh.kvStore.Client != nil {
+		dh.kvStore.Client.Close(ctx)
+		dh.kvStore.Client = nil
+	}
+	// Drop the resource managers' references to the now-closed shared backend so
+	// any later access does not operate on a closed client.
 	if dh.resourceMgr != nil {
 		for _, rscMgr := range dh.resourceMgr {
 			if rscMgr != nil {
-				rscMgr.CloseKVClient(ctx)
-			}
-		}
-	}
-	if dh.flowMgr != nil {
-		for _, flMgr := range dh.flowMgr {
-			if flMgr != nil {
-				flMgr.CloseKVClient(ctx)
+				rscMgr.KVStore = nil
 			}
 		}
 	}
@@ -604,13 +574,14 @@
 					if err = indications.CloseSend(); err != nil {
 						// Ok to ignore here, because we landed here due to a problem on the stream
 						// In all probability, the closeSend call may fail
-						logger.Debugw(ctx, "error-closing-send stream--error-ignored",
+						logger.Warnw(ctx, "error-closing-send stream--error-ignored",
 							log.Fields{"err": err,
 								"device-id": dh.device.Id})
 					}
 					if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
 						return err
 					}
+					logger.Debugw(ctx, "successfully-restarted-indication-stream", log.Fields{"device-id": dh.device.Id})
 					// once we re-initialized the indication stream, continue to read indications
 					continue
 				}
@@ -1353,7 +1324,8 @@
 		dh.StopAllFlowRoutines(ctx)
 	}
 
-	dh.CloseKVClient(ctx)
+	// Do NOT close the shared KV client on OLT reboot/re-init
+	// dh.CloseKVClient(ctx)
 
 	if err != nil {
 		return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
@@ -1377,7 +1349,7 @@
 	// There is only one NNI manager since multiple NNI is not supported for now
 	for i = 0; i < dh.totalPonPorts+1; i++ {
 		// Instantiate resource manager
-		if dh.resourceMgr[i] = rsrcMgr.NewResourceMgr(ctx, i, dh.device.Id, dh.openOLT.KVStoreAddress, dh.openOLT.KVStoreType, dh.device.Type, dh.deviceInfo, dh.cm.Backend.PathPrefix); dh.resourceMgr[i] == nil {
+		if dh.resourceMgr[i] = rsrcMgr.NewResourceMgr(ctx, i, dh.device.Id, dh.openOLT.KVStoreAddress, dh.openOLT.KVStoreType, dh.device.Type, dh.deviceInfo, dh.cm.Backend.PathPrefix, dh.kvStore, dh.openOLT.PonRsrcMgr, dh.openOLT.PonRsrcMgrTech); dh.resourceMgr[i] == nil {
 			return olterrors.ErrResourceManagerInstantiating
 		}
 	}
@@ -1630,7 +1602,8 @@
 
 // ProxyOmciRequests sends the proxied OMCI message to the target device
 func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
-	if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
+	if (DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE)) ||
+		(DeviceState(dh.device.OperStatus) != DeviceState(voltha.OperStatus_ACTIVE)) {
 		return status.Error(codes.Unavailable, "OLT unreachable")
 	}
 	if omciMsgs.GetProxyAddress() == nil {
@@ -2670,6 +2643,8 @@
 	} else {
 		logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
 	}
+	// Only close the KV client connection in case of 'DeleteDevice', the connection is still being used for 'doStateUp' & 'updateStateRebooted'.
+	dh.CloseKVClient(ctx)
 
 	dh.removeOnuIndicationChannels(ctx)
 	// Reset the state
@@ -2717,6 +2692,7 @@
 func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
 	var errs []error
 	if dh.resourceMgr != nil && dh.totalPonPorts > 0 {
+		logger.Debugw(ctx, "resource cleanup", log.Fields{"device-id": dh.device.Id})
 		var ponPort uint32
 		for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
 			if dh.resourceMgr[ponPort] == nil {
@@ -2752,13 +2728,12 @@
 	}
 
 	if len(errs) == 0 {
+		logger.Debugw(ctx, "resource cleanup completed successfully", log.Fields{"device-id": dh.device.Id})
 		// Take one final sweep at cleaning up KV store for the OLT device
 		// Clean everything at <base-path-prefix>/openolt/<device-id>
 		if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
 			errs = append(errs, err)
 		}
-		logger.Debugw(ctx, "lockDevice for KVStore close client", log.Fields{"deviceID": dh.device.Id})
-		dh.CloseKVClient(ctx)
 	}
 
 	/*Delete ONU map for the device*/
@@ -3109,6 +3084,8 @@
 		if dh.isReadIndicationRoutineActive {
 			dh.stopIndications <- true
 		}
+		// Stop the routines that are processing indications as the OLT is unreachable and any further processing of indications will lead to inconsistencies/panics
+		dh.removeOnuIndicationChannels(ctx)
 		dh.lockDevice.RUnlock()
 		dh.transitionMap.Handle(ctx, DeviceInit)
 	}
@@ -3146,7 +3123,8 @@
 	if dh.isHeartbeatCheckActive {
 		dh.stopHeartbeatCheck <- true
 	}
-
+	// Stop the routines that are processing indications as the OLT is unreachable and any further processing of indications will lead to inconsistencies/panics
+	dh.removeOnuIndicationChannels(ctx)
 	dh.lockDevice.RUnlock()
 
 	if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
diff --git a/internal/pkg/core/device_handler_test.go b/internal/pkg/core/device_handler_test.go
index b4274c9..bb74e35 100644
--- a/internal/pkg/core/device_handler_test.go
+++ b/internal/pkg/core/device_handler_test.go
@@ -160,7 +160,8 @@
 			ChannelId:      1,
 			ChannelGroupId: 1,
 		},
-		ConnectStatus: 2,
+		ConnectStatus: cmn.ConnectStatus_REACHABLE,
+		OperStatus:    cmn.OperStatus_ACTIVE,
 	}
 	mcs := newMockCoreService()
 	cc := mocks.NewMockCoreClient(mcs)
diff --git a/internal/pkg/core/openolt.go b/internal/pkg/core/openolt.go
index 0dd2325..f85d06d 100644
--- a/internal/pkg/core/openolt.go
+++ b/internal/pkg/core/openolt.go
@@ -24,11 +24,13 @@
 	"time"
 
 	conf "github.com/opencord/voltha-lib-go/v7/pkg/config"
+	"github.com/opencord/voltha-lib-go/v7/pkg/db"
 	"github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
 	vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
 	"github.com/opencord/voltha-lib-go/v7/pkg/log"
 	"github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
 	"github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
+	rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
 	"github.com/opencord/voltha-protos/v5/go/adapter_service"
 	"github.com/opencord/voltha-protos/v5/go/common"
 	ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
@@ -63,6 +65,11 @@
 	enableGemStats                     bool
 	CheckOnuDevExistenceAtOnuDiscovery bool
 	ForceOnuDiscIndProcessing          bool
+	PonRsrcMgr                         *db.Backend
+	PonRsrcMgrTech                     *db.Backend
+	TpDefault                          *db.Backend
+	Tprofiles                          *db.Backend
+	TpInstances                        *db.Backend
 }
 
 // NewOpenOLT returns a new instance of OpenOLT
@@ -88,6 +95,15 @@
 	openOLT.rpcTimeout = cfg.RPCTimeout
 	openOLT.CheckOnuDevExistenceAtOnuDiscovery = cfg.CheckOnuDevExistenceAtOnuDiscovery
 	openOLT.ForceOnuDiscIndProcessing = cfg.ForceOnuDiscIndProcessing
+	logger.Infow(ctx, "cm-backend-prefix", log.Fields{"prefix": cm.Backend.PathPrefix})
+	// kvStore backends for resource manager and technology profiles. These are used by the device handlers to store the allocated resources and other relevant information.
+	openOLT.PonRsrcMgr = db.NewBackend(ctx, cfg.KVStoreType, cfg.KVStoreAddress, rsrcMgr.KvstoreTimeout, cm.Backend.PathPrefix+"/resource_manager")
+	openOLT.PonRsrcMgrTech = db.NewBackend(ctx, cfg.KVStoreType, cfg.KVStoreAddress, rsrcMgr.KvstoreTimeout, cm.Backend.PathPrefix+"/resource_manager/config")
+	openOLT.TpDefault = db.NewBackend(ctx, cfg.KVStoreType, cfg.KVStoreAddress, rsrcMgr.KvstoreTimeout, cm.Backend.PathPrefix+"/technology_profiles")
+	// Tprofiles uses a fixed global path because tech-profile definitions are shared across all VOLTHA stacks.
+	openOLT.Tprofiles = db.NewBackend(ctx, cfg.KVStoreType, cfg.KVStoreAddress, rsrcMgr.KvstoreTimeout, "service/voltha/technology_profiles")
+	openOLT.TpInstances = db.NewBackend(ctx, cfg.KVStoreType, cfg.KVStoreAddress, rsrcMgr.KvstoreTimeout, cm.Backend.PathPrefix+"/resource_instances")
+
 	return &openOLT
 }
 
@@ -105,6 +121,14 @@
 	// Stop the device handlers
 	oo.stopAllDeviceHandlers(ctx)
 
+	// Close shared KV store backends and nil out clients to prevent double-close from downstream CloseKVClient calls.
+	for _, backend := range []*db.Backend{oo.PonRsrcMgr, oo.PonRsrcMgrTech, oo.TpDefault, oo.Tprofiles, oo.TpInstances} {
+		if backend != nil && backend.Client != nil {
+			backend.Client.Close(ctx)
+			backend.Client = nil
+		}
+	}
+
 	// Stop the core grpc client connection
 	if oo.coreClient != nil {
 		oo.coreClient.Stop(ctx)
diff --git a/internal/pkg/core/openolt_flowmgr.go b/internal/pkg/core/openolt_flowmgr.go
index 640a00b..6485084 100644
--- a/internal/pkg/core/openolt_flowmgr.go
+++ b/internal/pkg/core/openolt_flowmgr.go
@@ -218,16 +218,9 @@
 	ponPortIdx uint32 // Pon Port this FlowManager is responsible for
 }
 
-// CloseKVClient closes open KV clients
-func (f *OpenOltFlowMgr) CloseKVClient(ctx context.Context) {
-	if f.techprofile != nil {
-		f.techprofile.CloseKVClient(ctx)
-	}
-}
-
 // NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
 func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
-	logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
+	logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id, "pon-port-idx": ponPortIdx})
 	var flowMgr OpenOltFlowMgr
 	var err error
 
@@ -261,7 +254,7 @@
 
 	// load interface to multicast queue map from kv store
 	flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
-	logger.Debugw(ctx, "initialization-of-flow-manager-success", log.Fields{"device-id": dh.device.Id})
+	logger.Debugw(ctx, "initialization-of-flow-manager-success", log.Fields{"device-id": dh.device.Id, "pon-port-idx": ponPortIdx})
 	return &flowMgr
 }
 
@@ -996,7 +989,8 @@
 			if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
 				var err error
 				f.techprofile, err = tp.NewTechProfile(ctx, intfID, f.resourceMgr.DeviceID, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
-					f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
+					f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix, f.deviceHandler.openOLT.TpDefault, f.deviceHandler.openOLT.Tprofiles,
+					f.deviceHandler.openOLT.TpInstances)
 				if err != nil || f.techprofile == nil {
 					logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
 					return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
diff --git a/internal/pkg/core/openolt_test.go b/internal/pkg/core/openolt_test.go
index 720861e..5c0a508 100644
--- a/internal/pkg/core/openolt_test.go
+++ b/internal/pkg/core/openolt_test.go
@@ -29,6 +29,7 @@
 	"testing"
 
 	conf "github.com/opencord/voltha-lib-go/v7/pkg/config"
+	"github.com/opencord/voltha-lib-go/v7/pkg/db"
 	vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
 	"github.com/opencord/voltha-protos/v5/go/openolt"
 	"github.com/stretchr/testify/assert"
@@ -93,6 +94,7 @@
 }
 
 func TestNewOpenOLT(t *testing.T) {
+	mockCm := &conf.ConfigManager{Backend: &db.Backend{PathPrefix: "service/voltha"}}
 	tests := []struct {
 		name        string
 		fields      *fields
@@ -100,9 +102,9 @@
 		cm          *conf.ConfigManager
 		want        *OpenOLT
 	}{
-		{"newopenolt-1", &fields{}, &config.AdapterFlags{OnuNumber: 1, KVStoreAddress: "1.1.1.1:1", KVStoreType: "etcd"}, &conf.ConfigManager{},
+		{"newopenolt-1", &fields{}, &config.AdapterFlags{OnuNumber: 1, KVStoreAddress: "1.1.1.1:1", KVStoreType: "etcd"}, mockCm,
 			&OpenOLT{numOnus: 1, KVStoreAddress: "1.1.1.1:1", KVStoreType: "etcd"}},
-		{"newopenolt-2", &fields{}, &config.AdapterFlags{OnuNumber: 2, KVStoreAddress: "2.2.2.2:2", KVStoreType: "etcd"}, &conf.ConfigManager{},
+		{"newopenolt-2", &fields{}, &config.AdapterFlags{OnuNumber: 2, KVStoreAddress: "2.2.2.2:2", KVStoreType: "etcd"}, mockCm,
 			&OpenOLT{numOnus: 2, KVStoreAddress: "2.2.2.2:2", KVStoreType: "etcd"}},
 	}
 	for _, tt := range tests {
diff --git a/internal/pkg/resourcemanager/resourcemanager.go b/internal/pkg/resourcemanager/resourcemanager.go
index 96245ca..da46408 100644
--- a/internal/pkg/resourcemanager/resourcemanager.go
+++ b/internal/pkg/resourcemanager/resourcemanager.go
@@ -209,21 +209,10 @@
 	return kvbackend
 }
 
-// CloseKVClient closes open KV clients
-func (rsrcMgr *OpenOltResourceMgr) CloseKVClient(ctx context.Context) {
-	if rsrcMgr.KVStore != nil {
-		rsrcMgr.KVStore.Client.Close(ctx)
-		rsrcMgr.KVStore = nil
-	}
-	if rsrcMgr.PonRsrMgr != nil {
-		rsrcMgr.PonRsrMgr.CloseKVClient(ctx)
-	}
-}
-
 // NewResourceMgr init a New resource manager instance which in turn instantiates pon resource manager
 // instances according to technology. Initializes the default resource ranges for all
 // the resources.
-func NewResourceMgr(ctx context.Context, PonIntfID uint32, deviceID string, KVStoreAddress string, kvStoreType string, deviceType string, devInfo *openolt.DeviceInfo, basePathKvStore string) *OpenOltResourceMgr {
+func NewResourceMgr(ctx context.Context, PonIntfID uint32, deviceID string, KVStoreAddress string, kvStoreType string, deviceType string, devInfo *openolt.DeviceInfo, basePathKvStore string, kvStore *db.Backend, ponrsrcmgr *db.Backend, ponmgrTech *db.Backend) *OpenOltResourceMgr {
 	var ResourceMgr OpenOltResourceMgr
 	logger.Debugf(ctx, "Init new resource manager , ponIf: %v, address: %s, device-id: %s", PonIntfID, KVStoreAddress, deviceID)
 	ResourceMgr.PonIntfID = PonIntfID
@@ -232,8 +221,7 @@
 	ResourceMgr.DeviceType = deviceType
 	ResourceMgr.DevInfo = devInfo
 
-	Backend := kvStoreType
-	ResourceMgr.KVStore = SetKVClient(ctx, Backend, ResourceMgr.Address, deviceID, basePathKvStore)
+	ResourceMgr.KVStore = kvStore
 	if ResourceMgr.KVStore == nil {
 		logger.Error(ctx, "Failed to setup KV store")
 	}
@@ -249,7 +237,7 @@
 				logger.Debugf(ctx, "Device info technology %s, intf-id %v", technology, PonIntfID)
 
 				rsrMgr, err := ponrmgr.NewPONResourceManager(ctx, technology, deviceType, deviceID,
-					Backend, ResourceMgr.Address, basePathKvStore)
+					kvStoreType, ResourceMgr.Address, basePathKvStore, ponrsrcmgr, ponmgrTech)
 				if err != nil {
 					logger.Errorf(ctx, "Failed to create pon resource manager instance for technology %s", technology)
 					return nil
diff --git a/internal/pkg/resourcemanager/resourcemanager_test.go b/internal/pkg/resourcemanager/resourcemanager_test.go
index 4763a31..6eb058f 100644
--- a/internal/pkg/resourcemanager/resourcemanager_test.go
+++ b/internal/pkg/resourcemanager/resourcemanager_test.go
@@ -335,7 +335,8 @@
 		t.Run(tt.name, func(t *testing.T) {
 			ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
 			defer cancel()
-			if got := NewResourceMgr(ctx, tt.args.intfID, tt.args.deviceID, tt.args.KVStoreAddress, tt.args.kvStoreType, tt.args.deviceType, tt.args.devInfo, tt.args.kvStorePrefix); reflect.TypeOf(got) != reflect.TypeOf(tt.want) {
+			mockBackend := &db.Backend{Client: &MockResKVClient{}}
+			if got := NewResourceMgr(ctx, tt.args.intfID, tt.args.deviceID, tt.args.KVStoreAddress, tt.args.kvStoreType, tt.args.deviceType, tt.args.devInfo, tt.args.kvStorePrefix, mockBackend, &db.Backend{Client: &MockResKVClient{}}, &db.Backend{Client: &MockResKVClient{}}); reflect.TypeOf(got) != reflect.TypeOf(tt.want) {
 				t.Errorf("NewResourceMgr() = %v, want %v", got, tt.want)
 			}
 		})
diff --git a/pkg/mocks/mockEventproxy.go b/pkg/mocks/mockEventproxy.go
index f0e8a5d..43d0489 100644
--- a/pkg/mocks/mockEventproxy.go
+++ b/pkg/mocks/mockEventproxy.go
@@ -47,6 +47,15 @@
 	return nil
 }
 
+// SendKpiEvent3 mocks the SendKpiEvent3 function
+func (me *MockEventProxy) SendKpiEvent3(ctx context.Context, id string, deviceEvent *voltha.KpiEvent3, category voltha.EventCategory_Types,
+	subCategory voltha.EventSubCategory_Types, raisedTs int64) error {
+	if raisedTs == 0 {
+		return errors.New("raisedTS cannot be zero")
+	}
+	return nil
+}
+
 // SendRPCEvent mocks the SendRPCEvent function
 func (me *MockEventProxy) SendRPCEvent(ctx context.Context, id string, deviceEvent *voltha.RPCEvent, category voltha.EventCategory_Types,
 	subCategory *voltha.EventSubCategory_Types, raisedTs int64) error {
@@ -80,12 +89,3 @@
 	subCategory eventif.EventSubCategory, raisedTs int64, key string) error {
 	return nil
 }
-
-// SendKpiEvent3 mocks the SendKpiEvent3 function
-func (me *MockEventProxy) SendKpiEvent3(ctx context.Context, id string, deviceEvent *voltha.KpiEvent3, category eventif.EventCategory,
-	subCategory eventif.EventSubCategory, raisedTs int64) error {
-	if raisedTs == 0 {
-		return errors.New("raisedTS cannot be zero")
-	}
-	return nil
-}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore/redisclient.go b/vendor/github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore/redisclient.go
index 3a7e512..f27fc06 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore/redisclient.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore/redisclient.go
@@ -33,6 +33,7 @@
 	watchedChannels     sync.Map
 	writeLock           sync.Mutex
 	keyReservationsLock sync.RWMutex
+	pageSize            int
 }
 
 func NewRedisClient(addr string, timeout time.Duration, useSentinel bool) (*RedisClient, error) {
@@ -49,7 +50,7 @@
 	}
 
 	reservations := make(map[string]time.Duration)
-	return &RedisClient{redisAPI: r, keyReservations: reservations}, nil
+	return &RedisClient{redisAPI: r, keyReservations: reservations, pageSize: 5000}, nil
 }
 
 func (c *RedisClient) Get(ctx context.Context, key string) (*KVPair, error) {
@@ -62,8 +63,12 @@
 	return NewKVPair(key, valBytes, "", 0, 0), nil
 }
 
-func (c *RedisClient) Put(ctx context.Context, key string, value interface{}) error {
+const (
+	// Sorted set name for storing all keys
+	keysSetName = "voltha:keys"
+)
 
+func (c *RedisClient) Put(ctx context.Context, key string, value interface{}) error {
 	// Validate that we can convert value to a string as etcd API expects a string
 	var val string
 	var er error
@@ -71,53 +76,197 @@
 		return fmt.Errorf("unexpected-type-%T", value)
 	}
 
-	// Check if there is already a lease for this key - if there is then use it, otherwise a PUT will make
-	// that KV key permanent instead of automatically removing it after a lease expiration
-	setErr := c.redisAPI.Set(ctx, key, val, 0)
-	err := setErr.Err()
+	// Use a pipeline for atomic operations
+	pipe := c.redisAPI.TxPipeline()
 
+	// Set the key-value pair
+	pipe.Set(ctx, key, val, 0)
+
+	// Add key to sorted set with score 0 for efficient prefix queries
+	pipe.ZAdd(ctx, keysSetName, &redis.Z{
+		Score:  0,
+		Member: key,
+	})
+
+	// Execute pipeline
+	cmds, err := pipe.Exec(ctx)
 	if err != nil {
-		switch setErr.Err() {
+		switch err {
 		case context.Canceled:
-			logger.Warnw(ctx, "context-cancelled", log.Fields{"error": err})
+			logger.Warnw(ctx, "redis put failed : context-cancelled", log.Fields{"error": err, "key": key})
 		case context.DeadlineExceeded:
-			logger.Warnw(ctx, "context-deadline-exceeded", log.Fields{"error": err})
+			logger.Warnw(ctx, "redis put failed : context-deadline-exceeded", log.Fields{"error": err, "key": key})
 		default:
-			logger.Warnw(ctx, "bad-endpoints", log.Fields{"error": err})
+			logger.Warnw(ctx, "redis put failed : bad-endpoints", log.Fields{"error": err, "key": key})
 		}
 		return err
 	}
+
+	// Check individual command errors
+	for _, cmd := range cmds {
+		if cmd.Err() != nil {
+			logger.Warnw(ctx, "redis-pipeline-command-failed", log.Fields{"error": cmd.Err(), "key": key, "Cmd": cmd.String()})
+			return cmd.Err()
+		}
+	}
 	return nil
 }
 
-func (c *RedisClient) scanAllKeysWithPrefix(ctx context.Context, key string) ([]string, error) {
-	var err error
-	allkeys := []string{}
-	cont := true
-	cursor := uint64(0)
-	matchPrefix := key + "*"
+func (c *RedisClient) Delete(ctx context.Context, key string) error {
+	// Use a pipeline for atomic operations
+	pipe := c.redisAPI.TxPipeline()
 
-	for cont {
-		// search in the first 10000 entries starting from the point indicated by the cursor
-		logger.Debugw(ctx, "redis-scan", log.Fields{"matchPrefix": matchPrefix, "cursor": cursor})
-		var keys []string
-		keys, cursor, err = c.redisAPI.Scan(context.Background(), cursor, matchPrefix, 10000).Result()
+	// Delete the key
+	pipe.Del(ctx, key)
+
+	// Remove key from sorted set
+	pipe.ZRem(ctx, keysSetName, key)
+
+	// Execute pipeline
+	cmds, err := pipe.Exec(ctx)
+	if err != nil {
+		logger.Errorw(ctx, "failed-to-delete-key", log.Fields{"key": key, "error": err})
+		return err
+	}
+	// Check individual command errors
+	for _, cmd := range cmds {
+		if cmd.Err() != nil && cmd.Err() != redis.Nil {
+			logger.Warnw(ctx, "redis-pipeline-command-failed", log.Fields{"error": cmd.Err(), "key": key, "Cmd": cmd.String()})
+			return cmd.Err()
+		}
+	}
+
+	logger.Debugw(ctx, "key-deleted", log.Fields{"key": key})
+	return nil
+}
+
+func (c *RedisClient) DeleteWithPrefix(ctx context.Context, prefixKey string) error {
+	var keys []string
+	var err error
+
+	// Use ZRANGEBYLEX to get keys with prefix efficiently
+	if keys, err = c.getKeysWithPrefixFromSortedSet(ctx, prefixKey); err != nil {
+		return err
+	}
+
+	if len(keys) == 0 {
+		logger.Warn(ctx, "nothing-to-delete-from-kv", log.Fields{"key": prefixKey})
+		return nil
+	}
+
+	// Delete keys in batches using pipeline
+	entryCount := int64(0)
+	start := 0
+	length := len(keys)
+
+	for start < length {
+		end := start + c.pageSize
+		if end >= length {
+			end = length
+		}
+		keysToDelete := keys[start:end]
+
+		pipe := c.redisAPI.TxPipeline()
+
+		// Delete the actual key-value pairs
+		pipe.Del(ctx, keysToDelete...)
+
+		// Remove keys from sorted set
+		members := make([]interface{}, len(keysToDelete))
+		for i, k := range keysToDelete {
+			members[i] = k
+		}
+		pipe.ZRem(ctx, keysSetName, members...)
+
+		// Execute pipeline
+		cmds, err := pipe.Exec(ctx)
+		if err != nil {
+			logger.Errorw(ctx, "DeleteWithPrefix method failed", log.Fields{"prefixKey": prefixKey, "numOfMatchedKeys": len(keysToDelete), "err": err})
+			return err
+		}
+		// Check individual command errors
+		for _, cmd := range cmds {
+			if cmd.Err() != nil && cmd.Err() != redis.Nil {
+				logger.Warnw(ctx, "redis-pipeline-command-failed", log.Fields{"error": cmd.Err(), "key": prefixKey, "Cmd": cmd.String()})
+				return cmd.Err()
+			}
+		}
+
+		// First command is Del, get its result
+		if len(cmds) > 0 {
+			if delCmd, ok := cmds[0].(*redis.IntCmd); ok {
+				count, _ := delCmd.Result()
+				entryCount += count
+			}
+		}
+
+		start = end
+	}
+
+	logger.Debugf(ctx, "%d entries matching with the key prefix %s have been deleted successfully", entryCount, prefixKey)
+	return nil
+}
+
+func (c *RedisClient) GetWithPrefix(ctx context.Context, prefix string) (map[string]*KVPair, error) {
+	var err error
+	var keys []string
+	m := make(map[string]*KVPair)
+	var values []interface{}
+
+	// Use ZRANGEBYLEX to get keys with prefix efficiently
+	if keys, err = c.getKeysWithPrefixFromSortedSet(ctx, prefix); err != nil {
+		return nil, err
+	}
+
+	if len(keys) != 0 {
+		values, err = c.redisAPI.MGet(ctx, keys...).Result()
 		if err != nil {
 			return nil, err
 		}
-		if cursor == 0 {
-			// all data searched. break the loop
-			logger.Debugw(ctx, "redis-scan-ended", log.Fields{"matchPrefix": matchPrefix, "cursor": cursor})
-			cont = false
-		}
-		if len(keys) == 0 {
-			// no matched data found in this cycle. Continue to search
-			logger.Debugw(ctx, "redis-scan-no-data-found-continue", log.Fields{"matchPrefix": matchPrefix, "cursor": cursor})
-			continue
-		}
-		allkeys = append(allkeys, keys...)
 	}
-	return allkeys, nil
+
+	for i, key := range keys {
+		if valBytes, err := ToByte(values[i]); err == nil {
+			m[key] = NewKVPair(key, interface{}(valBytes), "", 0, 0)
+		}
+	}
+	return m, nil
+}
+
+func (c *RedisClient) GetWithPrefixKeysOnly(ctx context.Context, prefix string) ([]string, error) {
+	// Use ZRANGEBYLEX to get keys with prefix efficiently
+	keys, err := c.getKeysWithPrefixFromSortedSet(ctx, prefix)
+	if err != nil {
+		return nil, fmt.Errorf("failed to get keys with prefix %s: %v", prefix, err)
+	}
+
+	if len(keys) == 0 {
+		logger.Debugw(ctx, "no-keys-found", log.Fields{"prefix": prefix})
+	}
+
+	return keys, nil
+}
+
+// Helper function to retrieve keys with prefix using ZRANGEBYLEX
+func (c *RedisClient) getKeysWithPrefixFromSortedSet(ctx context.Context, prefix string) ([]string, error) {
+	// ZRANGEBYLEX uses lexicographical ordering
+	// min: [prefix - includes prefix
+	// max: [prefix\xff - includes all keys starting with prefix
+	min := "[" + prefix
+	max := "[" + prefix + "\xff"
+
+	keys, err := c.redisAPI.ZRangeByLex(ctx, keysSetName, &redis.ZRangeBy{
+		Min: min,
+		Max: max,
+	}).Result()
+
+	if err != nil {
+		logger.Errorw(ctx, "failed-to-get-keys-with-prefix", log.Fields{"prefix": prefix, "error": err})
+		return nil, err
+	}
+
+	logger.Debugw(ctx, "keys-retrieved-with-prefix", log.Fields{"prefix": prefix, "count": len(keys)})
+	return keys, nil
 }
 
 func (c *RedisClient) KeyExists(ctx context.Context, key string) (bool, error) {
@@ -139,7 +288,8 @@
 	m := make(map[string]*KVPair)
 	var values []interface{}
 
-	if keys, err = c.scanAllKeysWithPrefix(ctx, key); err != nil {
+	// Use ZRANGEBYLEX to get keys with prefix efficiently
+	if keys, err = c.getKeysWithPrefixFromSortedSet(ctx, key); err != nil {
 		return nil, err
 	}
 
@@ -157,49 +307,6 @@
 	return m, nil
 }
 
-func (c *RedisClient) Delete(ctx context.Context, key string) error {
-	// delete the key
-	if _, err := c.redisAPI.Del(ctx, key).Result(); err != nil {
-		logger.Errorw(ctx, "failed-to-delete-key", log.Fields{"key": key, "error": err})
-		return err
-	}
-	logger.Debugw(ctx, "key(s)-deleted", log.Fields{"key": key})
-	return nil
-}
-
-func (c *RedisClient) DeleteWithPrefix(ctx context.Context, prefixKey string) error {
-	var keys []string
-	var err error
-	if keys, err = c.scanAllKeysWithPrefix(ctx, prefixKey); err != nil {
-		return err
-	}
-	if len(keys) == 0 {
-		logger.Warn(ctx, "nothing-to-delete-from-kv", log.Fields{"key": prefixKey})
-		return nil
-	}
-	//call delete for keys
-	entryCount := int64(0)
-	start := 0
-	pageSize := 5000
-	length := len(keys)
-	for start < length {
-		end := start + pageSize
-		if end >= length {
-			end = length
-		}
-		keysToDelete := keys[start:end]
-		count := int64(0)
-		if count, err = c.redisAPI.Del(ctx, keysToDelete...).Result(); err != nil {
-			logger.Errorw(ctx, "DeleteWithPrefix method failed", log.Fields{"prefixKey": prefixKey, "numOfMatchedKeys": len(keysToDelete), "err": err})
-			return err
-		}
-		entryCount += count
-		start = end
-	}
-	logger.Debugf(ctx, "%d entries matching with the key prefix %s have been deleted successfully", entryCount, prefixKey)
-	return nil
-}
-
 func (c *RedisClient) Reserve(ctx context.Context, key string, value interface{}, ttl time.Duration) (interface{}, error) {
 	var val string
 	var er error
@@ -428,41 +535,3 @@
 		logger.Errorw(ctx, "error-closing-client", log.Fields{"error": err})
 	}
 }
-
-func (c *RedisClient) GetWithPrefix(ctx context.Context, prefix string) (map[string]*KVPair, error) {
-	var err error
-	var keys []string
-	m := make(map[string]*KVPair)
-	var values []interface{}
-
-	if keys, err = c.scanAllKeysWithPrefix(ctx, prefix); err != nil {
-		return nil, err
-	}
-
-	if len(keys) != 0 {
-		values, err = c.redisAPI.MGet(ctx, keys...).Result()
-		if err != nil {
-			return nil, err
-		}
-	}
-	for i, key := range keys {
-		if valBytes, err := ToByte(values[i]); err == nil {
-			m[key] = NewKVPair(key, interface{}(valBytes), "", 0, 0)
-		}
-	}
-	return m, nil
-}
-
-func (c *RedisClient) GetWithPrefixKeysOnly(ctx context.Context, prefix string) ([]string, error) {
-	// Use the scanAllKeysWithPrefix function to fetch keys matching the prefix
-	keys, err := c.scanAllKeysWithPrefix(ctx, prefix)
-	if err != nil {
-		return nil, fmt.Errorf("failed to scan keys with prefix %s: %v", prefix, err)
-	}
-
-	if len(keys) == 0 {
-		logger.Debugw(ctx, "no-keys-found", log.Fields{"prefix": prefix})
-	}
-
-	return keys, nil
-}
diff --git a/vendor/github.com/opencord/voltha-lib-go/v7/pkg/ponresourcemanager/ponresourcemanager.go b/vendor/github.com/opencord/voltha-lib-go/v7/pkg/ponresourcemanager/ponresourcemanager.go
index 0eec452..0008e00 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v7/pkg/ponresourcemanager/ponresourcemanager.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v7/pkg/ponresourcemanager/ponresourcemanager.go
@@ -192,6 +192,10 @@
 	return kvbackend
 }
 
+// CloseKVClient closes the KV store connections held by this manager.
+// Note: The KV backends may be shared with other managers (e.g., TechProfileMgr).
+// The nil check and nil assignment ensure that duplicate close calls are safe —
+// once closed by one manager, the other will see nil and skip closing.
 func (PONRMgr *PONResourceManager) CloseKVClient(ctx context.Context) {
 	if PONRMgr.KVStore != nil {
 		PONRMgr.KVStore.Client.Close(ctx)
@@ -204,20 +208,20 @@
 }
 
 // NewPONResourceManager creates a new PON resource manager.
-func NewPONResourceManager(ctx context.Context, Technology string, DeviceType string, DeviceID string, Backend string, Address string, basePathKvStore string) (*PONResourceManager, error) {
+func NewPONResourceManager(ctx context.Context, Technology string, DeviceType string, DeviceID string, Backend string, Address string, basePathKvStore string, ponrsrcmgr *db.Backend, ponmgrTech *db.Backend) (*PONResourceManager, error) {
 	var PONMgr PONResourceManager
 	PONMgr.Technology = Technology
 	PONMgr.DeviceType = DeviceType
 	PONMgr.DeviceID = DeviceID
 	PONMgr.Backend = Backend
 	PONMgr.Address = Address
-	PONMgr.KVStore = SetKVClient(ctx, Technology, Backend, Address, false, basePathKvStore)
+	PONMgr.KVStore = ponrsrcmgr
 	if PONMgr.KVStore == nil {
 		logger.Error(ctx, "KV Client initilization failed")
 		return nil, errors.New("failed to init KV client")
 	}
 	// init kv client to read from the config path
-	PONMgr.KVStoreForConfig = SetKVClient(ctx, Technology, Backend, Address, true, basePathKvStore)
+	PONMgr.KVStoreForConfig = ponmgrTech
 	if PONMgr.KVStoreForConfig == nil {
 		logger.Error(ctx, "KV Config Client initilization failed")
 		return nil, errors.New("failed to init KV Config client")
@@ -990,7 +994,7 @@
 	}
 
 	FlowIDPath := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
-	if FlowIDs, err := PONRMgr.KVStore.List(ctx, FlowIDPath); err != nil {
+	if FlowIDs, err := PONRMgr.KVStore.List(ctx, FlowIDPath); err == nil {
 		for _, Flow := range FlowIDs {
 			FlowIDInfoPath := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, PONIntfONUID, Flow.Value)
 			if err = PONRMgr.KVStore.Delete(ctx, FlowIDInfoPath); err != nil {
diff --git a/vendor/github.com/opencord/voltha-lib-go/v7/pkg/techprofile/tech_profile.go b/vendor/github.com/opencord/voltha-lib-go/v7/pkg/techprofile/tech_profile.go
index 1bfb964..089988d 100644
--- a/vendor/github.com/opencord/voltha-lib-go/v7/pkg/techprofile/tech_profile.go
+++ b/vendor/github.com/opencord/voltha-lib-go/v7/pkg/techprofile/tech_profile.go
@@ -178,6 +178,10 @@
 	*/
 }
 
+// CloseKVClient closes the KV store connections held by this manager.
+// Note: The KV backends may be shared with other managers (e.g., PONResourceManager).
+// The nil check and nil assignment ensure that duplicate close calls are safe —
+// once closed by one manager, the other will see nil and skip closing.
 func (t *TechProfileMgr) CloseKVClient(ctx context.Context) {
 	if t.config.KVBackend != nil {
 		t.config.KVBackend.Client.Close(ctx)
@@ -193,17 +197,17 @@
 	}
 }
 
-func NewTechProfile(ctx context.Context, IntfId uint32, deviceId string, resourceMgr iPonResourceMgr, kvStoreType string, kvStoreAddress string, basePathKvStore string) (*TechProfileMgr, error) {
+func NewTechProfile(ctx context.Context, IntfId uint32, deviceId string, resourceMgr iPonResourceMgr, kvStoreType string, kvStoreAddress string, basePathKvStore string, TpDefault *db.Backend, Tprofiles *db.Backend, TpInstances *db.Backend) (*TechProfileMgr, error) {
 	var techprofileObj TechProfileMgr
 	logger.Debug(ctx, "initializing-techprofile-mananger ", log.Fields{"IntId": IntfId, "device-id": deviceId})
 	techprofileObj.config = NewTechProfileFlags(kvStoreType, kvStoreAddress, basePathKvStore)
-	techprofileObj.config.KVBackend = techprofileObj.SetKVClient(ctx, techprofileObj.config.TPKVPathPrefix)
-	techprofileObj.config.DefaultTpKVBackend = techprofileObj.SetKVClient(ctx, techprofileObj.config.defaultTpKvPathPrefix)
+	techprofileObj.config.KVBackend = Tprofiles
+	techprofileObj.config.DefaultTpKVBackend = TpDefault
 	if techprofileObj.config.KVBackend == nil {
 		logger.Error(ctx, "failed-to-initialize-backend")
 		return nil, errors.New("kv-backend-init-failed")
 	}
-	techprofileObj.config.ResourceInstanceKVBacked = techprofileObj.SetKVClient(ctx, techprofileObj.config.ResourceInstanceKVPathPrefix)
+	techprofileObj.config.ResourceInstanceKVBacked = TpInstances
 	if techprofileObj.config.ResourceInstanceKVBacked == nil {
 		logger.Error(ctx, "failed-to-initialize-resource-instance-kv-backend")
 		return nil, errors.New("resource-instance-kv-backend-init-failed")
@@ -213,12 +217,12 @@
 	techprofileObj.eponTpInstanceMap = make(map[string]*tp_pb.EponTechProfileInstance)
 	techprofileObj.tpMap = make(map[uint32]*tp_pb.TechProfile)
 	techprofileObj.eponTpMap = make(map[uint32]*tp_pb.EponTechProfile)
-	logger.Debug(ctx, "reconcile-tp-instance-cache-start")
+	logger.Debugw(ctx, "reconcile-tp-instance-cache-start", log.Fields{"IntId": IntfId, "device-id": deviceId})
 	if err := techprofileObj.reconcileTpInstancesToCache(ctx, IntfId, deviceId); err != nil {
 		logger.Errorw(ctx, "failed-to-reconcile-tp-instances", log.Fields{"err": err})
 		return nil, err
 	}
-	logger.Debug(ctx, "reconcile-tp-instance-cache-end")
+	logger.Debugw(ctx, "reconcile-tp-instance-cache-end", log.Fields{"IntId": IntfId, "device-id": deviceId})
 	logger.Debug(ctx, "initializing-tech-profile-manager-object-success")
 	return &techprofileObj, nil
 }
@@ -1388,6 +1392,7 @@
 
 	//Fetching the techprofile Keys  from the KV Store.
 	tpkeys, _ := t.config.DefaultTpKVBackend.GetWithPrefixKeysOnly(ctx, tech)
+	logger.Debugw(ctx, "get-all-tech-profile-keys", log.Fields{"len(tpkeys)": len(tpkeys), "tech": tech, "deviceId": deviceId, "IntfId": IntfId})
 
 	// Extract the techprofile Ids from the keys
 	// The tpkeys will be of the format "service/voltha/technology_profiles/GPON/65"
@@ -1414,6 +1419,7 @@
 	for _, tpId := range tpIds {
 		prefix := fmt.Sprintf("%s/%d/olt-{%s}/pon-{%d}", tech, tpId, deviceId, IntfId)
 		kvPairs, _ := t.config.ResourceInstanceKVBacked.GetWithPrefix(newCtx, prefix)
+		logger.Debugw(ctx, "get-resource-instances-with-prefix", log.Fields{"prefix": prefix, "len(kvPairs)": len(kvPairs), "tech": tech, "deviceId": deviceId, "IntfId": IntfId})
 		//check if KvPairs is empty and if not then reconcile the techprofile instance
 		if len(kvPairs) > 0 {
 			for keyPath, kvPair := range kvPairs {
@@ -1467,10 +1473,7 @@
 				} else {
 					logger.Errorw(ctx, "error-converting-kv-pair-value-to-byte", log.Fields{"err": err})
 				}
-
 			}
-
-			return nil
 		}
 	}
 	return nil
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 9f9374f..f7aa113 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -229,7 +229,7 @@
 # github.com/olekukonko/tablewriter v0.0.5
 ## explicit; go 1.12
 github.com/olekukonko/tablewriter
-# github.com/opencord/voltha-lib-go/v7 v7.8.4
+# github.com/opencord/voltha-lib-go/v7 v7.9.1
 ## explicit; go 1.25.5
 github.com/opencord/voltha-lib-go/v7/pkg/config
 github.com/opencord/voltha-lib-go/v7/pkg/db