fix: the database switch might lead to other operations becoming ineffective

This commit is contained in:
Lykin 2023-12-06 18:25:51 +08:00
parent b7c10b33e7
commit d59221f11e
4 changed files with 34 additions and 23 deletions

View File

@ -51,7 +51,7 @@ type connectionItem struct {
type browserService struct { type browserService struct {
ctx context.Context ctx context.Context
connMap map[string]connectionItem connMap map[string]*connectionItem
cmdHistory []cmdHistoryItem cmdHistory []cmdHistoryItem
} }
@ -62,7 +62,7 @@ func Browser() *browserService {
if browser == nil { if browser == nil {
onceBrowser.Do(func() { onceBrowser.Do(func() {
browser = &browserService{ browser = &browserService{
connMap: map[string]connectionItem{}, connMap: map[string]*connectionItem{},
} }
}) })
} }
@ -80,21 +80,20 @@ func (b *browserService) Stop() {
item.client.Close() item.client.Close()
} }
} }
b.connMap = map[string]connectionItem{} b.connMap = map[string]*connectionItem{}
} }
// OpenConnection open redis server connection // OpenConnection open redis server connection
func (b *browserService) OpenConnection(name string) (resp types.JSResp) { func (b *browserService) OpenConnection(name string) (resp types.JSResp) {
item, err := b.getRedisClient(name, 0) // get connection config
selConn := Connection().getConnection(name)
item, err := b.getRedisClient(name, selConn.LastDB)
if err != nil { if err != nil {
resp.Msg = err.Error() resp.Msg = err.Error()
return return
} }
client, ctx := item.client, item.ctx client, ctx := item.client, item.ctx
// get connection config
selConn := Connection().getConnection(name)
var totaldb int var totaldb int
if selConn.DBFilterType == "" || selConn.DBFilterType == "none" { if selConn.DBFilterType == "" || selConn.DBFilterType == "none" {
// get total databases // get total databases
@ -222,7 +221,7 @@ func (b *browserService) CloseConnection(name string) (resp types.JSResp) {
// get a redis client from local cache or create a new open // get a redis client from local cache or create a new open
// if db >= 0, will also switch to db index // if db >= 0, will also switch to db index
func (b *browserService) getRedisClient(connName string, db int) (item connectionItem, err error) { func (b *browserService) getRedisClient(connName string, db int) (item *connectionItem, err error) {
var ok bool var ok bool
var client redis.UniversalClient var client redis.UniversalClient
if item, ok = b.connMap[connName]; ok { if item, ok = b.connMap[connName]; ok {
@ -275,7 +274,7 @@ func (b *browserService) getRedisClient(connName string, db int) (item connectio
return return
} }
ctx, cancelFunc := context.WithCancel(b.ctx) ctx, cancelFunc := context.WithCancel(b.ctx)
item = connectionItem{ item = &connectionItem{
client: client, client: client,
ctx: ctx, ctx: ctx,
cancelFunc: cancelFunc, cancelFunc: cancelFunc,
@ -289,14 +288,19 @@ func (b *browserService) getRedisClient(connName string, db int) (item connectio
b.connMap[connName] = item b.connMap[connName] = item
} }
if db >= 0 && item.db != db { // BUG: go-redis might not be executing commands on the corresponding database
// requiring a database switch with each command
if db >= 0 /*&& item.db != db*/ {
var rdb *redis.Client var rdb *redis.Client
if rdb, ok = client.(*redis.Client); ok && rdb != nil { if rdb, ok = client.(*redis.Client); ok && rdb != nil {
if err = rdb.Do(item.ctx, "select", strconv.Itoa(db)).Err(); err != nil { _, err = rdb.Pipelined(item.ctx, func(pipe redis.Pipeliner) error {
return pipe.Select(item.ctx, db).Err()
})
if err != nil {
return return
} }
item.db = db item.db = db
b.connMap[connName] = item b.connMap[connName].db = db
} }
} }
return return
@ -358,7 +362,7 @@ func (b *browserService) parseDBItemInfo(info string) map[string]int {
// ServerInfo get server info // ServerInfo get server info
func (b *browserService) ServerInfo(name string) (resp types.JSResp) { func (b *browserService) ServerInfo(name string) (resp types.JSResp) {
item, err := b.getRedisClient(name, 0) item, err := b.getRedisClient(name, -1)
if err != nil { if err != nil {
resp.Msg = err.Error() resp.Msg = err.Error()
return return

View File

@ -154,8 +154,8 @@ const onDisconnect = () => {
const handleSelectDB = async (db) => { const handleSelectDB = async (db) => {
try { try {
loading.value = true loading.value = true
browserStore.closeDatabase(props.server, props.db)
browserStore.setKeyFilter(props.server, {}) browserStore.setKeyFilter(props.server, {})
browserStore.closeDatabase(props.server, props.db)
await browserStore.openDatabase(props.server, db) await browserStore.openDatabase(props.server, db)
await nextTick() await nextTick()
await connectionStore.saveLastDB(props.server, db) await connectionStore.saveLastDB(props.server, db)
@ -163,6 +163,7 @@ const handleSelectDB = async (db) => {
// browserTreeRef.value?.resetExpandKey(props.server, db) // browserTreeRef.value?.resetExpandKey(props.server, db)
fullyLoaded.value = await browserStore.loadMoreKeys(props.server, db) fullyLoaded.value = await browserStore.loadMoreKeys(props.server, db)
browserTreeRef.value?.refreshTree() browserTreeRef.value?.refreshTree()
tabStore.setSelectedKeys(props.server)
} catch (e) { } catch (e) {
$message.error(e.message) $message.error(e.message)
} finally { } finally {

View File

@ -379,7 +379,7 @@ const renderPrefix = ({ option }) => {
}, },
) )
} }
if (option.redisType == null || option.redisType === 'loading') { if (isEmpty(option.redisType) || option.redisType === 'loading') {
browserStore.loadKeyType({ browserStore.loadKeyType({
server: props.server, server: props.server,
db: option.db, db: option.db,

View File

@ -477,16 +477,22 @@ const useBrowserStore = defineStore('browser', {
* @return {Promise<void>} * @return {Promise<void>}
*/ */
async loadKeyType({ server, db, key, keyCode }) { async loadKeyType({ server, db, key, keyCode }) {
const nodeMap = this._getNodeMap(server, db)
const node = nodeMap.get(`${ConnectionType.RedisValue}/${key}`)
if (node == null || !isEmpty(node.redisType)) {
return
}
try { try {
const nodeMap = this._getNodeMap(server, db)
const node = nodeMap.get(`${ConnectionType.RedisValue}/${key}`)
if (node == null || node.redisType != null) {
return
}
node.redisType = 'loading' node.redisType = 'loading'
const { data } = await GetKeyType({ server, db, key: keyCode || key }) const { data, success } = await GetKeyType({ server, db, key: keyCode || key })
const { type } = data || {} if (success) {
node.redisType = type const { type } = data || {}
node.redisType = type
} else {
node.redisType = 'NONE'
}
} catch (e) {
node.redisType = 'NONE'
} finally { } finally {
} }
}, },