// Code generated by rediczar gen tool. DO NOT EDIT

package rediczar

import (
	"context"
	"time"

	"github.com/go-redis/redis/v7"
)

// Commands defines context-aware Redis commands
type Commands interface {
	// Pipeline can send batches of commands and get a reply in a single step. See https://redis.io/topics/pipelining
	// Exec() on the Pipeliner executes the batch. Close() the pipeliner after using it
	Pipeline(ctx context.Context) redis.Pipeliner

	// Pipelined is like Pipeline. The commands are automatically executed at the end of fn
	Pipelined(ctx context.Context, fn func(redis.Pipeliner) error) ([]redis.Cmder, error)

	// TxPipeline is like Pipeline, but executes in a transaction using MULTI and EXEC. See https://redis.io/topics/transactions
	// Exec() on the Pipeliner executes the transaction. Close() the pipeliner after using it
	TxPipeline(ctx context.Context) redis.Pipeliner

	// TxPipelined is like TxPipeline. The commands are automatically executed at the end of fn
	TxPipelined(ctx context.Context, fn func(redis.Pipeliner) error) ([]redis.Cmder, error)

	// Append executes the Append command
	Append(ctx context.Context, key string, value string) (int64, error)

	// BLPop executes the BLPop command
	BLPop(ctx context.Context, timeout time.Duration, keys ...string) ([]string, error)

	// BRPop executes the BRPop command
	BRPop(ctx context.Context, timeout time.Duration, keys ...string) ([]string, error)

	// BRPopLPush executes the BRPopLPush command
	BRPopLPush(ctx context.Context, source string, destination string, timeout time.Duration) (string, error)

	// BZPopMax executes the BZPopMax command
	BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) (*redis.ZWithKey, error)

	// BZPopMin executes the BZPopMin command
	BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) (*redis.ZWithKey, error)

	// BgRewriteAOF executes the BgRewriteAOF command
	BgRewriteAOF(ctx context.Context) (string, error)

	// BgSave executes the BgSave command
	BgSave(ctx context.Context) (string, error)

	// BitCount executes the BitCount command
	BitCount(ctx context.Context, key string, bitCount *redis.BitCount) (int64, error)

	// BitField executes the BitField command
	BitField(ctx context.Context, key string, args ...interface{}) ([]int64, error)

	// BitOpAnd executes the BitOpAnd command
	BitOpAnd(ctx context.Context, destKey string, keys ...string) (int64, error)

	// BitOpNot executes the BitOpNot command
	BitOpNot(ctx context.Context, destKey string, key string) (int64, error)

	// BitOpOr executes the BitOpOr command
	BitOpOr(ctx context.Context, destKey string, keys ...string) (int64, error)

	// BitOpXor executes the BitOpXor command
	BitOpXor(ctx context.Context, destKey string, keys ...string) (int64, error)

	// BitPos executes the BitPos command
	BitPos(ctx context.Context, key string, bit int64, pos ...int64) (int64, error)

	// ClientGetName executes the ClientGetName command
	ClientGetName(ctx context.Context) (string, error)

	// ClientID executes the ClientID command
	ClientID(ctx context.Context) (int64, error)

	// ClientKill executes the ClientKill command
	ClientKill(ctx context.Context, ipPort string) (string, error)

	// ClientKillByFilter executes the ClientKillByFilter command
	ClientKillByFilter(ctx context.Context, keys ...string) (int64, error)

	// ClientList executes the ClientList command
	ClientList(ctx context.Context) (string, error)

	// ClientPause executes the ClientPause command
	ClientPause(ctx context.Context, dur time.Duration) (bool, error)

	// ClusterAddSlots executes the ClusterAddSlots command
	ClusterAddSlots(ctx context.Context, slots ...int) (string, error)

	// ClusterAddSlotsRange executes the ClusterAddSlotsRange command
	ClusterAddSlotsRange(ctx context.Context, min int, max int) (string, error)

	// ClusterCountFailureReports executes the ClusterCountFailureReports command
	ClusterCountFailureReports(ctx context.Context, nodeID string) (int64, error)

	// ClusterCountKeysInSlot executes the ClusterCountKeysInSlot command
	ClusterCountKeysInSlot(ctx context.Context, slot int) (int64, error)

	// ClusterDelSlots executes the ClusterDelSlots command
	ClusterDelSlots(ctx context.Context, slots ...int) (string, error)

	// ClusterDelSlotsRange executes the ClusterDelSlotsRange command
	ClusterDelSlotsRange(ctx context.Context, min int, max int) (string, error)

	// ClusterFailover executes the ClusterFailover command
	ClusterFailover(ctx context.Context) (string, error)

	// ClusterForget executes the ClusterForget command
	ClusterForget(ctx context.Context, nodeID string) (string, error)

	// ClusterGetKeysInSlot executes the ClusterGetKeysInSlot command
	ClusterGetKeysInSlot(ctx context.Context, slot int, count int) ([]string, error)

	// ClusterInfo executes the ClusterInfo command
	ClusterInfo(ctx context.Context) (string, error)

	// ClusterKeySlot executes the ClusterKeySlot command
	ClusterKeySlot(ctx context.Context, key string) (int64, error)

	// ClusterMeet executes the ClusterMeet command
	ClusterMeet(ctx context.Context, host string, port string) (string, error)

	// ClusterNodes executes the ClusterNodes command
	ClusterNodes(ctx context.Context) (string, error)

	// ClusterReplicate executes the ClusterReplicate command
	ClusterReplicate(ctx context.Context, nodeID string) (string, error)

	// ClusterResetHard executes the ClusterResetHard command
	ClusterResetHard(ctx context.Context) (string, error)

	// ClusterResetSoft executes the ClusterResetSoft command
	ClusterResetSoft(ctx context.Context) (string, error)

	// ClusterSaveConfig executes the ClusterSaveConfig command
	ClusterSaveConfig(ctx context.Context) (string, error)

	// ClusterSlaves executes the ClusterSlaves command
	ClusterSlaves(ctx context.Context, nodeID string) ([]string, error)

	// ClusterSlots executes the ClusterSlots command
	ClusterSlots(ctx context.Context) ([]redis.ClusterSlot, error)

	// Command executes the Command command
	Command(ctx context.Context) (map[string]*redis.CommandInfo, error)

	// ConfigGet executes the ConfigGet command
	ConfigGet(ctx context.Context, parameter string) ([]interface{}, error)

	// ConfigResetStat executes the ConfigResetStat command
	ConfigResetStat(ctx context.Context) (string, error)

	// ConfigRewrite executes the ConfigRewrite command
	ConfigRewrite(ctx context.Context) (string, error)

	// ConfigSet executes the ConfigSet command
	ConfigSet(ctx context.Context, parameter string, value string) (string, error)

	// DBSize executes the DBSize command
	DBSize(ctx context.Context) (int64, error)

	// DebugObject executes the DebugObject command
	DebugObject(ctx context.Context, key string) (string, error)

	// Decr executes the Decr command
	Decr(ctx context.Context, key string) (int64, error)

	// DecrBy executes the DecrBy command
	DecrBy(ctx context.Context, key string, decrement int64) (int64, error)

	// Del executes the Del command
	Del(ctx context.Context, keys ...string) (int64, error)

	// Dump executes the Dump command
	Dump(ctx context.Context, key string) (string, error)

	// Echo executes the Echo command
	Echo(ctx context.Context, message interface{}) (string, error)

	// Eval executes the Eval command
	Eval(ctx context.Context, script string, keys []string, args ...interface{}) (interface{}, error)

	// EvalSha executes the EvalSha command
	EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) (interface{}, error)

	// Exists executes the Exists command
	Exists(ctx context.Context, keys ...string) (int64, error)

	// Expire executes the Expire command
	Expire(ctx context.Context, key string, expiration time.Duration) (bool, error)

	// ExpireAt executes the ExpireAt command
	ExpireAt(ctx context.Context, key string, tm time.Time) (bool, error)

	// FlushAll executes the FlushAll command
	FlushAll(ctx context.Context) (string, error)

	// FlushAllAsync executes the FlushAllAsync command
	FlushAllAsync(ctx context.Context) (string, error)

	// FlushDB executes the FlushDB command
	FlushDB(ctx context.Context) (string, error)

	// FlushDBAsync executes the FlushDBAsync command
	FlushDBAsync(ctx context.Context) (string, error)

	// GeoAdd executes the GeoAdd command
	GeoAdd(ctx context.Context, key string, geoLocation ...*redis.GeoLocation) (int64, error)

	// GeoDist executes the GeoDist command
	GeoDist(ctx context.Context, key string, member1 string, member2 string, unit string) (float64, error)

	// GeoHash executes the GeoHash command
	GeoHash(ctx context.Context, key string, members ...string) ([]string, error)

	// GeoPos executes the GeoPos command
	GeoPos(ctx context.Context, key string, members ...string) ([]*redis.GeoPos, error)

	// GeoRadius executes the GeoRadius command
	GeoRadius(ctx context.Context, key string, longitude float64, latitude float64, query *redis.GeoRadiusQuery) ([]redis.GeoLocation, error)

	// GeoRadiusByMember executes the GeoRadiusByMember command
	GeoRadiusByMember(ctx context.Context, key string, member string, query *redis.GeoRadiusQuery) ([]redis.GeoLocation, error)

	// GeoRadiusByMemberStore executes the GeoRadiusByMemberStore command
	GeoRadiusByMemberStore(ctx context.Context, key string, member string, query *redis.GeoRadiusQuery) (int64, error)

	// GeoRadiusStore executes the GeoRadiusStore command
	GeoRadiusStore(ctx context.Context, key string, longitude float64, latitude float64, query *redis.GeoRadiusQuery) (int64, error)

	// Get executes the Get command
	Get(ctx context.Context, key string) (string, error)

	// GetBit executes the GetBit command
	GetBit(ctx context.Context, key string, offset int64) (int64, error)

	// GetRange executes the GetRange command
	GetRange(ctx context.Context, key string, start int64, end int64) (string, error)

	// GetSet executes the GetSet command
	GetSet(ctx context.Context, key string, value interface{}) (string, error)

	// HDel executes the HDel command
	HDel(ctx context.Context, key string, fields ...string) (int64, error)

	// HExists executes the HExists command
	HExists(ctx context.Context, key string, field string) (bool, error)

	// HGet executes the HGet command
	HGet(ctx context.Context, key string, field string) (string, error)

	// HGetAll executes the HGetAll command
	HGetAll(ctx context.Context, key string) (map[string]string, error)

	// HIncrBy executes the HIncrBy command
	HIncrBy(ctx context.Context, key string, field string, incr int64) (int64, error)

	// HIncrByFloat executes the HIncrByFloat command
	HIncrByFloat(ctx context.Context, key string, field string, incr float64) (float64, error)

	// HKeys executes the HKeys command
	HKeys(ctx context.Context, key string) ([]string, error)

	// HLen executes the HLen command
	HLen(ctx context.Context, key string) (int64, error)

	// HMGet executes the HMGet command
	HMGet(ctx context.Context, key string, fields ...string) ([]interface{}, error)

	// HMSet executes the HMSet command
	HMSet(ctx context.Context, key string, fields map[string]interface{}) (string, error)

	// HScan executes the HScan command
	HScan(ctx context.Context, key string, cursor uint64, match string, count int64) ([]string, uint64, error)

	// HSet executes the HSet command
	HSet(ctx context.Context, key string, field string, value interface{}) (bool, error)

	// HSetNX executes the HSetNX command
	HSetNX(ctx context.Context, key string, field string, value interface{}) (bool, error)

	// HVals executes the HVals command
	HVals(ctx context.Context, key string) ([]string, error)

	// Incr executes the Incr command
	Incr(ctx context.Context, key string) (int64, error)

	// IncrBy executes the IncrBy command
	IncrBy(ctx context.Context, key string, value int64) (int64, error)

	// IncrByFloat executes the IncrByFloat command
	IncrByFloat(ctx context.Context, key string, value float64) (float64, error)

	// Info executes the Info command
	Info(ctx context.Context, section ...string) (string, error)

	// Keys executes the Keys command
	Keys(ctx context.Context, pattern string) ([]string, error)

	// LIndex executes the LIndex command
	LIndex(ctx context.Context, key string, index int64) (string, error)

	// LInsert executes the LInsert command
	LInsert(ctx context.Context, key string, op string, pivot interface{}, value interface{}) (int64, error)

	// LInsertAfter executes the LInsertAfter command
	LInsertAfter(ctx context.Context, key string, pivot interface{}, value interface{}) (int64, error)

	// LInsertBefore executes the LInsertBefore command
	LInsertBefore(ctx context.Context, key string, pivot interface{}, value interface{}) (int64, error)

	// LLen executes the LLen command
	LLen(ctx context.Context, key string) (int64, error)

	// LPop executes the LPop command
	LPop(ctx context.Context, key string) (string, error)

	// LPush executes the LPush command
	LPush(ctx context.Context, key string, values ...interface{}) (int64, error)

	// LPushX executes the LPushX command
	LPushX(ctx context.Context, key string, values ...interface{}) (int64, error)

	// LRange executes the LRange command
	LRange(ctx context.Context, key string, start int64, stop int64) ([]string, error)

	// LRem executes the LRem command
	LRem(ctx context.Context, key string, count int64, value interface{}) (int64, error)

	// LSet executes the LSet command
	LSet(ctx context.Context, key string, index int64, value interface{}) (string, error)

	// LTrim executes the LTrim command
	LTrim(ctx context.Context, key string, start int64, stop int64) (string, error)

	// LastSave executes the LastSave command
	LastSave(ctx context.Context) (int64, error)

	// MGet executes the MGet command
	MGet(ctx context.Context, keys ...string) ([]interface{}, error)

	// MSet executes the MSet command
	MSet(ctx context.Context, pairs ...interface{}) (string, error)

	// MSetNX executes the MSetNX command
	MSetNX(ctx context.Context, pairs ...interface{}) (bool, error)

	// MemoryUsage executes the MemoryUsage command
	MemoryUsage(ctx context.Context, key string, samples ...int) (int64, error)

	// Migrate executes the Migrate command
	Migrate(ctx context.Context, host string, port string, key string, db int, timeout time.Duration) (string, error)

	// Move executes the Move command
	Move(ctx context.Context, key string, db int) (bool, error)

	// ObjectEncoding executes the ObjectEncoding command
	ObjectEncoding(ctx context.Context, key string) (string, error)

	// ObjectIdleTime executes the ObjectIdleTime command
	ObjectIdleTime(ctx context.Context, key string) (time.Duration, error)

	// ObjectRefCount executes the ObjectRefCount command
	ObjectRefCount(ctx context.Context, key string) (int64, error)

	// PExpire executes the PExpire command
	PExpire(ctx context.Context, key string, expiration time.Duration) (bool, error)

	// PExpireAt executes the PExpireAt command
	PExpireAt(ctx context.Context, key string, tm time.Time) (bool, error)

	// PFAdd executes the PFAdd command
	PFAdd(ctx context.Context, key string, els ...interface{}) (int64, error)

	// PFCount executes the PFCount command
	PFCount(ctx context.Context, keys ...string) (int64, error)

	// PFMerge executes the PFMerge command
	PFMerge(ctx context.Context, dest string, keys ...string) (string, error)

	// PTTL executes the PTTL command
	PTTL(ctx context.Context, key string) (time.Duration, error)

	// Persist executes the Persist command
	Persist(ctx context.Context, key string) (bool, error)

	// Ping executes the Ping command
	Ping(ctx context.Context) (string, error)

	// PubSubChannels executes the PubSubChannels command
	PubSubChannels(ctx context.Context, pattern string) ([]string, error)

	// PubSubNumPat executes the PubSubNumPat command
	PubSubNumPat(ctx context.Context) (int64, error)

	// PubSubNumSub executes the PubSubNumSub command
	PubSubNumSub(ctx context.Context, channels ...string) (map[string]int64, error)

	// Publish executes the Publish command
	Publish(ctx context.Context, channel string, message interface{}) (int64, error)

	// Quit executes the Quit command
	Quit(ctx context.Context) (string, error)

	// RPop executes the RPop command
	RPop(ctx context.Context, key string) (string, error)

	// RPopLPush executes the RPopLPush command
	RPopLPush(ctx context.Context, source string, destination string) (string, error)

	// RPush executes the RPush command
	RPush(ctx context.Context, key string, values ...interface{}) (int64, error)

	// RPushX executes the RPushX command
	RPushX(ctx context.Context, key string, values ...interface{}) (int64, error)

	// RandomKey executes the RandomKey command
	RandomKey(ctx context.Context) (string, error)

	// ReadOnly executes the ReadOnly command
	ReadOnly(ctx context.Context) (string, error)

	// ReadWrite executes the ReadWrite command
	ReadWrite(ctx context.Context) (string, error)

	// Rename executes the Rename command
	Rename(ctx context.Context, key string, newkey string) (string, error)

	// RenameNX executes the RenameNX command
	RenameNX(ctx context.Context, key string, newkey string) (bool, error)

	// Restore executes the Restore command
	Restore(ctx context.Context, key string, ttl time.Duration, value string) (string, error)

	// RestoreReplace executes the RestoreReplace command
	RestoreReplace(ctx context.Context, key string, ttl time.Duration, value string) (string, error)

	// SAdd executes the SAdd command
	SAdd(ctx context.Context, key string, members ...interface{}) (int64, error)

	// SCard executes the SCard command
	SCard(ctx context.Context, key string) (int64, error)

	// SDiff executes the SDiff command
	SDiff(ctx context.Context, keys ...string) ([]string, error)

	// SDiffStore executes the SDiffStore command
	SDiffStore(ctx context.Context, destination string, keys ...string) (int64, error)

	// SInter executes the SInter command
	SInter(ctx context.Context, keys ...string) ([]string, error)

	// SInterStore executes the SInterStore command
	SInterStore(ctx context.Context, destination string, keys ...string) (int64, error)

	// SIsMember executes the SIsMember command
	SIsMember(ctx context.Context, key string, member interface{}) (bool, error)

	// SMembers executes the SMembers command
	SMembers(ctx context.Context, key string) ([]string, error)

	// SMembersMap executes the SMembersMap command
	SMembersMap(ctx context.Context, key string) (map[string]struct{}, error)

	// SMove executes the SMove command
	SMove(ctx context.Context, source string, destination string, member interface{}) (bool, error)

	// SPop executes the SPop command
	SPop(ctx context.Context, key string) (string, error)

	// SPopN executes the SPopN command
	SPopN(ctx context.Context, key string, count int64) ([]string, error)

	// SRandMember executes the SRandMember command
	SRandMember(ctx context.Context, key string) (string, error)

	// SRandMemberN executes the SRandMemberN command
	SRandMemberN(ctx context.Context, key string, count int64) ([]string, error)

	// SRem executes the SRem command
	SRem(ctx context.Context, key string, members ...interface{}) (int64, error)

	// SScan executes the SScan command
	SScan(ctx context.Context, key string, cursor uint64, match string, count int64) ([]string, uint64, error)

	// SUnion executes the SUnion command
	SUnion(ctx context.Context, keys ...string) ([]string, error)

	// SUnionStore executes the SUnionStore command
	SUnionStore(ctx context.Context, destination string, keys ...string) (int64, error)

	// Save executes the Save command
	Save(ctx context.Context) (string, error)

	// Scan executes the Scan command
	Scan(ctx context.Context, cursor uint64, match string, count int64) ([]string, uint64, error)

	// ScriptExists executes the ScriptExists command
	ScriptExists(ctx context.Context, hashes ...string) ([]bool, error)

	// ScriptFlush executes the ScriptFlush command
	ScriptFlush(ctx context.Context) (string, error)

	// ScriptKill executes the ScriptKill command
	ScriptKill(ctx context.Context) (string, error)

	// ScriptLoad executes the ScriptLoad command
	ScriptLoad(ctx context.Context, script string) (string, error)

	// Set executes the Set command
	Set(ctx context.Context, key string, value interface{}, expiration time.Duration) (string, error)

	// SetBit executes the SetBit command
	SetBit(ctx context.Context, key string, offset int64, value int) (int64, error)

	// SetNX executes the SetNX command
	SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) (bool, error)

	// SetRange executes the SetRange command
	SetRange(ctx context.Context, key string, offset int64, value string) (int64, error)

	// SetXX executes the SetXX command
	SetXX(ctx context.Context, key string, value interface{}, expiration time.Duration) (bool, error)

	// Shutdown executes the Shutdown command
	Shutdown(ctx context.Context) (string, error)

	// ShutdownNoSave executes the ShutdownNoSave command
	ShutdownNoSave(ctx context.Context) (string, error)

	// ShutdownSave executes the ShutdownSave command
	ShutdownSave(ctx context.Context) (string, error)

	// SlaveOf executes the SlaveOf command
	SlaveOf(ctx context.Context, host string, port string) (string, error)

	// Sort executes the Sort command
	Sort(ctx context.Context, key string, sort *redis.Sort) ([]string, error)

	// SortInterfaces executes the SortInterfaces command
	SortInterfaces(ctx context.Context, key string, sort *redis.Sort) ([]interface{}, error)

	// SortStore executes the SortStore command
	SortStore(ctx context.Context, key string, store string, sort *redis.Sort) (int64, error)

	// StrLen executes the StrLen command
	StrLen(ctx context.Context, key string) (int64, error)

	// TTL executes the TTL command
	TTL(ctx context.Context, key string) (time.Duration, error)

	// Time executes the Time command
	Time(ctx context.Context) (time.Time, error)

	// Touch executes the Touch command
	Touch(ctx context.Context, keys ...string) (int64, error)

	// Type executes the Type command
	Type(ctx context.Context, key string) (string, error)

	// Unlink executes the Unlink command
	Unlink(ctx context.Context, keys ...string) (int64, error)

	// XAck executes the XAck command
	XAck(ctx context.Context, stream string, group string, ids ...string) (int64, error)

	// XAdd executes the XAdd command
	XAdd(ctx context.Context, a *redis.XAddArgs) (string, error)

	// XClaim executes the XClaim command
	XClaim(ctx context.Context, a *redis.XClaimArgs) ([]redis.XMessage, error)

	// XClaimJustID executes the XClaimJustID command
	XClaimJustID(ctx context.Context, a *redis.XClaimArgs) ([]string, error)

	// XDel executes the XDel command
	XDel(ctx context.Context, stream string, ids ...string) (int64, error)

	// XGroupCreate executes the XGroupCreate command
	XGroupCreate(ctx context.Context, stream string, group string, start string) (string, error)

	// XGroupCreateMkStream executes the XGroupCreateMkStream command
	XGroupCreateMkStream(ctx context.Context, stream string, group string, start string) (string, error)

	// XGroupDelConsumer executes the XGroupDelConsumer command
	XGroupDelConsumer(ctx context.Context, stream string, group string, consumer string) (int64, error)

	// XGroupDestroy executes the XGroupDestroy command
	XGroupDestroy(ctx context.Context, stream string, group string) (int64, error)

	// XGroupSetID executes the XGroupSetID command
	XGroupSetID(ctx context.Context, stream string, group string, start string) (string, error)

	// XLen executes the XLen command
	XLen(ctx context.Context, stream string) (int64, error)

	// XPending executes the XPending command
	XPending(ctx context.Context, stream string, group string) (*redis.XPending, error)

	// XPendingExt executes the XPendingExt command
	XPendingExt(ctx context.Context, a *redis.XPendingExtArgs) ([]redis.XPendingExt, error)

	// XRange executes the XRange command
	XRange(ctx context.Context, stream string, start string, stop string) ([]redis.XMessage, error)

	// XRangeN executes the XRangeN command
	XRangeN(ctx context.Context, stream string, start string, stop string, count int64) ([]redis.XMessage, error)

	// XRead executes the XRead command
	XRead(ctx context.Context, a *redis.XReadArgs) ([]redis.XStream, error)

	// XReadGroup executes the XReadGroup command
	XReadGroup(ctx context.Context, a *redis.XReadGroupArgs) ([]redis.XStream, error)

	// XReadStreams executes the XReadStreams command
	XReadStreams(ctx context.Context, streams ...string) ([]redis.XStream, error)

	// XRevRange executes the XRevRange command
	XRevRange(ctx context.Context, stream string, start string, stop string) ([]redis.XMessage, error)

	// XRevRangeN executes the XRevRangeN command
	XRevRangeN(ctx context.Context, stream string, start string, stop string, count int64) ([]redis.XMessage, error)

	// XTrim executes the XTrim command
	XTrim(ctx context.Context, key string, maxLen int64) (int64, error)

	// XTrimApprox executes the XTrimApprox command
	XTrimApprox(ctx context.Context, key string, maxLen int64) (int64, error)

	// ZAdd executes the ZAdd command
	ZAdd(ctx context.Context, key string, members ...*redis.Z) (int64, error)

	// ZAddCh executes the ZAddCh command
	ZAddCh(ctx context.Context, key string, members ...*redis.Z) (int64, error)

	// ZAddNX executes the ZAddNX command
	ZAddNX(ctx context.Context, key string, members ...*redis.Z) (int64, error)

	// ZAddNXCh executes the ZAddNXCh command
	ZAddNXCh(ctx context.Context, key string, members ...*redis.Z) (int64, error)

	// ZAddXX executes the ZAddXX command
	ZAddXX(ctx context.Context, key string, members ...*redis.Z) (int64, error)

	// ZAddXXCh executes the ZAddXXCh command
	ZAddXXCh(ctx context.Context, key string, members ...*redis.Z) (int64, error)

	// ZCard executes the ZCard command
	ZCard(ctx context.Context, key string) (int64, error)

	// ZCount executes the ZCount command
	ZCount(ctx context.Context, key string, min string, max string) (int64, error)

	// ZIncr executes the ZIncr command
	ZIncr(ctx context.Context, key string, member *redis.Z) (float64, error)

	// ZIncrBy executes the ZIncrBy command
	ZIncrBy(ctx context.Context, key string, increment float64, member string) (float64, error)

	// ZIncrNX executes the ZIncrNX command
	ZIncrNX(ctx context.Context, key string, member *redis.Z) (float64, error)

	// ZIncrXX executes the ZIncrXX command
	ZIncrXX(ctx context.Context, key string, member *redis.Z) (float64, error)

	// ZInterStore executes the ZInterStore command
	ZInterStore(ctx context.Context, destination string, store *redis.ZStore) (int64, error)

	// ZLexCount executes the ZLexCount command
	ZLexCount(ctx context.Context, key string, min string, max string) (int64, error)

	// ZPopMax executes the ZPopMax command
	ZPopMax(ctx context.Context, key string, count ...int64) ([]redis.Z, error)

	// ZPopMin executes the ZPopMin command
	ZPopMin(ctx context.Context, key string, count ...int64) ([]redis.Z, error)

	// ZRange executes the ZRange command
	ZRange(ctx context.Context, key string, start int64, stop int64) ([]string, error)

	// ZRangeByLex executes the ZRangeByLex command
	ZRangeByLex(ctx context.Context, key string, opt *redis.ZRangeBy) ([]string, error)

	// ZRangeByScore executes the ZRangeByScore command
	ZRangeByScore(ctx context.Context, key string, opt *redis.ZRangeBy) ([]string, error)

	// ZRangeByScoreWithScores executes the ZRangeByScoreWithScores command
	ZRangeByScoreWithScores(ctx context.Context, key string, opt *redis.ZRangeBy) ([]redis.Z, error)

	// ZRangeWithScores executes the ZRangeWithScores command
	ZRangeWithScores(ctx context.Context, key string, start int64, stop int64) ([]redis.Z, error)

	// ZRank executes the ZRank command
	ZRank(ctx context.Context, key string, member string) (int64, error)

	// ZRem executes the ZRem command
	ZRem(ctx context.Context, key string, members ...interface{}) (int64, error)

	// ZRemRangeByLex executes the ZRemRangeByLex command
	ZRemRangeByLex(ctx context.Context, key string, min string, max string) (int64, error)

	// ZRemRangeByRank executes the ZRemRangeByRank command
	ZRemRangeByRank(ctx context.Context, key string, start int64, stop int64) (int64, error)

	// ZRemRangeByScore executes the ZRemRangeByScore command
	ZRemRangeByScore(ctx context.Context, key string, min string, max string) (int64, error)

	// ZRevRange executes the ZRevRange command
	ZRevRange(ctx context.Context, key string, start int64, stop int64) ([]string, error)

	// ZRevRangeByLex executes the ZRevRangeByLex command
	ZRevRangeByLex(ctx context.Context, key string, opt *redis.ZRangeBy) ([]string, error)

	// ZRevRangeByScore executes the ZRevRangeByScore command
	ZRevRangeByScore(ctx context.Context, key string, opt *redis.ZRangeBy) ([]string, error)

	// ZRevRangeByScoreWithScores executes the ZRevRangeByScoreWithScores command
	ZRevRangeByScoreWithScores(ctx context.Context, key string, opt *redis.ZRangeBy) ([]redis.Z, error)

	// ZRevRangeWithScores executes the ZRevRangeWithScores command
	ZRevRangeWithScores(ctx context.Context, key string, start int64, stop int64) ([]redis.Z, error)

	// ZRevRank executes the ZRevRank command
	ZRevRank(ctx context.Context, key string, member string) (int64, error)

	// ZScan executes the ZScan command
	ZScan(ctx context.Context, key string, cursor uint64, match string, count int64) ([]string, uint64, error)

	// ZScore executes the ZScore command
	ZScore(ctx context.Context, key string, member string) (float64, error)

	// ZUnionStore executes the ZUnionStore command
	ZUnionStore(ctx context.Context, dest string, store *redis.ZStore) (int64, error)
}

