mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-27 16:17:34 +00:00
Fix: add auto refresh to topology view and fix the refresh bug in resource view
Signed-off-by: HanMengnan <1448189829@qq.com>
This commit is contained in:
@@ -38,9 +38,10 @@ type TopologyView struct {
|
||||
actions model.KeyActions
|
||||
ctx context.Context
|
||||
focusTopology bool
|
||||
cache gcache.Cache
|
||||
cache gcache.Cache // lru cache with expired time
|
||||
appTopologyInstance *TopologyTree
|
||||
resourceTopologyInstance *TopologyTree
|
||||
cancelFunc func() // auto refresh cancel function
|
||||
}
|
||||
|
||||
type cacheView struct {
|
||||
@@ -55,7 +56,10 @@ type TopologyTree struct {
|
||||
|
||||
const (
|
||||
numberOfCacheView = 10
|
||||
expireTime = 10
|
||||
// cache expire time
|
||||
expireTime = 10
|
||||
// request timeout time
|
||||
topologyReqTimeout = 5
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -85,49 +89,22 @@ func (v *TopologyView) Init() {
|
||||
v.SetRows(0).SetColumns(-1, -1)
|
||||
v.SetBorder(true)
|
||||
v.SetBorderAttributes(tcell.AttrItalic)
|
||||
v.SetTitle(title).SetTitleColor(config.ResourceTableTitleColor)
|
||||
v.SetTitle(title)
|
||||
v.SetTitleColor(config.ResourceTableTitleColor)
|
||||
v.bindKeys()
|
||||
v.SetInputCapture(v.keyboard)
|
||||
}
|
||||
|
||||
// Start the topology view
|
||||
func (v *TopologyView) Start() {
|
||||
appName := v.ctx.Value(&model.CtxKeyAppName).(string)
|
||||
namespace := v.ctx.Value(&model.CtxKeyNamespace).(string)
|
||||
key := fmt.Sprintf("%s-%s", appName, namespace)
|
||||
|
||||
value, err := v.cache.Get(key)
|
||||
if err != nil {
|
||||
v.resourceTopologyInstance = v.NewResourceTopologyView()
|
||||
v.appTopologyInstance = v.NewAppTopologyView()
|
||||
_ = v.cache.Set(key, &cacheView{
|
||||
resourceTopologyInstance: v.resourceTopologyInstance,
|
||||
appTopologyInstance: v.appTopologyInstance,
|
||||
})
|
||||
} else {
|
||||
view, ok := value.(*cacheView)
|
||||
if ok {
|
||||
v.appTopologyInstance = view.appTopologyInstance
|
||||
v.resourceTopologyInstance = view.resourceTopologyInstance
|
||||
} else {
|
||||
v.resourceTopologyInstance = v.NewResourceTopologyView()
|
||||
v.appTopologyInstance = v.NewAppTopologyView()
|
||||
_ = v.cache.Set(key, &cacheView{
|
||||
resourceTopologyInstance: v.resourceTopologyInstance,
|
||||
appTopologyInstance: v.appTopologyInstance,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
v.Grid.AddItem(v.appTopologyInstance, 0, 0, 1, 1, 0, 0, true)
|
||||
v.Grid.AddItem(v.resourceTopologyInstance, 0, 1, 1, 1, 0, 0, true)
|
||||
|
||||
v.app.SetFocus(v.appTopologyInstance)
|
||||
v.Update(func() {})
|
||||
v.AutoRefresh(v.Update)
|
||||
}
|
||||
|
||||
// Stop the topology view
|
||||
func (v *TopologyView) Stop() {
|
||||
v.Grid.Clear()
|
||||
v.cancelFunc()
|
||||
}
|
||||
|
||||
// Hint return the menu hints of topology view
|
||||
@@ -140,6 +117,49 @@ func (v *TopologyView) Name() string {
|
||||
return "Topology"
|
||||
}
|
||||
|
||||
// Update the topology view
|
||||
func (v *TopologyView) Update(timeoutCancel func()) {
|
||||
appName := v.ctx.Value(&model.CtxKeyAppName).(string)
|
||||
namespace := v.ctx.Value(&model.CtxKeyNamespace).(string)
|
||||
key := fmt.Sprintf("%s-%s", appName, namespace)
|
||||
|
||||
value, err := v.cache.Get(key)
|
||||
|
||||
generateTopology := func() {
|
||||
v.resourceTopologyInstance = v.NewResourceTopologyView()
|
||||
v.appTopologyInstance = v.NewAppTopologyView()
|
||||
// add new topology view to cache
|
||||
_ = v.cache.Set(key, &cacheView{
|
||||
resourceTopologyInstance: v.resourceTopologyInstance,
|
||||
appTopologyInstance: v.appTopologyInstance,
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
generateTopology()
|
||||
} else {
|
||||
view, ok := value.(*cacheView)
|
||||
if ok {
|
||||
v.appTopologyInstance = view.appTopologyInstance
|
||||
v.resourceTopologyInstance = view.resourceTopologyInstance
|
||||
} else {
|
||||
generateTopology()
|
||||
}
|
||||
}
|
||||
|
||||
v.Grid.AddItem(v.appTopologyInstance, 0, 0, 1, 1, 0, 0, true)
|
||||
v.Grid.AddItem(v.resourceTopologyInstance, 0, 1, 1, 1, 0, 0, true)
|
||||
|
||||
// reset focus
|
||||
if v.focusTopology {
|
||||
v.app.SetFocus(v.resourceTopologyInstance)
|
||||
} else {
|
||||
v.app.SetFocus(v.appTopologyInstance)
|
||||
}
|
||||
// ctx done
|
||||
timeoutCancel()
|
||||
}
|
||||
|
||||
func (v *TopologyView) keyboard(event *tcell.EventKey) *tcell.EventKey {
|
||||
key := event.Key()
|
||||
if key == tcell.KeyUp || key == tcell.KeyDown {
|
||||
@@ -281,3 +301,40 @@ func buildTopology(node *types.ResourceTreeNode) *tview.TreeNode {
|
||||
|
||||
return rootNode
|
||||
}
|
||||
|
||||
// Refresh the topology view
|
||||
func (v *TopologyView) Refresh(clear bool, update func(timeoutCancel func())) {
|
||||
if clear {
|
||||
v.Grid.Clear()
|
||||
}
|
||||
|
||||
updateWithTimeout := func() {
|
||||
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*topologyReqTimeout)
|
||||
defer cancelFunc()
|
||||
go update(cancelFunc)
|
||||
|
||||
select {
|
||||
case <-time.After(time.Second * topologyReqTimeout): // timeout
|
||||
case <-ctx.Done(): // success
|
||||
}
|
||||
}
|
||||
|
||||
v.app.QueueUpdateDraw(updateWithTimeout)
|
||||
}
|
||||
|
||||
// AutoRefresh will refresh the view in every RefreshDelay delay
|
||||
func (v *TopologyView) AutoRefresh(update func(timeoutCancel func())) {
|
||||
var ctx context.Context
|
||||
ctx, v.cancelFunc = context.WithCancel(context.Background())
|
||||
go func() {
|
||||
for {
|
||||
time.Sleep(RefreshDelay * time.Second)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
v.Refresh(true, update)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ func (v *ApplicationView) Init() {
|
||||
// Start the application view
|
||||
func (v *ApplicationView) Start() {
|
||||
v.Clear()
|
||||
v.Update()
|
||||
v.Update(func() {})
|
||||
v.CommonResourceView.AutoRefresh(v.Update)
|
||||
}
|
||||
|
||||
@@ -78,9 +78,10 @@ func (v *ApplicationView) Refresh(_ *tcell.EventKey) *tcell.EventKey {
|
||||
}
|
||||
|
||||
// Update refresh the content of body of view
|
||||
func (v *ApplicationView) Update() {
|
||||
func (v *ApplicationView) Update(timeoutCancel func()) {
|
||||
v.BuildHeader()
|
||||
v.BuildBody()
|
||||
timeoutCancel()
|
||||
}
|
||||
|
||||
// BuildHeader render the header of table
|
||||
|
||||
@@ -49,7 +49,7 @@ func (v *ClusterNamespaceView) Init() {
|
||||
// Start the cluster namespace view
|
||||
func (v *ClusterNamespaceView) Start() {
|
||||
v.Clear()
|
||||
v.Update()
|
||||
v.Update(func() {})
|
||||
v.AutoRefresh(v.Update)
|
||||
}
|
||||
|
||||
@@ -78,9 +78,10 @@ func (v *ClusterNamespaceView) Refresh(_ *tcell.EventKey) *tcell.EventKey {
|
||||
}
|
||||
|
||||
// Update refresh the content of body of view
|
||||
func (v *ClusterNamespaceView) Update() {
|
||||
func (v *ClusterNamespaceView) Update(timeoutCancel func()) {
|
||||
v.BuildHeader()
|
||||
v.BuildBody()
|
||||
timeoutCancel()
|
||||
}
|
||||
|
||||
// BuildHeader render the header of table
|
||||
|
||||
@@ -48,7 +48,7 @@ func (v *ClusterView) Name() string {
|
||||
// Start the cluster view
|
||||
func (v *ClusterView) Start() {
|
||||
v.Clear()
|
||||
v.Update()
|
||||
v.Update(func() {})
|
||||
v.CommonResourceView.AutoRefresh(v.Update)
|
||||
}
|
||||
|
||||
@@ -77,9 +77,10 @@ func (v *ClusterView) Refresh(_ *tcell.EventKey) *tcell.EventKey {
|
||||
}
|
||||
|
||||
// Update refresh the content of body of view
|
||||
func (v *ClusterView) Update() {
|
||||
func (v *ClusterView) Update(timeoutCancel func()) {
|
||||
v.BuildHeader()
|
||||
v.BuildBody()
|
||||
timeoutCancel()
|
||||
}
|
||||
|
||||
// BuildHeader render the header of table
|
||||
|
||||
@@ -49,7 +49,7 @@ func (v *ContainerView) Name() string {
|
||||
// Start the container view
|
||||
func (v *ContainerView) Start() {
|
||||
v.Clear()
|
||||
v.Update()
|
||||
v.Update(func() {})
|
||||
v.CommonResourceView.AutoRefresh(v.Update)
|
||||
}
|
||||
|
||||
@@ -78,9 +78,10 @@ func (v *ContainerView) Refresh(_ *tcell.EventKey) *tcell.EventKey {
|
||||
}
|
||||
|
||||
// Update refresh the content of body of view
|
||||
func (v *ContainerView) Update() {
|
||||
func (v *ContainerView) Update(timeoutCancel func()) {
|
||||
v.BuildHeader()
|
||||
v.BuildBody()
|
||||
timeoutCancel()
|
||||
}
|
||||
|
||||
// BuildHeader render the header of table
|
||||
|
||||
@@ -50,7 +50,7 @@ func (v *ManagedResourceView) Init() {
|
||||
// Start the managed resource view
|
||||
func (v *ManagedResourceView) Start() {
|
||||
v.Clear()
|
||||
v.Update()
|
||||
v.Update(func() {})
|
||||
v.CommonResourceView.AutoRefresh(v.Update)
|
||||
}
|
||||
|
||||
@@ -92,9 +92,10 @@ func (v *ManagedResourceView) Refresh(_ *tcell.EventKey) *tcell.EventKey {
|
||||
}
|
||||
|
||||
// Update refresh the content of body of view
|
||||
func (v *ManagedResourceView) Update() {
|
||||
func (v *ManagedResourceView) Update(timeoutCancel func()) {
|
||||
v.BuildHeader()
|
||||
v.BuildBody()
|
||||
timeoutCancel()
|
||||
}
|
||||
|
||||
// BuildHeader render the header of table
|
||||
|
||||
@@ -49,7 +49,7 @@ func (v *NamespaceView) Name() string {
|
||||
// Start the managed namespace view
|
||||
func (v *NamespaceView) Start() {
|
||||
v.Clear()
|
||||
v.Update()
|
||||
v.Update(func() {})
|
||||
v.CommonResourceView.AutoRefresh(v.Update)
|
||||
}
|
||||
|
||||
@@ -78,9 +78,10 @@ func (v *NamespaceView) Refresh(_ *tcell.EventKey) *tcell.EventKey {
|
||||
}
|
||||
|
||||
// Update refresh the content of body of view
|
||||
func (v *NamespaceView) Update() {
|
||||
func (v *NamespaceView) Update(timeoutCancel func()) {
|
||||
v.BuildHeader()
|
||||
v.BuildBody()
|
||||
timeoutCancel()
|
||||
}
|
||||
|
||||
// BuildHeader render the header of table
|
||||
|
||||
@@ -42,7 +42,7 @@ func (v *PodView) Name() string {
|
||||
// Start the pod view
|
||||
func (v *PodView) Start() {
|
||||
v.Clear()
|
||||
v.Update()
|
||||
v.Update(func() {})
|
||||
v.AutoRefresh(v.Update)
|
||||
}
|
||||
|
||||
@@ -78,9 +78,10 @@ func (v *PodView) Refresh(_ *tcell.EventKey) *tcell.EventKey {
|
||||
}
|
||||
|
||||
// Update refresh the content of body of view
|
||||
func (v *PodView) Update() {
|
||||
func (v *PodView) Update(timeoutCancel func()) {
|
||||
v.BuildHeader()
|
||||
v.BuildBody()
|
||||
timeoutCancel()
|
||||
}
|
||||
|
||||
// BuildHeader render the header of table
|
||||
|
||||
@@ -28,15 +28,18 @@ import (
|
||||
"github.com/oam-dev/kubevela/references/cli/top/model"
|
||||
)
|
||||
|
||||
// RefreshDelay is refresh delay
|
||||
const RefreshDelay = 10 * time.Second
|
||||
const (
|
||||
// RefreshDelay is refresh delay
|
||||
RefreshDelay = 10
|
||||
resourceReqTimeout = 3
|
||||
)
|
||||
|
||||
// ResourceView is the interface to abstract resource view
|
||||
type ResourceView interface {
|
||||
model.View
|
||||
InitView(ctx context.Context, app *App)
|
||||
Refresh(event *tcell.EventKey) *tcell.EventKey
|
||||
Update()
|
||||
Update(timeoutCancel func())
|
||||
BuildHeader()
|
||||
BuildBody()
|
||||
}
|
||||
@@ -115,25 +118,36 @@ func (v *CommonResourceView) Stop() {
|
||||
}
|
||||
|
||||
// Refresh the base resource view
|
||||
func (v *CommonResourceView) Refresh(clear bool, update func()) {
|
||||
func (v *CommonResourceView) Refresh(clear bool, update func(timeoutCancel func())) {
|
||||
if clear {
|
||||
v.Clear()
|
||||
}
|
||||
v.app.QueueUpdateDraw(update)
|
||||
updateWithTimeout := func() {
|
||||
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*resourceReqTimeout)
|
||||
defer cancelFunc()
|
||||
go update(cancelFunc)
|
||||
|
||||
select {
|
||||
case <-time.After(time.Second * resourceReqTimeout): // timeout
|
||||
case <-ctx.Done(): // success
|
||||
}
|
||||
}
|
||||
|
||||
v.app.QueueUpdateDraw(updateWithTimeout)
|
||||
}
|
||||
|
||||
// AutoRefresh will refresh the view in every RefreshDelay delay
|
||||
func (v *CommonResourceView) AutoRefresh(update func()) {
|
||||
func (v *CommonResourceView) AutoRefresh(update func(timeoutCancel func())) {
|
||||
var ctx context.Context
|
||||
ctx, v.cancelFunc = context.WithCancel(context.Background())
|
||||
go func() {
|
||||
for {
|
||||
time.Sleep(RefreshDelay * time.Second)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
v.Refresh(false, update)
|
||||
time.Sleep(RefreshDelay)
|
||||
v.Refresh(true, update)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -39,11 +39,11 @@ func TestResourceView(t *testing.T) {
|
||||
assert.Equal(t, view.GetCell(1, 0).Text, "Name1")
|
||||
assert.Equal(t, view.GetCell(1, 1).Text, "Data1")
|
||||
|
||||
view.Refresh(true, func() {})
|
||||
view.Refresh(true, func(func()) {})
|
||||
assert.Equal(t, view.GetCell(0, 0).Text, "")
|
||||
|
||||
view.BuildHeader([]string{"Name", "Data"})
|
||||
view.Refresh(false, func() {})
|
||||
view.Refresh(false, func(func()) {})
|
||||
assert.Equal(t, view.GetCell(0, 0).Text, "Name")
|
||||
|
||||
view.BuildHeader([]string{"Name", "Data"})
|
||||
|
||||
Reference in New Issue
Block a user