Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • oss/libraries/go/services/job-queues
1 result
Select Git revision
Show changes
Commits on Source (2)
......@@ -4,7 +4,9 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="9979eb22-471e-4f2f-b624-fd3edb5e8c6e" name="Changes" comment="" />
<list default="true" id="9979eb22-471e-4f2f-b624-fd3edb5e8c6e" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
......@@ -38,37 +40,38 @@
<option name="sortByType" value="true" />
<option name="sortKey" value="BY_TYPE" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;DefaultGoTemplateProperty&quot;: &quot;Go File&quot;,
&quot;Go Test.TestDummyRunnable in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor&quot;: &quot;Debug&quot;,
&quot;Go Test.TestManagerEventHandling in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor&quot;: &quot;Debug&quot;,
&quot;Go Test.TestResetStats in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor&quot;: &quot;Debug&quot;,
&quot;Go Test.TestRoundTrip in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor&quot;: &quot;Debug&quot;,
&quot;Go Test.TestScheduleJob in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor&quot;: &quot;Debug&quot;,
&quot;Go Test.TestStructure in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor&quot;: &quot;Debug&quot;,
&quot;Go Test.TestTimeFunctionSame in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor&quot;: &quot;Debug&quot;,
&quot;Go Test.TestWriteToDB1 in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor&quot;: &quot;Debug&quot;,
&quot;Go Test.TestWriteToDB2 in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor&quot;: &quot;Debug&quot;,
&quot;Go Test.TestWriteToDB4 in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor&quot;: &quot;Debug&quot;,
&quot;Go Test.go test gitlab.schukai.com/oss/libraries/go/services/job-queues.executor&quot;: &quot;Debug&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.go.formatter.settings.were.checked&quot;: &quot;true&quot;,
&quot;RunOnceActivity.go.migrated.go.modules.settings&quot;: &quot;true&quot;,
&quot;SHARE_PROJECT_CONFIGURATION_FILES&quot;: &quot;true&quot;,
&quot;git-widget-placeholder&quot;: &quot;master&quot;,
&quot;go.import.settings.migrated&quot;: &quot;true&quot;,
&quot;go.sdk.automatically.set&quot;: &quot;true&quot;,
&quot;last_opened_file_path&quot;: &quot;/home/vs/workspaces/oss/go-libs/job-queues/nix/scripts&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;http.proxy&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"DefaultGoTemplateProperty": "Go File",
"Go Test.TestDummyRunnable in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor": "Debug",
"Go Test.TestManagerEventHandling in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor": "Debug",
"Go Test.TestResetStats in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor": "Debug",
"Go Test.TestRoundTrip in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor": "Debug",
"Go Test.TestScheduleJob in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor": "Debug",
"Go Test.TestStructure in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor": "Debug",
"Go Test.TestTimeFunctionSame in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor": "Debug",
"Go Test.TestWriteToDB1 in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor": "Debug",
"Go Test.TestWriteToDB2 in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor": "Debug",
"Go Test.TestWriteToDB4 in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor": "Debug",
"Go Test.go test gitlab.schukai.com/oss/libraries/go/services/job-queues.executor": "Debug",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.go.formatter.settings.were.checked": "true",
"RunOnceActivity.go.migrated.go.modules.settings": "true",
"RunOnceActivity.go.modules.automatic.dependencies.download": "true",
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
"git-widget-placeholder": "master",
"go.import.settings.migrated": "true",
"go.sdk.automatically.set": "true",
"last_opened_file_path": "/home/vs/workspaces/oss/go-libs/job-queues/nix/scripts",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "http.proxy",
"vue.rearranger.settings.migration": "true"
}
}</component>
}]]></component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/nix/scripts" />
......
......@@ -113,7 +113,7 @@ func (eb *EventBus) Publish(name EventName, data any) {
eb.mu.RLock()
defer eb.mu.RUnlock()
Info("EventBus: publishing event %s", name)
Info("EventBus: publishing event " + name.String())
select {
case <-eb.shutdownChan:
......
......@@ -10,14 +10,14 @@ require (
github.com/google/uuid v1.6.0
github.com/pkg/sftp v1.13.6
github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v3 v3.24.3
github.com/shirou/gopsutil/v3 v3.24.4
github.com/stretchr/testify v1.9.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.22.0
gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/mysql v1.5.6
gorm.io/driver/sqlite v1.5.5
gorm.io/gorm v1.25.9
gorm.io/gorm v1.25.10
gotest.tools/v3 v3.5.1
)
......@@ -45,8 +45,8 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/tklauser/go-sysconf v0.3.13 // indirect
github.com/tklauser/numcpus v0.7.0 // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.8.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/mod v0.8.0 // indirect
......
......@@ -67,8 +67,8 @@ github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE=
github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg=
github.com/shirou/gopsutil/v3 v3.24.4 h1:dEHgzZXt4LMNm+oYELpzl9YCqV65Yr/6SfrvgRBtXeU=
github.com/shirou/gopsutil/v3 v3.24.4/go.mod h1:lTd2mdiOspcqLgAnr9/nGi71NkeMpWKdmhuxm9GusH8=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
......@@ -83,11 +83,11 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
......@@ -138,7 +138,6 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
......@@ -173,7 +172,7 @@ gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkD
gorm.io/driver/sqlite v1.5.5 h1:7MDMtUZhV065SilG62E0MquljeArQZNfJnjd9i9gx3E=
gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATavE=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8=
gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
......@@ -21,9 +21,9 @@ type GenericJob interface {
GetMaxRetries() uint
GetRetryDelay() time.Duration
GetRetryDelay() *time.Duration
GetTimeout() time.Duration
GetTimeout() *time.Duration
GetPersistence() JobPersistence
......
......@@ -38,9 +38,9 @@ type Job[T any] struct {
description string
priority Priority
timeout time.Duration
timeout *time.Duration
maxRetries uint
RetryDelay time.Duration
retryDelay *time.Duration
scheduler Scheduler
......@@ -101,7 +101,7 @@ func (j *Job[T]) GetPersistence() JobPersistence {
Priority: j.priority,
Timeout: j.timeout,
MaxRetries: j.maxRetries,
RetryDelay: j.RetryDelay,
RetryDelay: j.retryDelay,
Dependencies: j.dependencies,
Runnable: j.runner.GetPersistence(),
......@@ -314,12 +314,12 @@ func (j *Job[T]) SetTimeout(timeout time.Duration) *Job[T] {
j.mu.Lock()
defer j.mu.Unlock()
j.timeout = timeout
j.timeout = &timeout
return j
}
// GetTimeout returns the timeout of the job
func (j *Job[T]) GetTimeout() time.Duration {
func (j *Job[T]) GetTimeout() *time.Duration {
j.mu.Lock()
defer j.mu.Unlock()
......@@ -348,16 +348,16 @@ func (j *Job[T]) SetRetryDelay(retryDelay time.Duration) *Job[T] {
j.mu.Lock()
defer j.mu.Unlock()
j.RetryDelay = retryDelay
j.retryDelay = &retryDelay
return j
}
// GetRetryDelay returns the retry delay of the job
func (j *Job[T]) GetRetryDelay() time.Duration {
func (j *Job[T]) GetRetryDelay() *time.Duration {
j.mu.Lock()
defer j.mu.Unlock()
return j.RetryDelay
return j.retryDelay
}
// SetDependencies sets the dependencies of the job
......
......@@ -39,7 +39,7 @@ func TestSetPriority(t *testing.T) {
func TestSetAndGetTimeout(t *testing.T) {
job := NewJob[ShellResult]("id1", &ShellRunnable{})
job.SetTimeout(5 * time.Minute)
assert.Equal(t, 5*time.Minute, job.GetTimeout())
assert.Equal(t, 5*time.Minute, *job.GetTimeout())
}
func TestSetAndGetMaxRetries(t *testing.T) {
......@@ -57,7 +57,7 @@ func TestSetAndGetRunnable(t *testing.T) {
func TestSetAndGetRetryDelay(t *testing.T) {
job := NewJob[ShellResult]("id1", &ShellRunnable{})
job.SetRetryDelay(2 * time.Second)
assert.Equal(t, 2*time.Second, job.GetRetryDelay())
assert.Equal(t, 2*time.Second, *job.GetRetryDelay())
}
func TestSetAndGetDependencies(t *testing.T) {
......@@ -90,7 +90,7 @@ func TestGetPriority(t *testing.T) {
func TestGetTimeout(t *testing.T) {
job := NewJob[ShellResult]("id2", &ShellRunnable{})
assert.Equal(t, time.Duration(0), job.GetTimeout())
assert.Nil(t, job.GetTimeout())
}
func TestGetMaxRetries(t *testing.T) {
......@@ -100,7 +100,7 @@ func TestGetMaxRetries(t *testing.T) {
func TestGetRetryDelay(t *testing.T) {
job := NewJob[ShellResult]("id2", &ShellRunnable{})
assert.Equal(t, time.Duration(0), job.GetRetryDelay())
assert.Nil(t, job.GetRetryDelay())
}
func TestGetDependencies(t *testing.T) {
......
......@@ -72,12 +72,14 @@ func (m *MockGenericJob) GetMaxRetries() uint {
return 0
}
func (m *MockGenericJob) GetRetryDelay() time.Duration {
return 0
func (m *MockGenericJob) GetRetryDelay() *time.Duration {
dur := time.Duration(0)
return &dur
}
func (m *MockGenericJob) GetTimeout() time.Duration {
return 0
func (m *MockGenericJob) GetTimeout() *time.Duration {
dur := time.Duration(0)
return &dur
}
func (m *MockGenericJob) GetID() JobID {
......
......@@ -19,16 +19,20 @@ type JobPersistence struct {
ID JobID `yaml:"id" json:"id" gorm:"type:varchar(255);primaryKey"`
Description string `yaml:"description" json:"description" gorm:"column:description"`
Priority Priority `yaml:"priority" json:"priority" gorm:"column:priority"`
Timeout time.Duration `yaml:"timeout" json:"timeout" gorm:"column:timeout"`
Timeout *time.Duration `yaml:"-" json:"-" gorm:"column:timeout"`
MaxRetries uint `yaml:"maxRetries" json:"maxRetries" gorm:"column:max_retries"`
RetryDelay time.Duration `yaml:"retryDelay" json:"retryDelay" gorm:"column:retry_delay"`
RetryDelay *time.Duration `yaml:"-" json:"-" gorm:"column:retry_delay"`
Dependencies []JobID `yaml:"dependencies" json:"dependencies,omitempty" gorm:"column:dependencies;type:json"`
Runnable RunnableImport `yaml:"runnable" json:"runnable" gorm:"embedded;embeddedPrefix:runnable_"`
Scheduler SchedulerPersistence `yaml:"scheduler" json:"scheduler,omitempty" gorm:"embedded;embeddedPrefix:scheduler_"`
Pause bool `yaml:"pause" json:"pause" gorm:"column:pause"`
PauseReason string `yaml:"pauseReason" json:"pauseReason" gorm:"column:pause_reason"`
PauseUntil *time.Time `yaml:"pauseUntil" json:"pauseUntil" gorm:"column:pause_until"`
PauseUntil *time.Time `yaml:"-" json:"-" gorm:"column:pause_until"`
TimeoutString *string `yaml:"timeout,omitempty" json:"timeout,omitempty" gorm:"-"`
RetryDelayString *string `yaml:"retryDelay,omitempty" json:"retryDelay,omitempty" gorm:"-"`
PauseUntilString *string `yaml:"pauseUntil" json:"pauseUntil,omitempty" gorm:"-"`
Logs []JobLog `gorm:"foreignKey:JobID;references:ID" json:"-" yaml:"-"`
Stats JobStats `gorm:"foreignKey:JobID" json:"stats" yaml:"stats"`
......@@ -38,39 +42,95 @@ type JobPersistence struct {
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;index" json:"-" yaml:"-"`
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (jp *JobPersistence) UnmarshalJSON(data []byte) error {
// Anonymous struct for unmarshalling with custom time format
func (j *JobPersistence) MarshalJSON() ([]byte, error) {
type Alias JobPersistence
return json.Marshal(&struct {
*Alias
TimeoutString string `json:"timeout,omitempty"`
RetryDelayString string `json:"retryDelay,omitempty"`
PauseUntilString string `json:"pauseUntil,omitempty"`
}{
Alias: (*Alias)(j),
TimeoutString: formatDuration(j.Timeout),
RetryDelayString: formatDuration(j.RetryDelay),
PauseUntilString: formatTime(j.PauseUntil),
})
}
func (j *JobPersistence) UnmarshalJSON(data []byte) error {
type Alias JobPersistence
aux := &struct {
PauseUntil *string `json:"pauseUntil,omitempty"`
*Alias
TimeoutString *string `json:"timeout,omitempty"`
RetryDelayString *string `json:"retryDelay,omitempty"`
PauseUntilString *string `json:"pauseUntil,omitempty"`
}{
Alias: (*Alias)(jp),
Alias: (*Alias)(j),
}
if err := json.Unmarshal(data, &aux); err != nil {
if err := json.Unmarshal(data, aux); err != nil {
return err
}
if aux.PauseUntil != nil {
var t time.Time
var err error
for _, format := range SupportedTimeFormats {
t, err = time.Parse(format, *aux.PauseUntil)
if err == nil {
break
}
if aux.TimeoutString != nil && *aux.TimeoutString != "" {
d, err := time.ParseDuration(*aux.TimeoutString)
if err != nil {
return err
}
j.Timeout = &d
}
if aux.RetryDelayString != nil && *aux.RetryDelayString != "" {
d, err := time.ParseDuration(*aux.RetryDelayString)
if err != nil {
return err
}
jp.PauseUntil = &t
j.RetryDelay = &d
}
if aux.PauseUntilString != nil && *aux.PauseUntilString != "" {
t, err := parseMultipleDateFormats(*aux.PauseUntilString, []string{
time.RFC3339, time.RFC3339Nano,
"2006-01-02T15:04:05",
"2006-01-02T15:04:05.999999999",
"2006-01-02T15:04:05Z07:00",
"2006-01-02T15:04:05",
"2006-01-02T15:04",
"2006-01-02T15",
"2006-01-02T",
"2006-01-02",
})
if err != nil {
return err
}
j.PauseUntil = &t
}
return nil
}
func parseMultipleDateFormats(value string, formats []string) (time.Time, error) {
var t time.Time
var err error
for _, format := range formats {
t, err = time.Parse(format, value)
if err == nil {
return t, nil
}
}
return t, fmt.Errorf("date string '%s' does not match any known format", value)
}
func formatDuration(d *time.Duration) string {
if d != nil {
return d.String()
}
return ""
}
func formatTime(t *time.Time) string {
if t != nil {
return t.Format(time.RFC3339)
}
return ""
}
func (jp JobPersistence) GetLogs() []JobLog {
return jp.Logs
}
......@@ -96,7 +156,7 @@ func (jp JobPersistence) GetPriority() Priority {
}
func (jp JobPersistence) GetTimeout() time.Duration {
return jp.Timeout
return *jp.Timeout
}
func (JobPersistence) TableName() string {
......@@ -182,13 +242,14 @@ func ReadFromGORM(db *gorm.DB) ([]JobPersistence, error) {
}
func CreateGenericJobFromPersistence[T any](jobImport JobPersistence, runner Runnable[T]) GenericJob {
return &Job[T]{
id: jobImport.ID,
description: jobImport.Description,
priority: jobImport.Priority,
timeout: jobImport.Timeout,
maxRetries: jobImport.MaxRetries,
RetryDelay: jobImport.RetryDelay,
retryDelay: jobImport.RetryDelay,
dependencies: jobImport.Dependencies,
pause: jobImport.Pause,
pauseReason: jobImport.PauseReason,
......
......@@ -14,6 +14,10 @@ import (
)
func TestCreateJobAndSchedulerFromInput(t *testing.T) {
time10s := 10 * time.Second
time2s := 5 * time.Minute
tests := []struct {
name string
input JobPersistence
......@@ -26,9 +30,9 @@ func TestCreateJobAndSchedulerFromInput(t *testing.T) {
input: JobPersistence{
ID: "1",
Priority: 1,
Timeout: 10 * time.Second,
Timeout: &time10s,
MaxRetries: 3,
RetryDelay: 2 * time.Second,
RetryDelay: &time2s,
Runnable: RunnableImport{
Type: "Shell",
Data: map[string]any{"ScriptPath": "script.sh"},
......@@ -89,6 +93,89 @@ func TestCreateJobAndSchedulerFromInput(t *testing.T) {
}
}
func TestJobPersistence_MarshalUnmarshalJSON(t *testing.T) {
timeRef := time.Now().Round(time.Second) // Runden, um Genauigkeitsverlust zu vermeiden
// set timezone to UTC
timeRef = timeRef.UTC()
timeRefString := timeRef.Format(time.RFC3339)
time5m := 5 * time.Minute
time10s := 10 * time.Second
time30s := 30 * time.Second
time1Hour := 1 * time.Hour
time10sString := "10s"
time30sString := "30s"
time5m0sString := "5m0s"
time1h0m0sString := "1h0m0s"
emptyString := ""
tests := []struct {
name string
job JobPersistence
expected string
}{
{
name: "All fields present",
job: JobPersistence{
Timeout: &time5m,
RetryDelay: &time10s,
PauseUntil: &timeRef,
TimeoutString: &time5m0sString,
RetryDelayString: &time10sString,
PauseUntilString: &timeRefString,
},
expected: ` {"id":"","description":"","priority":0,"maxRetries":0,"runnable":{"type":""},"scheduler":{"type":""},"pause":false,"pauseReason":"","timeout":"5m0s","retryDelay":"10s","pauseUntil":"` + timeRefString + `","stats":{"jobId":"","runCount":0,"successCount":0,"errorCount":0,"timeMetrics":{"avg":0,"max":0,"min":0,"total":0},"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z"},"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z"}`,
},
{
name: "Nil pauseUntil",
job: JobPersistence{
Timeout: &time1Hour,
RetryDelay: &time30s,
PauseUntil: nil,
TimeoutString: &time1h0m0sString,
RetryDelayString: &time30sString,
PauseUntilString: &emptyString,
},
expected: `{"id":"","description":"","priority":0,"maxRetries":0,"runnable":{"type":""},"scheduler":{"type":""},"pause":false,"pauseReason":"","timeout":"1h0m0s","retryDelay":"30s","pauseUntil":"","stats":{"jobId":"","runCount":0,"successCount":0,"errorCount":0,"timeMetrics":{"avg":0,"max":0,"min":0,"total":0},"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z"},"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z"}`,
},
{
name: "Nil timeout and retryDelay",
job: JobPersistence{
Timeout: nil,
RetryDelay: nil,
PauseUntil: nil,
TimeoutString: &emptyString,
RetryDelayString: &emptyString,
PauseUntilString: &emptyString,
},
expected: `{"id":"","description":"","priority":0,"maxRetries":0,"runnable":{"type":""},"scheduler":{"type":""},"pause":false,"pauseReason":"","timeout":"","retryDelay":"","pauseUntil":"","stats":{"jobId":"","runCount":0,"successCount":0,"errorCount":0,"timeMetrics":{"avg":0,"max":0,"min":0,"total":0},"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z"},"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z"}`,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// MarshalJSON testen
data, err := json.Marshal(tc.job)
assert.NoError(t, err)
assert.JSONEq(t, tc.expected, string(data))
var job JobPersistence
err = json.Unmarshal(data, &job)
assert.NoError(t, err)
assert.Equal(t, tc.job.Timeout, job.Timeout)
assert.Equal(t, tc.job.RetryDelay, job.RetryDelay)
if tc.job.PauseUntil != nil {
assert.Equal(t, *tc.job.PauseUntil, *job.PauseUntil)
} else {
assert.Nil(t, job.PauseUntil)
}
})
}
}
func TestReadJsonFile(t *testing.T) {
testContent := `[{"id": "1", "priority": 1}]`
tempFile, err := ioutil.TempFile("", "test.json")
......
......@@ -208,8 +208,8 @@ func (w *LocalWorker) run(jobChannel chan GenericJob, stopChan chan bool, cancel
var cancel context.CancelFunc
timeout := job.GetTimeout()
if timeout > 0 {
ctx, cancel = context.WithTimeout(ctx, timeout)
if timeout != nil && *timeout > 0 {
ctx, cancel = context.WithTimeout(ctx, *timeout)
}
Info("Executing job on worker thread", "worker", w.ID, "thread_id", workerThreadID, "job_id", job.GetID())
......@@ -230,8 +230,8 @@ func (w *LocalWorker) run(jobChannel chan GenericJob, stopChan chan bool, cancel
break
}
if retryDelay > 0 {
time.Sleep(retryDelay)
if retryDelay != nil && *retryDelay > 0 {
time.Sleep(*retryDelay)
}
retries--
......
......@@ -47,12 +47,12 @@ func (j DummyJob) GetMaxRetries() uint {
return 0
}
func (j DummyJob) GetRetryDelay() time.Duration {
return 0
func (j DummyJob) GetRetryDelay() *time.Duration {
return nil
}
func (j DummyJob) GetTimeout() time.Duration {
return 0
func (j DummyJob) GetTimeout() *time.Duration {
return nil
}
func (j DummyJob) Execute(_ context.Context) (RunGenericResult, error) {
......