// PrefixedCommands is a context-aware Redis command client with key prefixing support
type PrefixedCommands struct {
	// Redis is the go-redis client
	Redis redis.Cmdable
	// KeyPrefix (if non-blank) is prepended to all keys with ":" as the delimiter
	KeyPrefix string
	// RunMetrics is optional for tracking metrics
	RunMetrics RunMetrics
}

// Append executes the Append command
func (c *PrefixedCommands) Append(ctx context.Context, key string, value string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Append(key, value)
	trackCommand(c.RunMetrics, "Append", cmd.Err(), startTime)
	return cmd.Result()
}

// BLPop executes the BLPop command
func (c *PrefixedCommands) BLPop(ctx context.Context, timeout time.Duration, keys ...string) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.BLPop(timeout, keys...)
	trackCommand(c.RunMetrics, "BLPop", cmd.Err(), startTime)
	return cmd.Result()
}

// BRPop executes the BRPop command
func (c *PrefixedCommands) BRPop(ctx context.Context, timeout time.Duration, keys ...string) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.BRPop(timeout, keys...)
	trackCommand(c.RunMetrics, "BRPop", cmd.Err(), startTime)
	return cmd.Result()
}

// BRPopLPush executes the BRPopLPush command
func (c *PrefixedCommands) BRPopLPush(ctx context.Context, source string, destination string, timeout time.Duration) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.BRPopLPush(source, destination, timeout)
	trackCommand(c.RunMetrics, "BRPopLPush", cmd.Err(), startTime)
	return cmd.Result()
}

