mirror of
https://github.com/hibiken/asynq.git
synced 2025-09-19 13:21:58 +08:00
(cli): Add event handler for left/right arrows
This commit is contained in:
@@ -31,7 +31,8 @@ type State struct {
|
|||||||
redisInfo redisInfo
|
redisInfo redisInfo
|
||||||
err error
|
err error
|
||||||
|
|
||||||
rowIdx int // highlighted row
|
rowIdx int // highlighted row
|
||||||
|
taskState asynq.TaskState // highlighted task state in queue details view
|
||||||
|
|
||||||
selectedQueue *asynq.QueueInfo // queue shown on queue details view
|
selectedQueue *asynq.QueueInfo // queue shown on queue details view
|
||||||
|
|
||||||
@@ -140,6 +141,7 @@ func Run(opts Options) {
|
|||||||
if state.view == viewTypeQueues && state.rowIdx != 0 {
|
if state.view == viewTypeQueues && state.rowIdx != 0 {
|
||||||
state.selectedQueue = state.queues[state.rowIdx-1]
|
state.selectedQueue = state.queues[state.rowIdx-1]
|
||||||
state.view = viewTypeQueueDetails
|
state.view = viewTypeQueueDetails
|
||||||
|
state.taskState = asynq.TaskStateActive
|
||||||
drawDash(s, baseStyle, &state, opts)
|
drawDash(s, baseStyle, &state, opts)
|
||||||
}
|
}
|
||||||
} else if ev.Rune() == '?' {
|
} else if ev.Rune() == '?' {
|
||||||
@@ -164,6 +166,12 @@ func Run(opts Options) {
|
|||||||
ticker.Reset(interval)
|
ticker.Reset(interval)
|
||||||
state.view = viewTypeRedis
|
state.view = viewTypeRedis
|
||||||
drawDash(s, baseStyle, &state, opts)
|
drawDash(s, baseStyle, &state, opts)
|
||||||
|
} else if (ev.Key() == tcell.KeyRight || ev.Rune() == 'l') && state.view == viewTypeQueueDetails {
|
||||||
|
state.taskState = nextTaskState(state.taskState)
|
||||||
|
drawDash(s, baseStyle, &state, opts)
|
||||||
|
} else if (ev.Key() == tcell.KeyLeft || ev.Rune() == 'h') && state.view == viewTypeQueueDetails {
|
||||||
|
state.taskState = prevTaskState(state.taskState)
|
||||||
|
drawDash(s, baseStyle, &state, opts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,37 +22,40 @@ func drawDash(s tcell.Screen, style tcell.Style, state *State, opts Options) {
|
|||||||
switch state.view {
|
switch state.view {
|
||||||
case viewTypeQueues:
|
case viewTypeQueues:
|
||||||
d.Println("=== Queues ===", style.Bold(true))
|
d.Println("=== Queues ===", style.Bold(true))
|
||||||
d.NL() // empty line
|
d.NL()
|
||||||
drawQueueSizeGraphs(d, style, state)
|
drawQueueSizeGraphs(d, style, state)
|
||||||
d.NL() // empty line
|
d.NL()
|
||||||
drawQueueTable(d, style, state)
|
drawQueueTable(d, style, state)
|
||||||
case viewTypeQueueDetails:
|
case viewTypeQueueDetails:
|
||||||
d.Println(fmt.Sprintf("=== Queues > %s ===", state.selectedQueue.Queue), style)
|
d.Println(fmt.Sprintf("=== Queues > %s ===", state.selectedQueue.Queue), style.Bold(true))
|
||||||
d.NL()
|
d.NL()
|
||||||
drawQueueInfoBanner(d, style, state)
|
drawQueueInfoBanner(d, style, state)
|
||||||
|
d.NL()
|
||||||
|
d.Println("+++ Tasks +++", style.Bold(true))
|
||||||
|
drawTaskStateBreakdown(d, style, state)
|
||||||
case viewTypeServers:
|
case viewTypeServers:
|
||||||
d.Println("=== Servers ===", style.Bold(true))
|
d.Println("=== Servers ===", style.Bold(true))
|
||||||
d.NL() // empty line
|
d.NL()
|
||||||
// TODO: Draw body
|
// TODO: Draw body
|
||||||
case viewTypeSchedulers:
|
case viewTypeSchedulers:
|
||||||
d.Println("=== Schedulers === ", style.Bold(true))
|
d.Println("=== Schedulers === ", style.Bold(true))
|
||||||
d.NL() // empty line
|
d.NL()
|
||||||
// TODO: Draw body
|
// TODO: Draw body
|
||||||
case viewTypeRedis:
|
case viewTypeRedis:
|
||||||
d.Println("=== Redis Info === ", style.Bold(true))
|
d.Println("=== Redis Info === ", style.Bold(true))
|
||||||
d.NL() // empty line
|
d.NL()
|
||||||
d.Println(fmt.Sprintf("Version: %s", state.redisInfo.version), style)
|
d.Println(fmt.Sprintf("Version: %s", state.redisInfo.version), style)
|
||||||
d.Println(fmt.Sprintf("Uptime: %s", state.redisInfo.uptime), style)
|
d.Println(fmt.Sprintf("Uptime: %s", state.redisInfo.uptime), style)
|
||||||
d.Println(fmt.Sprintf("Memory Usage: %s", ByteCount(int64(state.redisInfo.memoryUsage))), style)
|
d.Println(fmt.Sprintf("Memory Usage: %s", ByteCount(int64(state.redisInfo.memoryUsage))), style)
|
||||||
d.Println(fmt.Sprintf("Peak Memory Usage: %s", ByteCount(int64(state.redisInfo.peakMemoryUsage))), style)
|
d.Println(fmt.Sprintf("Peak Memory Usage: %s", ByteCount(int64(state.redisInfo.peakMemoryUsage))), style)
|
||||||
case viewTypeHelp:
|
case viewTypeHelp:
|
||||||
d.Println("=== HELP ===", style.Bold(true))
|
d.Println("=== HELP ===", style.Bold(true))
|
||||||
d.NL() // empty line
|
d.NL()
|
||||||
// TODO: Draw HELP body
|
// TODO: Draw HELP body
|
||||||
}
|
}
|
||||||
if opts.DebugMode {
|
if opts.DebugMode {
|
||||||
d.Println(fmt.Sprintf("DEBUG: rowIdx = %d", state.rowIdx), style)
|
d.Println(fmt.Sprintf("DEBUG: rowIdx = %d", state.rowIdx), style)
|
||||||
d.Println(fmt.Sprintf("DEBUG: selectedQueue = %s", state.selectedQueue), style)
|
d.Println(fmt.Sprintf("DEBUG: selectedQueue = %s", state.selectedQueue.Queue), style)
|
||||||
d.Println(fmt.Sprintf("DEBUG: view = %v", state.view), style)
|
d.Println(fmt.Sprintf("DEBUG: view = %v", state.view), style)
|
||||||
}
|
}
|
||||||
d.GoToBottom()
|
d.GoToBottom()
|
||||||
@@ -226,3 +229,72 @@ func drawQueueTable(d *ScreenDrawer, style tcell.Style, state *State) {
|
|||||||
func drawQueueInfoBanner(d *ScreenDrawer, style tcell.Style, state *State) {
|
func drawQueueInfoBanner(d *ScreenDrawer, style tcell.Style, state *State) {
|
||||||
drawTable(d, style, queueColumnConfigs, []*asynq.QueueInfo{state.selectedQueue}, -1 /* no highlited row */)
|
drawTable(d, style, queueColumnConfigs, []*asynq.QueueInfo{state.selectedQueue}, -1 /* no highlited row */)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Define the order of states to show
|
||||||
|
var taskStates = []asynq.TaskState{
|
||||||
|
asynq.TaskStateActive,
|
||||||
|
asynq.TaskStatePending,
|
||||||
|
asynq.TaskStateAggregating,
|
||||||
|
asynq.TaskStateScheduled,
|
||||||
|
asynq.TaskStateRetry,
|
||||||
|
asynq.TaskStateArchived,
|
||||||
|
asynq.TaskStateCompleted,
|
||||||
|
}
|
||||||
|
|
||||||
|
func nextTaskState(current asynq.TaskState) asynq.TaskState {
|
||||||
|
for i, ts := range taskStates {
|
||||||
|
if current == ts {
|
||||||
|
if i == len(taskStates)-1 {
|
||||||
|
return taskStates[0]
|
||||||
|
} else {
|
||||||
|
return taskStates[i+1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("unkown task state")
|
||||||
|
}
|
||||||
|
|
||||||
|
func prevTaskState(current asynq.TaskState) asynq.TaskState {
|
||||||
|
for i, ts := range taskStates {
|
||||||
|
if current == ts {
|
||||||
|
if i == 0 {
|
||||||
|
return taskStates[len(taskStates)-1]
|
||||||
|
} else {
|
||||||
|
return taskStates[i-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("unkown task state")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTaskCount(queue *asynq.QueueInfo, taskState asynq.TaskState) int {
|
||||||
|
switch taskState {
|
||||||
|
case asynq.TaskStateActive:
|
||||||
|
return queue.Active
|
||||||
|
case asynq.TaskStatePending:
|
||||||
|
return queue.Pending
|
||||||
|
case asynq.TaskStateAggregating:
|
||||||
|
return queue.Aggregating
|
||||||
|
case asynq.TaskStateScheduled:
|
||||||
|
return queue.Scheduled
|
||||||
|
case asynq.TaskStateRetry:
|
||||||
|
return queue.Retry
|
||||||
|
case asynq.TaskStateArchived:
|
||||||
|
return queue.Archived
|
||||||
|
case asynq.TaskStateCompleted:
|
||||||
|
return queue.Completed
|
||||||
|
}
|
||||||
|
panic("unkonwn task state")
|
||||||
|
}
|
||||||
|
|
||||||
|
func drawTaskStateBreakdown(d *ScreenDrawer, style tcell.Style, state *State) {
|
||||||
|
const pad = " " // padding between states
|
||||||
|
for _, ts := range taskStates {
|
||||||
|
s := style
|
||||||
|
if state.taskState == ts {
|
||||||
|
s = s.Background(tcell.ColorDarkOliveGreen)
|
||||||
|
}
|
||||||
|
d.Print(fmt.Sprintf("%s:%d", ts.String(), getTaskCount(state.selectedQueue, ts)), s)
|
||||||
|
d.Print(pad, style)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user