feat: multi-connection parallel support
- connection store: connectedIds array, per-connection health/serverInfo maps - connect() no longer disconnects existing connections - New switchTo(id), disconnectById(id), isConnectedById(id) methods - Per-connection health check timers (Map-based) - ConnectionCard: switch to connected, connect if not, disconnect if active - MainArea: per-connection tab state (save/restore on switch) - Connection switcher dropdown in tab bar showing all open connections - Clean up tab state when connection disconnects
This commit is contained in:
+58
-23
@@ -36,16 +36,23 @@ export interface ConnectionConfig {
|
||||
export const useConnectionStore = defineStore('connection', () => {
|
||||
const connections = ref<ConnectionConfig[]>([])
|
||||
const activeId = ref<string | null>(null)
|
||||
const connectedIds = ref<string[]>([])
|
||||
const connecting = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
const serverInfo = ref<string | null>(null)
|
||||
const healthOk = ref(true)
|
||||
let healthTimer: ReturnType<typeof setInterval> | null = null
|
||||
const serverInfoMap = ref<Record<string, string>>({})
|
||||
const healthMap = ref<Record<string, boolean>>({})
|
||||
const healthTimers = new Map<string, ReturnType<typeof setInterval>>()
|
||||
|
||||
const activeConnection = computed(() =>
|
||||
connections.value.find((c: ConnectionConfig) => c.id === activeId.value) ?? null
|
||||
)
|
||||
const isConnected = computed(() => activeId.value !== null)
|
||||
const isConnected = computed(() => activeId.value !== null && connectedIds.value.includes(activeId.value))
|
||||
const serverInfo = computed(() => activeId.value ? serverInfoMap.value[activeId.value] ?? null : null)
|
||||
const healthOk = computed(() => activeId.value ? healthMap.value[activeId.value] ?? false : false)
|
||||
|
||||
function isConnectedById(id: string): boolean {
|
||||
return connectedIds.value.includes(id)
|
||||
}
|
||||
|
||||
async function loadConnections() {
|
||||
connections.value = await window.electronAPI.storage.getConnections()
|
||||
@@ -66,7 +73,7 @@ export const useConnectionStore = defineStore('connection', () => {
|
||||
}
|
||||
|
||||
async function deleteConnection(id: string) {
|
||||
if (activeId.value === id) await disconnect()
|
||||
if (connectedIds.value.includes(id)) await disconnectById(id)
|
||||
connections.value = await window.electronAPI.storage.deleteConnection(id)
|
||||
}
|
||||
|
||||
@@ -75,6 +82,11 @@ export const useConnectionStore = defineStore('connection', () => {
|
||||
}
|
||||
|
||||
async function connect(conn: ConnectionConfig) {
|
||||
// If already connected, just switch
|
||||
if (connectedIds.value.includes(conn.id)) {
|
||||
activeId.value = conn.id
|
||||
return
|
||||
}
|
||||
connecting.value = true
|
||||
error.value = null
|
||||
try {
|
||||
@@ -107,8 +119,9 @@ export const useConnectionStore = defineStore('connection', () => {
|
||||
sshPassphrase: conn.sshPassphrase,
|
||||
})
|
||||
if (result.success) {
|
||||
connectedIds.value.push(conn.id)
|
||||
activeId.value = conn.id
|
||||
serverInfo.value = await window.electronAPI.redis.getInfo(conn.id)
|
||||
serverInfoMap.value[conn.id] = await window.electronAPI.redis.getInfo(conn.id)
|
||||
startHealthCheck(conn.id)
|
||||
} else {
|
||||
error.value = result.error || 'Connection failed'
|
||||
@@ -120,12 +133,26 @@ export const useConnectionStore = defineStore('connection', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function switchTo(id: string) {
|
||||
if (connectedIds.value.includes(id)) {
|
||||
activeId.value = id
|
||||
}
|
||||
}
|
||||
|
||||
async function disconnectById(id: string) {
|
||||
stopHealthCheck(id)
|
||||
await window.electronAPI.redis.disconnect(id)
|
||||
connectedIds.value = connectedIds.value.filter(i => i !== id)
|
||||
delete serverInfoMap.value[id]
|
||||
delete healthMap.value[id]
|
||||
if (activeId.value === id) {
|
||||
activeId.value = connectedIds.value[0] ?? null
|
||||
}
|
||||
}
|
||||
|
||||
async function disconnect() {
|
||||
stopHealthCheck()
|
||||
if (activeId.value) {
|
||||
await window.electronAPI.redis.disconnect(activeId.value)
|
||||
activeId.value = null
|
||||
serverInfo.value = null
|
||||
await disconnectById(activeId.value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +160,7 @@ export const useConnectionStore = defineStore('connection', () => {
|
||||
if (!activeId.value) return ''
|
||||
try {
|
||||
const info = await window.electronAPI.redis.getInfo(activeId.value)
|
||||
serverInfo.value = info
|
||||
serverInfoMap.value[activeId.value] = info
|
||||
return info
|
||||
} catch {
|
||||
return ''
|
||||
@@ -141,26 +168,34 @@ export const useConnectionStore = defineStore('connection', () => {
|
||||
}
|
||||
|
||||
function startHealthCheck(connId: string) {
|
||||
stopHealthCheck()
|
||||
healthOk.value = true
|
||||
healthTimer = setInterval(async () => {
|
||||
stopHealthCheck(connId)
|
||||
healthMap.value[connId] = true
|
||||
const timer = setInterval(async () => {
|
||||
try {
|
||||
const ok = await window.electronAPI.redis.isConnected(connId)
|
||||
healthOk.value = ok
|
||||
healthMap.value[connId] = ok
|
||||
if (!ok && activeId.value === connId) {
|
||||
// Connection lost
|
||||
error.value = 'Connection lost'
|
||||
}
|
||||
} catch {
|
||||
healthOk.value = false
|
||||
healthMap.value[connId] = false
|
||||
}
|
||||
}, 5000)
|
||||
healthTimers.set(connId, timer)
|
||||
}
|
||||
|
||||
function stopHealthCheck() {
|
||||
if (healthTimer) {
|
||||
clearInterval(healthTimer)
|
||||
healthTimer = null
|
||||
function stopHealthCheck(connId?: string) {
|
||||
if (connId) {
|
||||
const timer = healthTimers.get(connId)
|
||||
if (timer) {
|
||||
clearInterval(timer)
|
||||
healthTimers.delete(connId)
|
||||
}
|
||||
} else {
|
||||
for (const [, timer] of healthTimers) {
|
||||
clearInterval(timer)
|
||||
}
|
||||
healthTimers.clear()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,9 +273,9 @@ export const useConnectionStore = defineStore('connection', () => {
|
||||
}
|
||||
|
||||
return {
|
||||
connections, activeId, connecting, error, serverInfo, healthOk,
|
||||
connections, activeId, connectedIds, connecting, error, serverInfo, healthOk,
|
||||
activeConnection, isConnected,
|
||||
loadConnections, decryptPassword, getInfo, saveConnection, deleteConnection, reorderConnections,
|
||||
connect, disconnect, testConnection, exportConnections, importConnections,
|
||||
connect, disconnect, disconnectById, switchTo, isConnectedById, testConnection, exportConnections, importConnections,
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user