// BZPopMax executes the BZPopMax command
func (c *PrefixedCommands) BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) (*redis.ZWithKey, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.BZPopMax(timeout, keys...)
	trackCommand(c.RunMetrics, "BZPopMax", cmd.Err(), startTime)
	return cmd.Result()
}

// BZPopMin executes the BZPopMin command
func (c *PrefixedCommands) BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) (*redis.ZWithKey, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.BZPopMin(timeout, keys...)
	trackCommand(c.RunMetrics, "BZPopMin", cmd.Err(), startTime)
	return cmd.Result()
}

// BgRewriteAOF executes the BgRewriteAOF command
func (c *PrefixedCommands) BgRewriteAOF(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.BgRewriteAOF()
	trackCommand(c.RunMetrics, "BgRewriteAOF", cmd.Err(), startTime)
	return cmd.Result()
}

// BgSave executes the BgSave command
func (c *PrefixedCommands) BgSave(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.BgSave()
	trackCommand(c.RunMetrics, "BgSave", cmd.Err(), startTime)
	return cmd.Result()
}

// BitCount executes the BitCount command
func (c *PrefixedCommands) BitCount(ctx context.Context, key string, bitCount *redis.BitCount) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.BitCount(key, bitCount)
	trackCommand(c.RunMetrics, "BitCount", cmd.Err(), startTime)
	return cmd.Result()
}

// BitField executes the BitField command
func (c *PrefixedCommands) BitField(ctx context.Context, key string, args ...interface{}) ([]int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.BitField(key, args...)
	trackCommand(c.RunMetrics, "BitField", cmd.Err(), startTime)
	return cmd.Result()
}

// BitOpAnd executes the BitOpAnd command
func (c *PrefixedCommands) BitOpAnd(ctx context.Context, destKey string, keys ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.BitOpAnd(destKey, keys...)
	trackCommand(c.RunMetrics, "BitOpAnd", cmd.Err(), startTime)
	return cmd.Result()
}

// BitOpNot executes the BitOpNot command
func (c *PrefixedCommands) BitOpNot(ctx context.Context, destKey string, key string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.BitOpNot(destKey, key)
	trackCommand(c.RunMetrics, "BitOpNot", cmd.Err(), startTime)
	return cmd.Result()
}

// BitOpOr executes the BitOpOr command
func (c *PrefixedCommands) BitOpOr(ctx context.Context, destKey string, keys ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.BitOpOr(destKey, keys...)
	trackCommand(c.RunMetrics, "BitOpOr", cmd.Err(), startTime)
	return cmd.Result()
}

// BitOpXor executes the BitOpXor command
func (c *PrefixedCommands) BitOpXor(ctx context.Context, destKey string, keys ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.BitOpXor(destKey, keys...)
	trackCommand(c.RunMetrics, "BitOpXor", cmd.Err(), startTime)
	return cmd.Result()
}

// BitPos executes the BitPos command
func (c *PrefixedCommands) BitPos(ctx context.Context, key string, bit int64, pos ...int64) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.BitPos(key, bit, pos...)
	trackCommand(c.RunMetrics, "BitPos", cmd.Err(), startTime)
	return cmd.Result()
}

// ClientGetName executes the ClientGetName command
func (c *PrefixedCommands) ClientGetName(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClientGetName()
	trackCommand(c.RunMetrics, "ClientGetName", cmd.Err(), startTime)
	return cmd.Result()
}

// ClientID executes the ClientID command
func (c *PrefixedCommands) ClientID(ctx context.Context) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClientID()
	trackCommand(c.RunMetrics, "ClientID", cmd.Err(), startTime)
	return cmd.Result()
}

// ClientKill executes the ClientKill command
func (c *PrefixedCommands) ClientKill(ctx context.Context, ipPort string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClientKill(ipPort)
	trackCommand(c.RunMetrics, "ClientKill", cmd.Err(), startTime)
	return cmd.Result()
}

// ClientKillByFilter executes the ClientKillByFilter command
func (c *PrefixedCommands) ClientKillByFilter(ctx context.Context, keys ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClientKillByFilter(keys...)
	trackCommand(c.RunMetrics, "ClientKillByFilter", cmd.Err(), startTime)
	return cmd.Result()
}

// ClientList executes the ClientList command
func (c *PrefixedCommands) ClientList(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClientList()
	trackCommand(c.RunMetrics, "ClientList", cmd.Err(), startTime)
	return cmd.Result()
}

