241 lines
5.4 KiB
Go
241 lines
5.4 KiB
Go
package jobmgr
|
||
|
||
import (
|
||
"fmt"
|
||
"sync"
|
||
"time"
|
||
|
||
schsdk "gitlink.org.cn/cloudream/common/sdks/scheduler"
|
||
jobmod "gitlink.org.cn/cloudream/scheduler/common/models/job"
|
||
"gitlink.org.cn/cloudream/scheduler/common/pkgs/db"
|
||
"gitlink.org.cn/cloudream/scheduler/manager/internal/advisormgr"
|
||
"gitlink.org.cn/cloudream/scheduler/manager/internal/executormgr"
|
||
)
|
||
|
||
type mgrJob struct {
|
||
job Job
|
||
eventSet EventSet
|
||
state JobState
|
||
}
|
||
|
||
type mgrJobSet struct {
|
||
jobs map[schsdk.JobID]*mgrJob
|
||
}
|
||
|
||
type Manager struct {
|
||
// 任何修改job、jobset的操作,都需要加这个锁
|
||
pubLock sync.Mutex
|
||
|
||
ExecMgr *executormgr.Manager
|
||
AdvMgr *advisormgr.Manager
|
||
DB *db.DB
|
||
|
||
jobSetIDIndex int
|
||
jobSets map[schsdk.JobSetID]*mgrJobSet
|
||
jobIDIndex int
|
||
jobs map[schsdk.JobID]*mgrJob
|
||
}
|
||
|
||
func NewManager(execMgr *executormgr.Manager, advMgr *advisormgr.Manager, db *db.DB) (*Manager, error) {
|
||
mgr := &Manager{
|
||
ExecMgr: execMgr,
|
||
AdvMgr: advMgr,
|
||
DB: db,
|
||
jobSets: make(map[schsdk.JobSetID]*mgrJobSet),
|
||
jobs: make(map[schsdk.JobID]*mgrJob),
|
||
}
|
||
|
||
return mgr, nil
|
||
}
|
||
|
||
func (m *Manager) Serve() error {
|
||
|
||
ticker := time.NewTicker(time.Minute)
|
||
defer ticker.Stop()
|
||
|
||
return nil
|
||
}
|
||
|
||
func (m *Manager) Stop() {
|
||
|
||
}
|
||
|
||
func (m *Manager) ChangeState(job *Job, state JobState) {
|
||
m.pubLock.Lock()
|
||
defer m.pubLock.Unlock()
|
||
|
||
mgrJob, ok := m.jobs[job.JobID]
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
lastState := mgrJob.state
|
||
mgrJob.state = state
|
||
|
||
go func() {
|
||
state.Run(JobStateRunContext{
|
||
Mgr: m,
|
||
EventSet: &mgrJob.eventSet,
|
||
LastState: lastState,
|
||
}, job)
|
||
}()
|
||
}
|
||
|
||
func (m *Manager) PostEvent(jobID schsdk.JobID, evt Event) {
|
||
m.pubLock.Lock()
|
||
defer m.pubLock.Unlock()
|
||
|
||
mgrJob, ok := m.jobs[jobID]
|
||
if !ok {
|
||
return
|
||
}
|
||
|
||
go func() {
|
||
mgrJob.eventSet.Post(evt)
|
||
}()
|
||
}
|
||
|
||
// BroadcastEvent 向所有属于指定 jobSet 的任务广播一个事件。
|
||
// jobSetID: 代表作业集的唯一标识符。
|
||
// evt: 需要广播的事件。
|
||
func (m *Manager) BroadcastEvent(jobSetID schsdk.JobSetID, evt Event) {
|
||
// 加锁以确保发布事件时的线程安全
|
||
m.pubLock.Lock()
|
||
defer m.pubLock.Unlock() // 确保函数退出时释放锁
|
||
|
||
// 尝试从管理器的作业集中获取指定的作业集
|
||
jobSet, ok := m.jobSets[jobSetID]
|
||
if !ok {
|
||
// 如果作业集不存在,则直接返回
|
||
return
|
||
}
|
||
|
||
// 遍历作业集中的所有任务,并为每个任务发布事件
|
||
for _, mjob := range jobSet.jobs {
|
||
go func(j *mgrJob) {
|
||
// 使用 goroutine 为每个任务发布事件,以异步方式处理,避免阻塞
|
||
j.eventSet.Post(evt)
|
||
}(mjob)
|
||
}
|
||
}
|
||
|
||
type SubmittingJob struct {
|
||
Body JobBody
|
||
InitState JobState
|
||
}
|
||
|
||
// SubmitJobSet 提交一个作业集,将一组提交作业转换为系统可识别的作业集,并为每个提交的作业创建一个唯一的作业ID。
|
||
//
|
||
// 参数:
|
||
//
|
||
// jobs []SubmittingJob - 要提交的作业列表,每个作业包含作业的初始状态和内容。
|
||
//
|
||
// 返回值:
|
||
//
|
||
// schsdk.JobSetID - 生成的作业集ID,用于标识这个作业集。
|
||
func (m *Manager) SubmitJobSet(jobs []SubmittingJob) schsdk.JobSetID {
|
||
// 加锁以保护对作业集ID和作业ID索引的修改
|
||
m.pubLock.Lock()
|
||
defer m.pubLock.Unlock()
|
||
|
||
// 生成一个新的作业集ID,并递增作业集ID索引
|
||
jobSetID := schsdk.JobSetID(fmt.Sprintf("%d", m.jobSetIDIndex))
|
||
m.jobSetIDIndex += 1
|
||
|
||
// 创建一个新的作业集实例,并初始化其作业映射
|
||
jobSet := &mgrJobSet{
|
||
jobs: make(map[schsdk.JobID]*mgrJob),
|
||
}
|
||
m.jobSets[jobSetID] = jobSet
|
||
|
||
// 遍历提交的作业,为每个作业创建一个唯一的作业ID,初始化作业状态,并将其添加到作业集中
|
||
for i, subJob := range jobs {
|
||
jobID := schsdk.JobID(fmt.Sprintf("%d", m.jobIDIndex+i))
|
||
job := &mgrJob{
|
||
job: Job{
|
||
JobSetID: jobSetID,
|
||
JobID: jobID,
|
||
Body: subJob.Body,
|
||
},
|
||
eventSet: NewEventSet(),
|
||
state: subJob.InitState,
|
||
}
|
||
jobSet.jobs[jobID] = job
|
||
m.jobs[jobID] = job
|
||
|
||
// 更改作业的初始状态
|
||
//m.ChangeState(&job.job, subJob.InitState)
|
||
go func() {
|
||
subJob.InitState.Run(JobStateRunContext{
|
||
Mgr: m,
|
||
EventSet: &job.eventSet,
|
||
LastState: nil,
|
||
}, &job.job)
|
||
}()
|
||
}
|
||
// 更新作业ID索引,基于提交的作业数量
|
||
m.jobIDIndex += len(jobs)
|
||
|
||
// 返回生成的作业集ID
|
||
return jobSetID
|
||
}
|
||
|
||
func (m *Manager) DumpJobSet(jobSetID schsdk.JobSetID) []jobmod.JobDump {
|
||
m.pubLock.Lock()
|
||
defer m.pubLock.Unlock()
|
||
|
||
jobSet, ok := m.jobSets[jobSetID]
|
||
if !ok {
|
||
return nil
|
||
}
|
||
|
||
var jobDumps []jobmod.JobDump
|
||
for _, mgrJob := range jobSet.jobs {
|
||
jobDumps = append(jobDumps, mgrJob.job.Dump(JobStateRunContext{
|
||
Mgr: m,
|
||
EventSet: &mgrJob.eventSet,
|
||
LastState: mgrJob.state,
|
||
}, &mgrJob.job, mgrJob.state))
|
||
}
|
||
|
||
return jobDumps
|
||
}
|
||
|
||
type PreSchedulerInstJob struct {
|
||
Body JobBody
|
||
InitState JobState
|
||
}
|
||
|
||
// AddJob 添加一个作业到指定的作业集。
|
||
func (m *Manager) AddJob(jobSetID schsdk.JobSetID, jobBody JobBody, jobState JobState) schsdk.JobID {
|
||
m.pubLock.Lock()
|
||
defer m.pubLock.Unlock()
|
||
|
||
jobID := schsdk.JobID(fmt.Sprintf("%d", m.jobIDIndex+1))
|
||
m.jobIDIndex += 1
|
||
|
||
job := &mgrJob{
|
||
job: Job{
|
||
JobSetID: jobSetID,
|
||
JobID: jobID,
|
||
Body: jobBody,
|
||
},
|
||
state: jobState,
|
||
eventSet: NewEventSet(),
|
||
}
|
||
|
||
m.jobs[jobID] = job
|
||
jobSet := m.jobSets[jobSetID]
|
||
jobSet.jobs[jobID] = job
|
||
|
||
go func() {
|
||
jobState.Run(JobStateRunContext{
|
||
Mgr: m,
|
||
EventSet: &job.eventSet,
|
||
LastState: nil,
|
||
}, &job.job)
|
||
}()
|
||
|
||
return jobID
|
||
}
|