Optimize VM listing logic with singleflight to deduplicate concurrent request
This commit is contained in:
parent
c7f669d23c
commit
f07ed68a84
|
|
@ -312,26 +312,40 @@ func (controller *Controller) listVMs(ctx *gin.Context) responder.Responder {
|
|||
}
|
||||
}
|
||||
|
||||
return controller.storeView(func(txn storepkg.Transaction) responder.Responder {
|
||||
allVMs, err := txn.ListVMs()
|
||||
allVMs, err, _ := controller.single.Do("list-vms", func() (interface{}, error) {
|
||||
var vms []v1.VM
|
||||
|
||||
if err != nil {
|
||||
return responder.Error(err)
|
||||
}
|
||||
viewErr := controller.store.View(func(txn storepkg.Transaction) (err error) {
|
||||
vms, err = txn.ListVMs()
|
||||
return
|
||||
})
|
||||
|
||||
vms := make([]v1.VM, 0)
|
||||
Outer:
|
||||
for _, vm := range allVMs {
|
||||
for _, filter := range filters {
|
||||
if !vm.Match(filter) {
|
||||
continue Outer
|
||||
}
|
||||
}
|
||||
vms = append(vms, vm)
|
||||
}
|
||||
|
||||
return responder.JSON(http.StatusOK, vms)
|
||||
return vms, viewErr
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return responder.Error(err)
|
||||
}
|
||||
|
||||
vmList, ok := allVMs.([]v1.VM)
|
||||
if !ok {
|
||||
controller.logger.Errorf("failed to cast list-vms result to []v1.VM: %T", allVMs)
|
||||
return responder.Code(http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
vms := make([]v1.VM, 0, len(vmList))
|
||||
|
||||
Outer:
|
||||
for _, vm := range vmList {
|
||||
for _, filter := range filters {
|
||||
if !vm.Match(filter) {
|
||||
continue Outer
|
||||
}
|
||||
}
|
||||
vms = append(vms, vm)
|
||||
}
|
||||
|
||||
return responder.JSON(http.StatusOK, vms)
|
||||
}
|
||||
|
||||
func (controller *Controller) deleteVM(ctx *gin.Context) responder.Responder {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import (
|
|||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/h2c"
|
||||
"golang.org/x/sync/singleflight"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
)
|
||||
|
|
@ -73,6 +74,8 @@ type Controller struct {
|
|||
sshNoClientAuth bool
|
||||
sshServer *sshserver.SSHServer
|
||||
|
||||
single singleflight.Group
|
||||
|
||||
rpc.UnimplementedControllerServer
|
||||
}
|
||||
|
||||
|
|
@ -83,6 +86,7 @@ func New(opts ...Option) (*Controller, error) {
|
|||
workerOfflineTimeout: 3 * time.Minute,
|
||||
maxWorkersPerLicense: maxWorkersPerDefaultLicense,
|
||||
pingInterval: 30 * time.Second,
|
||||
single: singleflight.Group{},
|
||||
}
|
||||
|
||||
// Apply options
|
||||
|
|
|
|||
Loading…
Reference in New Issue