// ClientPause executes the ClientPause command
func (c *PrefixedCommands) ClientPause(ctx context.Context, dur time.Duration) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClientPause(dur)
	trackCommand(c.RunMetrics, "ClientPause", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterAddSlots executes the ClusterAddSlots command
func (c *PrefixedCommands) ClusterAddSlots(ctx context.Context, slots ...int) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterAddSlots(slots...)
	trackCommand(c.RunMetrics, "ClusterAddSlots", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterAddSlotsRange executes the ClusterAddSlotsRange command
func (c *PrefixedCommands) ClusterAddSlotsRange(ctx context.Context, min int, max int) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterAddSlotsRange(min, max)
	trackCommand(c.RunMetrics, "ClusterAddSlotsRange", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterCountFailureReports executes the ClusterCountFailureReports command
func (c *PrefixedCommands) ClusterCountFailureReports(ctx context.Context, nodeID string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterCountFailureReports(nodeID)
	trackCommand(c.RunMetrics, "ClusterCountFailureReports", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterCountKeysInSlot executes the ClusterCountKeysInSlot command
func (c *PrefixedCommands) ClusterCountKeysInSlot(ctx context.Context, slot int) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterCountKeysInSlot(slot)
	trackCommand(c.RunMetrics, "ClusterCountKeysInSlot", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterDelSlots executes the ClusterDelSlots command
func (c *PrefixedCommands) ClusterDelSlots(ctx context.Context, slots ...int) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterDelSlots(slots...)
	trackCommand(c.RunMetrics, "ClusterDelSlots", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterDelSlotsRange executes the ClusterDelSlotsRange command
func (c *PrefixedCommands) ClusterDelSlotsRange(ctx context.Context, min int, max int) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterDelSlotsRange(min, max)
	trackCommand(c.RunMetrics, "ClusterDelSlotsRange", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterFailover executes the ClusterFailover command
func (c *PrefixedCommands) ClusterFailover(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterFailover()
	trackCommand(c.RunMetrics, "ClusterFailover", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterForget executes the ClusterForget command
func (c *PrefixedCommands) ClusterForget(ctx context.Context, nodeID string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterForget(nodeID)
	trackCommand(c.RunMetrics, "ClusterForget", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterGetKeysInSlot executes the ClusterGetKeysInSlot command
func (c *PrefixedCommands) ClusterGetKeysInSlot(ctx context.Context, slot int, count int) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterGetKeysInSlot(slot, count)
	trackCommand(c.RunMetrics, "ClusterGetKeysInSlot", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterInfo executes the ClusterInfo command
func (c *PrefixedCommands) ClusterInfo(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterInfo()
	trackCommand(c.RunMetrics, "ClusterInfo", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterKeySlot executes the ClusterKeySlot command
func (c *PrefixedCommands) ClusterKeySlot(ctx context.Context, key string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterKeySlot(key)
	trackCommand(c.RunMetrics, "ClusterKeySlot", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterMeet executes the ClusterMeet command
func (c *PrefixedCommands) ClusterMeet(ctx context.Context, host string, port string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterMeet(host, port)
	trackCommand(c.RunMetrics, "ClusterMeet", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterNodes executes the ClusterNodes command
func (c *PrefixedCommands) ClusterNodes(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterNodes()
	trackCommand(c.RunMetrics, "ClusterNodes", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterReplicate executes the ClusterReplicate command
func (c *PrefixedCommands) ClusterReplicate(ctx context.Context, nodeID string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterReplicate(nodeID)
	trackCommand(c.RunMetrics, "ClusterReplicate", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterResetHard executes the ClusterResetHard command
func (c *PrefixedCommands) ClusterResetHard(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterResetHard()
	trackCommand(c.RunMetrics, "ClusterResetHard", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterResetSoft executes the ClusterResetSoft command
func (c *PrefixedCommands) ClusterResetSoft(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterResetSoft()
	trackCommand(c.RunMetrics, "ClusterResetSoft", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterSaveConfig executes the ClusterSaveConfig command
func (c *PrefixedCommands) ClusterSaveConfig(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterSaveConfig()
	trackCommand(c.RunMetrics, "ClusterSaveConfig", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterSlaves executes the ClusterSlaves command
func (c *PrefixedCommands) ClusterSlaves(ctx context.Context, nodeID string) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterSlaves(nodeID)
	trackCommand(c.RunMetrics, "ClusterSlaves", cmd.Err(), startTime)
	return cmd.Result()
}

// ClusterSlots executes the ClusterSlots command
func (c *PrefixedCommands) ClusterSlots(ctx context.Context) ([]redis.ClusterSlot, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ClusterSlots()
	trackCommand(c.RunMetrics, "ClusterSlots", cmd.Err(), startTime)
	return cmd.Result()
}

// Command executes the Command command
func (c *PrefixedCommands) Command(ctx context.Context) (map[string]*redis.CommandInfo, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Command()
	trackCommand(c.RunMetrics, "Command", cmd.Err(), startTime)
	return cmd.Result()
}

// ConfigGet executes the ConfigGet command
func (c *PrefixedCommands) ConfigGet(ctx context.Context, parameter string) ([]interface{}, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ConfigGet(parameter)
	trackCommand(c.RunMetrics, "ConfigGet", cmd.Err(), startTime)
	return cmd.Result()
}

// ConfigResetStat executes the ConfigResetStat command
func (c *PrefixedCommands) ConfigResetStat(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ConfigResetStat()
	trackCommand(c.RunMetrics, "ConfigResetStat", cmd.Err(), startTime)
	return cmd.Result()
}

// ConfigRewrite executes the ConfigRewrite command
func (c *PrefixedCommands) ConfigRewrite(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ConfigRewrite()
	trackCommand(c.RunMetrics, "ConfigRewrite", cmd.Err(), startTime)
	return cmd.Result()
}

// ConfigSet executes the ConfigSet command
func (c *PrefixedCommands) ConfigSet(ctx context.Context, parameter string, value string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ConfigSet(parameter, value)
	trackCommand(c.RunMetrics, "ConfigSet", cmd.Err(), startTime)
	return cmd.Result()
}

// DBSize executes the DBSize command
func (c *PrefixedCommands) DBSize(ctx context.Context) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.DBSize()
	trackCommand(c.RunMetrics, "DBSize", cmd.Err(), startTime)
	return cmd.Result()
}

// DebugObject executes the DebugObject command
func (c *PrefixedCommands) DebugObject(ctx context.Context, key string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.DebugObject(key)
	trackCommand(c.RunMetrics, "DebugObject", cmd.Err(), startTime)
	return cmd.Result()
}

// Decr executes the Decr command
func (c *PrefixedCommands) Decr(ctx context.Context, key string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Decr(key)
	trackCommand(c.RunMetrics, "Decr", cmd.Err(), startTime)
	return cmd.Result()
}

// DecrBy executes the DecrBy command
func (c *PrefixedCommands) DecrBy(ctx context.Context, key string, decrement int64) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.DecrBy(key, decrement)
	trackCommand(c.RunMetrics, "DecrBy", cmd.Err(), startTime)
	return cmd.Result()
}

// Del executes the Del command
func (c *PrefixedCommands) Del(ctx context.Context, keys ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Del(keys...)
	trackCommand(c.RunMetrics, "Del", cmd.Err(), startTime)
	return cmd.Result()
}

// Dump executes the Dump command
func (c *PrefixedCommands) Dump(ctx context.Context, key string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Dump(key)
	trackCommand(c.RunMetrics, "Dump", cmd.Err(), startTime)
	return cmd.Result()
}

// Echo executes the Echo command
func (c *PrefixedCommands) Echo(ctx context.Context, message interface{}) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Echo(message)
	trackCommand(c.RunMetrics, "Echo", cmd.Err(), startTime)
	return cmd.Result()
}

// Eval executes the Eval command
func (c *PrefixedCommands) Eval(ctx context.Context, script string, keys []string, args ...interface{}) (interface{}, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	args = flattenArgs(args)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Eval(script, keys, args...)
	trackCommand(c.RunMetrics, "Eval", cmd.Err(), startTime)
	return cmd.Result()
}

// EvalSha executes the EvalSha command
func (c *PrefixedCommands) EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) (interface{}, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	args = flattenArgs(args)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.EvalSha(sha1, keys, args...)
	trackCommand(c.RunMetrics, "EvalSha", cmd.Err(), startTime)
	return cmd.Result()
}

// Exists executes the Exists command
func (c *PrefixedCommands) Exists(ctx context.Context, keys ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Exists(keys...)
	trackCommand(c.RunMetrics, "Exists", cmd.Err(), startTime)
	return cmd.Result()
}

// Expire executes the Expire command
func (c *PrefixedCommands) Expire(ctx context.Context, key string, expiration time.Duration) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Expire(key, expiration)
	trackCommand(c.RunMetrics, "Expire", cmd.Err(), startTime)
	return cmd.Result()
}

// ExpireAt executes the ExpireAt command
func (c *PrefixedCommands) ExpireAt(ctx context.Context, key string, tm time.Time) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ExpireAt(key, tm)
	trackCommand(c.RunMetrics, "ExpireAt", cmd.Err(), startTime)
	return cmd.Result()
}

// FlushAll executes the FlushAll command
func (c *PrefixedCommands) FlushAll(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.FlushAll()
	trackCommand(c.RunMetrics, "FlushAll", cmd.Err(), startTime)
	return cmd.Result()
}

// FlushAllAsync executes the FlushAllAsync command
func (c *PrefixedCommands) FlushAllAsync(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.FlushAllAsync()
	trackCommand(c.RunMetrics, "FlushAllAsync", cmd.Err(), startTime)
	return cmd.Result()
}

// FlushDB executes the FlushDB command
func (c *PrefixedCommands) FlushDB(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.FlushDB()
	trackCommand(c.RunMetrics, "FlushDB", cmd.Err(), startTime)
	return cmd.Result()
}

// FlushDBAsync executes the FlushDBAsync command
func (c *PrefixedCommands) FlushDBAsync(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.FlushDBAsync()
	trackCommand(c.RunMetrics, "FlushDBAsync", cmd.Err(), startTime)
	return cmd.Result()
}

// GeoAdd executes the GeoAdd command
func (c *PrefixedCommands) GeoAdd(ctx context.Context, key string, geoLocation ...*redis.GeoLocation) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.GeoAdd(key, geoLocation...)
	trackCommand(c.RunMetrics, "GeoAdd", cmd.Err(), startTime)
	return cmd.Result()
}

// GeoDist executes the GeoDist command
func (c *PrefixedCommands) GeoDist(ctx context.Context, key string, member1 string, member2 string, unit string) (float64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.GeoDist(key, member1, member2, unit)
	trackCommand(c.RunMetrics, "GeoDist", cmd.Err(), startTime)
	return cmd.Result()
}

// GeoHash executes the GeoHash command
func (c *PrefixedCommands) GeoHash(ctx context.Context, key string, members ...string) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.GeoHash(key, members...)
	trackCommand(c.RunMetrics, "GeoHash", cmd.Err(), startTime)
	return cmd.Result()
}

// GeoPos executes the GeoPos command
func (c *PrefixedCommands) GeoPos(ctx context.Context, key string, members ...string) ([]*redis.GeoPos, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.GeoPos(key, members...)
	trackCommand(c.RunMetrics, "GeoPos", cmd.Err(), startTime)
	return cmd.Result()
}

// GeoRadius executes the GeoRadius command
func (c *PrefixedCommands) GeoRadius(ctx context.Context, key string, longitude float64, latitude float64, query *redis.GeoRadiusQuery) ([]redis.GeoLocation, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.GeoRadius(key, longitude, latitude, query)
	trackCommand(c.RunMetrics, "GeoRadius", cmd.Err(), startTime)
	return cmd.Result()
}

// GeoRadiusByMember executes the GeoRadiusByMember command
func (c *PrefixedCommands) GeoRadiusByMember(ctx context.Context, key string, member string, query *redis.GeoRadiusQuery) ([]redis.GeoLocation, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.GeoRadiusByMember(key, member, query)
	trackCommand(c.RunMetrics, "GeoRadiusByMember", cmd.Err(), startTime)
	return cmd.Result()
}

// GeoRadiusByMemberStore executes the GeoRadiusByMemberStore command
func (c *PrefixedCommands) GeoRadiusByMemberStore(ctx context.Context, key string, member string, query *redis.GeoRadiusQuery) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.GeoRadiusByMemberStore(key, member, query)
	trackCommand(c.RunMetrics, "GeoRadiusByMemberStore", cmd.Err(), startTime)
	return cmd.Result()
}

// GeoRadiusStore executes the GeoRadiusStore command
func (c *PrefixedCommands) GeoRadiusStore(ctx context.Context, key string, longitude float64, latitude float64, query *redis.GeoRadiusQuery) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.GeoRadiusStore(key, longitude, latitude, query)
	trackCommand(c.RunMetrics, "GeoRadiusStore", cmd.Err(), startTime)
	return cmd.Result()
}

// Get executes the Get command
func (c *PrefixedCommands) Get(ctx context.Context, key string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Get(key)
	trackCommand(c.RunMetrics, "Get", cmd.Err(), startTime)
	return cmd.Result()
}

// GetBit executes the GetBit command
func (c *PrefixedCommands) GetBit(ctx context.Context, key string, offset int64) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.GetBit(key, offset)
	trackCommand(c.RunMetrics, "GetBit", cmd.Err(), startTime)
	return cmd.Result()
}

// GetRange executes the GetRange command
func (c *PrefixedCommands) GetRange(ctx context.Context, key string, start int64, end int64) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.GetRange(key, start, end)
	trackCommand(c.RunMetrics, "GetRange", cmd.Err(), startTime)
	return cmd.Result()
}

// GetSet executes the GetSet command
func (c *PrefixedCommands) GetSet(ctx context.Context, key string, value interface{}) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.GetSet(key, value)
	trackCommand(c.RunMetrics, "GetSet", cmd.Err(), startTime)
	return cmd.Result()
}

// HDel executes the HDel command
func (c *PrefixedCommands) HDel(ctx context.Context, key string, fields ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.HDel(key, fields...)
	trackCommand(c.RunMetrics, "HDel", cmd.Err(), startTime)
	return cmd.Result()
}

// HExists executes the HExists command
func (c *PrefixedCommands) HExists(ctx context.Context, key string, field string) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.HExists(key, field)
	trackCommand(c.RunMetrics, "HExists", cmd.Err(), startTime)
	return cmd.Result()
}

// HGet executes the HGet command
func (c *PrefixedCommands) HGet(ctx context.Context, key string, field string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.HGet(key, field)
	trackCommand(c.RunMetrics, "HGet", cmd.Err(), startTime)
	return cmd.Result()
}

// HGetAll executes the HGetAll command
func (c *PrefixedCommands) HGetAll(ctx context.Context, key string) (map[string]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.HGetAll(key)
	trackCommand(c.RunMetrics, "HGetAll", cmd.Err(), startTime)
	return cmd.Result()
}

// HIncrBy executes the HIncrBy command
func (c *PrefixedCommands) HIncrBy(ctx context.Context, key string, field string, incr int64) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.HIncrBy(key, field, incr)
	trackCommand(c.RunMetrics, "HIncrBy", cmd.Err(), startTime)
	return cmd.Result()
}

// HIncrByFloat executes the HIncrByFloat command
func (c *PrefixedCommands) HIncrByFloat(ctx context.Context, key string, field string, incr float64) (float64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.HIncrByFloat(key, field, incr)
	trackCommand(c.RunMetrics, "HIncrByFloat", cmd.Err(), startTime)
	return cmd.Result()
}

// HKeys executes the HKeys command
func (c *PrefixedCommands) HKeys(ctx context.Context, key string) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.HKeys(key)
	trackCommand(c.RunMetrics, "HKeys", cmd.Err(), startTime)
	return cmd.Result()
}

// HLen executes the HLen command
func (c *PrefixedCommands) HLen(ctx context.Context, key string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.HLen(key)
	trackCommand(c.RunMetrics, "HLen", cmd.Err(), startTime)
	return cmd.Result()
}

// HMGet executes the HMGet command
func (c *PrefixedCommands) HMGet(ctx context.Context, key string, fields ...string) ([]interface{}, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.HMGet(key, fields...)
	trackCommand(c.RunMetrics, "HMGet", cmd.Err(), startTime)
	return cmd.Result()
}

// HMSet executes the HMSet command
func (c *PrefixedCommands) HMSet(ctx context.Context, key string, fields map[string]interface{}) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.HMSet(key, fields)
	trackCommand(c.RunMetrics, "HMSet", cmd.Err(), startTime)
	return cmd.Result()
}

// HScan executes the HScan command
func (c *PrefixedCommands) HScan(ctx context.Context, key string, cursor uint64, match string, count int64) ([]string, uint64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.HScan(key, cursor, match, count)
	trackCommand(c.RunMetrics, "HScan", cmd.Err(), startTime)
	return cmd.Result()
}

// HSet executes the HSet command
func (c *PrefixedCommands) HSet(ctx context.Context, key string, field string, value interface{}) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.HSet(key, field, value)
	trackCommand(c.RunMetrics, "HSet", cmd.Err(), startTime)
	return cmd.Result()
}

// HSetNX executes the HSetNX command
func (c *PrefixedCommands) HSetNX(ctx context.Context, key string, field string, value interface{}) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.HSetNX(key, field, value)
	trackCommand(c.RunMetrics, "HSetNX", cmd.Err(), startTime)
	return cmd.Result()
}

// HVals executes the HVals command
func (c *PrefixedCommands) HVals(ctx context.Context, key string) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.HVals(key)
	trackCommand(c.RunMetrics, "HVals", cmd.Err(), startTime)
	return cmd.Result()
}

// Incr executes the Incr command
func (c *PrefixedCommands) Incr(ctx context.Context, key string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Incr(key)
	trackCommand(c.RunMetrics, "Incr", cmd.Err(), startTime)
	return cmd.Result()
}

// IncrBy executes the IncrBy command
func (c *PrefixedCommands) IncrBy(ctx context.Context, key string, value int64) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.IncrBy(key, value)
	trackCommand(c.RunMetrics, "IncrBy", cmd.Err(), startTime)
	return cmd.Result()
}

// IncrByFloat executes the IncrByFloat command
func (c *PrefixedCommands) IncrByFloat(ctx context.Context, key string, value float64) (float64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.IncrByFloat(key, value)
	trackCommand(c.RunMetrics, "IncrByFloat", cmd.Err(), startTime)
	return cmd.Result()
}

// Info executes the Info command
func (c *PrefixedCommands) Info(ctx context.Context, section ...string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Info(section...)
	trackCommand(c.RunMetrics, "Info", cmd.Err(), startTime)
	return cmd.Result()
}

// Keys executes the Keys command
func (c *PrefixedCommands) Keys(ctx context.Context, pattern string) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Keys(pattern)
	trackCommand(c.RunMetrics, "Keys", cmd.Err(), startTime)
	return cmd.Result()
}

// LIndex executes the LIndex command
func (c *PrefixedCommands) LIndex(ctx context.Context, key string, index int64) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.LIndex(key, index)
	trackCommand(c.RunMetrics, "LIndex", cmd.Err(), startTime)
	return cmd.Result()
}

// LInsert executes the LInsert command
func (c *PrefixedCommands) LInsert(ctx context.Context, key string, op string, pivot interface{}, value interface{}) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.LInsert(key, op, pivot, value)
	trackCommand(c.RunMetrics, "LInsert", cmd.Err(), startTime)
	return cmd.Result()
}

// LInsertAfter executes the LInsertAfter command
func (c *PrefixedCommands) LInsertAfter(ctx context.Context, key string, pivot interface{}, value interface{}) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.LInsertAfter(key, pivot, value)
	trackCommand(c.RunMetrics, "LInsertAfter", cmd.Err(), startTime)
	return cmd.Result()
}

// LInsertBefore executes the LInsertBefore command
func (c *PrefixedCommands) LInsertBefore(ctx context.Context, key string, pivot interface{}, value interface{}) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.LInsertBefore(key, pivot, value)
	trackCommand(c.RunMetrics, "LInsertBefore", cmd.Err(), startTime)
	return cmd.Result()
}

// LLen executes the LLen command
func (c *PrefixedCommands) LLen(ctx context.Context, key string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.LLen(key)
	trackCommand(c.RunMetrics, "LLen", cmd.Err(), startTime)
	return cmd.Result()
}

// LPop executes the LPop command
func (c *PrefixedCommands) LPop(ctx context.Context, key string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.LPop(key)
	trackCommand(c.RunMetrics, "LPop", cmd.Err(), startTime)
	return cmd.Result()
}

// LPush executes the LPush command
func (c *PrefixedCommands) LPush(ctx context.Context, key string, values ...interface{}) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.LPush(key, values...)
	trackCommand(c.RunMetrics, "LPush", cmd.Err(), startTime)
	return cmd.Result()
}

// LPushX executes the LPushX command
func (c *PrefixedCommands) LPushX(ctx context.Context, key string, values ...interface{}) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.LPushX(key, values...)
	trackCommand(c.RunMetrics, "LPushX", cmd.Err(), startTime)
	return cmd.Result()
}

