
As it was decided that the name "tags" would be better for the clarity of the feature, all files and code named "cluster" or "worker cluster" have been removed and replaced with "tag" and "worker tag". This is only a name change, no other features were touched. This addresses part of #104204. Reviewed-on: https://projects.blender.org/studio/flamenco/pulls/104223 As a note to anyone who already ran a pre-release version of Flamenco and configured some worker clusters, with the help of an SQLite client you can migrate the clusters to tags. First build Flamenco Manager and start it, to create the new database schema. Then run these SQL queries via an sqlite commandline client: ```sql insert into worker_tags (id, created_at, updated_at, uuid, name, description) select id, created_at, updated_at, uuid, name, description from worker_clusters; insert into worker_tag_membership (worker_tag_id, worker_id) select worker_cluster_id, worker_id from worker_cluster_membership; ```
141 lines
3.4 KiB
Go
141 lines
3.4 KiB
Go
package job_compilers
|
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/dop251/goja"
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"git.blender.org/flamenco/internal/uuid"
|
|
"git.blender.org/flamenco/pkg/api"
|
|
)
|
|
|
|
// Author allows scripts to author tasks and commands.
|
|
type Author struct {
|
|
runtime *goja.Runtime
|
|
}
|
|
|
|
type AuthoredJob struct {
|
|
JobID string
|
|
WorkerTagUUID string
|
|
|
|
Name string
|
|
JobType string
|
|
Priority int
|
|
Status api.JobStatus
|
|
|
|
Created time.Time
|
|
|
|
Settings JobSettings
|
|
Metadata JobMetadata
|
|
Storage JobStorageInfo
|
|
|
|
Tasks []AuthoredTask
|
|
}
|
|
|
|
type JobSettings map[string]interface{}
|
|
type JobMetadata map[string]string
|
|
|
|
type JobStorageInfo struct {
|
|
ShamanCheckoutID string
|
|
}
|
|
|
|
type AuthoredTask struct {
|
|
// Tasks already get their UUID in the authoring stage. This makes it simpler
|
|
// to store the dependencies, as the code doesn't have to worry about value
|
|
// vs. pointer semantics. Tasks can always be unambiguously referenced by
|
|
// their UUID.
|
|
UUID string
|
|
Name string
|
|
Type string
|
|
Priority int
|
|
Commands []AuthoredCommand
|
|
|
|
// Dependencies are tasks that need to be completed before this one can run.
|
|
Dependencies []*AuthoredTask `json:"omitempty" yaml:"omitempty"`
|
|
}
|
|
|
|
type AuthoredCommand struct {
|
|
Name string
|
|
Parameters AuthoredCommandParameters
|
|
}
|
|
type AuthoredCommandParameters map[string]interface{}
|
|
|
|
func (a *Author) Task(name string, taskType string) (*AuthoredTask, error) {
|
|
name = strings.TrimSpace(name)
|
|
taskType = strings.TrimSpace(taskType)
|
|
if name == "" {
|
|
return nil, errors.New("author.Task(name, type): name is required")
|
|
}
|
|
if taskType == "" {
|
|
return nil, errors.New("author.Task(name, type): type is required")
|
|
}
|
|
|
|
at := AuthoredTask{
|
|
uuid.New(),
|
|
name,
|
|
taskType,
|
|
50, // TODO: handle default priority somehow.
|
|
make([]AuthoredCommand, 0),
|
|
make([]*AuthoredTask, 0),
|
|
}
|
|
return &at, nil
|
|
}
|
|
|
|
func (a *Author) Command(cmdName string, parameters AuthoredCommandParameters) (*AuthoredCommand, error) {
|
|
ac := AuthoredCommand{cmdName, parameters}
|
|
return &ac, nil
|
|
}
|
|
|
|
// AuthorModule exports the Author module members to Goja.
|
|
func AuthorModule(r *goja.Runtime, module *goja.Object) {
|
|
a := &Author{
|
|
runtime: r,
|
|
}
|
|
obj := module.Get("exports").(*goja.Object)
|
|
mustExport := func(name string, value interface{}) {
|
|
err := obj.Set(name, value)
|
|
if err != nil {
|
|
log.Panic().Err(err).Msgf("unable to register '%s' in Goja 'author' module", name)
|
|
}
|
|
}
|
|
|
|
mustExport("Task", a.Task)
|
|
mustExport("Command", a.Command)
|
|
}
|
|
|
|
func (aj *AuthoredJob) AddTask(at *AuthoredTask) {
|
|
// Construct a task without dependencies, and a separate list of dependency
|
|
// UUIDs, just for logging. Simply logging `at` would recursively include all
|
|
// dependent tasks, which gets way too big to log.
|
|
if log.Debug().Enabled() {
|
|
deps := make([]string, len(at.Dependencies))
|
|
for i := range at.Dependencies {
|
|
deps[i] = at.Dependencies[i].UUID
|
|
}
|
|
logTask := *at
|
|
logTask.Dependencies = nil
|
|
|
|
log.Debug().
|
|
Str("job", aj.Name).
|
|
Strs("depTaskIDs", deps).
|
|
Interface("task", logTask).Msg("add task")
|
|
}
|
|
|
|
aj.Tasks = append(aj.Tasks, *at)
|
|
}
|
|
|
|
func (at *AuthoredTask) AddCommand(ac *AuthoredCommand) {
|
|
at.Commands = append(at.Commands, *ac)
|
|
}
|
|
|
|
func (at *AuthoredTask) AddDependency(dep *AuthoredTask) error {
|
|
// TODO: check for dependency cycles, return error if there.
|
|
at.Dependencies = append(at.Dependencies, dep)
|
|
return nil
|
|
}
|