Refactor Oc-Sheduler
This commit is contained in:
233
infrastructure/session/session.go
Normal file
233
infrastructure/session/session.go
Normal file
@@ -0,0 +1,233 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"oc-scheduler/infrastructure/execution"
|
||||
"oc-scheduler/infrastructure/scheduling_resources"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"cloud.o-forge.io/core/oc-lib/dbs"
|
||||
"cloud.o-forge.io/core/oc-lib/models/bill"
|
||||
"cloud.o-forge.io/core/oc-lib/models/booking"
|
||||
"cloud.o-forge.io/core/oc-lib/models/common/enum"
|
||||
"cloud.o-forge.io/core/oc-lib/models/order"
|
||||
"cloud.o-forge.io/core/oc-lib/models/resources/purchase_resource"
|
||||
"cloud.o-forge.io/core/oc-lib/models/utils"
|
||||
"cloud.o-forge.io/core/oc-lib/models/workflow_execution"
|
||||
"cloud.o-forge.io/core/oc-lib/tools"
|
||||
|
||||
oclib "cloud.o-forge.io/core/oc-lib"
|
||||
)
|
||||
|
||||
type SessionExecutionsService struct {
|
||||
Mu sync.RWMutex
|
||||
ExecutionsSessionID string
|
||||
}
|
||||
|
||||
func NewSessionExecutionsService(sessionID string) *SessionExecutionsService {
|
||||
return &SessionExecutionsService{ExecutionsSessionID: sessionID}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// DB helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func (s *SessionExecutionsService) sessionIDFilter(field, id string) *dbs.Filters {
|
||||
return &dbs.Filters{
|
||||
And: map[string][]dbs.Filter{
|
||||
field: {{Operator: dbs.EQUAL.String(), Value: id}},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SessionExecutionsService) loadSession(dt tools.DataType) []scheduling_resources.SchedulerObject {
|
||||
results := oclib.NewRequestAdmin(oclib.LibDataEnum(dt), nil).Search(
|
||||
s.sessionIDFilter("executions_id", s.ExecutionsSessionID), "", true)
|
||||
out := make([]scheduling_resources.SchedulerObject, 0, len(results.Data))
|
||||
for _, obj := range results.Data {
|
||||
out = append(out, scheduling_resources.ToSchedulerObject(dt, obj))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (s *SessionExecutionsService) LoadSessionExecs() []*workflow_execution.WorkflowExecution {
|
||||
adminReq := &tools.APIRequest{Admin: true}
|
||||
results, _, _ := workflow_execution.NewAccessor(adminReq).Search(
|
||||
s.sessionIDFilter("executions_id", s.ExecutionsSessionID), "", true)
|
||||
out := make([]*workflow_execution.WorkflowExecution, 0)
|
||||
for _, obj := range results {
|
||||
if exec, ok := obj.(*workflow_execution.WorkflowExecution); ok {
|
||||
out = append(out, exec)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (s *SessionExecutionsService) loadSessionOrder() *order.Order {
|
||||
adminReq := &tools.APIRequest{Admin: true}
|
||||
results, _, _ := order.NewAccessor(adminReq).Search(
|
||||
s.sessionIDFilter("executions_id", s.ExecutionsSessionID), "", true)
|
||||
for _, obj := range results {
|
||||
if o, ok := obj.(*order.Order); ok {
|
||||
return o
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Session upsert
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func (s *SessionExecutionsService) UpsertSessionDrafts(
|
||||
purchases, bookings []scheduling_resources.SchedulerObject,
|
||||
execs []*workflow_execution.WorkflowExecution,
|
||||
request *tools.APIRequest,
|
||||
) {
|
||||
adminReq := &tools.APIRequest{Admin: true}
|
||||
|
||||
for dt, datas := range map[tools.DataType][]scheduling_resources.SchedulerObject{
|
||||
tools.BOOKING: bookings,
|
||||
tools.PURCHASE_RESOURCE: purchases,
|
||||
} {
|
||||
existing := map[string]scheduling_resources.SchedulerObject{}
|
||||
seen := map[string]bool{}
|
||||
for _, bk := range s.loadSession(dt) {
|
||||
existing[bk.GetKey()] = bk
|
||||
}
|
||||
s.upsertDrafts(dt, datas, existing, seen, request)
|
||||
for key, prev := range existing {
|
||||
if !seen[key] {
|
||||
scheduling_resources.GetService().Delete(dt, prev, request)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, old := range s.LoadSessionExecs() {
|
||||
execution.UnregisterExecLock(old.GetID())
|
||||
workflow_execution.NewAccessor(adminReq).DeleteOne(old.GetID())
|
||||
}
|
||||
for _, exec := range execs {
|
||||
exec.ExecutionsID = s.ExecutionsSessionID
|
||||
exec.IsDraft = true
|
||||
ex, _, err := utils.GenericStoreOne(exec, workflow_execution.NewAccessor(adminReq))
|
||||
if err == nil {
|
||||
execution.RegisterExecLock(ex.GetID())
|
||||
go execution.WatchDeadline(ex.GetID(), s.ExecutionsSessionID, exec.ExecDate, request)
|
||||
}
|
||||
}
|
||||
|
||||
if existing := s.loadSessionOrder(); existing == nil {
|
||||
GenerateOrder(purchases, bookings, s.ExecutionsSessionID, request)
|
||||
} else {
|
||||
for _, purch := range purchases {
|
||||
existing.Purchases = append(existing.Purchases,
|
||||
scheduling_resources.FromSchedulerObject(tools.PURCHASE_RESOURCE, purch).(*purchase_resource.PurchaseResource))
|
||||
}
|
||||
for _, b := range bookings {
|
||||
existing.Bookings = append(existing.Bookings,
|
||||
scheduling_resources.FromSchedulerObject(tools.BOOKING, b).(*booking.Booking))
|
||||
}
|
||||
utils.GenericRawUpdateOne(existing, existing.GetID(), order.NewAccessor(adminReq))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SessionExecutionsService) upsertDrafts(
|
||||
dt tools.DataType,
|
||||
datas []scheduling_resources.SchedulerObject,
|
||||
existing map[string]scheduling_resources.SchedulerObject,
|
||||
seen map[string]bool,
|
||||
request *tools.APIRequest,
|
||||
) {
|
||||
self := scheduling_resources.GetService().Self()
|
||||
fmt.Println("upsertDrafts", len(datas), len(existing))
|
||||
for _, bk := range datas {
|
||||
if self != nil {
|
||||
bk.SetSchedulerPeerID(self.PeerID)
|
||||
}
|
||||
bk.SetExecutionsID(s.ExecutionsSessionID)
|
||||
seen[bk.GetKey()] = true
|
||||
if prev, ok := existing[bk.GetKey()]; ok {
|
||||
bk.SetID(prev.GetID())
|
||||
bk.SetIsDraft(false)
|
||||
needsConsiders := scheduling_resources.GetService().PropagateWrite(
|
||||
scheduling_resources.FromSchedulerDBObject(dt, bk), bk.GetDestPeer(), dt, request)
|
||||
if needsConsiders {
|
||||
if payload, err := json.Marshal(execution.ConsidersPayload{ID: bk.GetID()}); err == nil {
|
||||
go execution.UpdateExecutionState(payload, dt)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
errCh := make(chan error, 1)
|
||||
scheduling_resources.GetService().PropagateCreate(
|
||||
scheduling_resources.FromSchedulerDBObject(dt, bk), bk.GetDestPeer(), dt, request, errCh)
|
||||
<-errCh
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Session lifecycle
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func (s *SessionExecutionsService) CleanupSession(request *tools.APIRequest) {
|
||||
adminReq := &tools.APIRequest{Admin: true}
|
||||
for _, exec := range s.LoadSessionExecs() {
|
||||
execution.Unschedule(exec.GetID(), request)
|
||||
workflow_execution.NewAccessor(adminReq).DeleteOne(exec.GetID())
|
||||
}
|
||||
if o := s.loadSessionOrder(); o != nil {
|
||||
order.NewAccessor(adminReq).DeleteOne(o.GetID())
|
||||
}
|
||||
}
|
||||
|
||||
func GenerateOrder(
|
||||
purchases, bookings []scheduling_resources.SchedulerObject,
|
||||
executionsID string,
|
||||
request *tools.APIRequest,
|
||||
) (string, error) {
|
||||
newOrder := &order.Order{
|
||||
AbstractObject: utils.AbstractObject{
|
||||
Name: "order_" + request.PeerID + "_" + time.Now().UTC().Format("2006-01-02T15:04:05"),
|
||||
IsDraft: true,
|
||||
},
|
||||
ExecutionsID: executionsID,
|
||||
Purchases: []*purchase_resource.PurchaseResource{},
|
||||
Bookings: []*booking.Booking{},
|
||||
Status: enum.PENDING,
|
||||
}
|
||||
for _, purch := range purchases {
|
||||
newOrder.Purchases = append(newOrder.Purchases,
|
||||
scheduling_resources.FromSchedulerObject(tools.PURCHASE_RESOURCE, purch).(*purchase_resource.PurchaseResource))
|
||||
}
|
||||
for _, b := range bookings {
|
||||
newOrder.Bookings = append(newOrder.Bookings,
|
||||
scheduling_resources.FromSchedulerObject(tools.BOOKING, b).(*booking.Booking))
|
||||
}
|
||||
res, _, err := order.NewAccessor(request).StoreOne(newOrder)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if _, err := bill.DraftFirstBill(res.(*order.Order), request); err != nil {
|
||||
return res.GetID(), err
|
||||
}
|
||||
return res.GetID(), nil
|
||||
}
|
||||
|
||||
func (s *SessionExecutionsService) ConfirmSession(request *tools.APIRequest) error {
|
||||
for _, dt := range []tools.DataType{tools.BOOKING, tools.PURCHASE_RESOURCE} {
|
||||
for _, bk := range s.loadSession(dt) {
|
||||
bk.SetIsDraft(false)
|
||||
needsConsiders := scheduling_resources.GetService().PropagateWrite(
|
||||
scheduling_resources.FromSchedulerDBObject(dt, bk), bk.GetDestPeer(), dt, request)
|
||||
if needsConsiders {
|
||||
if payload, err := json.Marshal(execution.ConsidersPayload{ID: bk.GetID()}); err == nil {
|
||||
go execution.UpdateExecutionState(payload, dt)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user