// LRange executes the LRange command
func (c *PrefixedCommands) LRange(ctx context.Context, key string, start int64, stop int64) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.LRange(key, start, stop)
	trackCommand(c.RunMetrics, "LRange", cmd.Err(), startTime)
	return cmd.Result()
}

// LRem executes the LRem command
func (c *PrefixedCommands) LRem(ctx context.Context, key string, count int64, value interface{}) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.LRem(key, count, value)
	trackCommand(c.RunMetrics, "LRem", cmd.Err(), startTime)
	return cmd.Result()
}

// LSet executes the LSet command
func (c *PrefixedCommands) LSet(ctx context.Context, key string, index int64, value interface{}) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.LSet(key, index, value)
	trackCommand(c.RunMetrics, "LSet", cmd.Err(), startTime)
	return cmd.Result()
}

// LTrim executes the LTrim command
func (c *PrefixedCommands) LTrim(ctx context.Context, key string, start int64, stop int64) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.LTrim(key, start, stop)
	trackCommand(c.RunMetrics, "LTrim", cmd.Err(), startTime)
	return cmd.Result()
}

// LastSave executes the LastSave command
func (c *PrefixedCommands) LastSave(ctx context.Context) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.LastSave()
	trackCommand(c.RunMetrics, "LastSave", cmd.Err(), startTime)
	return cmd.Result()
}

// MGet executes the MGet command
func (c *PrefixedCommands) MGet(ctx context.Context, keys ...string) ([]interface{}, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.MGet(keys...)
	trackCommand(c.RunMetrics, "MGet", cmd.Err(), startTime)
	return cmd.Result()
}

// MSet executes the MSet command
func (c *PrefixedCommands) MSet(ctx context.Context, pairs ...interface{}) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.MSet(pairs...)
	trackCommand(c.RunMetrics, "MSet", cmd.Err(), startTime)
	return cmd.Result()
}

// MSetNX executes the MSetNX command
func (c *PrefixedCommands) MSetNX(ctx context.Context, pairs ...interface{}) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.MSetNX(pairs...)
	trackCommand(c.RunMetrics, "MSetNX", cmd.Err(), startTime)
	return cmd.Result()
}

// MemoryUsage executes the MemoryUsage command
func (c *PrefixedCommands) MemoryUsage(ctx context.Context, key string, samples ...int) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.MemoryUsage(key, samples...)
	trackCommand(c.RunMetrics, "MemoryUsage", cmd.Err(), startTime)
	return cmd.Result()
}

