Make the GET /api/jobs/types
endpoint work
This commit is contained in:
parent
6520dc2d66
commit
d0fafb5063
@ -49,7 +49,6 @@ func main() {
|
||||
|
||||
log.Info().Str("version", appinfo.ApplicationVersion).Msgf("starting %v", appinfo.ApplicationName)
|
||||
|
||||
gojaPoC()
|
||||
echoOpenAPIPoC()
|
||||
}
|
||||
|
||||
@ -113,7 +112,12 @@ func echoOpenAPIPoC() {
|
||||
})
|
||||
e.Use(validator)
|
||||
|
||||
flamenco := api_impl.NewFlamenco()
|
||||
compiler, err := job_compilers.Load()
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("error loading job compilers")
|
||||
}
|
||||
|
||||
flamenco := api_impl.NewFlamenco(compiler)
|
||||
api.RegisterHandlers(e, flamenco)
|
||||
|
||||
// Log available routes
|
||||
|
@ -27,12 +27,20 @@ import (
|
||||
)
|
||||
|
||||
type Flamenco struct {
|
||||
jobCompiler JobCompiler
|
||||
}
|
||||
|
||||
type JobCompiler interface {
|
||||
ListJobTypes() api.AvailableJobTypes
|
||||
}
|
||||
|
||||
var _ api.ServerInterface = (*Flamenco)(nil)
|
||||
|
||||
func NewFlamenco() *Flamenco {
|
||||
return &Flamenco{}
|
||||
// NewFlamenco creates a new Flamenco service, using the given JobCompiler.
|
||||
func NewFlamenco(jc JobCompiler) *Flamenco {
|
||||
return &Flamenco{
|
||||
jobCompiler: jc,
|
||||
}
|
||||
}
|
||||
|
||||
// sendPetstoreError wraps sending of an error in the Error format, and
|
||||
|
@ -24,52 +24,15 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitlab.com/blender/flamenco-goja-test/pkg/api"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func (f *Flamenco) GetJobTypes(e echo.Context) error {
|
||||
// Some helper functions because Go doesn't allow taking the address of a literal.
|
||||
defaultString := func(s string) *interface{} {
|
||||
var iValue interface{} = s
|
||||
return &iValue
|
||||
}
|
||||
defaultInt32 := func(i int32) *interface{} {
|
||||
var iValue interface{} = i
|
||||
return &iValue
|
||||
}
|
||||
defaultBool := func(b bool) *interface{} {
|
||||
var iValue interface{} = b
|
||||
return &iValue
|
||||
}
|
||||
boolPtr := func(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
choicesStr := func(choices ...string) *[]string {
|
||||
return &choices
|
||||
if f.jobCompiler == nil {
|
||||
log.Error().Msg("Flamenco is running without job compiler")
|
||||
return sendAPIError(e, http.StatusInternalServerError, "no job types available")
|
||||
}
|
||||
|
||||
// TODO: dynamically build based on the actually registered job types.
|
||||
types := api.AvailableJobTypes{
|
||||
JobTypes: []api.AvailableJobType{{
|
||||
Name: "simple-blender-render",
|
||||
Settings: []api.AvailableJobSetting{
|
||||
{Key: "blender_cmd", Type: "string", Default: defaultString("{blender}")},
|
||||
{Key: "chunk_size", Type: "int32", Default: defaultInt32(1)},
|
||||
{Key: "frames", Type: "string", Required: boolPtr(true)},
|
||||
{Key: "render_output", Type: "string", Required: boolPtr(true)},
|
||||
{Key: "fps", Type: "int32"},
|
||||
{Key: "extract_audio", Type: "bool", Default: defaultBool(true)},
|
||||
{Key: "images_or_video",
|
||||
Type: "string",
|
||||
Required: boolPtr(true),
|
||||
Choices: choicesStr("images", "video"),
|
||||
Visible: boolPtr(false),
|
||||
},
|
||||
{Key: "format", Type: "string", Required: boolPtr(true)},
|
||||
{Key: "output_file_extension", Type: "string", Required: boolPtr(true)},
|
||||
},
|
||||
}},
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, &types)
|
||||
jobTypes := f.jobCompiler.ListJobTypes()
|
||||
return e.JSON(http.StatusOK, &jobTypes)
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
// Package job_compilers contains functionality to convert a Flamenco job
|
||||
// definition into concrete tasks and commands to execute by Workers.
|
||||
package job_compilers
|
||||
|
||||
/* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
@ -28,24 +30,32 @@ import (
|
||||
"github.com/dop251/goja_nodejs/require"
|
||||
"github.com/google/uuid"
|
||||
"github.com/rs/zerolog/log"
|
||||
"gitlab.com/blender/flamenco-goja-test/pkg/api"
|
||||
)
|
||||
|
||||
var ErrJobTypeUnknown = errors.New("job type unknown")
|
||||
var ErrScriptIncomplete = errors.New("job compiler script incomplete")
|
||||
|
||||
type GojaJobCompiler struct {
|
||||
jobtypes map[string]JobType // Mapping from job type name to jobType struct.
|
||||
registry *require.Registry // Goja module registry.
|
||||
// Service contains job compilers defined in JavaScript.
|
||||
type Service struct {
|
||||
compilers map[string]Compiler // Mapping from job type name to the job compiler of that type.
|
||||
registry *require.Registry // Goja module registry.
|
||||
}
|
||||
|
||||
type JobType struct {
|
||||
type Compiler struct {
|
||||
jobType string
|
||||
program *goja.Program // Compiled JavaScript file.
|
||||
filename string // The filename of that JS file.
|
||||
}
|
||||
|
||||
func Load() (*GojaJobCompiler, error) {
|
||||
compiler := GojaJobCompiler{
|
||||
jobtypes: map[string]JobType{},
|
||||
type VM struct {
|
||||
runtime *goja.Runtime // Goja VM containing the job compiler script.
|
||||
compiler Compiler // Program loaded into this VM.
|
||||
}
|
||||
|
||||
func Load() (*Service, error) {
|
||||
compiler := Service{
|
||||
compilers: map[string]Compiler{},
|
||||
}
|
||||
|
||||
if err := compiler.loadScripts(); err != nil {
|
||||
@ -53,7 +63,7 @@ func Load() (*GojaJobCompiler, error) {
|
||||
}
|
||||
|
||||
staticFileLoader := func(path string) ([]byte, error) {
|
||||
content, err := compiler.loadScript(path)
|
||||
content, err := compiler.loadScriptBytes(path)
|
||||
if err != nil {
|
||||
// The 'require' module uses this to try different variations of the path
|
||||
// in order to find it (without .js, with .js, etc.), so don't log any of
|
||||
@ -71,34 +81,15 @@ func Load() (*GojaJobCompiler, error) {
|
||||
return &compiler, nil
|
||||
}
|
||||
|
||||
func (c *GojaJobCompiler) newGojaVM() *goja.Runtime {
|
||||
vm := goja.New()
|
||||
vm.SetFieldNameMapper(goja.UncapFieldNameMapper())
|
||||
|
||||
mustSet := func(name string, value interface{}) {
|
||||
err := vm.Set(name, value)
|
||||
if err != nil {
|
||||
log.Panic().Err(err).Msgf("unable to register '%s' in Goja VM", name)
|
||||
}
|
||||
func (s *Service) Run(jobTypeName string) error {
|
||||
vm, err := s.compilerForJobType(jobTypeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set some global functions for script debugging purposes.
|
||||
mustSet("print", jsPrint)
|
||||
mustSet("alert", jsAlert)
|
||||
|
||||
// Pre-import some useful modules.
|
||||
c.registry.Enable(vm)
|
||||
mustSet("author", require.Require(vm, "author"))
|
||||
mustSet("path", require.Require(vm, "path"))
|
||||
mustSet("process", require.Require(vm, "process"))
|
||||
|
||||
return vm
|
||||
}
|
||||
|
||||
func (c *GojaJobCompiler) Run(jobTypeName string) error {
|
||||
jobType, ok := c.jobtypes[jobTypeName]
|
||||
if !ok {
|
||||
return ErrJobTypeUnknown
|
||||
compileJob, err := vm.getCompileJob()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
created, err := time.Parse(time.RFC3339, "2022-01-03T18:53:00+01:00")
|
||||
@ -130,24 +121,7 @@ func (c *GojaJobCompiler) Run(jobTypeName string) error {
|
||||
},
|
||||
}
|
||||
|
||||
vm := c.newGojaVM()
|
||||
|
||||
// This should register the `compileJob()` function called below:
|
||||
if _, err := vm.RunProgram(jobType.program); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
compileJob, isCallable := goja.AssertFunction(vm.Get("compileJob"))
|
||||
if !isCallable {
|
||||
log.Error().
|
||||
Str("jobType", jobTypeName).
|
||||
Str("script", jobType.filename).
|
||||
Msg("script does not define a compileJob(job) function")
|
||||
return ErrScriptIncomplete
|
||||
|
||||
}
|
||||
|
||||
if _, err := compileJob(nil, vm.ToValue(&job)); err != nil {
|
||||
if err := compileJob(&job); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -159,3 +133,60 @@ func (c *GojaJobCompiler) Run(jobTypeName string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListJobTypes returns the list of available job types.
|
||||
func (s *Service) ListJobTypes() api.AvailableJobTypes {
|
||||
jobTypes := make([]api.AvailableJobType, 0)
|
||||
for typeName := range s.compilers {
|
||||
compiler, err := s.compilerForJobType(typeName)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Str("jobType", typeName).Msg("unable to determine job type settings")
|
||||
continue
|
||||
}
|
||||
|
||||
description, err := compiler.getJobTypeInfo()
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Str("jobType", typeName).Msg("unable to determine job type settings")
|
||||
continue
|
||||
}
|
||||
|
||||
jobTypes = append(jobTypes, *description)
|
||||
}
|
||||
return api.AvailableJobTypes{JobTypes: jobTypes}
|
||||
}
|
||||
|
||||
func (vm *VM) getCompileJob() (func(job *AuthoredJob) error, error) {
|
||||
compileJob, isCallable := goja.AssertFunction(vm.runtime.Get("compileJob"))
|
||||
if !isCallable {
|
||||
// TODO: construct a more elaborate Error object that contains this info, instead of logging here.
|
||||
log.Error().
|
||||
Str("jobType", vm.compiler.jobType).
|
||||
Str("script", vm.compiler.filename).
|
||||
Msg("script does not define a compileJob(job) function")
|
||||
return nil, ErrScriptIncomplete
|
||||
}
|
||||
|
||||
// TODO: wrap this in a nicer way.
|
||||
return func(job *AuthoredJob) error {
|
||||
_, err := compileJob(nil, vm.runtime.ToValue(job))
|
||||
return err
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (vm *VM) getJobTypeInfo() (*api.AvailableJobType, error) {
|
||||
jtValue := vm.runtime.Get("JOB_TYPE")
|
||||
|
||||
var ajt api.AvailableJobType
|
||||
if err := vm.runtime.ExportTo(jtValue, &ajt); err != nil {
|
||||
// TODO: construct a more elaborate Error object that contains this info, instead of logging here.
|
||||
log.Error().
|
||||
Err(err).
|
||||
Str("jobType", vm.compiler.jobType).
|
||||
Str("script", vm.compiler.filename).
|
||||
Msg("script does not define a proper JOB_TYPE object")
|
||||
return nil, ErrScriptIncomplete
|
||||
}
|
||||
|
||||
ajt.Name = vm.compiler.jobType
|
||||
return &ajt, nil
|
||||
}
|
||||
|
@ -28,13 +28,14 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/dop251/goja"
|
||||
"github.com/dop251/goja_nodejs/require"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
//go:embed scripts
|
||||
var scriptsFS embed.FS
|
||||
|
||||
func (c *GojaJobCompiler) loadScripts() error {
|
||||
func (s *Service) loadScripts() error {
|
||||
scripts, err := scriptsFS.ReadDir("scripts")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find scripts: %w", err)
|
||||
@ -46,7 +47,7 @@ func (c *GojaJobCompiler) loadScripts() error {
|
||||
}
|
||||
filename := path.Join("scripts", script.Name())
|
||||
|
||||
script_bytes, err := c.loadScript(filename)
|
||||
script_bytes, err := s.loadScriptBytes(filename)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("filename", filename).Msg("failed to read script")
|
||||
continue
|
||||
@ -59,7 +60,7 @@ func (c *GojaJobCompiler) loadScripts() error {
|
||||
}
|
||||
|
||||
jobTypeName := filenameToJobType(script.Name())
|
||||
c.jobtypes[jobTypeName] = JobType{
|
||||
s.compilers[jobTypeName] = Compiler{
|
||||
program: program,
|
||||
filename: script.Name(),
|
||||
}
|
||||
@ -70,7 +71,7 @@ func (c *GojaJobCompiler) loadScripts() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *GojaJobCompiler) loadScript(path string) ([]byte, error) {
|
||||
func (s *Service) loadScriptBytes(path string) ([]byte, error) {
|
||||
file, err := scriptsFS.Open(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open embedded script: %w", err)
|
||||
@ -83,3 +84,46 @@ func filenameToJobType(filename string) string {
|
||||
stem := filename[:len(filename)-len(extension)]
|
||||
return strings.ReplaceAll(stem, "_", "-")
|
||||
}
|
||||
|
||||
func (s *Service) newGojaVM() *goja.Runtime {
|
||||
vm := goja.New()
|
||||
vm.SetFieldNameMapper(goja.UncapFieldNameMapper())
|
||||
|
||||
mustSet := func(name string, value interface{}) {
|
||||
err := vm.Set(name, value)
|
||||
if err != nil {
|
||||
log.Panic().Err(err).Msgf("unable to register '%s' in Goja VM", name)
|
||||
}
|
||||
}
|
||||
|
||||
// Set some global functions for script debugging purposes.
|
||||
mustSet("print", jsPrint)
|
||||
mustSet("alert", jsAlert)
|
||||
|
||||
// Pre-import some useful modules.
|
||||
s.registry.Enable(vm)
|
||||
mustSet("author", require.Require(vm, "author"))
|
||||
mustSet("path", require.Require(vm, "path"))
|
||||
mustSet("process", require.Require(vm, "process"))
|
||||
|
||||
return vm
|
||||
}
|
||||
|
||||
// compilerForJobType returns a Goja *Runtime that has the job compiler script for
|
||||
// the given job type loaded up.
|
||||
func (s *Service) compilerForJobType(jobTypeName string) (*VM, error) {
|
||||
program, ok := s.compilers[jobTypeName]
|
||||
if !ok {
|
||||
return nil, ErrJobTypeUnknown
|
||||
}
|
||||
|
||||
vm := s.newGojaVM()
|
||||
if _, err := vm.RunProgram(program.program); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &VM{
|
||||
runtime: vm,
|
||||
compiler: program,
|
||||
}, nil
|
||||
}
|
||||
|
@ -18,6 +18,28 @@
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK ***** */
|
||||
|
||||
const JOB_TYPE = {
|
||||
label: "Simple Blender Render",
|
||||
settings: [
|
||||
{ key: "blender_cmd", type: "string", default: "{blender}" },
|
||||
{ key: "chunk_size", type: "int32", default: 1 },
|
||||
{ key: "frames", type: "string", required: true },
|
||||
{ key: "render_output", type: "string", required: true },
|
||||
{ key: "fps", type: "int32" },
|
||||
{ key: "extract_audio", type: "bool", default: true },
|
||||
{
|
||||
key: "images_or_video",
|
||||
type: "string",
|
||||
required: true,
|
||||
choices: ["images", "video"],
|
||||
visible: false,
|
||||
},
|
||||
{ key: "format", type: "string", required: true },
|
||||
{ key: "output_file_extension", type: "string", required: true },
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
// Set of scene.render.image_settings.file_format values that produce
|
||||
// files which FFmpeg is known not to handle as input.
|
||||
const ffmpegIncompatibleImageFormats = new Set([
|
||||
|
@ -77,6 +77,8 @@ paths:
|
||||
tags:
|
||||
- name: worker
|
||||
description: API for Flamenco Workers to communicate with Flamenco Manager.
|
||||
- name: jobs
|
||||
description: Blablabla for users to get job metadata balbla
|
||||
|
||||
components:
|
||||
schemas:
|
||||
@ -154,10 +156,11 @@ components:
|
||||
description: Job type supported by this Manager, and its parameters.
|
||||
properties:
|
||||
"name": {type: string}
|
||||
"label": {type: string}
|
||||
"settings":
|
||||
type: array
|
||||
items: {$ref: "#/components/schemas/AvailableJobSetting"}
|
||||
required: [name, settings]
|
||||
required: [name, label, settings]
|
||||
|
||||
AvailableJobSetting:
|
||||
type: object
|
||||
|
@ -18,35 +18,36 @@ import (
|
||||
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||
var swaggerSpec = []string{
|
||||
|
||||
"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",
|
||||
"MSpkhCWapcH+wNhV97f7fwcAAP//KSYvdP0WAAA=",
|
||||
}
|
||||
|
||||
// GetSwagger returns the content of the embedded swagger specification file
|
||||
|
@ -81,6 +81,7 @@ type AvailableJobSettingType string
|
||||
|
||||
// Job type supported by this Manager, and its parameters.
|
||||
type AvailableJobType struct {
|
||||
Label string `json:"label"`
|
||||
Name string `json:"name"`
|
||||
Settings []AvailableJobSetting `json:"settings"`
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user