-
Notifications
You must be signed in to change notification settings - Fork 23
/
ensembling_job.go
148 lines (130 loc) · 4.19 KB
/
ensembling_job.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package models
import (
"database/sql/driver"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"gorm.io/gorm"
openapi "github.com/caraml-dev/turing/api/turing/generated"
)
// EnsemblingJob holds the information required for an ensembling job to be done asynchronously
type EnsemblingJob struct {
Model
Name string `json:"name"`
EnsemblerID ID `json:"ensembler_id" validate:"required"`
ProjectID ID `json:"project_id"`
EnvironmentName string `json:"environment_name"`
InfraConfig *InfraConfig `json:"infra_config" validate:"required"`
JobConfig *JobConfig `json:"job_config" validate:"required"`
RetryCount int `json:"-" gorm:"default:0"`
Status Status `json:"status" gorm:"default:pending"`
Error string `json:"error"`
MonitoringURL string `json:"monitoring_url" gorm:"-"`
RunID int `json:"-"`
}
// BeforeCreate sets the ensembling job name and run_id before creating
func (job *EnsemblingJob) BeforeCreate(tx *gorm.DB) error {
if job.Model.IsNew() {
// Only update fields if the record is new.
// See: https://github.com/go-gorm/gorm/issues/4553
var latest EnsemblingJob
err := tx.Select("ensembling_jobs.run_id").
Where("ensembler_id = ?", job.EnsemblerID).
Order("run_id desc").
FirstOrInit(&latest, &EnsemblingJob{RunID: 0}).
Error
if err != nil {
return err
}
job.RunID = latest.RunID + 1
job.Name = fmt.Sprintf("%s-%d", *job.InfraConfig.EnsemblerName, job.RunID)
}
return nil
}
// JobConfig stores the infra and ensembler config
type JobConfig openapi.EnsemblerConfig
// Value returns json value, implement driver.Valuer interface
func (c JobConfig) Value() (driver.Value, error) {
return json.Marshal(c)
}
// Scan scans value into Jsonb, implements sql.Scanner interface
func (c *JobConfig) Scan(value interface{}) error {
b, ok := value.([]byte)
if !ok {
return errors.New("type assertion to []byte failed")
}
return json.Unmarshal(b, &c)
}
// InfraConfig stores the infrastructure related configurations required.
type InfraConfig struct {
openapi.EnsemblerInfraConfig
}
// Value returns json value, implement driver.Valuer interface
func (r *InfraConfig) Value() (driver.Value, error) {
return json.Marshal(r)
}
// Scan scans value into Jsonb, implements sql.Scanner interface
func (r *InfraConfig) Scan(value interface{}) error {
b, ok := value.([]byte)
if !ok {
return errors.New("type assertion to []byte failed")
}
return json.Unmarshal(b, &r)
}
// Status is the state of the finite machine ensembling job.
// Possible statuses:
// JobPending --▶ JobFailedSubmission
//
// |
// |
// |
// |
//
// JobBuildingImage --▶ JobFailedBuildImage
//
// |
// |
// |
// |
// ▼
//
// JobRunning --▶ JobFailed
//
// |
// |
// |--▶ JobTerminating --▶ JobTerminated
// |
// |
// ▼
//
// JobCompleted
type Status string
const (
// JobPending is when the job has just been introduced.
JobPending Status = "pending"
// JobBuildingImage is when the job is builing a OCI image.
JobBuildingImage Status = "building"
// JobRunning is when the job has been picked up and running.
JobRunning Status = "running"
// JobTerminating is when the job has been requested to terminate.
JobTerminating Status = "terminating"
// JobTerminated is when the job has stopped. This is a terminal state.
JobTerminated Status = "terminated"
// JobCompleted is when the job has successfully completed. This is a terminal state.
JobCompleted Status = "completed"
// JobFailed is when the job has failed. This is a terminal state.
JobFailed Status = "failed"
// JobFailedSubmission is when the job has failed to submit. This is a terminal state.
JobFailedSubmission Status = "failed_submission"
// JobFailedBuildImage is when the job has failed to build an ensembling image.
JobFailedBuildImage Status = "failed_building"
)
// IsTerminal checks if the job has reached a final state.
func (s Status) IsTerminal() bool {
return s == JobTerminated || s == JobFailedSubmission ||
s == JobFailed || s == JobCompleted || s == JobFailedBuildImage
}
// IsSuccessful checks if the ensembling job has completed.
func (s Status) IsSuccessful() bool {
return s == JobCompleted
}