// Migrate executes the Migrate command
func (c *PrefixedCommands) Migrate(ctx context.Context, host string, port string, key string, db int, timeout time.Duration) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Migrate(host, port, key, db, timeout)
	trackCommand(c.RunMetrics, "Migrate", cmd.Err(), startTime)
	return cmd.Result()
}

// Move executes the Move command
func (c *PrefixedCommands) Move(ctx context.Context, key string, db int) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Move(key, db)
	trackCommand(c.RunMetrics, "Move", cmd.Err(), startTime)
	return cmd.Result()
}

// ObjectEncoding executes the ObjectEncoding command
func (c *PrefixedCommands) ObjectEncoding(ctx context.Context, key string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ObjectEncoding(key)
	trackCommand(c.RunMetrics, "ObjectEncoding", cmd.Err(), startTime)
	return cmd.Result()
}

// ObjectIdleTime executes the ObjectIdleTime command
func (c *PrefixedCommands) ObjectIdleTime(ctx context.Context, key string) (time.Duration, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ObjectIdleTime(key)
	trackCommand(c.RunMetrics, "ObjectIdleTime", cmd.Err(), startTime)
	return cmd.Result()
}

// ObjectRefCount executes the ObjectRefCount command
func (c *PrefixedCommands) ObjectRefCount(ctx context.Context, key string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ObjectRefCount(key)
	trackCommand(c.RunMetrics, "ObjectRefCount", cmd.Err(), startTime)
	return cmd.Result()
}

// PExpire executes the PExpire command
func (c *PrefixedCommands) PExpire(ctx context.Context, key string, expiration time.Duration) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.PExpire(key, expiration)
	trackCommand(c.RunMetrics, "PExpire", cmd.Err(), startTime)
	return cmd.Result()
}

// PExpireAt executes the PExpireAt command
func (c *PrefixedCommands) PExpireAt(ctx context.Context, key string, tm time.Time) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.PExpireAt(key, tm)
	trackCommand(c.RunMetrics, "PExpireAt", cmd.Err(), startTime)
	return cmd.Result()
}

// PFAdd executes the PFAdd command
func (c *PrefixedCommands) PFAdd(ctx context.Context, key string, els ...interface{}) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.PFAdd(key, els...)
	trackCommand(c.RunMetrics, "PFAdd", cmd.Err(), startTime)
	return cmd.Result()
}

// PFCount executes the PFCount command
func (c *PrefixedCommands) PFCount(ctx context.Context, keys ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.PFCount(keys...)
	trackCommand(c.RunMetrics, "PFCount", cmd.Err(), startTime)
	return cmd.Result()
}

// PFMerge executes the PFMerge command
func (c *PrefixedCommands) PFMerge(ctx context.Context, dest string, keys ...string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.PFMerge(dest, keys...)
	trackCommand(c.RunMetrics, "PFMerge", cmd.Err(), startTime)
	return cmd.Result()
}

// PTTL executes the PTTL command
func (c *PrefixedCommands) PTTL(ctx context.Context, key string) (time.Duration, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.PTTL(key)
	trackCommand(c.RunMetrics, "PTTL", cmd.Err(), startTime)
	return cmd.Result()
}

// Persist executes the Persist command
func (c *PrefixedCommands) Persist(ctx context.Context, key string) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Persist(key)
	trackCommand(c.RunMetrics, "Persist", cmd.Err(), startTime)
	return cmd.Result()
}

// Ping executes the Ping command
func (c *PrefixedCommands) Ping(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Ping()
	trackCommand(c.RunMetrics, "Ping", cmd.Err(), startTime)
	return cmd.Result()
}

// PubSubChannels executes the PubSubChannels command
func (c *PrefixedCommands) PubSubChannels(ctx context.Context, pattern string) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.PubSubChannels(pattern)
	trackCommand(c.RunMetrics, "PubSubChannels", cmd.Err(), startTime)
	return cmd.Result()
}

// PubSubNumPat executes the PubSubNumPat command
func (c *PrefixedCommands) PubSubNumPat(ctx context.Context) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.PubSubNumPat()
	trackCommand(c.RunMetrics, "PubSubNumPat", cmd.Err(), startTime)
	return cmd.Result()
}

// PubSubNumSub executes the PubSubNumSub command
func (c *PrefixedCommands) PubSubNumSub(ctx context.Context, channels ...string) (map[string]int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.PubSubNumSub(channels...)
	trackCommand(c.RunMetrics, "PubSubNumSub", cmd.Err(), startTime)
	return cmd.Result()
}

// Publish executes the Publish command
func (c *PrefixedCommands) Publish(ctx context.Context, channel string, message interface{}) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Publish(channel, message)
	trackCommand(c.RunMetrics, "Publish", cmd.Err(), startTime)
	return cmd.Result()
}

// Quit executes the Quit command
func (c *PrefixedCommands) Quit(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Quit()
	trackCommand(c.RunMetrics, "Quit", cmd.Err(), startTime)
	return cmd.Result()
}

// RPop executes the RPop command
func (c *PrefixedCommands) RPop(ctx context.Context, key string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.RPop(key)
	trackCommand(c.RunMetrics, "RPop", cmd.Err(), startTime)
	return cmd.Result()
}

// RPopLPush executes the RPopLPush command
func (c *PrefixedCommands) RPopLPush(ctx context.Context, source string, destination string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.RPopLPush(source, destination)
	trackCommand(c.RunMetrics, "RPopLPush", cmd.Err(), startTime)
	return cmd.Result()
}

// RPush executes the RPush command
func (c *PrefixedCommands) RPush(ctx context.Context, key string, values ...interface{}) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.RPush(key, values...)
	trackCommand(c.RunMetrics, "RPush", cmd.Err(), startTime)
	return cmd.Result()
}

// RPushX executes the RPushX command
func (c *PrefixedCommands) RPushX(ctx context.Context, key string, values ...interface{}) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.RPushX(key, values...)
	trackCommand(c.RunMetrics, "RPushX", cmd.Err(), startTime)
	return cmd.Result()
}

// RandomKey executes the RandomKey command
func (c *PrefixedCommands) RandomKey(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.RandomKey()
	trackCommand(c.RunMetrics, "RandomKey", cmd.Err(), startTime)
	return cmd.Result()
}

// ReadOnly executes the ReadOnly command
func (c *PrefixedCommands) ReadOnly(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ReadOnly()
	trackCommand(c.RunMetrics, "ReadOnly", cmd.Err(), startTime)
	return cmd.Result()
}

// ReadWrite executes the ReadWrite command
func (c *PrefixedCommands) ReadWrite(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ReadWrite()
	trackCommand(c.RunMetrics, "ReadWrite", cmd.Err(), startTime)
	return cmd.Result()
}

// Rename executes the Rename command
func (c *PrefixedCommands) Rename(ctx context.Context, key string, newkey string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Rename(key, newkey)
	trackCommand(c.RunMetrics, "Rename", cmd.Err(), startTime)
	return cmd.Result()
}

// RenameNX executes the RenameNX command
func (c *PrefixedCommands) RenameNX(ctx context.Context, key string, newkey string) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.RenameNX(key, newkey)
	trackCommand(c.RunMetrics, "RenameNX", cmd.Err(), startTime)
	return cmd.Result()
}

// Restore executes the Restore command
func (c *PrefixedCommands) Restore(ctx context.Context, key string, ttl time.Duration, value string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Restore(key, ttl, value)
	trackCommand(c.RunMetrics, "Restore", cmd.Err(), startTime)
	return cmd.Result()
}

// RestoreReplace executes the RestoreReplace command
func (c *PrefixedCommands) RestoreReplace(ctx context.Context, key string, ttl time.Duration, value string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.RestoreReplace(key, ttl, value)
	trackCommand(c.RunMetrics, "RestoreReplace", cmd.Err(), startTime)
	return cmd.Result()
}

// SAdd executes the SAdd command
func (c *PrefixedCommands) SAdd(ctx context.Context, key string, members ...interface{}) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SAdd(key, members...)
	trackCommand(c.RunMetrics, "SAdd", cmd.Err(), startTime)
	return cmd.Result()
}

// SCard executes the SCard command
func (c *PrefixedCommands) SCard(ctx context.Context, key string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SCard(key)
	trackCommand(c.RunMetrics, "SCard", cmd.Err(), startTime)
	return cmd.Result()
}

// SDiff executes the SDiff command
func (c *PrefixedCommands) SDiff(ctx context.Context, keys ...string) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SDiff(keys...)
	trackCommand(c.RunMetrics, "SDiff", cmd.Err(), startTime)
	return cmd.Result()
}

// SDiffStore executes the SDiffStore command
func (c *PrefixedCommands) SDiffStore(ctx context.Context, destination string, keys ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SDiffStore(destination, keys...)
	trackCommand(c.RunMetrics, "SDiffStore", cmd.Err(), startTime)
	return cmd.Result()
}

// SInter executes the SInter command
func (c *PrefixedCommands) SInter(ctx context.Context, keys ...string) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SInter(keys...)
	trackCommand(c.RunMetrics, "SInter", cmd.Err(), startTime)
	return cmd.Result()
}

// SInterStore executes the SInterStore command
func (c *PrefixedCommands) SInterStore(ctx context.Context, destination string, keys ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SInterStore(destination, keys...)
	trackCommand(c.RunMetrics, "SInterStore", cmd.Err(), startTime)
	return cmd.Result()
}

// SIsMember executes the SIsMember command
func (c *PrefixedCommands) SIsMember(ctx context.Context, key string, member interface{}) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SIsMember(key, member)
	trackCommand(c.RunMetrics, "SIsMember", cmd.Err(), startTime)
	return cmd.Result()
}

// SMembers executes the SMembers command
func (c *PrefixedCommands) SMembers(ctx context.Context, key string) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SMembers(key)
	trackCommand(c.RunMetrics, "SMembers", cmd.Err(), startTime)
	return cmd.Result()
}

// SMembersMap executes the SMembersMap command
func (c *PrefixedCommands) SMembersMap(ctx context.Context, key string) (map[string]struct{}, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SMembersMap(key)
	trackCommand(c.RunMetrics, "SMembersMap", cmd.Err(), startTime)
	return cmd.Result()
}

// SMove executes the SMove command
func (c *PrefixedCommands) SMove(ctx context.Context, source string, destination string, member interface{}) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SMove(source, destination, member)
	trackCommand(c.RunMetrics, "SMove", cmd.Err(), startTime)
	return cmd.Result()
}

// SPop executes the SPop command
func (c *PrefixedCommands) SPop(ctx context.Context, key string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SPop(key)
	trackCommand(c.RunMetrics, "SPop", cmd.Err(), startTime)
	return cmd.Result()
}

// SPopN executes the SPopN command
func (c *PrefixedCommands) SPopN(ctx context.Context, key string, count int64) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SPopN(key, count)
	trackCommand(c.RunMetrics, "SPopN", cmd.Err(), startTime)
	return cmd.Result()
}

// SRandMember executes the SRandMember command
func (c *PrefixedCommands) SRandMember(ctx context.Context, key string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SRandMember(key)
	trackCommand(c.RunMetrics, "SRandMember", cmd.Err(), startTime)
	return cmd.Result()
}

// SRandMemberN executes the SRandMemberN command
func (c *PrefixedCommands) SRandMemberN(ctx context.Context, key string, count int64) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SRandMemberN(key, count)
	trackCommand(c.RunMetrics, "SRandMemberN", cmd.Err(), startTime)
	return cmd.Result()
}

// SRem executes the SRem command
func (c *PrefixedCommands) SRem(ctx context.Context, key string, members ...interface{}) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SRem(key, members...)
	trackCommand(c.RunMetrics, "SRem", cmd.Err(), startTime)
	return cmd.Result()
}

// SScan executes the SScan command
func (c *PrefixedCommands) SScan(ctx context.Context, key string, cursor uint64, match string, count int64) ([]string, uint64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SScan(key, cursor, match, count)
	trackCommand(c.RunMetrics, "SScan", cmd.Err(), startTime)
	return cmd.Result()
}

