JCC-CSScheduler/manager/internal/jobmgr/jobmgr.go

241 lines
5.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}