mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2024-12-25 04:49:05 +01:00
Merge pull request #116 from ClusterCockpit/97_107_mark_and_show_shared
97 107 mark and show shared
This commit is contained in:
commit
0d4935e244
@ -27,11 +27,17 @@ type Job {
|
|||||||
state: JobState!
|
state: JobState!
|
||||||
tags: [Tag!]!
|
tags: [Tag!]!
|
||||||
resources: [Resource!]!
|
resources: [Resource!]!
|
||||||
|
concurrentJobs: JobLinkResultList
|
||||||
|
|
||||||
metaData: Any
|
metaData: Any
|
||||||
userData: User
|
userData: User
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type JobLink {
|
||||||
|
id: ID!
|
||||||
|
jobId: Int!
|
||||||
|
}
|
||||||
|
|
||||||
type Cluster {
|
type Cluster {
|
||||||
name: String!
|
name: String!
|
||||||
partitions: [String!]! # Slurm partitions
|
partitions: [String!]! # Slurm partitions
|
||||||
@ -230,6 +236,12 @@ input JobFilter {
|
|||||||
memBwAvg: FloatRange
|
memBwAvg: FloatRange
|
||||||
loadAvg: FloatRange
|
loadAvg: FloatRange
|
||||||
memUsedMax: FloatRange
|
memUsedMax: FloatRange
|
||||||
|
|
||||||
|
exclusive: Int
|
||||||
|
sharedNode: StringInput
|
||||||
|
selfJobId: StringInput
|
||||||
|
selfStartTime: Time
|
||||||
|
selfDuration: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
input OrderByInput {
|
input OrderByInput {
|
||||||
@ -244,6 +256,7 @@ enum SortDirectionEnum {
|
|||||||
|
|
||||||
input StringInput {
|
input StringInput {
|
||||||
eq: String
|
eq: String
|
||||||
|
neq: String
|
||||||
contains: String
|
contains: String
|
||||||
startsWith: String
|
startsWith: String
|
||||||
endsWith: String
|
endsWith: String
|
||||||
@ -261,6 +274,11 @@ type JobResultList {
|
|||||||
count: Int
|
count: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type JobLinkResultList {
|
||||||
|
items: [JobLink!]!
|
||||||
|
count: Int
|
||||||
|
}
|
||||||
|
|
||||||
type HistoPoint {
|
type HistoPoint {
|
||||||
count: Int!
|
count: Int!
|
||||||
value: Int!
|
value: Int!
|
||||||
|
@ -85,6 +85,7 @@ type ComplexityRoot struct {
|
|||||||
Job struct {
|
Job struct {
|
||||||
ArrayJobId func(childComplexity int) int
|
ArrayJobId func(childComplexity int) int
|
||||||
Cluster func(childComplexity int) int
|
Cluster func(childComplexity int) int
|
||||||
|
ConcurrentJobs func(childComplexity int) int
|
||||||
Duration func(childComplexity int) int
|
Duration func(childComplexity int) int
|
||||||
Exclusive func(childComplexity int) int
|
Exclusive func(childComplexity int) int
|
||||||
ID func(childComplexity int) int
|
ID func(childComplexity int) int
|
||||||
@ -108,6 +109,16 @@ type ComplexityRoot struct {
|
|||||||
Walltime func(childComplexity int) int
|
Walltime func(childComplexity int) int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JobLink struct {
|
||||||
|
ID func(childComplexity int) int
|
||||||
|
JobID func(childComplexity int) int
|
||||||
|
}
|
||||||
|
|
||||||
|
JobLinkResultList struct {
|
||||||
|
Count func(childComplexity int) int
|
||||||
|
Items func(childComplexity int) int
|
||||||
|
}
|
||||||
|
|
||||||
JobMetric struct {
|
JobMetric struct {
|
||||||
Series func(childComplexity int) int
|
Series func(childComplexity int) int
|
||||||
StatisticsSeries func(childComplexity int) int
|
StatisticsSeries func(childComplexity int) int
|
||||||
@ -280,6 +291,7 @@ type JobResolver interface {
|
|||||||
|
|
||||||
Tags(ctx context.Context, obj *schema.Job) ([]*schema.Tag, error)
|
Tags(ctx context.Context, obj *schema.Job) ([]*schema.Tag, error)
|
||||||
|
|
||||||
|
ConcurrentJobs(ctx context.Context, obj *schema.Job) (*model.JobLinkResultList, error)
|
||||||
MetaData(ctx context.Context, obj *schema.Job) (interface{}, error)
|
MetaData(ctx context.Context, obj *schema.Job) (interface{}, error)
|
||||||
UserData(ctx context.Context, obj *schema.Job) (*model.User, error)
|
UserData(ctx context.Context, obj *schema.Job) (*model.User, error)
|
||||||
}
|
}
|
||||||
@ -442,6 +454,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.Job.Cluster(childComplexity), true
|
return e.complexity.Job.Cluster(childComplexity), true
|
||||||
|
|
||||||
|
case "Job.concurrentJobs":
|
||||||
|
if e.complexity.Job.ConcurrentJobs == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Job.ConcurrentJobs(childComplexity), true
|
||||||
|
|
||||||
case "Job.duration":
|
case "Job.duration":
|
||||||
if e.complexity.Job.Duration == nil {
|
if e.complexity.Job.Duration == nil {
|
||||||
break
|
break
|
||||||
@ -589,6 +608,34 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.Job.Walltime(childComplexity), true
|
return e.complexity.Job.Walltime(childComplexity), true
|
||||||
|
|
||||||
|
case "JobLink.id":
|
||||||
|
if e.complexity.JobLink.ID == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.JobLink.ID(childComplexity), true
|
||||||
|
|
||||||
|
case "JobLink.jobId":
|
||||||
|
if e.complexity.JobLink.JobID == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.JobLink.JobID(childComplexity), true
|
||||||
|
|
||||||
|
case "JobLinkResultList.count":
|
||||||
|
if e.complexity.JobLinkResultList.Count == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.JobLinkResultList.Count(childComplexity), true
|
||||||
|
|
||||||
|
case "JobLinkResultList.items":
|
||||||
|
if e.complexity.JobLinkResultList.Items == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.JobLinkResultList.Items(childComplexity), true
|
||||||
|
|
||||||
case "JobMetric.series":
|
case "JobMetric.series":
|
||||||
if e.complexity.JobMetric.Series == nil {
|
if e.complexity.JobMetric.Series == nil {
|
||||||
break
|
break
|
||||||
@ -1468,11 +1515,17 @@ type Job {
|
|||||||
state: JobState!
|
state: JobState!
|
||||||
tags: [Tag!]!
|
tags: [Tag!]!
|
||||||
resources: [Resource!]!
|
resources: [Resource!]!
|
||||||
|
concurrentJobs: JobLinkResultList
|
||||||
|
|
||||||
metaData: Any
|
metaData: Any
|
||||||
userData: User
|
userData: User
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type JobLink {
|
||||||
|
id: ID!
|
||||||
|
jobId: Int!
|
||||||
|
}
|
||||||
|
|
||||||
type Cluster {
|
type Cluster {
|
||||||
name: String!
|
name: String!
|
||||||
partitions: [String!]! # Slurm partitions
|
partitions: [String!]! # Slurm partitions
|
||||||
@ -1671,6 +1724,12 @@ input JobFilter {
|
|||||||
memBwAvg: FloatRange
|
memBwAvg: FloatRange
|
||||||
loadAvg: FloatRange
|
loadAvg: FloatRange
|
||||||
memUsedMax: FloatRange
|
memUsedMax: FloatRange
|
||||||
|
|
||||||
|
exclusive: Int
|
||||||
|
sharedNode: StringInput
|
||||||
|
selfJobId: StringInput
|
||||||
|
selfStartTime: Time
|
||||||
|
selfDuration: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
input OrderByInput {
|
input OrderByInput {
|
||||||
@ -1685,6 +1744,7 @@ enum SortDirectionEnum {
|
|||||||
|
|
||||||
input StringInput {
|
input StringInput {
|
||||||
eq: String
|
eq: String
|
||||||
|
neq: String
|
||||||
contains: String
|
contains: String
|
||||||
startsWith: String
|
startsWith: String
|
||||||
endsWith: String
|
endsWith: String
|
||||||
@ -1702,6 +1762,11 @@ type JobResultList {
|
|||||||
count: Int
|
count: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type JobLinkResultList {
|
||||||
|
items: [JobLink!]!
|
||||||
|
count: Int
|
||||||
|
}
|
||||||
|
|
||||||
type HistoPoint {
|
type HistoPoint {
|
||||||
count: Int!
|
count: Int!
|
||||||
value: Int!
|
value: Int!
|
||||||
@ -3875,6 +3940,53 @@ func (ec *executionContext) fieldContext_Job_resources(ctx context.Context, fiel
|
|||||||
return fc, nil
|
return fc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Job_concurrentJobs(ctx context.Context, field graphql.CollectedField, obj *schema.Job) (ret graphql.Marshaler) {
|
||||||
|
fc, err := ec.fieldContext_Job_concurrentJobs(ctx, field)
|
||||||
|
if err != nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return ec.resolvers.Job().ConcurrentJobs(rctx, obj)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(*model.JobLinkResultList)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalOJobLinkResultList2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐJobLinkResultList(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_Job_concurrentJobs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||||
|
fc = &graphql.FieldContext{
|
||||||
|
Object: "Job",
|
||||||
|
Field: field,
|
||||||
|
IsMethod: true,
|
||||||
|
IsResolver: true,
|
||||||
|
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||||
|
switch field.Name {
|
||||||
|
case "items":
|
||||||
|
return ec.fieldContext_JobLinkResultList_items(ctx, field)
|
||||||
|
case "count":
|
||||||
|
return ec.fieldContext_JobLinkResultList_count(ctx, field)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("no field named %q was found under type JobLinkResultList", field.Name)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return fc, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Job_metaData(ctx context.Context, field graphql.CollectedField, obj *schema.Job) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Job_metaData(ctx context.Context, field graphql.CollectedField, obj *schema.Job) (ret graphql.Marshaler) {
|
||||||
fc, err := ec.fieldContext_Job_metaData(ctx, field)
|
fc, err := ec.fieldContext_Job_metaData(ctx, field)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -3965,6 +4077,185 @@ func (ec *executionContext) fieldContext_Job_userData(ctx context.Context, field
|
|||||||
return fc, nil
|
return fc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _JobLink_id(ctx context.Context, field graphql.CollectedField, obj *model.JobLink) (ret graphql.Marshaler) {
|
||||||
|
fc, err := ec.fieldContext_JobLink_id(ctx, field)
|
||||||
|
if err != nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return obj.ID, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(string)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNID2string(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_JobLink_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||||
|
fc = &graphql.FieldContext{
|
||||||
|
Object: "JobLink",
|
||||||
|
Field: field,
|
||||||
|
IsMethod: false,
|
||||||
|
IsResolver: false,
|
||||||
|
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||||
|
return nil, errors.New("field of type ID does not have child fields")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return fc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _JobLink_jobId(ctx context.Context, field graphql.CollectedField, obj *model.JobLink) (ret graphql.Marshaler) {
|
||||||
|
fc, err := ec.fieldContext_JobLink_jobId(ctx, field)
|
||||||
|
if err != nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return obj.JobID, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(int)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNInt2int(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_JobLink_jobId(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||||
|
fc = &graphql.FieldContext{
|
||||||
|
Object: "JobLink",
|
||||||
|
Field: field,
|
||||||
|
IsMethod: false,
|
||||||
|
IsResolver: false,
|
||||||
|
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||||
|
return nil, errors.New("field of type Int does not have child fields")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return fc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _JobLinkResultList_items(ctx context.Context, field graphql.CollectedField, obj *model.JobLinkResultList) (ret graphql.Marshaler) {
|
||||||
|
fc, err := ec.fieldContext_JobLinkResultList_items(ctx, field)
|
||||||
|
if err != nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return obj.Items, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.([]*model.JobLink)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNJobLink2ᚕᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐJobLinkᚄ(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_JobLinkResultList_items(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||||
|
fc = &graphql.FieldContext{
|
||||||
|
Object: "JobLinkResultList",
|
||||||
|
Field: field,
|
||||||
|
IsMethod: false,
|
||||||
|
IsResolver: false,
|
||||||
|
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||||
|
switch field.Name {
|
||||||
|
case "id":
|
||||||
|
return ec.fieldContext_JobLink_id(ctx, field)
|
||||||
|
case "jobId":
|
||||||
|
return ec.fieldContext_JobLink_jobId(ctx, field)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("no field named %q was found under type JobLink", field.Name)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return fc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _JobLinkResultList_count(ctx context.Context, field graphql.CollectedField, obj *model.JobLinkResultList) (ret graphql.Marshaler) {
|
||||||
|
fc, err := ec.fieldContext_JobLinkResultList_count(ctx, field)
|
||||||
|
if err != nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return obj.Count, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(*int)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalOInt2ᚖint(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_JobLinkResultList_count(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||||
|
fc = &graphql.FieldContext{
|
||||||
|
Object: "JobLinkResultList",
|
||||||
|
Field: field,
|
||||||
|
IsMethod: false,
|
||||||
|
IsResolver: false,
|
||||||
|
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||||
|
return nil, errors.New("field of type Int does not have child fields")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return fc, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _JobMetric_unit(ctx context.Context, field graphql.CollectedField, obj *schema.JobMetric) (ret graphql.Marshaler) {
|
func (ec *executionContext) _JobMetric_unit(ctx context.Context, field graphql.CollectedField, obj *schema.JobMetric) (ret graphql.Marshaler) {
|
||||||
fc, err := ec.fieldContext_JobMetric_unit(ctx, field)
|
fc, err := ec.fieldContext_JobMetric_unit(ctx, field)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -4379,6 +4670,8 @@ func (ec *executionContext) fieldContext_JobResultList_items(ctx context.Context
|
|||||||
return ec.fieldContext_Job_tags(ctx, field)
|
return ec.fieldContext_Job_tags(ctx, field)
|
||||||
case "resources":
|
case "resources":
|
||||||
return ec.fieldContext_Job_resources(ctx, field)
|
return ec.fieldContext_Job_resources(ctx, field)
|
||||||
|
case "concurrentJobs":
|
||||||
|
return ec.fieldContext_Job_concurrentJobs(ctx, field)
|
||||||
case "metaData":
|
case "metaData":
|
||||||
return ec.fieldContext_Job_metaData(ctx, field)
|
return ec.fieldContext_Job_metaData(ctx, field)
|
||||||
case "userData":
|
case "userData":
|
||||||
@ -6376,6 +6669,8 @@ func (ec *executionContext) fieldContext_Query_job(ctx context.Context, field gr
|
|||||||
return ec.fieldContext_Job_tags(ctx, field)
|
return ec.fieldContext_Job_tags(ctx, field)
|
||||||
case "resources":
|
case "resources":
|
||||||
return ec.fieldContext_Job_resources(ctx, field)
|
return ec.fieldContext_Job_resources(ctx, field)
|
||||||
|
case "concurrentJobs":
|
||||||
|
return ec.fieldContext_Job_concurrentJobs(ctx, field)
|
||||||
case "metaData":
|
case "metaData":
|
||||||
return ec.fieldContext_Job_metaData(ctx, field)
|
return ec.fieldContext_Job_metaData(ctx, field)
|
||||||
case "userData":
|
case "userData":
|
||||||
@ -10741,7 +11036,7 @@ func (ec *executionContext) unmarshalInputJobFilter(ctx context.Context, obj int
|
|||||||
asMap[k] = v
|
asMap[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldsInOrder := [...]string{"tags", "jobId", "arrayJobId", "user", "project", "jobName", "cluster", "partition", "duration", "minRunningFor", "numNodes", "numAccelerators", "numHWThreads", "startTime", "state", "flopsAnyAvg", "memBwAvg", "loadAvg", "memUsedMax"}
|
fieldsInOrder := [...]string{"tags", "jobId", "arrayJobId", "user", "project", "jobName", "cluster", "partition", "duration", "minRunningFor", "numNodes", "numAccelerators", "numHWThreads", "startTime", "state", "flopsAnyAvg", "memBwAvg", "loadAvg", "memUsedMax", "exclusive", "sharedNode", "selfJobId", "selfStartTime", "selfDuration"}
|
||||||
for _, k := range fieldsInOrder {
|
for _, k := range fieldsInOrder {
|
||||||
v, ok := asMap[k]
|
v, ok := asMap[k]
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -10900,6 +11195,46 @@ func (ec *executionContext) unmarshalInputJobFilter(ctx context.Context, obj int
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return it, err
|
return it, err
|
||||||
}
|
}
|
||||||
|
case "exclusive":
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("exclusive"))
|
||||||
|
it.Exclusive, err = ec.unmarshalOInt2ᚖint(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
|
case "sharedNode":
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("sharedNode"))
|
||||||
|
it.SharedNode, err = ec.unmarshalOStringInput2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐStringInput(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
|
case "selfJobId":
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("selfJobId"))
|
||||||
|
it.SelfJobID, err = ec.unmarshalOStringInput2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐStringInput(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
|
case "selfStartTime":
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("selfStartTime"))
|
||||||
|
it.SelfStartTime, err = ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
|
case "selfDuration":
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("selfDuration"))
|
||||||
|
it.SelfDuration, err = ec.unmarshalOInt2ᚖint(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10989,7 +11324,7 @@ func (ec *executionContext) unmarshalInputStringInput(ctx context.Context, obj i
|
|||||||
asMap[k] = v
|
asMap[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldsInOrder := [...]string{"eq", "contains", "startsWith", "endsWith", "in"}
|
fieldsInOrder := [...]string{"eq", "neq", "contains", "startsWith", "endsWith", "in"}
|
||||||
for _, k := range fieldsInOrder {
|
for _, k := range fieldsInOrder {
|
||||||
v, ok := asMap[k]
|
v, ok := asMap[k]
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -11004,6 +11339,14 @@ func (ec *executionContext) unmarshalInputStringInput(ctx context.Context, obj i
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return it, err
|
return it, err
|
||||||
}
|
}
|
||||||
|
case "neq":
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("neq"))
|
||||||
|
it.Neq, err = ec.unmarshalOString2ᚖstring(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
case "contains":
|
case "contains":
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@ -11510,6 +11853,23 @@ func (ec *executionContext) _Job(ctx context.Context, sel ast.SelectionSet, obj
|
|||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
atomic.AddUint32(&invalids, 1)
|
atomic.AddUint32(&invalids, 1)
|
||||||
}
|
}
|
||||||
|
case "concurrentJobs":
|
||||||
|
field := field
|
||||||
|
|
||||||
|
innerFunc := func(ctx context.Context) (res graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
res = ec._Job_concurrentJobs(ctx, field, obj)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
out.Concurrently(i, func() graphql.Marshaler {
|
||||||
|
return innerFunc(ctx)
|
||||||
|
|
||||||
|
})
|
||||||
case "metaData":
|
case "metaData":
|
||||||
field := field
|
field := field
|
||||||
|
|
||||||
@ -11555,6 +11915,73 @@ func (ec *executionContext) _Job(ctx context.Context, sel ast.SelectionSet, obj
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var jobLinkImplementors = []string{"JobLink"}
|
||||||
|
|
||||||
|
func (ec *executionContext) _JobLink(ctx context.Context, sel ast.SelectionSet, obj *model.JobLink) graphql.Marshaler {
|
||||||
|
fields := graphql.CollectFields(ec.OperationContext, sel, jobLinkImplementors)
|
||||||
|
out := graphql.NewFieldSet(fields)
|
||||||
|
var invalids uint32
|
||||||
|
for i, field := range fields {
|
||||||
|
switch field.Name {
|
||||||
|
case "__typename":
|
||||||
|
out.Values[i] = graphql.MarshalString("JobLink")
|
||||||
|
case "id":
|
||||||
|
|
||||||
|
out.Values[i] = ec._JobLink_id(ctx, field, obj)
|
||||||
|
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
|
case "jobId":
|
||||||
|
|
||||||
|
out.Values[i] = ec._JobLink_jobId(ctx, field, obj)
|
||||||
|
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("unknown field " + strconv.Quote(field.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.Dispatch()
|
||||||
|
if invalids > 0 {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
var jobLinkResultListImplementors = []string{"JobLinkResultList"}
|
||||||
|
|
||||||
|
func (ec *executionContext) _JobLinkResultList(ctx context.Context, sel ast.SelectionSet, obj *model.JobLinkResultList) graphql.Marshaler {
|
||||||
|
fields := graphql.CollectFields(ec.OperationContext, sel, jobLinkResultListImplementors)
|
||||||
|
out := graphql.NewFieldSet(fields)
|
||||||
|
var invalids uint32
|
||||||
|
for i, field := range fields {
|
||||||
|
switch field.Name {
|
||||||
|
case "__typename":
|
||||||
|
out.Values[i] = graphql.MarshalString("JobLinkResultList")
|
||||||
|
case "items":
|
||||||
|
|
||||||
|
out.Values[i] = ec._JobLinkResultList_items(ctx, field, obj)
|
||||||
|
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
|
case "count":
|
||||||
|
|
||||||
|
out.Values[i] = ec._JobLinkResultList_count(ctx, field, obj)
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("unknown field " + strconv.Quote(field.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.Dispatch()
|
||||||
|
if invalids > 0 {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
var jobMetricImplementors = []string{"JobMetric"}
|
var jobMetricImplementors = []string{"JobMetric"}
|
||||||
|
|
||||||
func (ec *executionContext) _JobMetric(ctx context.Context, sel ast.SelectionSet, obj *schema.JobMetric) graphql.Marshaler {
|
func (ec *executionContext) _JobMetric(ctx context.Context, sel ast.SelectionSet, obj *schema.JobMetric) graphql.Marshaler {
|
||||||
@ -13686,6 +14113,60 @@ func (ec *executionContext) unmarshalNJobFilter2ᚖgithubᚗcomᚋClusterCockpit
|
|||||||
return &res, graphql.ErrorOnPath(ctx, err)
|
return &res, graphql.ErrorOnPath(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) marshalNJobLink2ᚕᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐJobLinkᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.JobLink) graphql.Marshaler {
|
||||||
|
ret := make(graphql.Array, len(v))
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
isLen1 := len(v) == 1
|
||||||
|
if !isLen1 {
|
||||||
|
wg.Add(len(v))
|
||||||
|
}
|
||||||
|
for i := range v {
|
||||||
|
i := i
|
||||||
|
fc := &graphql.FieldContext{
|
||||||
|
Index: &i,
|
||||||
|
Result: &v[i],
|
||||||
|
}
|
||||||
|
ctx := graphql.WithFieldContext(ctx, fc)
|
||||||
|
f := func(i int) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if !isLen1 {
|
||||||
|
defer wg.Done()
|
||||||
|
}
|
||||||
|
ret[i] = ec.marshalNJobLink2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐJobLink(ctx, sel, v[i])
|
||||||
|
}
|
||||||
|
if isLen1 {
|
||||||
|
f(i)
|
||||||
|
} else {
|
||||||
|
go f(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
for _, e := range ret {
|
||||||
|
if e == graphql.Null {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) marshalNJobLink2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐJobLink(ctx context.Context, sel ast.SelectionSet, v *model.JobLink) graphql.Marshaler {
|
||||||
|
if v == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||||
|
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
return ec._JobLink(ctx, sel, v)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) marshalNJobMetric2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋpkgᚋschemaᚐJobMetric(ctx context.Context, sel ast.SelectionSet, v *schema.JobMetric) graphql.Marshaler {
|
func (ec *executionContext) marshalNJobMetric2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋpkgᚋschemaᚐJobMetric(ctx context.Context, sel ast.SelectionSet, v *schema.JobMetric) graphql.Marshaler {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||||
@ -14944,6 +15425,13 @@ func (ec *executionContext) unmarshalOJobFilter2ᚖgithubᚗcomᚋClusterCockpit
|
|||||||
return &res, graphql.ErrorOnPath(ctx, err)
|
return &res, graphql.ErrorOnPath(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) marshalOJobLinkResultList2ᚖgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋinternalᚋgraphᚋmodelᚐJobLinkResultList(ctx context.Context, sel ast.SelectionSet, v *model.JobLinkResultList) graphql.Marshaler {
|
||||||
|
if v == nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
return ec._JobLinkResultList(ctx, sel, v)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) unmarshalOJobState2ᚕgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋpkgᚋschemaᚐJobStateᚄ(ctx context.Context, v interface{}) ([]schema.JobState, error) {
|
func (ec *executionContext) unmarshalOJobState2ᚕgithubᚗcomᚋClusterCockpitᚋccᚑbackendᚋpkgᚋschemaᚐJobStateᚄ(ctx context.Context, v interface{}) ([]schema.JobState, error) {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -56,6 +56,21 @@ type JobFilter struct {
|
|||||||
MemBwAvg *FloatRange `json:"memBwAvg"`
|
MemBwAvg *FloatRange `json:"memBwAvg"`
|
||||||
LoadAvg *FloatRange `json:"loadAvg"`
|
LoadAvg *FloatRange `json:"loadAvg"`
|
||||||
MemUsedMax *FloatRange `json:"memUsedMax"`
|
MemUsedMax *FloatRange `json:"memUsedMax"`
|
||||||
|
Exclusive *int `json:"exclusive"`
|
||||||
|
SharedNode *StringInput `json:"sharedNode"`
|
||||||
|
SelfJobID *StringInput `json:"selfJobId"`
|
||||||
|
SelfStartTime *time.Time `json:"selfStartTime"`
|
||||||
|
SelfDuration *int `json:"selfDuration"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JobLink struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
JobID int `json:"jobId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JobLinkResultList struct {
|
||||||
|
Items []*JobLink `json:"items"`
|
||||||
|
Count *int `json:"count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type JobMetricWithName struct {
|
type JobMetricWithName struct {
|
||||||
@ -105,6 +120,7 @@ type PageRequest struct {
|
|||||||
|
|
||||||
type StringInput struct {
|
type StringInput struct {
|
||||||
Eq *string `json:"eq"`
|
Eq *string `json:"eq"`
|
||||||
|
Neq *string `json:"neq"`
|
||||||
Contains *string `json:"contains"`
|
Contains *string `json:"contains"`
|
||||||
StartsWith *string `json:"startsWith"`
|
StartsWith *string `json:"startsWith"`
|
||||||
EndsWith *string `json:"endsWith"`
|
EndsWith *string `json:"endsWith"`
|
||||||
|
@ -36,6 +36,39 @@ func (r *jobResolver) Tags(ctx context.Context, obj *schema.Job) ([]*schema.Tag,
|
|||||||
return r.Repo.GetTags(&obj.ID)
|
return r.Repo.GetTags(&obj.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConcurrentJobs is the resolver for the concurrentJobs field.
|
||||||
|
func (r *jobResolver) ConcurrentJobs(ctx context.Context, obj *schema.Job) (*model.JobLinkResultList, error) {
|
||||||
|
|
||||||
|
exc := int(obj.Exclusive)
|
||||||
|
if exc != 1 {
|
||||||
|
filter := []*model.JobFilter{}
|
||||||
|
jid := fmt.Sprint(obj.JobID)
|
||||||
|
jdu := int(obj.Duration)
|
||||||
|
filter = append(filter, &model.JobFilter{Exclusive: &exc})
|
||||||
|
filter = append(filter, &model.JobFilter{SharedNode: &model.StringInput{Contains: &obj.Resources[0].Hostname}})
|
||||||
|
filter = append(filter, &model.JobFilter{SelfJobID: &model.StringInput{Neq: &jid}})
|
||||||
|
filter = append(filter, &model.JobFilter{SelfStartTime: &obj.StartTime, SelfDuration: &jdu})
|
||||||
|
|
||||||
|
jobLinks, err := r.Repo.QueryJobLinks(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Error while querying jobLinks")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := r.Repo.CountJobs(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Error while counting jobLinks")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := &model.JobLinkResultList{Items: jobLinks, Count: &count}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// MetaData is the resolver for the metaData field.
|
// MetaData is the resolver for the metaData field.
|
||||||
func (r *jobResolver) MetaData(ctx context.Context, obj *schema.Job) (interface{}, error) {
|
func (r *jobResolver) MetaData(ctx context.Context, obj *schema.Job) (interface{}, error) {
|
||||||
return r.Repo.FetchMetadata(obj)
|
return r.Repo.FetchMetadata(obj)
|
||||||
|
@ -74,7 +74,7 @@ func scanJob(row interface{ Scan(...interface{}) error }) (*schema.Job, error) {
|
|||||||
&job.ID, &job.JobID, &job.User, &job.Project, &job.Cluster, &job.SubCluster, &job.StartTimeUnix, &job.Partition, &job.ArrayJobId,
|
&job.ID, &job.JobID, &job.User, &job.Project, &job.Cluster, &job.SubCluster, &job.StartTimeUnix, &job.Partition, &job.ArrayJobId,
|
||||||
&job.NumNodes, &job.NumHWThreads, &job.NumAcc, &job.Exclusive, &job.MonitoringStatus, &job.SMT, &job.State,
|
&job.NumNodes, &job.NumHWThreads, &job.NumAcc, &job.Exclusive, &job.MonitoringStatus, &job.SMT, &job.State,
|
||||||
&job.Duration, &job.Walltime, &job.RawResources /*&job.RawMetaData*/); err != nil {
|
&job.Duration, &job.Walltime, &job.RawResources /*&job.RawMetaData*/); err != nil {
|
||||||
log.Warnf("Error while scanning rows: %v", err)
|
log.Warnf("Error while scanning rows (Job): %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +140,17 @@ func (r *JobRepository) Flush() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func scanJobLink(row interface{ Scan(...interface{}) error }) (*model.JobLink, error) {
|
||||||
|
jobLink := &model.JobLink{}
|
||||||
|
if err := row.Scan(
|
||||||
|
&jobLink.ID, &jobLink.JobID); err != nil {
|
||||||
|
log.Warn("Error while scanning rows (jobLink)")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return jobLink, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *JobRepository) FetchJobName(job *schema.Job) (*string, error) {
|
func (r *JobRepository) FetchJobName(job *schema.Job) (*string, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
cachekey := fmt.Sprintf("metadata:%d", job.ID)
|
cachekey := fmt.Sprintf("metadata:%d", job.ID)
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SecurityCheck-less, private: Returns a list of jobs matching the provided filters. page and order are optional-
|
||||||
func (r *JobRepository) queryJobs(
|
func (r *JobRepository) queryJobs(
|
||||||
query sq.SelectBuilder,
|
query sq.SelectBuilder,
|
||||||
filters []*model.JobFilter,
|
filters []*model.JobFilter,
|
||||||
@ -65,7 +66,7 @@ func (r *JobRepository) queryJobs(
|
|||||||
job, err := scanJob(rows)
|
job, err := scanJob(rows)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rows.Close()
|
rows.Close()
|
||||||
log.Warn("Error while scanning rows")
|
log.Warn("Error while scanning rows (Jobs)")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
jobs = append(jobs, job)
|
jobs = append(jobs, job)
|
||||||
@ -74,6 +75,7 @@ func (r *JobRepository) queryJobs(
|
|||||||
return jobs, nil
|
return jobs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// testFunction for queryJobs
|
||||||
func (r *JobRepository) testQueryJobs(
|
func (r *JobRepository) testQueryJobs(
|
||||||
filters []*model.JobFilter,
|
filters []*model.JobFilter,
|
||||||
page *model.PageRequest,
|
page *model.PageRequest,
|
||||||
@ -83,7 +85,7 @@ func (r *JobRepository) testQueryJobs(
|
|||||||
filters, page, order)
|
filters, page, order)
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryJobs returns a list of jobs matching the provided filters. page and order are optional-
|
// Public function with added securityCheck, calls private queryJobs function above
|
||||||
func (r *JobRepository) QueryJobs(
|
func (r *JobRepository) QueryJobs(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
filters []*model.JobFilter,
|
filters []*model.JobFilter,
|
||||||
@ -100,6 +102,63 @@ func (r *JobRepository) QueryJobs(
|
|||||||
filters, page, order)
|
filters, page, order)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SecurityCheck-less, private: returns a list of minimal job information (DB-ID and jobId) of shared jobs for link-building based the provided filters.
|
||||||
|
func (r *JobRepository) queryJobLinks(
|
||||||
|
query sq.SelectBuilder,
|
||||||
|
filters []*model.JobFilter) ([]*model.JobLink, error) {
|
||||||
|
|
||||||
|
for _, f := range filters {
|
||||||
|
query = BuildWhereClause(f, query)
|
||||||
|
}
|
||||||
|
|
||||||
|
sql, args, err := query.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Error while converting query to sql")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("SQL query: `%s`, args: %#v", sql, args)
|
||||||
|
rows, err := query.RunWith(r.stmtCache).Query()
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error while running query")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
jobLinks := make([]*model.JobLink, 0, 50)
|
||||||
|
for rows.Next() {
|
||||||
|
jobLink, err := scanJobLink(rows)
|
||||||
|
if err != nil {
|
||||||
|
rows.Close()
|
||||||
|
log.Warn("Error while scanning rows (JobLinks)")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
jobLinks = append(jobLinks, jobLink)
|
||||||
|
}
|
||||||
|
|
||||||
|
return jobLinks, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFunction for queryJobLinks
|
||||||
|
func (r *JobRepository) testQueryJobLinks(
|
||||||
|
filters []*model.JobFilter) ([]*model.JobLink, error) {
|
||||||
|
|
||||||
|
return r.queryJobLinks(sq.Select(jobColumns...).From("job"), filters)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *JobRepository) QueryJobLinks(
|
||||||
|
ctx context.Context,
|
||||||
|
filters []*model.JobFilter) ([]*model.JobLink, error) {
|
||||||
|
|
||||||
|
query, qerr := SecurityCheck(ctx, sq.Select("job.id", "job.job_id").From("job"))
|
||||||
|
|
||||||
|
if qerr != nil {
|
||||||
|
return nil, qerr
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.queryJobLinks(query, filters)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SecurityCheck-less, private: Returns the number of jobs matching the filters
|
||||||
func (r *JobRepository) countJobs(query sq.SelectBuilder,
|
func (r *JobRepository) countJobs(query sq.SelectBuilder,
|
||||||
filters []*model.JobFilter) (int, error) {
|
filters []*model.JobFilter) (int, error) {
|
||||||
|
|
||||||
@ -122,12 +181,14 @@ func (r *JobRepository) countJobs(query sq.SelectBuilder,
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// testFunction for countJobs
|
||||||
func (r *JobRepository) testCountJobs(
|
func (r *JobRepository) testCountJobs(
|
||||||
filters []*model.JobFilter) (int, error) {
|
filters []*model.JobFilter) (int, error) {
|
||||||
|
|
||||||
return r.countJobs(sq.Select("count(*)").From("job"), filters)
|
return r.countJobs(sq.Select("count(*)").From("job"), filters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Public function with added securityCheck, calls private countJobs function above
|
||||||
func (r *JobRepository) CountJobs(
|
func (r *JobRepository) CountJobs(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
filters []*model.JobFilter) (int, error) {
|
filters []*model.JobFilter) (int, error) {
|
||||||
@ -226,6 +287,21 @@ func BuildWhereClause(filter *model.JobFilter, query sq.SelectBuilder) sq.Select
|
|||||||
if filter.MemUsedMax != nil {
|
if filter.MemUsedMax != nil {
|
||||||
query = buildFloatCondition("job.mem_used_max", filter.MemUsedMax, query)
|
query = buildFloatCondition("job.mem_used_max", filter.MemUsedMax, query)
|
||||||
}
|
}
|
||||||
|
// Shared Jobs Query
|
||||||
|
if filter.Exclusive != nil {
|
||||||
|
query = query.Where("job.exclusive = ?", *filter.Exclusive)
|
||||||
|
}
|
||||||
|
if filter.SharedNode != nil {
|
||||||
|
query = buildStringCondition("job.resources", filter.SharedNode, query)
|
||||||
|
}
|
||||||
|
if filter.SelfJobID != nil {
|
||||||
|
query = buildStringCondition("job.job_id", filter.SelfJobID, query)
|
||||||
|
}
|
||||||
|
if filter.SelfStartTime != nil && filter.SelfDuration != nil {
|
||||||
|
start := filter.SelfStartTime.Unix() + 10 // There does not seem to be a portable way to get the current unix timestamp accross different DBs.
|
||||||
|
end := start + int64(*filter.SelfDuration) - 20
|
||||||
|
query = query.Where("((job.start_time BETWEEN ? AND ?) OR ((job.start_time + job.duration) BETWEEN ? AND ?))", start, end, start, end)
|
||||||
|
}
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,6 +329,9 @@ func buildStringCondition(field string, cond *model.StringInput, query sq.Select
|
|||||||
if cond.Eq != nil {
|
if cond.Eq != nil {
|
||||||
return query.Where(field+" = ?", *cond.Eq)
|
return query.Where(field+" = ?", *cond.Eq)
|
||||||
}
|
}
|
||||||
|
if cond.Neq != nil {
|
||||||
|
return query.Where(field+" != ?", *cond.Neq)
|
||||||
|
}
|
||||||
if cond.StartsWith != nil {
|
if cond.StartsWith != nil {
|
||||||
return query.Where(field+" LIKE ?", fmt.Sprint(*cond.StartsWith, "%"))
|
return query.Where(field+" LIKE ?", fmt.Sprint(*cond.StartsWith, "%"))
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ type BaseJob struct {
|
|||||||
Resources []*Resource `json:"resources"` // Resources used by job
|
Resources []*Resource `json:"resources"` // Resources used by job
|
||||||
RawMetaData []byte `json:"-" db:"meta_data"` // Additional information about the job [As Bytes]
|
RawMetaData []byte `json:"-" db:"meta_data"` // Additional information about the job [As Bytes]
|
||||||
MetaData map[string]string `json:"metaData"` // Additional information about the job
|
MetaData map[string]string `json:"metaData"` // Additional information about the job
|
||||||
|
ConcurrentJobs JobLinkResultList `json:"concurrentJobs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Job struct type
|
// Job struct type
|
||||||
@ -72,6 +73,17 @@ type Job struct {
|
|||||||
// *int64 `json:"id,omitempty"` >> never used in the job-archive, only
|
// *int64 `json:"id,omitempty"` >> never used in the job-archive, only
|
||||||
// available via REST-API
|
// available via REST-API
|
||||||
//
|
//
|
||||||
|
|
||||||
|
type JobLink struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
JobID int64 `json:"jobId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JobLinkResultList struct {
|
||||||
|
Items []*JobLink `json:"items"`
|
||||||
|
Count int `json:"count"`
|
||||||
|
}
|
||||||
|
|
||||||
// JobMeta model
|
// JobMeta model
|
||||||
// @Description Meta data information of a HPC job.
|
// @Description Meta data information of a HPC job.
|
||||||
type JobMeta struct {
|
type JobMeta struct {
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
import { getContext } from 'svelte'
|
import { getContext } from 'svelte'
|
||||||
|
|
||||||
export let dbid
|
export let dbid
|
||||||
|
export let authlevel
|
||||||
|
export let roles
|
||||||
|
|
||||||
const { query: initq } = init(`
|
const { query: initq } = init(`
|
||||||
job(id: "${dbid}") {
|
job(id: "${dbid}") {
|
||||||
@ -23,8 +25,9 @@
|
|||||||
monitoringStatus, state, walltime,
|
monitoringStatus, state, walltime,
|
||||||
tags { id, type, name },
|
tags { id, type, name },
|
||||||
resources { hostname, hwthreads, accelerators },
|
resources { hostname, hwthreads, accelerators },
|
||||||
metaData
|
metaData,
|
||||||
userData { name, email }
|
userData { name, email },
|
||||||
|
concurrentJobs { items { id, jobId }, count }
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
@ -101,6 +104,23 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</Col>
|
</Col>
|
||||||
{#if $jobMetrics.data && $initq.data}
|
{#if $jobMetrics.data && $initq.data}
|
||||||
|
{#if $initq.data.job.concurrentJobs != null}
|
||||||
|
{#if authlevel > roles.manager}
|
||||||
|
<Col>
|
||||||
|
<h5>Concurrent Jobs <Icon name="info-circle" style="cursor:help;" title="Shared jobs running on the same node with overlapping runtimes"/></h5>
|
||||||
|
<ul>
|
||||||
|
{#each $initq.data.job.concurrentJobs.items as pjob, index}
|
||||||
|
<li><a href="/monitoring/job/{pjob.id}" target="_blank">{pjob.jobId}</a></li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</Col>
|
||||||
|
{:else}
|
||||||
|
<Col>
|
||||||
|
<h5>{$initq.data.job.concurrentJobs.items.length} Concurrent Jobs</h5>
|
||||||
|
<p>Number of shared jobs on the same node with overlapping runtimes.</p>
|
||||||
|
</Col>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
<Col>
|
<Col>
|
||||||
<PolarPlot
|
<PolarPlot
|
||||||
width={polarPlotSize} height={polarPlotSize}
|
width={polarPlotSize} height={polarPlotSize}
|
||||||
@ -166,7 +186,8 @@
|
|||||||
metricName={item.metric}
|
metricName={item.metric}
|
||||||
rawData={item.data.map(x => x.metric)}
|
rawData={item.data.map(x => x.metric)}
|
||||||
scopes={item.data.map(x => x.scope)}
|
scopes={item.data.map(x => x.scope)}
|
||||||
width={width}/>
|
width={width}
|
||||||
|
isShared={($initq.data.job.exclusive != 1)}/>
|
||||||
{:else}
|
{:else}
|
||||||
<Card body color="warning">No data for <code>{item.metric}</code></Card>
|
<Card body color="warning">No data for <code>{item.metric}</code></Card>
|
||||||
{/if}
|
{/if}
|
||||||
@ -250,4 +271,10 @@
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
columns: 2;
|
||||||
|
-webkit-columns: 2;
|
||||||
|
-moz-columns: 2;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
export let scopes
|
export let scopes
|
||||||
export let width
|
export let width
|
||||||
export let rawData
|
export let rawData
|
||||||
|
export let isShared = false
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const cluster = getContext('clusters').find(cluster => cluster.name == job.cluster)
|
const cluster = getContext('clusters').find(cluster => cluster.name == job.cluster)
|
||||||
@ -87,6 +88,7 @@
|
|||||||
cluster={cluster} subCluster={subCluster}
|
cluster={cluster} subCluster={subCluster}
|
||||||
timestep={data.timestep}
|
timestep={data.timestep}
|
||||||
scope={selectedScope} metric={metricName}
|
scope={selectedScope} metric={metricName}
|
||||||
series={series} />
|
series={series}
|
||||||
|
isShared={isShared} />
|
||||||
{/if}
|
{/if}
|
||||||
{/key}
|
{/key}
|
||||||
|
@ -4,7 +4,9 @@ import Job from './Job.root.svelte'
|
|||||||
new Job({
|
new Job({
|
||||||
target: document.getElementById('svelte-app'),
|
target: document.getElementById('svelte-app'),
|
||||||
props: {
|
props: {
|
||||||
dbid: jobInfos.id
|
dbid: jobInfos.id,
|
||||||
|
authlevel: authlevel,
|
||||||
|
roles: roles
|
||||||
},
|
},
|
||||||
context: new Map([
|
context: new Map([
|
||||||
['cc-config', clusterCockpitConfig]
|
['cc-config', clusterCockpitConfig]
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
const seconds = duration;
|
const seconds = duration;
|
||||||
return `${hours}:${('0' + minutes).slice(-2)}:${('0' + seconds).slice(-2)}`;
|
return `${hours}:${('0' + minutes).slice(-2)}:${('0' + seconds).slice(-2)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
@ -174,6 +174,7 @@
|
|||||||
metric={metric.data.name}
|
metric={metric.data.name}
|
||||||
{cluster}
|
{cluster}
|
||||||
subCluster={job.subCluster}
|
subCluster={job.subCluster}
|
||||||
|
isShared={(job.exclusive != 1)}
|
||||||
/>
|
/>
|
||||||
{:else if metric.removed == true && metric.data == null}
|
{:else if metric.removed == true && metric.data == null}
|
||||||
<Card body color="info"
|
<Card body color="info"
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
export let metric
|
export let metric
|
||||||
export let useStatsSeries = null
|
export let useStatsSeries = null
|
||||||
export let scope = 'node'
|
export let scope = 'node'
|
||||||
|
export let isShared = false
|
||||||
|
|
||||||
if (useStatsSeries == null)
|
if (useStatsSeries == null)
|
||||||
useStatsSeries = statisticsSeries != null
|
useStatsSeries = statisticsSeries != null
|
||||||
@ -142,13 +143,17 @@
|
|||||||
hooks: {
|
hooks: {
|
||||||
draw: [(u) => {
|
draw: [(u) => {
|
||||||
// Draw plot type label:
|
// Draw plot type label:
|
||||||
let text = `${scope}${plotSeries.length > 2 ? 's' : ''}${
|
let textl = `${scope}${plotSeries.length > 2 ? 's' : ''}${
|
||||||
useStatsSeries ? ': min/avg/max' : (metricConfig != null && scope != metricConfig.scope ? ` (${metricConfig.aggregation})` : '')}`
|
useStatsSeries ? ': min/avg/max' : (metricConfig != null && scope != metricConfig.scope ? ` (${metricConfig.aggregation})` : '')}`
|
||||||
|
let textr = `${(isShared && (scope != 'core' && scope != 'accelerator')) ? '[Shared]' : '' }`
|
||||||
u.ctx.save()
|
u.ctx.save()
|
||||||
u.ctx.textAlign = 'start' // 'end'
|
u.ctx.textAlign = 'start' // 'end'
|
||||||
u.ctx.fillStyle = 'black'
|
u.ctx.fillStyle = 'black'
|
||||||
u.ctx.fillText(text, u.bbox.left + 10, u.bbox.top + 10)
|
u.ctx.fillText(textl, u.bbox.left + 10, u.bbox.top + 10)
|
||||||
// u.ctx.fillText(text, u.bbox.left + u.bbox.width - 10, u.bbox.top + u.bbox.height - 10)
|
u.ctx.textAlign = 'end'
|
||||||
|
u.ctx.fillStyle = 'black'
|
||||||
|
u.ctx.fillText(textr, u.bbox.left + u.bbox.width - 10, u.bbox.top + 10)
|
||||||
|
// u.ctx.fillText(text, u.bbox.left + u.bbox.width - 10, u.bbox.top + u.bbox.height - 10) // Recipe for bottom right
|
||||||
|
|
||||||
if (!thresholds) {
|
if (!thresholds) {
|
||||||
u.ctx.restore()
|
u.ctx.restore()
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
clusterId: "{{ .Infos.clusterId }}"
|
clusterId: "{{ .Infos.clusterId }}"
|
||||||
};
|
};
|
||||||
const clusterCockpitConfig = {{ .Config }};
|
const clusterCockpitConfig = {{ .Config }};
|
||||||
|
const authlevel = {{ .User.GetAuthLevel }};
|
||||||
|
const roles = {{ .Roles }};
|
||||||
</script>
|
</script>
|
||||||
<script src='/build/job.js'></script>
|
<script src='/build/job.js'></script>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
Loading…
Reference in New Issue
Block a user