mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-27 16:17:34 +00:00
Fix: fix the stuck problem and use LRU cache to promote the speed of loading topology (#5002)
* Fix: fix the stuck problem and use lru cache to promote the speed of loading topology Signed-off-by: HanMengnan <1448189829@qq.com> * Fix: reuse existing lru golang library Signed-off-by: HanMengnan <1448189829@qq.com> Signed-off-by: HanMengnan <1448189829@qq.com>
This commit is contained in:
@@ -50,6 +50,7 @@ require (
|
||||
github.com/gosuri/uilive v0.0.4
|
||||
github.com/gosuri/uitable v0.0.4
|
||||
github.com/hashicorp/go-version v1.3.0
|
||||
github.com/hashicorp/golang-lru v0.5.4
|
||||
github.com/hashicorp/hcl/v2 v2.9.1
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174
|
||||
github.com/imdario/mergo v0.3.12
|
||||
|
||||
@@ -1180,6 +1180,7 @@ github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
|
||||
@@ -130,9 +130,7 @@ func (a *App) Refresh() {
|
||||
log.Printf("SystemInfo updater canceled!")
|
||||
return
|
||||
case <-time.After(delay):
|
||||
a.QueueUpdateDraw(func() {
|
||||
board.UpdateInfo(a.config.RestConfig)
|
||||
})
|
||||
board.UpdateInfo(a.config.RestConfig)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/rivo/tview"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/velaql/providers/query/types"
|
||||
@@ -32,20 +33,31 @@ import (
|
||||
// TopologyView display the resource topology of application
|
||||
type TopologyView struct {
|
||||
*tview.Grid
|
||||
app *App
|
||||
actions model.KeyActions
|
||||
ctx context.Context
|
||||
focusTopology bool
|
||||
app *App
|
||||
actions model.KeyActions
|
||||
ctx context.Context
|
||||
focusTopology bool
|
||||
cache *lru.Cache
|
||||
appTopologyInstance *TopologyTree
|
||||
resourceTopologyInstance *TopologyTree
|
||||
}
|
||||
|
||||
type topologyTree struct {
|
||||
type cacheView struct {
|
||||
appTopologyInstance *TopologyTree
|
||||
resourceTopologyInstance *TopologyTree
|
||||
}
|
||||
|
||||
// TopologyTree is the abstract of topology tree
|
||||
type TopologyTree struct {
|
||||
*tview.TreeView
|
||||
}
|
||||
|
||||
const (
|
||||
numberOfCacheView = 10
|
||||
)
|
||||
|
||||
var (
|
||||
topologyViewInstance = new(TopologyView)
|
||||
appTopologyInstance = new(topologyTree)
|
||||
resourceTopologyInstance = new(topologyTree)
|
||||
topologyViewInstance = new(TopologyView)
|
||||
)
|
||||
|
||||
// NewTopologyView return a new topology view
|
||||
@@ -56,6 +68,10 @@ func NewTopologyView(ctx context.Context, app *App) model.View {
|
||||
if topologyViewInstance.Grid == nil {
|
||||
topologyViewInstance.Grid = tview.NewGrid()
|
||||
topologyViewInstance.actions = make(model.KeyActions)
|
||||
topologyViewInstance.cache, _ = lru.New(numberOfCacheView)
|
||||
topologyViewInstance.appTopologyInstance = new(TopologyTree)
|
||||
topologyViewInstance.resourceTopologyInstance = new(TopologyTree)
|
||||
|
||||
topologyViewInstance.Init()
|
||||
}
|
||||
return topologyViewInstance
|
||||
@@ -74,13 +90,28 @@ func (v *TopologyView) Init() {
|
||||
|
||||
// Start the topology view
|
||||
func (v *TopologyView) Start() {
|
||||
appTopology := v.NewAppTopologyView()
|
||||
resourceTopology := v.NewResourceTopologyView()
|
||||
appName := v.ctx.Value(&model.CtxKeyAppName).(string)
|
||||
namespace := v.ctx.Value(&model.CtxKeyNamespace).(string)
|
||||
key := fmt.Sprintf("%s-%s", appName, namespace)
|
||||
|
||||
v.Grid.AddItem(appTopology, 0, 0, 1, 1, 0, 0, true)
|
||||
v.Grid.AddItem(resourceTopology, 0, 1, 1, 1, 0, 0, true)
|
||||
value, exist := v.cache.Get(key)
|
||||
view, ok := value.(*cacheView)
|
||||
if exist && ok {
|
||||
v.appTopologyInstance = view.appTopologyInstance
|
||||
v.resourceTopologyInstance = view.resourceTopologyInstance
|
||||
} else {
|
||||
v.resourceTopologyInstance = v.NewResourceTopologyView()
|
||||
v.appTopologyInstance = v.NewAppTopologyView()
|
||||
v.cache.Add(key, &cacheView{
|
||||
resourceTopologyInstance: v.resourceTopologyInstance,
|
||||
appTopologyInstance: v.appTopologyInstance,
|
||||
})
|
||||
}
|
||||
|
||||
v.app.SetFocus(appTopology)
|
||||
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)
|
||||
}
|
||||
|
||||
// Stop the topology view
|
||||
@@ -119,54 +150,49 @@ func (v *TopologyView) bindKeys() {
|
||||
}
|
||||
|
||||
// NewResourceTopologyView return a new resource topology view
|
||||
func (v *TopologyView) NewResourceTopologyView() tview.Primitive {
|
||||
if resourceTopologyInstance.TreeView == nil {
|
||||
resourceTopologyInstance.TreeView = tview.NewTreeView()
|
||||
resourceTopologyInstance.SetGraphics(true)
|
||||
resourceTopologyInstance.SetGraphicsColor(tcell.ColorCadetBlue)
|
||||
resourceTopologyInstance.SetBorder(true)
|
||||
resourceTopologyInstance.SetTitle(fmt.Sprintf("[ %s ]", "Resource"))
|
||||
}
|
||||
|
||||
func (v *TopologyView) NewResourceTopologyView() *TopologyTree {
|
||||
newTopology := new(TopologyTree)
|
||||
appName := v.ctx.Value(&model.CtxKeyAppName).(string)
|
||||
namespace := v.ctx.Value(&model.CtxKeyNamespace).(string)
|
||||
|
||||
newTopology.TreeView = tview.NewTreeView()
|
||||
newTopology.SetGraphics(true)
|
||||
newTopology.SetGraphicsColor(tcell.ColorCadetBlue)
|
||||
newTopology.SetBorder(true)
|
||||
newTopology.SetTitle(fmt.Sprintf("[ %s ]", "Resource"))
|
||||
|
||||
root := tview.NewTreeNode(component.EmojiFormat(fmt.Sprintf("%s (%s)", appName, namespace), "app")).SetSelectable(true)
|
||||
resourceTopologyInstance.SetRoot(root)
|
||||
newTopology.SetRoot(root)
|
||||
|
||||
resourceTree, err := model.ApplicationResourceTopology(v.app.client, appName, namespace)
|
||||
if err != nil {
|
||||
return resourceTopologyInstance
|
||||
if err == nil {
|
||||
for _, resource := range resourceTree {
|
||||
root.AddChild(buildTopology(resource.ResourceTree))
|
||||
}
|
||||
}
|
||||
for _, resource := range resourceTree {
|
||||
root.AddChild(buildTopology(resource.ResourceTree))
|
||||
}
|
||||
|
||||
return resourceTopologyInstance
|
||||
return newTopology
|
||||
}
|
||||
|
||||
// NewAppTopologyView return a new app topology view
|
||||
func (v *TopologyView) NewAppTopologyView() tview.Primitive {
|
||||
if appTopologyInstance.TreeView == nil {
|
||||
appTopologyInstance.TreeView = tview.NewTreeView()
|
||||
appTopologyInstance.SetGraphics(true)
|
||||
appTopologyInstance.SetGraphicsColor(tcell.ColorCadetBlue)
|
||||
appTopologyInstance.SetBorder(true)
|
||||
appTopologyInstance.SetTitle(fmt.Sprintf("[ %s ]", "App"))
|
||||
}
|
||||
|
||||
func (v *TopologyView) NewAppTopologyView() *TopologyTree {
|
||||
newTopology := new(TopologyTree)
|
||||
appName := v.ctx.Value(&model.CtxKeyAppName).(string)
|
||||
namespace := v.ctx.Value(&model.CtxKeyNamespace).(string)
|
||||
|
||||
newTopology.TreeView = tview.NewTreeView()
|
||||
newTopology.SetGraphics(true)
|
||||
newTopology.SetGraphicsColor(tcell.ColorCadetBlue)
|
||||
newTopology.SetBorder(true)
|
||||
newTopology.SetTitle(fmt.Sprintf("[ %s ]", "App"))
|
||||
|
||||
root := tview.NewTreeNode(component.EmojiFormat(fmt.Sprintf("%s (%s)", appName, namespace), "app")).SetSelectable(true)
|
||||
|
||||
appTopologyInstance.SetRoot(root)
|
||||
newTopology.SetRoot(root)
|
||||
|
||||
app, err := model.LoadApplication(v.app.client, appName, namespace)
|
||||
if err != nil {
|
||||
return appTopologyInstance
|
||||
return newTopology
|
||||
}
|
||||
|
||||
// workflow
|
||||
workflowNode := tview.NewTreeNode(component.EmojiFormat("WorkFlow", "workflow")).SetSelectable(true)
|
||||
root.AddChild(workflowNode)
|
||||
@@ -206,15 +232,14 @@ func (v *TopologyView) NewAppTopologyView() tview.Primitive {
|
||||
for _, policy := range app.Spec.Policies {
|
||||
policyNode.AddChild(tview.NewTreeNode(policy.Name))
|
||||
}
|
||||
|
||||
return appTopologyInstance
|
||||
return newTopology
|
||||
}
|
||||
|
||||
func (v *TopologyView) switchTopology(_ *tcell.EventKey) *tcell.EventKey {
|
||||
if v.focusTopology {
|
||||
v.app.SetFocus(appTopologyInstance)
|
||||
v.app.SetFocus(v.appTopologyInstance)
|
||||
} else {
|
||||
v.app.SetFocus(resourceTopologyInstance)
|
||||
v.app.SetFocus(v.resourceTopologyInstance)
|
||||
}
|
||||
v.focusTopology = !v.focusTopology
|
||||
return nil
|
||||
|
||||
@@ -61,10 +61,12 @@ func TestTopologyView(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("start", func(t *testing.T) {
|
||||
appTopologyView := topologyView.NewAppTopologyView()
|
||||
assert.Equal(t, appTopologyView.HasFocus(), false)
|
||||
topologyView.Start()
|
||||
assert.Equal(t, appTopologyView.HasFocus(), true)
|
||||
assert.Equal(t, topologyView.appTopologyInstance.HasFocus(), true)
|
||||
assert.Equal(t, topologyView.resourceTopologyInstance.HasFocus(), false)
|
||||
topologyView.switchTopology(nil)
|
||||
assert.Equal(t, topologyView.appTopologyInstance.HasFocus(), false)
|
||||
assert.Equal(t, topologyView.resourceTopologyInstance.HasFocus(), true)
|
||||
})
|
||||
|
||||
t.Run("stop", func(t *testing.T) {
|
||||
|
||||
@@ -48,7 +48,7 @@ func (ps *PageStack) StackPop(old, new model.View) {
|
||||
}
|
||||
ps.app.QueueUpdateDraw(new.Start)
|
||||
ps.app.SetFocus(new)
|
||||
ps.app.QueueUpdate(old.Stop)
|
||||
go old.Stop()
|
||||
}
|
||||
|
||||
// StackPush change itself when accept "pop" notify from app's main view
|
||||
@@ -56,6 +56,6 @@ func (ps *PageStack) StackPush(old, new model.View) {
|
||||
ps.app.QueueUpdateDraw(new.Start)
|
||||
ps.app.SetFocus(new)
|
||||
if old != nil {
|
||||
ps.app.QueueUpdate(old.Stop)
|
||||
go old.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user