Repository: DiceDB/dice
File: core/store.go (Go)

Code before:
			Del(k)
			storeMutex.RLock()
			keypoolMutex.RLock()
			return nil
		}
		v.LastAccessedAt = getCurrentClock()
	}
	return v
}

func GetDel(k string) *Obj {
	storeMutex.RLock()
	defer storeMutex.RUnlock()
	keypoolMutex.RLock()
	defer keypoolMutex.RUnlock()
	ptr, ok := keypool[k]
	if !ok {
		return nil
	}

	v := store[ptr]
	if v != nil {
		expired := hasExpired(v)
		keypoolMutex.RUnlock()
		storeMutex.RUnlock()
		Del(k)
		storeMutex.RLock()
		keypoolMutex.RLock()
		if expired {
			return nil
		}
	}
	return v
}

func Del(k string) bool {
	storeMutex.Lock()
	defer storeMutex.Unlock()
	keypoolMutex.Lock()
	defer keypoolMutex.Unlock()

	ptr, ok := keypool[k]
	if !ok {
		return false
	}

	if obj, ok := store[ptr]; ok {
		delete(store, ptr)
		delete(expires, obj)
		delete(keypool, k)
		KeyspaceStat[0]["keys"]--

Review comment (refactor):
Releasing the lock here takes away the atomicity guarantee. A better way to do this might be to define a helper method which both GetDel and Del depend upon:
```go
// Helper function to delete an object and return it (if it existed)
func deleteAndGet(k string) *Obj {
    storeMutex.Lock()
    defer storeMutex.Unlock()
    keypoolMutex.Lock()
    defer keypoolMutex.Unlock()

    ptr, ok := keypool[k]
    if !ok {
        return nil
    }

    obj, exists := store[ptr]
    if !exists {
        return nil
    }

    // Delete the object from all data structures
    delete(store, ptr)
    delete(expires, obj)
    delete(keypool, k)
    KeyspaceStat[0]["keys"]--

    // Notify watchers
    WatchChannel <- WatchEvent{k, "DEL", obj}

    return obj
}

// Del deletes the key and returns whether it existed
func Del(k string) bool {
    return deleteAndGet(k) != nil
}

// GetDel gets the value and deletes the key atomically
func GetDel(k string) *Obj {
    obj := deleteAndGet(k)
    if obj != nil && hasExpired(obj) {
        return nil
    }
    return obj
}
```

Code after:
		return delByPtr(ptr)
	}, WithStoreLock(), WithKeypoolLock())
}

// List all keys in the store by given pattern
func Keys(p string) ([]string, error) {
	var keys []string
	var err error

	withLocks(func() {
		keys = make([]string, 0, len(keypool))
		for k := range keypool {
			if found, e := path.Match(p, k); e != nil {
				err = e
				return
			} else if found {
				keys = append(keys, k)
			}
		}
	}, WithStoreRLock(), WithKeypoolRLock())

	return keys, err
}

// Function to add a new watcher to a query.
func AddWatcher(query DSQLQuery, clientFd int) {
	clients, _ := WatchList.LoadOrStore(query, &sync.Map{})
	clients.(*sync.Map).Store(clientFd, struct{}{})
}

// Function to remove a watcher from a query.
func RemoveWatcher(query DSQLQuery, clientFd int) {
	if clients, ok := WatchList.Load(query); ok {
		clients.(*sync.Map).Delete(clientFd)
		// If no more clients for this query, remove the query from WatchList
		if countClients(clients.(*sync.Map)) == 0 {
			WatchList.Delete(query)
		}
	}
}

// Rename function to implement RENAME functionality using existing helpers
func Rename(sourceKey string, destKey string) bool {
	return withLocksReturn(func() bool {
		// If source and destination are the same, do nothing and return true
		if sourceKey == destKey {
			return true
		}

		sourcePtr, sourceOk := keypool[sourceKey]
		if !sourceOk {