add websocket route

This commit is contained in:
mr 2025-06-18 11:18:12 +02:00
parent 81167f7b86
commit 4e1e3f20af
4 changed files with 45 additions and 18 deletions

View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"net/http"
"oc-datacenter/infrastructure" "oc-datacenter/infrastructure"
"time" "time"
@ -13,6 +14,7 @@ import (
b "cloud.o-forge.io/core/oc-lib/models/booking" b "cloud.o-forge.io/core/oc-lib/models/booking"
"cloud.o-forge.io/core/oc-lib/tools" "cloud.o-forge.io/core/oc-lib/tools"
beego "github.com/beego/beego/v2/server/web" beego "github.com/beego/beego/v2/server/web"
"github.com/gorilla/websocket"
"go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson/primitive"
) )
@ -109,6 +111,27 @@ func (o *BookingController) Get() {
o.ServeJSON() o.ServeJSON()
} }
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true }, // allow all origins
}
// @Title Log
// @Description find booking by id
// @Param id path string true "the id you want to get"
// @Success 200 {booking} models.booking
// @router /:id [get]
func (o *BookingController) Log() {
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
id := o.Ctx.Input.Param(":id")
conn, err := upgrader.Upgrade(o.Ctx.ResponseWriter, o.Ctx.Request, nil)
if err != nil {
o.Ctx.WriteString("WebSocket upgrade failed: " + err.Error())
return
}
defer conn.Close()
infrastructure.NewPrometheusService().Stream(id, 1*time.Second, user, peerID, groups, conn)
}
// @Title Update // @Title Update
// @Description create computes // @Description create computes
// @Param id path string true "the compute id you want to get" // @Param id path string true "the compute id you want to get"
@ -284,7 +307,7 @@ func (o *BookingController) Post() {
if b.Data.(*booking.Booking).ResourceType == tools.COMPUTE_RESOURCE { if b.Data.(*booking.Booking).ResourceType == tools.COMPUTE_RESOURCE {
go func() { go func() {
time.Sleep(time.Until(b.Data.(*booking.Booking).ExpectedStartDate)) time.Sleep(time.Until(b.Data.(*booking.Booking).ExpectedStartDate))
infrastructure.NewPrometheusService().Stream(b.Data.GetID(), b.Data.(*booking.Booking).ExpectedEndDate, 1*time.Second, nil, nil) infrastructure.NewPrometheusService().Stream(b.Data.GetID(), 1*time.Second, user, peerID, groups, nil)
}() }()
} }

1
go.mod
View File

@ -17,6 +17,7 @@ require (
require ( require (
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.2.6 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect

2
go.sum
View File

@ -87,6 +87,8 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGa
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/goraz/onion v0.1.3 h1:KhyvbDA2b70gcz/d5izfwTiOH8SmrvV43AsVzpng3n0= github.com/goraz/onion v0.1.3 h1:KhyvbDA2b70gcz/d5izfwTiOH8SmrvV43AsVzpng3n0=
github.com/goraz/onion v0.1.3/go.mod h1:XEmz1XoBz+wxTgWB8NwuvRm4RAu3vKxvrmYtzK+XCuQ= github.com/goraz/onion v0.1.3/go.mod h1:XEmz1XoBz+wxTgWB8NwuvRm4RAu3vKxvrmYtzK+XCuQ=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=

View File

@ -16,6 +16,7 @@ import (
"cloud.o-forge.io/core/oc-lib/models/booking" "cloud.o-forge.io/core/oc-lib/models/booking"
"cloud.o-forge.io/core/oc-lib/models/common/models" "cloud.o-forge.io/core/oc-lib/models/common/models"
"cloud.o-forge.io/core/oc-lib/models/compute_units" "cloud.o-forge.io/core/oc-lib/models/compute_units"
"github.com/gorilla/websocket"
) )
type MetricsSnapshot struct { type MetricsSnapshot struct {
@ -81,14 +82,14 @@ func (p *PrometheusService) queryPrometheus(promURL string, expr string, namespa
return metric return metric
} }
func (p *PrometheusService) Call(book *booking.Booking) (*booking.Booking, map[string]models.MetricsSnapshot) { func (p *PrometheusService) Call(book *booking.Booking, user string, peerID string, groups []string) (*booking.Booking, map[string]models.MetricsSnapshot) {
var wg sync.WaitGroup var wg sync.WaitGroup
metrics := map[string]models.MetricsSnapshot{} metrics := map[string]models.MetricsSnapshot{}
// get all booking... from executions_id == namespace typed datacenter. // get all booking... from executions_id == namespace typed datacenter.
cUAccess := oclib.NewRequest(oclib.LibDataEnum(oclib.COMPUTE_UNITS), "", "", []string{}, nil) cUAccess := oclib.NewRequest(oclib.LibDataEnum(oclib.COMPUTE_UNITS), user, peerID, groups, nil)
cRAccess := oclib.NewRequest(oclib.LibDataEnum(oclib.COMPUTE_RESOURCE), "", "", []string{}, nil) cRAccess := oclib.NewRequest(oclib.LibDataEnum(oclib.COMPUTE_RESOURCE), user, peerID, groups, nil)
rr := cRAccess.LoadOne(book.ResourceID) rr := cRAccess.LoadOne(book.ResourceID)
if rr.Err != "" { if rr.Err != "" {
@ -129,23 +130,24 @@ func (p *PrometheusService) Call(book *booking.Booking) (*booking.Booking, map[s
var LockKill = &sync.Mutex{} var LockKill = &sync.Mutex{}
func (p *PrometheusService) Stream(bookingID string, end *time.Time, interval time.Duration, flusher *http.Flusher, encoder *json.Encoder) { // TODO kill procedure
f := func(e *time.Time) bool { func (p *PrometheusService) Stream(bookingID string, interval time.Duration, user string, peerID string, groups []string, websocket *websocket.Conn) {
if end == nil {
return true
}
return time.Now().Before(*e)
}
max := 100 max := 100
bookIDS := []string{} bookIDS := []string{}
mets := map[string][]models.MetricsSnapshot{} mets := map[string][]models.MetricsSnapshot{}
bAccess := oclib.NewRequest(oclib.LibDataEnum(oclib.BOOKING), "", "", []string{}, nil) bAccess := oclib.NewRequest(oclib.LibDataEnum(oclib.BOOKING), user, peerID, groups, nil)
book := bAccess.LoadOne(bookingID) book := bAccess.LoadOne(bookingID)
if book.Err != "" { if book.Err != "" {
fmt.Errorf("stop because of empty : %s", book.Err) fmt.Errorf("stop because of empty : %s", book.Err)
} }
f := func(e *booking.Booking) bool {
for f(end) { if e.ExpectedEndDate == nil {
return true
}
return time.Now().Before(*e.ExpectedEndDate)
}
for f(book.Data.(*booking.Booking)) {
if slices.Contains(Kill, book.Data.(*booking.Booking).ExecutionsID) { if slices.Contains(Kill, book.Data.(*booking.Booking).ExecutionsID) {
newKill := []string{} newKill := []string{}
for _, k := range Kill { for _, k := range Kill {
@ -160,7 +162,7 @@ func (p *PrometheusService) Stream(bookingID string, end *time.Time, interval ti
} }
go func() { go func() {
book, metrics := p.Call(book.Data.(*booking.Booking)) book, metrics := p.Call(book.Data.(*booking.Booking), user, peerID, groups)
for k, v := range metrics { for k, v := range metrics {
if me, ok := mets[k]; !ok { if me, ok := mets[k]; !ok {
mets[k] = []models.MetricsSnapshot{v} mets[k] = []models.MetricsSnapshot{v}
@ -170,9 +172,8 @@ func (p *PrometheusService) Stream(bookingID string, end *time.Time, interval ti
} }
} }
bookIDS = append(bookIDS, bookingID) bookIDS = append(bookIDS, bookingID)
if flusher != nil { if websocket != nil {
encoder.Encode(metrics) (*websocket).WriteJSON(metrics)
(*flusher).Flush()
} }
if len(bookIDS) != max { if len(bookIDS) != max {
return return