// SUnion executes the SUnion command
func (c *PrefixedCommands) SUnion(ctx context.Context, keys ...string) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SUnion(keys...)
	trackCommand(c.RunMetrics, "SUnion", cmd.Err(), startTime)
	return cmd.Result()
}

// SUnionStore executes the SUnionStore command
func (c *PrefixedCommands) SUnionStore(ctx context.Context, destination string, keys ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SUnionStore(destination, keys...)
	trackCommand(c.RunMetrics, "SUnionStore", cmd.Err(), startTime)
	return cmd.Result()
}

// Save executes the Save command
func (c *PrefixedCommands) Save(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Save()
	trackCommand(c.RunMetrics, "Save", cmd.Err(), startTime)
	return cmd.Result()
}

// Scan executes the Scan command
func (c *PrefixedCommands) Scan(ctx context.Context, cursor uint64, match string, count int64) ([]string, uint64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Scan(cursor, match, count)
	trackCommand(c.RunMetrics, "Scan", cmd.Err(), startTime)
	return cmd.Result()
}

// ScriptExists executes the ScriptExists command
func (c *PrefixedCommands) ScriptExists(ctx context.Context, hashes ...string) ([]bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ScriptExists(hashes...)
	trackCommand(c.RunMetrics, "ScriptExists", cmd.Err(), startTime)
	return cmd.Result()
}

// ScriptFlush executes the ScriptFlush command
func (c *PrefixedCommands) ScriptFlush(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ScriptFlush()
	trackCommand(c.RunMetrics, "ScriptFlush", cmd.Err(), startTime)
	return cmd.Result()
}

// ScriptKill executes the ScriptKill command
func (c *PrefixedCommands) ScriptKill(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ScriptKill()
	trackCommand(c.RunMetrics, "ScriptKill", cmd.Err(), startTime)
	return cmd.Result()
}

// ScriptLoad executes the ScriptLoad command
func (c *PrefixedCommands) ScriptLoad(ctx context.Context, script string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ScriptLoad(script)
	trackCommand(c.RunMetrics, "ScriptLoad", cmd.Err(), startTime)
	return cmd.Result()
}

// Set executes the Set command
func (c *PrefixedCommands) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Set(key, value, expiration)
	trackCommand(c.RunMetrics, "Set", cmd.Err(), startTime)
	return cmd.Result()
}

// SetBit executes the SetBit command
func (c *PrefixedCommands) SetBit(ctx context.Context, key string, offset int64, value int) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SetBit(key, offset, value)
	trackCommand(c.RunMetrics, "SetBit", cmd.Err(), startTime)
	return cmd.Result()
}

// SetNX executes the SetNX command
func (c *PrefixedCommands) SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SetNX(key, value, expiration)
	trackCommand(c.RunMetrics, "SetNX", cmd.Err(), startTime)
	return cmd.Result()
}

// SetRange executes the SetRange command
func (c *PrefixedCommands) SetRange(ctx context.Context, key string, offset int64, value string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SetRange(key, offset, value)
	trackCommand(c.RunMetrics, "SetRange", cmd.Err(), startTime)
	return cmd.Result()
}

// SetXX executes the SetXX command
func (c *PrefixedCommands) SetXX(ctx context.Context, key string, value interface{}, expiration time.Duration) (bool, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SetXX(key, value, expiration)
	trackCommand(c.RunMetrics, "SetXX", cmd.Err(), startTime)
	return cmd.Result()
}

// Shutdown executes the Shutdown command
func (c *PrefixedCommands) Shutdown(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Shutdown()
	trackCommand(c.RunMetrics, "Shutdown", cmd.Err(), startTime)
	return cmd.Result()
}

// ShutdownNoSave executes the ShutdownNoSave command
func (c *PrefixedCommands) ShutdownNoSave(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ShutdownNoSave()
	trackCommand(c.RunMetrics, "ShutdownNoSave", cmd.Err(), startTime)
	return cmd.Result()
}

// ShutdownSave executes the ShutdownSave command
func (c *PrefixedCommands) ShutdownSave(ctx context.Context) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ShutdownSave()
	trackCommand(c.RunMetrics, "ShutdownSave", cmd.Err(), startTime)
	return cmd.Result()
}

// SlaveOf executes the SlaveOf command
func (c *PrefixedCommands) SlaveOf(ctx context.Context, host string, port string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SlaveOf(host, port)
	trackCommand(c.RunMetrics, "SlaveOf", cmd.Err(), startTime)
	return cmd.Result()
}

// Sort executes the Sort command
func (c *PrefixedCommands) Sort(ctx context.Context, key string, sort *redis.Sort) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Sort(key, sort)
	trackCommand(c.RunMetrics, "Sort", cmd.Err(), startTime)
	return cmd.Result()
}

// SortInterfaces executes the SortInterfaces command
func (c *PrefixedCommands) SortInterfaces(ctx context.Context, key string, sort *redis.Sort) ([]interface{}, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SortInterfaces(key, sort)
	trackCommand(c.RunMetrics, "SortInterfaces", cmd.Err(), startTime)
	return cmd.Result()
}

// SortStore executes the SortStore command
func (c *PrefixedCommands) SortStore(ctx context.Context, key string, store string, sort *redis.Sort) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.SortStore(key, store, sort)
	trackCommand(c.RunMetrics, "SortStore", cmd.Err(), startTime)
	return cmd.Result()
}

// StrLen executes the StrLen command
func (c *PrefixedCommands) StrLen(ctx context.Context, key string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.StrLen(key)
	trackCommand(c.RunMetrics, "StrLen", cmd.Err(), startTime)
	return cmd.Result()
}

// TTL executes the TTL command
func (c *PrefixedCommands) TTL(ctx context.Context, key string) (time.Duration, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.TTL(key)
	trackCommand(c.RunMetrics, "TTL", cmd.Err(), startTime)
	return cmd.Result()
}

// Time executes the Time command
func (c *PrefixedCommands) Time(ctx context.Context) (time.Time, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Time()
	trackCommand(c.RunMetrics, "Time", cmd.Err(), startTime)
	return cmd.Result()
}

// Touch executes the Touch command
func (c *PrefixedCommands) Touch(ctx context.Context, keys ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Touch(keys...)
	trackCommand(c.RunMetrics, "Touch", cmd.Err(), startTime)
	return cmd.Result()
}

// Type executes the Type command
func (c *PrefixedCommands) Type(ctx context.Context, key string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Type(key)
	trackCommand(c.RunMetrics, "Type", cmd.Err(), startTime)
	return cmd.Result()
}

// Unlink executes the Unlink command
func (c *PrefixedCommands) Unlink(ctx context.Context, keys ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.Unlink(keys...)
	trackCommand(c.RunMetrics, "Unlink", cmd.Err(), startTime)
	return cmd.Result()
}

// XAck executes the XAck command
func (c *PrefixedCommands) XAck(ctx context.Context, stream string, group string, ids ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XAck(stream, group, ids...)
	trackCommand(c.RunMetrics, "XAck", cmd.Err(), startTime)
	return cmd.Result()
}

// XAdd executes the XAdd command
func (c *PrefixedCommands) XAdd(ctx context.Context, a *redis.XAddArgs) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XAdd(a)
	trackCommand(c.RunMetrics, "XAdd", cmd.Err(), startTime)
	return cmd.Result()
}

// XClaim executes the XClaim command
func (c *PrefixedCommands) XClaim(ctx context.Context, a *redis.XClaimArgs) ([]redis.XMessage, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XClaim(a)
	trackCommand(c.RunMetrics, "XClaim", cmd.Err(), startTime)
	return cmd.Result()
}

// XClaimJustID executes the XClaimJustID command
func (c *PrefixedCommands) XClaimJustID(ctx context.Context, a *redis.XClaimArgs) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XClaimJustID(a)
	trackCommand(c.RunMetrics, "XClaimJustID", cmd.Err(), startTime)
	return cmd.Result()
}

// XDel executes the XDel command
func (c *PrefixedCommands) XDel(ctx context.Context, stream string, ids ...string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XDel(stream, ids...)
	trackCommand(c.RunMetrics, "XDel", cmd.Err(), startTime)
	return cmd.Result()
}

// XGroupCreate executes the XGroupCreate command
func (c *PrefixedCommands) XGroupCreate(ctx context.Context, stream string, group string, start string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XGroupCreate(stream, group, start)
	trackCommand(c.RunMetrics, "XGroupCreate", cmd.Err(), startTime)
	return cmd.Result()
}

// XGroupCreateMkStream executes the XGroupCreateMkStream command
func (c *PrefixedCommands) XGroupCreateMkStream(ctx context.Context, stream string, group string, start string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XGroupCreateMkStream(stream, group, start)
	trackCommand(c.RunMetrics, "XGroupCreateMkStream", cmd.Err(), startTime)
	return cmd.Result()
}

// XGroupDelConsumer executes the XGroupDelConsumer command
func (c *PrefixedCommands) XGroupDelConsumer(ctx context.Context, stream string, group string, consumer string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XGroupDelConsumer(stream, group, consumer)
	trackCommand(c.RunMetrics, "XGroupDelConsumer", cmd.Err(), startTime)
	return cmd.Result()
}

// XGroupDestroy executes the XGroupDestroy command
func (c *PrefixedCommands) XGroupDestroy(ctx context.Context, stream string, group string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XGroupDestroy(stream, group)
	trackCommand(c.RunMetrics, "XGroupDestroy", cmd.Err(), startTime)
	return cmd.Result()
}

// XGroupSetID executes the XGroupSetID command
func (c *PrefixedCommands) XGroupSetID(ctx context.Context, stream string, group string, start string) (string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XGroupSetID(stream, group, start)
	trackCommand(c.RunMetrics, "XGroupSetID", cmd.Err(), startTime)
	return cmd.Result()
}

// XLen executes the XLen command
func (c *PrefixedCommands) XLen(ctx context.Context, stream string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XLen(stream)
	trackCommand(c.RunMetrics, "XLen", cmd.Err(), startTime)
	return cmd.Result()
}

// XPending executes the XPending command
func (c *PrefixedCommands) XPending(ctx context.Context, stream string, group string) (*redis.XPending, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XPending(stream, group)
	trackCommand(c.RunMetrics, "XPending", cmd.Err(), startTime)
	return cmd.Result()
}

// XPendingExt executes the XPendingExt command
func (c *PrefixedCommands) XPendingExt(ctx context.Context, a *redis.XPendingExtArgs) ([]redis.XPendingExt, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XPendingExt(a)
	trackCommand(c.RunMetrics, "XPendingExt", cmd.Err(), startTime)
	return cmd.Result()
}

// XRange executes the XRange command
func (c *PrefixedCommands) XRange(ctx context.Context, stream string, start string, stop string) ([]redis.XMessage, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XRange(stream, start, stop)
	trackCommand(c.RunMetrics, "XRange", cmd.Err(), startTime)
	return cmd.Result()
}

// XRangeN executes the XRangeN command
func (c *PrefixedCommands) XRangeN(ctx context.Context, stream string, start string, stop string, count int64) ([]redis.XMessage, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XRangeN(stream, start, stop, count)
	trackCommand(c.RunMetrics, "XRangeN", cmd.Err(), startTime)
	return cmd.Result()
}

// XRead executes the XRead command
func (c *PrefixedCommands) XRead(ctx context.Context, a *redis.XReadArgs) ([]redis.XStream, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XRead(a)
	trackCommand(c.RunMetrics, "XRead", cmd.Err(), startTime)
	return cmd.Result()
}

// XReadGroup executes the XReadGroup command
func (c *PrefixedCommands) XReadGroup(ctx context.Context, a *redis.XReadGroupArgs) ([]redis.XStream, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XReadGroup(a)
	trackCommand(c.RunMetrics, "XReadGroup", cmd.Err(), startTime)
	return cmd.Result()
}

