Workspace is the new space

This commit is contained in:
mr
2026-06-22 07:41:32 +02:00
parent d887d92e57
commit 469011f7bd
7 changed files with 513 additions and 7 deletions
+91 -5
View File
@@ -6,7 +6,9 @@ import (
"strconv"
oclib "cloud.o-forge.io/core/oc-lib"
"cloud.o-forge.io/core/oc-lib/models/workspace"
"cloud.o-forge.io/core/oc-lib/tools"
"oc-workspace/infrastructure"
beego "github.com/beego/beego/v2/server/web"
)
@@ -53,18 +55,101 @@ func (o *WorkspaceController) Search() {
// @Success 200 {workspace} models.workspace
// @router /:id [put]
func (o *WorkspaceController) Put() {
//user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
// store and return Id or post with UUID
caller := tools.NewHTTPCaller(paths) // generate a http caller to send to peer shared workspace
caller := tools.NewHTTPCaller(paths)
caller.Disabled = oclib.IsQueryParamsEquals(o.Ctx.Input, "is_remote", true)
var res map[string]interface{}
id := o.Ctx.Input.Param(":id")
json.Unmarshal(o.Ctx.Input.CopyBody(10000), &res)
// o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.WORKSPACE), user, peerID, groups, caller).UpdateOne(res, id)
json.Unmarshal(o.Ctx.Input.CopyBody(2000000), &res)
// Snapshot resource IDs before the update to detect additions and removals.
oldResources := loadWorkspaceResourceMap(id)
o.Data["json"] = oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.WORKSPACE), caller).UpdateOne(res, id)
// Emit watch/unwatch events for resources that changed in this workspace.
go diffAndEmitWatchers(oldResources, extractResourceMap(res))
o.ServeJSON()
}
// resourceEntry holds the resource ID and its creator's libp2p PeerID.
type resourceEntry struct {
creatorPeerID string
dataType tools.DataType
}
// loadWorkspaceResourceMap returns the current resourceID→entry map for a workspace.
func loadWorkspaceResourceMap(id string) map[string]resourceEntry {
result := map[string]resourceEntry{}
data := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.WORKSPACE), nil).LoadOne(id)
if data.Data == nil {
return result
}
w, ok := data.Data.(*workspace.Workspace)
if !ok {
return result
}
for _, r := range w.DataResources { result[r.GetID()] = resourceEntry{creatorPeerID: r.GetCreatorID(), dataType: tools.DATA_RESOURCE} }
for _, r := range w.ComputeResources { result[r.GetID()] = resourceEntry{creatorPeerID: r.GetCreatorID(), dataType: tools.COMPUTE_RESOURCE} }
for _, r := range w.StorageResources { result[r.GetID()] = resourceEntry{creatorPeerID: r.GetCreatorID(), dataType: tools.STORAGE_RESOURCE} }
for _, r := range w.ProcessingResources { result[r.GetID()] = resourceEntry{creatorPeerID: r.GetCreatorID(), dataType: tools.PROCESSING_RESOURCE} }
for _, r := range w.WorkflowResources { result[r.GetID()] = resourceEntry{creatorPeerID: r.GetCreatorID(), dataType: tools.WORKFLOW_RESOURCE} }
for _, r := range w.ServiceResources { result[r.GetID()] = resourceEntry{creatorPeerID: r.GetCreatorID(), dataType: tools.SERVICE_RESOURCE} }
for _, r := range w.DynamicResources { result[r.GetID()] = resourceEntry{creatorPeerID: r.GetCreatorID(), dataType: tools.DYNAMIC_RESOURCE} }
for _, r := range w.NativeTools { result[r.GetID()] = resourceEntry{creatorPeerID: r.GetCreatorID(), dataType: tools.NATIVE_TOOL} }
return result
}
// extractResourceMap parses the PUT body to build a resourceID→entry map.
// creator_id is at the top level of each resource object (from Flutter toJSON()).
var resourceArrayKeys = map[string]tools.DataType{
"data_resources": tools.DATA_RESOURCE,
"compute_resources": tools.COMPUTE_RESOURCE,
"storage_resources": tools.STORAGE_RESOURCE,
"processing_resources": tools.PROCESSING_RESOURCE,
"workflow_resources": tools.WORKFLOW_RESOURCE,
"service_resources": tools.SERVICE_RESOURCE,
"dynamic_resources": tools.DYNAMIC_RESOURCE,
"native_tools": tools.NATIVE_TOOL,
}
func extractResourceMap(body map[string]interface{}) map[string]resourceEntry {
result := map[string]resourceEntry{}
for key, dt := range resourceArrayKeys {
arr, ok := body[key].([]interface{})
if !ok {
continue
}
for _, rawR := range arr {
r, ok := rawR.(map[string]interface{})
if !ok {
continue
}
id, _ := r["id"].(string)
creatorID, _ := r["creator_id"].(string)
if id != "" {
result[id] = resourceEntry{creatorPeerID: creatorID, dataType: dt}
}
}
}
return result
}
// diffAndEmitWatchers emits PB_WATCH_RESOURCE for added non-self resources
// and PB_UNWATCH_RESOURCE for removed ones.
func diffAndEmitWatchers(old, new map[string]resourceEntry) {
for id, entry := range new {
if _, existed := old[id]; !existed {
infrastructure.EmitWatchResource(id, entry.creatorPeerID, entry.dataType)
}
}
for id, entry := range old {
if _, stillPresent := new[id]; !stillPresent {
infrastructure.EmitUnwatchResource(id, entry.creatorPeerID, entry.dataType)
}
}
}
// @Title Create
// @Description create workspace
// @Param data body json true "body for data content (Json format)"
@@ -125,3 +210,4 @@ func (o *WorkspaceController) Delete() {
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.WORKSPACE), user, peerID, groups, caller).DeleteOne(id)
o.ServeJSON()
}