// XReadStreams executes the XReadStreams command
func (c *PrefixedCommands) XReadStreams(ctx context.Context, streams ...string) ([]redis.XStream, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XReadStreams(streams...)
	trackCommand(c.RunMetrics, "XReadStreams", cmd.Err(), startTime)
	return cmd.Result()
}

// XRevRange executes the XRevRange command
func (c *PrefixedCommands) XRevRange(ctx context.Context, stream string, start string, stop string) ([]redis.XMessage, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XRevRange(stream, start, stop)
	trackCommand(c.RunMetrics, "XRevRange", cmd.Err(), startTime)
	return cmd.Result()
}

// XRevRangeN executes the XRevRangeN command
func (c *PrefixedCommands) XRevRangeN(ctx context.Context, stream string, start string, stop string, count int64) ([]redis.XMessage, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XRevRangeN(stream, start, stop, count)
	trackCommand(c.RunMetrics, "XRevRangeN", cmd.Err(), startTime)
	return cmd.Result()
}

// XTrim executes the XTrim command
func (c *PrefixedCommands) XTrim(ctx context.Context, key string, maxLen int64) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XTrim(key, maxLen)
	trackCommand(c.RunMetrics, "XTrim", cmd.Err(), startTime)
	return cmd.Result()
}

// XTrimApprox executes the XTrimApprox command
func (c *PrefixedCommands) XTrimApprox(ctx context.Context, key string, maxLen int64) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.XTrimApprox(key, maxLen)
	trackCommand(c.RunMetrics, "XTrimApprox", cmd.Err(), startTime)
	return cmd.Result()
}

// ZAdd executes the ZAdd command
func (c *PrefixedCommands) ZAdd(ctx context.Context, key string, members ...*redis.Z) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZAdd(key, members...)
	trackCommand(c.RunMetrics, "ZAdd", cmd.Err(), startTime)
	return cmd.Result()
}

// ZAddCh executes the ZAddCh command
func (c *PrefixedCommands) ZAddCh(ctx context.Context, key string, members ...*redis.Z) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZAddCh(key, members...)
	trackCommand(c.RunMetrics, "ZAddCh", cmd.Err(), startTime)
	return cmd.Result()
}

// ZAddNX executes the ZAddNX command
func (c *PrefixedCommands) ZAddNX(ctx context.Context, key string, members ...*redis.Z) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZAddNX(key, members...)
	trackCommand(c.RunMetrics, "ZAddNX", cmd.Err(), startTime)
	return cmd.Result()
}

// ZAddNXCh executes the ZAddNXCh command
func (c *PrefixedCommands) ZAddNXCh(ctx context.Context, key string, members ...*redis.Z) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZAddNXCh(key, members...)
	trackCommand(c.RunMetrics, "ZAddNXCh", cmd.Err(), startTime)
	return cmd.Result()
}

// ZAddXX executes the ZAddXX command
func (c *PrefixedCommands) ZAddXX(ctx context.Context, key string, members ...*redis.Z) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZAddXX(key, members...)
	trackCommand(c.RunMetrics, "ZAddXX", cmd.Err(), startTime)
	return cmd.Result()
}

// ZAddXXCh executes the ZAddXXCh command
func (c *PrefixedCommands) ZAddXXCh(ctx context.Context, key string, members ...*redis.Z) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZAddXXCh(key, members...)
	trackCommand(c.RunMetrics, "ZAddXXCh", cmd.Err(), startTime)
	return cmd.Result()
}

// ZCard executes the ZCard command
func (c *PrefixedCommands) ZCard(ctx context.Context, key string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZCard(key)
	trackCommand(c.RunMetrics, "ZCard", cmd.Err(), startTime)
	return cmd.Result()
}

// ZCount executes the ZCount command
func (c *PrefixedCommands) ZCount(ctx context.Context, key string, min string, max string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZCount(key, min, max)
	trackCommand(c.RunMetrics, "ZCount", cmd.Err(), startTime)
	return cmd.Result()
}

// ZIncr executes the ZIncr command
func (c *PrefixedCommands) ZIncr(ctx context.Context, key string, member *redis.Z) (float64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZIncr(key, member)
	trackCommand(c.RunMetrics, "ZIncr", cmd.Err(), startTime)
	return cmd.Result()
}

// ZIncrBy executes the ZIncrBy command
func (c *PrefixedCommands) ZIncrBy(ctx context.Context, key string, increment float64, member string) (float64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZIncrBy(key, increment, member)
	trackCommand(c.RunMetrics, "ZIncrBy", cmd.Err(), startTime)
	return cmd.Result()
}

// ZIncrNX executes the ZIncrNX command
func (c *PrefixedCommands) ZIncrNX(ctx context.Context, key string, member *redis.Z) (float64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZIncrNX(key, member)
	trackCommand(c.RunMetrics, "ZIncrNX", cmd.Err(), startTime)
	return cmd.Result()
}

// ZIncrXX executes the ZIncrXX command
func (c *PrefixedCommands) ZIncrXX(ctx context.Context, key string, member *redis.Z) (float64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZIncrXX(key, member)
	trackCommand(c.RunMetrics, "ZIncrXX", cmd.Err(), startTime)
	return cmd.Result()
}

// ZInterStore executes the ZInterStore command
func (c *PrefixedCommands) ZInterStore(ctx context.Context, destination string, store *redis.ZStore) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZInterStore(destination, store)
	trackCommand(c.RunMetrics, "ZInterStore", cmd.Err(), startTime)
	return cmd.Result()
}

// ZLexCount executes the ZLexCount command
func (c *PrefixedCommands) ZLexCount(ctx context.Context, key string, min string, max string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZLexCount(key, min, max)
	trackCommand(c.RunMetrics, "ZLexCount", cmd.Err(), startTime)
	return cmd.Result()
}

// ZPopMax executes the ZPopMax command
func (c *PrefixedCommands) ZPopMax(ctx context.Context, key string, count ...int64) ([]redis.Z, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZPopMax(key, count...)
	trackCommand(c.RunMetrics, "ZPopMax", cmd.Err(), startTime)
	return cmd.Result()
}

// ZPopMin executes the ZPopMin command
func (c *PrefixedCommands) ZPopMin(ctx context.Context, key string, count ...int64) ([]redis.Z, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZPopMin(key, count...)
	trackCommand(c.RunMetrics, "ZPopMin", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRange executes the ZRange command
func (c *PrefixedCommands) ZRange(ctx context.Context, key string, start int64, stop int64) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRange(key, start, stop)
	trackCommand(c.RunMetrics, "ZRange", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRangeByLex executes the ZRangeByLex command
func (c *PrefixedCommands) ZRangeByLex(ctx context.Context, key string, opt *redis.ZRangeBy) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRangeByLex(key, opt)
	trackCommand(c.RunMetrics, "ZRangeByLex", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRangeByScore executes the ZRangeByScore command
func (c *PrefixedCommands) ZRangeByScore(ctx context.Context, key string, opt *redis.ZRangeBy) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRangeByScore(key, opt)
	trackCommand(c.RunMetrics, "ZRangeByScore", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRangeByScoreWithScores executes the ZRangeByScoreWithScores command
func (c *PrefixedCommands) ZRangeByScoreWithScores(ctx context.Context, key string, opt *redis.ZRangeBy) ([]redis.Z, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRangeByScoreWithScores(key, opt)
	trackCommand(c.RunMetrics, "ZRangeByScoreWithScores", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRangeWithScores executes the ZRangeWithScores command
func (c *PrefixedCommands) ZRangeWithScores(ctx context.Context, key string, start int64, stop int64) ([]redis.Z, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRangeWithScores(key, start, stop)
	trackCommand(c.RunMetrics, "ZRangeWithScores", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRank executes the ZRank command
func (c *PrefixedCommands) ZRank(ctx context.Context, key string, member string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRank(key, member)
	trackCommand(c.RunMetrics, "ZRank", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRem executes the ZRem command
func (c *PrefixedCommands) ZRem(ctx context.Context, key string, members ...interface{}) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRem(key, members...)
	trackCommand(c.RunMetrics, "ZRem", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRemRangeByLex executes the ZRemRangeByLex command
func (c *PrefixedCommands) ZRemRangeByLex(ctx context.Context, key string, min string, max string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRemRangeByLex(key, min, max)
	trackCommand(c.RunMetrics, "ZRemRangeByLex", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRemRangeByRank executes the ZRemRangeByRank command
func (c *PrefixedCommands) ZRemRangeByRank(ctx context.Context, key string, start int64, stop int64) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRemRangeByRank(key, start, stop)
	trackCommand(c.RunMetrics, "ZRemRangeByRank", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRemRangeByScore executes the ZRemRangeByScore command
func (c *PrefixedCommands) ZRemRangeByScore(ctx context.Context, key string, min string, max string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRemRangeByScore(key, min, max)
	trackCommand(c.RunMetrics, "ZRemRangeByScore", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRevRange executes the ZRevRange command
func (c *PrefixedCommands) ZRevRange(ctx context.Context, key string, start int64, stop int64) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRevRange(key, start, stop)
	trackCommand(c.RunMetrics, "ZRevRange", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRevRangeByLex executes the ZRevRangeByLex command
func (c *PrefixedCommands) ZRevRangeByLex(ctx context.Context, key string, opt *redis.ZRangeBy) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRevRangeByLex(key, opt)
	trackCommand(c.RunMetrics, "ZRevRangeByLex", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRevRangeByScore executes the ZRevRangeByScore command
func (c *PrefixedCommands) ZRevRangeByScore(ctx context.Context, key string, opt *redis.ZRangeBy) ([]string, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRevRangeByScore(key, opt)
	trackCommand(c.RunMetrics, "ZRevRangeByScore", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRevRangeByScoreWithScores executes the ZRevRangeByScoreWithScores command
func (c *PrefixedCommands) ZRevRangeByScoreWithScores(ctx context.Context, key string, opt *redis.ZRangeBy) ([]redis.Z, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRevRangeByScoreWithScores(key, opt)
	trackCommand(c.RunMetrics, "ZRevRangeByScoreWithScores", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRevRangeWithScores executes the ZRevRangeWithScores command
func (c *PrefixedCommands) ZRevRangeWithScores(ctx context.Context, key string, start int64, stop int64) ([]redis.Z, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRevRangeWithScores(key, start, stop)
	trackCommand(c.RunMetrics, "ZRevRangeWithScores", cmd.Err(), startTime)
	return cmd.Result()
}

// ZRevRank executes the ZRevRank command
func (c *PrefixedCommands) ZRevRank(ctx context.Context, key string, member string) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZRevRank(key, member)
	trackCommand(c.RunMetrics, "ZRevRank", cmd.Err(), startTime)
	return cmd.Result()
}

// ZScan executes the ZScan command
func (c *PrefixedCommands) ZScan(ctx context.Context, key string, cursor uint64, match string, count int64) ([]string, uint64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZScan(key, cursor, match, count)
	trackCommand(c.RunMetrics, "ZScan", cmd.Err(), startTime)
	return cmd.Result()
}

// ZScore executes the ZScore command
func (c *PrefixedCommands) ZScore(ctx context.Context, key string, member string) (float64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZScore(key, member)
	trackCommand(c.RunMetrics, "ZScore", cmd.Err(), startTime)
	return cmd.Result()
}

// ZUnionStore executes the ZUnionStore command
func (c *PrefixedCommands) ZUnionStore(ctx context.Context, dest string, store *redis.ZStore) (int64, error) {
	startTime := time.Now()
	ctxCmdable := cmdableWithContext(ctx, c.Redis)

	pfxCmdable := prefixerCmdable{
		cmdable:   ctxCmdable,
		keyPrefix: c.KeyPrefix,
	}

	cmd := pfxCmdable.ZUnionStore(dest, store)
	trackCommand(c.RunMetrics, "ZUnionStore", cmd.Err(), startTime)
	return cmd.Result()
}

var _ Commands = (*PrefixedCommands)(nil)
