Job status change system for SocketIO broadcasts
Not fully tested yet.
This commit is contained in:
parent
c875745bd4
commit
0c0df41f5d
@ -10,7 +10,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
__version__ = "781f1d93-dirty"
|
__version__ = "c875745b-dirty"
|
||||||
|
|
||||||
# import ApiClient
|
# import ApiClient
|
||||||
from flamenco.manager.api_client import ApiClient
|
from flamenco.manager.api_client import ApiClient
|
||||||
|
@ -76,7 +76,7 @@ class ApiClient(object):
|
|||||||
self.default_headers[header_name] = header_value
|
self.default_headers[header_name] = header_value
|
||||||
self.cookie = cookie
|
self.cookie = cookie
|
||||||
# Set default User-Agent.
|
# Set default User-Agent.
|
||||||
self.user_agent = 'Flamenco/781f1d93-dirty (Blender add-on)'
|
self.user_agent = 'Flamenco/c875745b-dirty (Blender add-on)'
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
|
@ -404,7 +404,7 @@ conf = flamenco.manager.Configuration(
|
|||||||
"OS: {env}\n"\
|
"OS: {env}\n"\
|
||||||
"Python Version: {pyversion}\n"\
|
"Python Version: {pyversion}\n"\
|
||||||
"Version of the API: 1.0.0\n"\
|
"Version of the API: 1.0.0\n"\
|
||||||
"SDK Package Version: 781f1d93-dirty".\
|
"SDK Package Version: c875745b-dirty".\
|
||||||
format(env=sys.platform, pyversion=sys.version)
|
format(env=sys.platform, pyversion=sys.version)
|
||||||
|
|
||||||
def get_host_settings(self):
|
def get_host_settings(self):
|
||||||
|
15
addon/flamenco/manager/docs/JobUpdate.md
Normal file
15
addon/flamenco/manager/docs/JobUpdate.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# JobUpdate
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**id** | **str** | UUID of the Job |
|
||||||
|
**updated** | **datetime** | Timestamp of last update |
|
||||||
|
**status** | [**JobStatus**](JobStatus.md) | |
|
||||||
|
**previous_status** | [**JobStatus**](JobStatus.md) | | [optional]
|
||||||
|
**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
283
addon/flamenco/manager/model/job_update.py
Normal file
283
addon/flamenco/manager/model/job_update.py
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
"""
|
||||||
|
Flamenco manager
|
||||||
|
|
||||||
|
Render Farm manager API # noqa: E501
|
||||||
|
|
||||||
|
The version of the OpenAPI document: 1.0.0
|
||||||
|
Generated by: https://openapi-generator.tech
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import re # noqa: F401
|
||||||
|
import sys # noqa: F401
|
||||||
|
|
||||||
|
from flamenco.manager.model_utils import ( # noqa: F401
|
||||||
|
ApiTypeError,
|
||||||
|
ModelComposed,
|
||||||
|
ModelNormal,
|
||||||
|
ModelSimple,
|
||||||
|
cached_property,
|
||||||
|
change_keys_js_to_python,
|
||||||
|
convert_js_args_to_python_args,
|
||||||
|
date,
|
||||||
|
datetime,
|
||||||
|
file_type,
|
||||||
|
none_type,
|
||||||
|
validate_get_composed_info,
|
||||||
|
OpenApiModel
|
||||||
|
)
|
||||||
|
from flamenco.manager.exceptions import ApiAttributeError
|
||||||
|
|
||||||
|
|
||||||
|
def lazy_import():
|
||||||
|
from flamenco.manager.model.job_status import JobStatus
|
||||||
|
globals()['JobStatus'] = JobStatus
|
||||||
|
|
||||||
|
|
||||||
|
class JobUpdate(ModelNormal):
|
||||||
|
"""NOTE: This class is auto generated by OpenAPI Generator.
|
||||||
|
Ref: https://openapi-generator.tech
|
||||||
|
|
||||||
|
Do not edit the class manually.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
allowed_values (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
with a capitalized key describing the allowed value and an allowed
|
||||||
|
value. These dicts store the allowed enum values.
|
||||||
|
attribute_map (dict): The key is attribute name
|
||||||
|
and the value is json key in definition.
|
||||||
|
discriminator_value_class_map (dict): A dict to go from the discriminator
|
||||||
|
variable value to the discriminator class name.
|
||||||
|
validations (dict): The key is the tuple path to the attribute
|
||||||
|
and the for var_name this is (var_name,). The value is a dict
|
||||||
|
that stores validations for max_length, min_length, max_items,
|
||||||
|
min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
|
||||||
|
inclusive_minimum, and regex.
|
||||||
|
additional_properties_type (tuple): A tuple of classes accepted
|
||||||
|
as additional properties values.
|
||||||
|
"""
|
||||||
|
|
||||||
|
allowed_values = {
|
||||||
|
}
|
||||||
|
|
||||||
|
validations = {
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def additional_properties_type():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
"""
|
||||||
|
lazy_import()
|
||||||
|
return (bool, date, datetime, dict, float, int, list, str, none_type,) # noqa: E501
|
||||||
|
|
||||||
|
_nullable = False
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def openapi_types():
|
||||||
|
"""
|
||||||
|
This must be a method because a model may have properties that are
|
||||||
|
of type self, this must run after the class is loaded
|
||||||
|
|
||||||
|
Returns
|
||||||
|
openapi_types (dict): The key is attribute name
|
||||||
|
and the value is attribute type.
|
||||||
|
"""
|
||||||
|
lazy_import()
|
||||||
|
return {
|
||||||
|
'id': (str,), # noqa: E501
|
||||||
|
'updated': (datetime,), # noqa: E501
|
||||||
|
'status': (JobStatus,), # noqa: E501
|
||||||
|
'previous_status': (JobStatus,), # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def discriminator():
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
attribute_map = {
|
||||||
|
'id': 'id', # noqa: E501
|
||||||
|
'updated': 'updated', # noqa: E501
|
||||||
|
'status': 'status', # noqa: E501
|
||||||
|
'previous_status': 'previous_status', # noqa: E501
|
||||||
|
}
|
||||||
|
|
||||||
|
read_only_vars = {
|
||||||
|
}
|
||||||
|
|
||||||
|
_composed_schemas = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def _from_openapi_data(cls, id, updated, status, *args, **kwargs): # noqa: E501
|
||||||
|
"""JobUpdate - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
id (str): UUID of the Job
|
||||||
|
updated (datetime): Timestamp of last update
|
||||||
|
status (JobStatus):
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
previous_status (JobStatus): [optional] # noqa: E501
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
self = super(OpenApiModel, cls).__new__(cls)
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
self.id = id
|
||||||
|
self.updated = updated
|
||||||
|
self.status = status
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name not in self.attribute_map and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self.additional_properties_type is None:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
required_properties = set([
|
||||||
|
'_data_store',
|
||||||
|
'_check_type',
|
||||||
|
'_spec_property_naming',
|
||||||
|
'_path_to_item',
|
||||||
|
'_configuration',
|
||||||
|
'_visited_composed_classes',
|
||||||
|
])
|
||||||
|
|
||||||
|
@convert_js_args_to_python_args
|
||||||
|
def __init__(self, id, updated, status, *args, **kwargs): # noqa: E501
|
||||||
|
"""JobUpdate - a model defined in OpenAPI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
id (str): UUID of the Job
|
||||||
|
updated (datetime): Timestamp of last update
|
||||||
|
status (JobStatus):
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
_check_type (bool): if True, values for parameters in openapi_types
|
||||||
|
will be type checked and a TypeError will be
|
||||||
|
raised if the wrong type is input.
|
||||||
|
Defaults to True
|
||||||
|
_path_to_item (tuple/list): This is a list of keys or values to
|
||||||
|
drill down to the model in received_data
|
||||||
|
when deserializing a response
|
||||||
|
_spec_property_naming (bool): True if the variable names in the input data
|
||||||
|
are serialized names, as specified in the OpenAPI document.
|
||||||
|
False if the variable names in the input data
|
||||||
|
are pythonic names, e.g. snake case (default)
|
||||||
|
_configuration (Configuration): the instance to use when
|
||||||
|
deserializing a file_type parameter.
|
||||||
|
If passed, type conversion is attempted
|
||||||
|
If omitted no type conversion is done.
|
||||||
|
_visited_composed_classes (tuple): This stores a tuple of
|
||||||
|
classes that we have traveled through so that
|
||||||
|
if we see that class again we will not use its
|
||||||
|
discriminator again.
|
||||||
|
When traveling through a discriminator, the
|
||||||
|
composed schema that is
|
||||||
|
is traveled through is added to this set.
|
||||||
|
For example if Animal has a discriminator
|
||||||
|
petType and we pass in "Dog", and the class Dog
|
||||||
|
allOf includes Animal, we move through Animal
|
||||||
|
once using the discriminator, and pick Dog.
|
||||||
|
Then in Dog, we will make an instance of the
|
||||||
|
Animal class but this time we won't travel
|
||||||
|
through its discriminator because we passed in
|
||||||
|
_visited_composed_classes = (Animal,)
|
||||||
|
previous_status (JobStatus): [optional] # noqa: E501
|
||||||
|
"""
|
||||||
|
|
||||||
|
_check_type = kwargs.pop('_check_type', True)
|
||||||
|
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
|
||||||
|
_path_to_item = kwargs.pop('_path_to_item', ())
|
||||||
|
_configuration = kwargs.pop('_configuration', None)
|
||||||
|
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
|
||||||
|
|
||||||
|
if args:
|
||||||
|
raise ApiTypeError(
|
||||||
|
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
|
||||||
|
args,
|
||||||
|
self.__class__.__name__,
|
||||||
|
),
|
||||||
|
path_to_item=_path_to_item,
|
||||||
|
valid_classes=(self.__class__,),
|
||||||
|
)
|
||||||
|
|
||||||
|
self._data_store = {}
|
||||||
|
self._check_type = _check_type
|
||||||
|
self._spec_property_naming = _spec_property_naming
|
||||||
|
self._path_to_item = _path_to_item
|
||||||
|
self._configuration = _configuration
|
||||||
|
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
|
||||||
|
|
||||||
|
self.id = id
|
||||||
|
self.updated = updated
|
||||||
|
self.status = status
|
||||||
|
for var_name, var_value in kwargs.items():
|
||||||
|
if var_name not in self.attribute_map and \
|
||||||
|
self._configuration is not None and \
|
||||||
|
self._configuration.discard_unknown_keys and \
|
||||||
|
self.additional_properties_type is None:
|
||||||
|
# discard variable.
|
||||||
|
continue
|
||||||
|
setattr(self, var_name, var_value)
|
||||||
|
if var_name in self.read_only_vars:
|
||||||
|
raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
|
||||||
|
f"class with read only attributes.")
|
@ -23,6 +23,7 @@ from flamenco.manager.model.job_all_of import JobAllOf
|
|||||||
from flamenco.manager.model.job_metadata import JobMetadata
|
from flamenco.manager.model.job_metadata import JobMetadata
|
||||||
from flamenco.manager.model.job_settings import JobSettings
|
from flamenco.manager.model.job_settings import JobSettings
|
||||||
from flamenco.manager.model.job_status import JobStatus
|
from flamenco.manager.model.job_status import JobStatus
|
||||||
|
from flamenco.manager.model.job_update import JobUpdate
|
||||||
from flamenco.manager.model.jobs_query import JobsQuery
|
from flamenco.manager.model.jobs_query import JobsQuery
|
||||||
from flamenco.manager.model.jobs_query_result import JobsQueryResult
|
from flamenco.manager.model.jobs_query_result import JobsQueryResult
|
||||||
from flamenco.manager.model.manager_configuration import ManagerConfiguration
|
from flamenco.manager.model.manager_configuration import ManagerConfiguration
|
||||||
|
@ -4,7 +4,7 @@ Render Farm manager API
|
|||||||
The `flamenco.manager` package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
The `flamenco.manager` package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||||
|
|
||||||
- API version: 1.0.0
|
- API version: 1.0.0
|
||||||
- Package version: 781f1d93-dirty
|
- Package version: c875745b-dirty
|
||||||
- Build package: org.openapitools.codegen.languages.PythonClientCodegen
|
- Build package: org.openapitools.codegen.languages.PythonClientCodegen
|
||||||
For more information, please visit [https://flamenco.io/](https://flamenco.io/)
|
For more information, please visit [https://flamenco.io/](https://flamenco.io/)
|
||||||
|
|
||||||
@ -101,6 +101,7 @@ Class | Method | HTTP request | Description
|
|||||||
- [JobMetadata](flamenco/manager/docs/JobMetadata.md)
|
- [JobMetadata](flamenco/manager/docs/JobMetadata.md)
|
||||||
- [JobSettings](flamenco/manager/docs/JobSettings.md)
|
- [JobSettings](flamenco/manager/docs/JobSettings.md)
|
||||||
- [JobStatus](flamenco/manager/docs/JobStatus.md)
|
- [JobStatus](flamenco/manager/docs/JobStatus.md)
|
||||||
|
- [JobUpdate](flamenco/manager/docs/JobUpdate.md)
|
||||||
- [JobsQuery](flamenco/manager/docs/JobsQuery.md)
|
- [JobsQuery](flamenco/manager/docs/JobsQuery.md)
|
||||||
- [JobsQueryResult](flamenco/manager/docs/JobsQueryResult.md)
|
- [JobsQueryResult](flamenco/manager/docs/JobsQueryResult.md)
|
||||||
- [ManagerConfiguration](flamenco/manager/docs/ManagerConfiguration.md)
|
- [ManagerConfiguration](flamenco/manager/docs/ManagerConfiguration.md)
|
||||||
|
@ -94,8 +94,8 @@ func main() {
|
|||||||
//
|
//
|
||||||
// go persist.PeriodicMaintenanceLoop(mainCtx)
|
// go persist.PeriodicMaintenanceLoop(mainCtx)
|
||||||
|
|
||||||
flamenco := buildFlamencoAPI(configService, persist)
|
|
||||||
webUpdater := webupdates.New()
|
webUpdater := webupdates.New()
|
||||||
|
flamenco := buildFlamencoAPI(configService, persist, webUpdater)
|
||||||
e := buildWebService(flamenco, persist, ssdp, webUpdater)
|
e := buildWebService(flamenco, persist, ssdp, webUpdater)
|
||||||
|
|
||||||
installSignalHandler(mainCtxCancel)
|
installSignalHandler(mainCtxCancel)
|
||||||
@ -132,14 +132,14 @@ func main() {
|
|||||||
log.Info().Msg("shutdown complete")
|
log.Info().Msg("shutdown complete")
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildFlamencoAPI(configService *config.Service, persist *persistence.DB) api.ServerInterface {
|
func buildFlamencoAPI(configService *config.Service, persist *persistence.DB, webUpdater *webupdates.BiDirComms) api.ServerInterface {
|
||||||
timeService := clock.New()
|
timeService := clock.New()
|
||||||
compiler, err := job_compilers.Load(timeService)
|
compiler, err := job_compilers.Load(timeService)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("error loading job compilers")
|
log.Fatal().Err(err).Msg("error loading job compilers")
|
||||||
}
|
}
|
||||||
logStorage := task_logs.NewStorage(configService.Get().TaskLogsPath)
|
logStorage := task_logs.NewStorage(configService.Get().TaskLogsPath)
|
||||||
taskStateMachine := task_state_machine.NewStateMachine(persist)
|
taskStateMachine := task_state_machine.NewStateMachine(persist, webUpdater)
|
||||||
shamanServer := shaman.NewServer(configService.Get().Shaman, nil)
|
shamanServer := shaman.NewServer(configService.Get().Shaman, nil)
|
||||||
flamenco := api_impl.NewFlamenco(compiler, persist, logStorage, configService, taskStateMachine, shamanServer)
|
flamenco := api_impl.NewFlamenco(compiler, persist, logStorage, configService, taskStateMachine, shamanServer)
|
||||||
return flamenco
|
return flamenco
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"git.blender.org/flamenco/internal/manager/job_compilers"
|
"git.blender.org/flamenco/internal/manager/job_compilers"
|
||||||
"git.blender.org/flamenco/internal/manager/persistence"
|
"git.blender.org/flamenco/internal/manager/persistence"
|
||||||
"git.blender.org/flamenco/internal/manager/task_state_machine"
|
"git.blender.org/flamenco/internal/manager/task_state_machine"
|
||||||
|
"git.blender.org/flamenco/internal/manager/webupdates"
|
||||||
"git.blender.org/flamenco/pkg/api"
|
"git.blender.org/flamenco/pkg/api"
|
||||||
"git.blender.org/flamenco/pkg/shaman"
|
"git.blender.org/flamenco/pkg/shaman"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
@ -66,6 +67,14 @@ type TaskStateMachine interface {
|
|||||||
// TaskStateMachine should be a subset of task_state_machine.StateMachine.
|
// TaskStateMachine should be a subset of task_state_machine.StateMachine.
|
||||||
var _ TaskStateMachine = (*task_state_machine.StateMachine)(nil)
|
var _ TaskStateMachine = (*task_state_machine.StateMachine)(nil)
|
||||||
|
|
||||||
|
type ChangeBroadcaster interface {
|
||||||
|
// BroadcastNewJob sends a 'new job' notification to all SocketIO clients.
|
||||||
|
BroadcastNewJob(jobUpdate api.JobUpdate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangeBroadcaster should be a subset of webupdates.BiDirComms.
|
||||||
|
var _ ChangeBroadcaster = (*webupdates.BiDirComms)(nil)
|
||||||
|
|
||||||
type JobCompiler interface {
|
type JobCompiler interface {
|
||||||
ListJobTypes() api.AvailableJobTypes
|
ListJobTypes() api.AvailableJobTypes
|
||||||
Compile(ctx context.Context, job api.SubmittedJob) (*job_compilers.AuthoredJob, error)
|
Compile(ctx context.Context, job api.SubmittedJob) (*job_compilers.AuthoredJob, error)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Code generated by MockGen. DO NOT EDIT.
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
// Source: git.blender.org/flamenco/internal/manager/task_state_machine (interfaces: PersistenceService)
|
// Source: git.blender.org/flamenco/internal/manager/task_state_machine (interfaces: PersistenceService,ChangeBroadcaster)
|
||||||
|
|
||||||
// Package mocks is a generated GoMock package.
|
// Package mocks is a generated GoMock package.
|
||||||
package mocks
|
package mocks
|
||||||
@ -122,3 +122,38 @@ func (mr *MockPersistenceServiceMockRecorder) UpdateJobsTaskStatusesConditional(
|
|||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateJobsTaskStatusesConditional", reflect.TypeOf((*MockPersistenceService)(nil).UpdateJobsTaskStatusesConditional), arg0, arg1, arg2, arg3, arg4)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateJobsTaskStatusesConditional", reflect.TypeOf((*MockPersistenceService)(nil).UpdateJobsTaskStatusesConditional), arg0, arg1, arg2, arg3, arg4)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MockChangeBroadcaster is a mock of ChangeBroadcaster interface.
|
||||||
|
type MockChangeBroadcaster struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockChangeBroadcasterMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockChangeBroadcasterMockRecorder is the mock recorder for MockChangeBroadcaster.
|
||||||
|
type MockChangeBroadcasterMockRecorder struct {
|
||||||
|
mock *MockChangeBroadcaster
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockChangeBroadcaster creates a new mock instance.
|
||||||
|
func NewMockChangeBroadcaster(ctrl *gomock.Controller) *MockChangeBroadcaster {
|
||||||
|
mock := &MockChangeBroadcaster{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockChangeBroadcasterMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockChangeBroadcaster) EXPECT() *MockChangeBroadcasterMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// BroadcastJobUpdate mocks base method.
|
||||||
|
func (m *MockChangeBroadcaster) BroadcastJobUpdate(arg0 api.JobUpdate) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
m.ctrl.Call(m, "BroadcastJobUpdate", arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BroadcastJobUpdate indicates an expected call of BroadcastJobUpdate.
|
||||||
|
func (mr *MockChangeBroadcasterMockRecorder) BroadcastJobUpdate(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BroadcastJobUpdate", reflect.TypeOf((*MockChangeBroadcaster)(nil).BroadcastJobUpdate), arg0)
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"git.blender.org/flamenco/internal/manager/persistence"
|
"git.blender.org/flamenco/internal/manager/persistence"
|
||||||
|
"git.blender.org/flamenco/internal/manager/webupdates"
|
||||||
"git.blender.org/flamenco/pkg/api"
|
"git.blender.org/flamenco/pkg/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,11 +20,12 @@ const taskFailJobPercentage = 10 // Integer from 0 to 100.
|
|||||||
|
|
||||||
// StateMachine handles task and job status changes.
|
// StateMachine handles task and job status changes.
|
||||||
type StateMachine struct {
|
type StateMachine struct {
|
||||||
persist PersistenceService
|
persist PersistenceService
|
||||||
|
broadcaster ChangeBroadcaster
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate mock implementations of these interfaces.
|
// Generate mock implementations of these interfaces.
|
||||||
//go:generate go run github.com/golang/mock/mockgen -destination mocks/interfaces_mock.gen.go -package mocks git.blender.org/flamenco/internal/manager/task_state_machine PersistenceService
|
//go:generate go run github.com/golang/mock/mockgen -destination mocks/interfaces_mock.gen.go -package mocks git.blender.org/flamenco/internal/manager/task_state_machine PersistenceService,ChangeBroadcaster
|
||||||
|
|
||||||
type PersistenceService interface {
|
type PersistenceService interface {
|
||||||
SaveTask(ctx context.Context, task *persistence.Task) error
|
SaveTask(ctx context.Context, task *persistence.Task) error
|
||||||
@ -45,9 +47,18 @@ type PersistenceService interface {
|
|||||||
// PersistenceService should be a subset of persistence.DB
|
// PersistenceService should be a subset of persistence.DB
|
||||||
var _ PersistenceService = (*persistence.DB)(nil)
|
var _ PersistenceService = (*persistence.DB)(nil)
|
||||||
|
|
||||||
func NewStateMachine(persist PersistenceService) *StateMachine {
|
type ChangeBroadcaster interface {
|
||||||
|
// BroadcastJobUpdate sends the job update to clients.
|
||||||
|
BroadcastJobUpdate(jobUpdate api.JobUpdate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangeBroadcaster should be a subset of webupdates.BiDirComms
|
||||||
|
var _ ChangeBroadcaster = (*webupdates.BiDirComms)(nil)
|
||||||
|
|
||||||
|
func NewStateMachine(persist PersistenceService, broadcaster ChangeBroadcaster) *StateMachine {
|
||||||
return &StateMachine{
|
return &StateMachine{
|
||||||
persist: persist,
|
persist: persist,
|
||||||
|
broadcaster: broadcaster,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,6 +255,15 @@ func (sm *StateMachine) JobStatusChange(ctx context.Context, job *persistence.Jo
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("updating job's tasks after job status change: %w", err)
|
return fmt.Errorf("updating job's tasks after job status change: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Broadcast this change to the SocketIO clients.
|
||||||
|
jobUpdate := api.JobUpdate{
|
||||||
|
Id: job.UUID,
|
||||||
|
Updated: job.UpdatedAt,
|
||||||
|
PreviousStatus: &oldJobStatus,
|
||||||
|
Status: job.Status,
|
||||||
|
}
|
||||||
|
sm.broadcaster.BroadcastJobUpdate(jobUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -18,7 +18,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type StateMachineMocks struct {
|
type StateMachineMocks struct {
|
||||||
persist *mocks.MockPersistenceService
|
persist *mocks.MockPersistenceService
|
||||||
|
broadcaster *mocks.MockChangeBroadcaster
|
||||||
}
|
}
|
||||||
|
|
||||||
// In the comments below, "T" indicates the performed task status change, and
|
// In the comments below, "T" indicates the performed task status change, and
|
||||||
@ -32,6 +33,8 @@ func TestTaskStatusChangeQueuedToActive(t *testing.T) {
|
|||||||
task := taskWithStatus(api.JobStatusQueued, api.TaskStatusQueued)
|
task := taskWithStatus(api.JobStatusQueued, api.TaskStatusQueued)
|
||||||
mocks.expectSaveTaskWithStatus(t, task, api.TaskStatusActive)
|
mocks.expectSaveTaskWithStatus(t, task, api.TaskStatusActive)
|
||||||
mocks.expectSaveJobWithStatus(t, task.Job, api.JobStatusActive)
|
mocks.expectSaveJobWithStatus(t, task.Job, api.JobStatusActive)
|
||||||
|
mocks.expectBroadcastJobChange(task.Job, api.JobStatusQueued, api.JobStatusActive)
|
||||||
|
|
||||||
assert.NoError(t, sm.TaskStatusChange(ctx, task, api.TaskStatusActive))
|
assert.NoError(t, sm.TaskStatusChange(ctx, task, api.TaskStatusActive))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,6 +84,8 @@ func TestTaskStatusChangeActiveToCompleted(t *testing.T) {
|
|||||||
mocks.expectSaveTaskWithStatus(t, task3, api.TaskStatusCompleted)
|
mocks.expectSaveTaskWithStatus(t, task3, api.TaskStatusCompleted)
|
||||||
mocks.persist.EXPECT().CountTasksOfJobInStatus(ctx, task.Job, api.TaskStatusCompleted).Return(3, 3, nil) // 3 of 3 complete.
|
mocks.persist.EXPECT().CountTasksOfJobInStatus(ctx, task.Job, api.TaskStatusCompleted).Return(3, 3, nil) // 3 of 3 complete.
|
||||||
mocks.expectSaveJobWithStatus(t, task.Job, api.JobStatusCompleted)
|
mocks.expectSaveJobWithStatus(t, task.Job, api.JobStatusCompleted)
|
||||||
|
mocks.expectBroadcastJobChange(task.Job, api.JobStatusActive, api.JobStatusCompleted)
|
||||||
|
|
||||||
assert.NoError(t, sm.TaskStatusChange(ctx, task3, api.TaskStatusCompleted))
|
assert.NoError(t, sm.TaskStatusChange(ctx, task3, api.TaskStatusCompleted))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +98,8 @@ func TestTaskStatusChangeQueuedToFailed(t *testing.T) {
|
|||||||
mocks.expectSaveTaskWithStatus(t, task, api.TaskStatusFailed)
|
mocks.expectSaveTaskWithStatus(t, task, api.TaskStatusFailed)
|
||||||
mocks.expectSaveJobWithStatus(t, task.Job, api.JobStatusActive)
|
mocks.expectSaveJobWithStatus(t, task.Job, api.JobStatusActive)
|
||||||
mocks.persist.EXPECT().CountTasksOfJobInStatus(ctx, task.Job, api.TaskStatusFailed).Return(1, 100, nil) // 1 out of 100 failed.
|
mocks.persist.EXPECT().CountTasksOfJobInStatus(ctx, task.Job, api.TaskStatusFailed).Return(1, 100, nil) // 1 out of 100 failed.
|
||||||
|
mocks.expectBroadcastJobChange(task.Job, api.JobStatusQueued, api.JobStatusActive)
|
||||||
|
|
||||||
assert.NoError(t, sm.TaskStatusChange(ctx, task, api.TaskStatusFailed))
|
assert.NoError(t, sm.TaskStatusChange(ctx, task, api.TaskStatusFailed))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +111,8 @@ func TestTaskStatusChangeActiveToFailedFailJob(t *testing.T) {
|
|||||||
task := taskWithStatus(api.JobStatusActive, api.TaskStatusActive)
|
task := taskWithStatus(api.JobStatusActive, api.TaskStatusActive)
|
||||||
mocks.expectSaveTaskWithStatus(t, task, api.TaskStatusFailed)
|
mocks.expectSaveTaskWithStatus(t, task, api.TaskStatusFailed)
|
||||||
mocks.expectSaveJobWithStatus(t, task.Job, api.JobStatusFailed)
|
mocks.expectSaveJobWithStatus(t, task.Job, api.JobStatusFailed)
|
||||||
|
mocks.expectBroadcastJobChange(task.Job, api.JobStatusActive, api.JobStatusFailed)
|
||||||
|
|
||||||
mocks.persist.EXPECT().CountTasksOfJobInStatus(ctx, task.Job, api.TaskStatusFailed).Return(10, 100, nil) // 10 out of 100 failed.
|
mocks.persist.EXPECT().CountTasksOfJobInStatus(ctx, task.Job, api.TaskStatusFailed).Return(10, 100, nil) // 10 out of 100 failed.
|
||||||
|
|
||||||
// Expect failure of the job to trigger cancellation of remaining tasks.
|
// Expect failure of the job to trigger cancellation of remaining tasks.
|
||||||
@ -127,6 +136,8 @@ func TestTaskStatusChangeRequeueOnCompletedJob(t *testing.T) {
|
|||||||
task := taskWithStatus(api.JobStatusCompleted, api.TaskStatusCompleted)
|
task := taskWithStatus(api.JobStatusCompleted, api.TaskStatusCompleted)
|
||||||
mocks.expectSaveTaskWithStatus(t, task, api.TaskStatusQueued)
|
mocks.expectSaveTaskWithStatus(t, task, api.TaskStatusQueued)
|
||||||
mocks.expectSaveJobWithStatus(t, task.Job, api.JobStatusRequeued)
|
mocks.expectSaveJobWithStatus(t, task.Job, api.JobStatusRequeued)
|
||||||
|
mocks.expectBroadcastJobChange(task.Job, api.JobStatusCompleted, api.JobStatusRequeued)
|
||||||
|
mocks.expectBroadcastJobChange(task.Job, api.JobStatusRequeued, api.JobStatusQueued)
|
||||||
|
|
||||||
// Expect queueing of the job to trigger queueing of all its tasks, if those tasks were all completed before.
|
// Expect queueing of the job to trigger queueing of all its tasks, if those tasks were all completed before.
|
||||||
// 2 out of 3 completed, because one was just queued.
|
// 2 out of 3 completed, because one was just queued.
|
||||||
@ -156,6 +167,8 @@ func TestTaskStatusChangeCancelSingleTask(t *testing.T) {
|
|||||||
mocks.expectSaveTaskWithStatus(t, task2, api.TaskStatusCanceled)
|
mocks.expectSaveTaskWithStatus(t, task2, api.TaskStatusCanceled)
|
||||||
mocks.persist.EXPECT().JobHasTasksInStatus(ctx, job, api.TaskStatusCancelRequested).Return(false, nil)
|
mocks.persist.EXPECT().JobHasTasksInStatus(ctx, job, api.TaskStatusCancelRequested).Return(false, nil)
|
||||||
mocks.expectSaveJobWithStatus(t, job, api.JobStatusCanceled)
|
mocks.expectSaveJobWithStatus(t, job, api.JobStatusCanceled)
|
||||||
|
mocks.expectBroadcastJobChange(task.Job, api.JobStatusCancelRequested, api.JobStatusCanceled)
|
||||||
|
|
||||||
assert.NoError(t, sm.TaskStatusChange(ctx, task2, api.TaskStatusCanceled))
|
assert.NoError(t, sm.TaskStatusChange(ctx, task2, api.TaskStatusCanceled))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,6 +209,10 @@ func TestJobRequeueWithSomeCompletedTasks(t *testing.T) {
|
|||||||
"Queued because job transitioned status from \"active\" to \"requeued\"",
|
"Queued because job transitioned status from \"active\" to \"requeued\"",
|
||||||
)
|
)
|
||||||
mocks.expectSaveJobWithStatus(t, job, api.JobStatusQueued)
|
mocks.expectSaveJobWithStatus(t, job, api.JobStatusQueued)
|
||||||
|
|
||||||
|
mocks.expectBroadcastJobChange(job, api.JobStatusActive, api.JobStatusRequeued)
|
||||||
|
mocks.expectBroadcastJobChange(job, api.JobStatusRequeued, api.JobStatusQueued)
|
||||||
|
|
||||||
assert.NoError(t, sm.JobStatusChange(ctx, job, api.JobStatusRequeued))
|
assert.NoError(t, sm.JobStatusChange(ctx, job, api.JobStatusRequeued))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,14 +241,18 @@ func TestJobRequeueWithAllCompletedTasks(t *testing.T) {
|
|||||||
Return(0, 3, nil). // By now all tasks are queued.
|
Return(0, 3, nil). // By now all tasks are queued.
|
||||||
After(call3)
|
After(call3)
|
||||||
|
|
||||||
|
mocks.expectBroadcastJobChange(job, api.JobStatusCompleted, api.JobStatusRequeued)
|
||||||
|
mocks.expectBroadcastJobChange(job, api.JobStatusRequeued, api.JobStatusQueued)
|
||||||
|
|
||||||
assert.NoError(t, sm.JobStatusChange(ctx, job, api.JobStatusRequeued))
|
assert.NoError(t, sm.JobStatusChange(ctx, job, api.JobStatusRequeued))
|
||||||
}
|
}
|
||||||
|
|
||||||
func mockedTaskStateMachine(mockCtrl *gomock.Controller) (*StateMachine, *StateMachineMocks) {
|
func mockedTaskStateMachine(mockCtrl *gomock.Controller) (*StateMachine, *StateMachineMocks) {
|
||||||
mocks := StateMachineMocks{
|
mocks := StateMachineMocks{
|
||||||
persist: mocks.NewMockPersistenceService(mockCtrl),
|
persist: mocks.NewMockPersistenceService(mockCtrl),
|
||||||
|
broadcaster: mocks.NewMockChangeBroadcaster(mockCtrl),
|
||||||
}
|
}
|
||||||
sm := NewStateMachine(mocks.persist)
|
sm := NewStateMachine(mocks.persist, mocks.broadcaster)
|
||||||
return sm, &mocks
|
return sm, &mocks
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,6 +282,19 @@ func (m *StateMachineMocks) expectSaveJobWithStatus(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *StateMachineMocks) expectBroadcastJobChange(
|
||||||
|
job *persistence.Job,
|
||||||
|
fromStatus, toStatus api.JobStatus,
|
||||||
|
) *gomock.Call {
|
||||||
|
expectUpdate := api.JobUpdate{
|
||||||
|
Id: job.UUID,
|
||||||
|
Updated: job.UpdatedAt,
|
||||||
|
PreviousStatus: &fromStatus,
|
||||||
|
Status: toStatus,
|
||||||
|
}
|
||||||
|
return m.broadcaster.EXPECT().BroadcastJobUpdate(expectUpdate)
|
||||||
|
}
|
||||||
|
|
||||||
/* taskWithStatus() creates a task of a certain status, with a job of a certain status. */
|
/* taskWithStatus() creates a task of a certain status, with a job of a certain status. */
|
||||||
func taskWithStatus(jobStatus api.JobStatus, taskStatus api.TaskStatus) *persistence.Task {
|
func taskWithStatus(jobStatus api.JobStatus, taskStatus api.TaskStatus) *persistence.Task {
|
||||||
job := persistence.Job{
|
job := persistence.Job{
|
||||||
|
19
internal/manager/webupdates/chatrooms.go
Normal file
19
internal/manager/webupdates/chatrooms.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
package webupdates
|
||||||
|
|
||||||
|
type SocketIORoomName string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Predefined SocketIO rooms.
|
||||||
|
SocketIORoomChat SocketIORoomName = "Chat" // For chat messages.
|
||||||
|
SocketIORoomJobs SocketIORoomName = "Jobs" // For job updates.
|
||||||
|
)
|
||||||
|
|
||||||
|
type SocketIOEventType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Predefined SocketIO event types.
|
||||||
|
SIOEventChatMessageRcv SocketIOEventType = "/chat" // clients send messages here
|
||||||
|
SIOEventChatMessageSend SocketIOEventType = "/message" // messages are broadcasted here
|
||||||
|
SIOEventJobUpdate SocketIOEventType = "/jobs" // sends api.JobUpdate
|
||||||
|
)
|
25
internal/manager/webupdates/job_updates.go
Normal file
25
internal/manager/webupdates/job_updates.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
package webupdates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
|
"git.blender.org/flamenco/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BroadcastJobUpdate sends the job update to clients.
|
||||||
|
func (b *BiDirComms) BroadcastJobUpdate(jobUpdate api.JobUpdate) {
|
||||||
|
log.Debug().Interface("jobUpdate", jobUpdate).Msg("socketIO: broadcasting job update")
|
||||||
|
b.sockserv.BroadcastTo(string(SocketIORoomJobs), "/jobs", jobUpdate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BroadcastNewJob sends a "new job" notification to clients.
|
||||||
|
func (b *BiDirComms) BroadcastNewJob(jobUpdate api.JobUpdate) {
|
||||||
|
if jobUpdate.PreviousStatus != nil {
|
||||||
|
log.Warn().Interface("jobUpdate", jobUpdate).Msg("socketIO: new jobs should not have a previous state")
|
||||||
|
jobUpdate.PreviousStatus = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug().Interface("jobUpdate", jobUpdate).Msg("socketIO: broadcasting new job")
|
||||||
|
b.sockserv.BroadcastTo(string(SocketIORoomJobs), "/jobs", jobUpdate)
|
||||||
|
}
|
@ -37,7 +37,7 @@ func socketIOServer() *gosocketio.Server {
|
|||||||
// socket connection
|
// socket connection
|
||||||
err = sio.On(gosocketio.OnConnection, func(c *gosocketio.Channel) {
|
err = sio.On(gosocketio.OnConnection, func(c *gosocketio.Channel) {
|
||||||
log.Debug().Str("clientID", c.Id()).Msg("socketIO: connected")
|
log.Debug().Str("clientID", c.Id()).Msg("socketIO: connected")
|
||||||
if err := c.Join("Room"); err != nil {
|
if err := c.Join(string(SocketIORoomChat)); err != nil {
|
||||||
log.Warn().Err(err).Str("clientID", c.Id()).Msg("socketIO: unable to make client join broadcast message room")
|
log.Warn().Err(err).Str("clientID", c.Id()).Msg("socketIO: unable to make client join broadcast message room")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -48,7 +48,7 @@ func socketIOServer() *gosocketio.Server {
|
|||||||
// socket disconnection
|
// socket disconnection
|
||||||
err = sio.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel) {
|
err = sio.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel) {
|
||||||
log.Debug().Str("clientID", c.Id()).Msg("socketIO: disconnected")
|
log.Debug().Str("clientID", c.Id()).Msg("socketIO: disconnected")
|
||||||
if err := c.Leave("Room"); err != nil {
|
if err := c.Leave(string(SocketIORoomChat)); err != nil {
|
||||||
log.Warn().Err(err).Str("clientID", c.Id()).Msg("socketIO: unable to make client leave broadcast message room")
|
log.Warn().Err(err).Str("clientID", c.Id()).Msg("socketIO: unable to make client leave broadcast message room")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -64,12 +64,12 @@ func socketIOServer() *gosocketio.Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// chat socket
|
// chat socket
|
||||||
err = sio.On("/chat", func(c *gosocketio.Channel, message Message) string {
|
err = sio.On(string(SIOEventChatMessageRcv), func(c *gosocketio.Channel, message Message) string {
|
||||||
log.Info().Str("clientID", c.Id()).
|
log.Info().Str("clientID", c.Id()).
|
||||||
Str("text", message.Text).
|
Str("text", message.Text).
|
||||||
Str("name", message.Name).
|
Str("name", message.Name).
|
||||||
Msg("socketIO: message received")
|
Msg("socketIO: message received")
|
||||||
c.BroadcastTo("Room", "/message", message.Text)
|
c.BroadcastTo(string(SocketIORoomChat), string(SIOEventChatMessageSend), message)
|
||||||
return "message sent successfully."
|
return "message sent successfully."
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -892,6 +892,25 @@ components:
|
|||||||
"status": {$ref: "#/components/schemas/ShamanFileStatus"}
|
"status": {$ref: "#/components/schemas/ShamanFileStatus"}
|
||||||
required: [status]
|
required: [status]
|
||||||
|
|
||||||
|
# SocketIO API. These types are not used in any HTTP operation defined in
|
||||||
|
# the 'paths' section of this document, so some code generators may choose
|
||||||
|
# to skip these.
|
||||||
|
|
||||||
|
JobUpdate:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
"id":
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
description: UUID of the Job
|
||||||
|
"updated":
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
description: Timestamp of last update
|
||||||
|
"status": {$ref: "#/components/schemas/JobStatus"}
|
||||||
|
"previous_status": {$ref: "#/components/schemas/JobStatus"}
|
||||||
|
required: [id, updated, status]
|
||||||
|
|
||||||
securitySchemes:
|
securitySchemes:
|
||||||
worker_auth:
|
worker_auth:
|
||||||
description: Username is the worker ID, password is the secret given at worker registration.
|
description: Username is the worker ID, password is the secret given at worker registration.
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
//go:generate oapi-codegen -generate types -o openapi_types.gen.go -package api flamenco-manager.yaml
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
//go:generate oapi-codegen -generate server -o openapi_server.gen.go -package api flamenco-manager.yaml
|
|
||||||
//go:generate oapi-codegen -generate spec -o openapi_spec.gen.go -package api flamenco-manager.yaml
|
|
||||||
//go:generate oapi-codegen -generate client -o openapi_client.gen.go -package api flamenco-manager.yaml
|
|
||||||
|
|
||||||
package api
|
package api
|
||||||
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
//go:generate oapi-codegen -generate types,skip-prune -o openapi_types.gen.go -package api flamenco-manager.yaml
|
||||||
|
//go:generate oapi-codegen -generate server,skip-prune -o openapi_server.gen.go -package api flamenco-manager.yaml
|
||||||
|
//go:generate oapi-codegen -generate spec,skip-prune -o openapi_spec.gen.go -package api flamenco-manager.yaml
|
||||||
|
//go:generate oapi-codegen -generate client,skip-prune -o openapi_client.gen.go -package api flamenco-manager.yaml
|
||||||
|
@ -18,100 +18,101 @@ import (
|
|||||||
// Base64 encoded, gzipped, json marshaled Swagger object
|
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||||
var swaggerSpec = []string{
|
var swaggerSpec = []string{
|
||||||
|
|
||||||
"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",
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSwagger returns the content of the embedded swagger specification file
|
// GetSwagger returns the content of the embedded swagger specification file
|
||||||
|
@ -225,6 +225,17 @@ type JobSettings struct {
|
|||||||
// JobStatus defines model for JobStatus.
|
// JobStatus defines model for JobStatus.
|
||||||
type JobStatus string
|
type JobStatus string
|
||||||
|
|
||||||
|
// JobUpdate defines model for JobUpdate.
|
||||||
|
type JobUpdate struct {
|
||||||
|
// UUID of the Job
|
||||||
|
Id string `json:"id"`
|
||||||
|
PreviousStatus *JobStatus `json:"previous_status,omitempty"`
|
||||||
|
Status JobStatus `json:"status"`
|
||||||
|
|
||||||
|
// Timestamp of last update
|
||||||
|
Updated time.Time `json:"updated"`
|
||||||
|
}
|
||||||
|
|
||||||
// JobsQuery defines model for JobsQuery.
|
// JobsQuery defines model for JobsQuery.
|
||||||
type JobsQuery struct {
|
type JobsQuery struct {
|
||||||
Limit *int `json:"limit,omitempty"`
|
Limit *int `json:"limit,omitempty"`
|
||||||
|
@ -5,46 +5,45 @@
|
|||||||
<chat-chatbox
|
<chat-chatbox
|
||||||
@sendMessage="sendMessage"
|
@sendMessage="sendMessage"
|
||||||
:chatHistory="messages"
|
:chatHistory="messages"
|
||||||
></chat-chatbox>
|
/>
|
||||||
|
<jobs-listener
|
||||||
|
ref="jobsListener"
|
||||||
|
:websocketURL="websocketURL"
|
||||||
|
@jobUpdate="onJobUpdate"
|
||||||
|
@message="onChatMessage"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import io from "socket.io-client";
|
|
||||||
import ChatNavbar from "./components/ChatNavbar.vue";
|
import ChatNavbar from "./components/ChatNavbar.vue";
|
||||||
import ChatChatbox from "./components/ChatChatbox.vue";
|
import ChatChatbox from "./components/ChatChatbox.vue";
|
||||||
|
import JobsListener from "./components/JobsListener.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "App",
|
name: "FlamencoWebApp",
|
||||||
components: {
|
components: {
|
||||||
ChatNavbar,
|
ChatNavbar,
|
||||||
ChatChatbox,
|
ChatChatbox,
|
||||||
|
JobsListener,
|
||||||
},
|
},
|
||||||
data: () => {
|
data: () => {
|
||||||
return {
|
return {
|
||||||
socket: null,
|
websocketURL: "ws://localhost:8080",
|
||||||
serverUrl: process.env.VUE_APP_SOCKET_URL || "ws://localhost:8080",
|
|
||||||
messages: [],
|
messages: [],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted: function () {
|
mounted: function () {
|
||||||
this.connectToWebsocket();
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
connectToWebsocket() {
|
|
||||||
console.log("connecting to WS", this.serverUrl);
|
|
||||||
this.socket = io(this.serverUrl, {
|
|
||||||
transports: ["websocket"],
|
|
||||||
});
|
|
||||||
this.socket.on("/message", (message) => {
|
|
||||||
console.log("message received: ", message);
|
|
||||||
this.messages.push(message);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
sendMessage(message) {
|
sendMessage(message) {
|
||||||
const payload = { name: "Nikita", text: message };
|
this.$refs.jobsListener.sendBroadcastMessage("typer", message);
|
||||||
console.log("sending:", payload);
|
},
|
||||||
this.socket.emit("/chat", payload);
|
onJobUpdate(jobUpdate) {
|
||||||
|
console.log("job update received:", jobUpdate);
|
||||||
|
},
|
||||||
|
onChatMessage(message) {
|
||||||
|
console.log("chat message received:", message);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
63
web/app/src/components/JobsListener.vue
Normal file
63
web/app/src/components/JobsListener.vue
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<span />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import io from "socket.io-client";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
emits: ["jobUpdate", "taskUpdate", "message"],
|
||||||
|
props: ["websocketURL"],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
socket: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted: function () {
|
||||||
|
this.connectToWebsocket();
|
||||||
|
},
|
||||||
|
beforeDestroy: function() {
|
||||||
|
this.disconnectWebsocket();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
connectToWebsocket() {
|
||||||
|
// The SocketIO client API docs are available at:
|
||||||
|
// https://github.com/socketio/socket.io-client/blob/2.4.x/docs/API.md
|
||||||
|
console.log("connecting JobsListener to WS", this.websocketURL);
|
||||||
|
this.socket = io(this.websocketURL, {
|
||||||
|
transports: ["websocket"],
|
||||||
|
});
|
||||||
|
|
||||||
|
this.socket.on("reconnect", (attemptNumber) => {
|
||||||
|
console.log("socketIO reconnected after", attemptNumber, "attempts");
|
||||||
|
})
|
||||||
|
|
||||||
|
this.socket.on("/jobs", (jobUpdate) => {
|
||||||
|
this.$emit("jobUpdate", jobUpdate);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Chat system, useful for debugging.
|
||||||
|
this.socket.on("/message", (message) => {
|
||||||
|
this.$emit("message", message);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
disconnectWebsocket() {
|
||||||
|
if (this.socket == null) {
|
||||||
|
console.log("no JobListener socket to disconnect");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("disconnecting JobsListener WS", this.websocketURL);
|
||||||
|
this.socket.disconnect();
|
||||||
|
this.socket = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
sendBroadcastMessage(name, message) {
|
||||||
|
const payload = { name: name, text: message };
|
||||||
|
console.log("sending broadcast message:", payload);
|
||||||
|
this.socket.emit("/chat", payload);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
@ -10,34 +10,27 @@ import {
|
|||||||
BButton,
|
BButton,
|
||||||
} from "bootstrap-vue";
|
} from "bootstrap-vue";
|
||||||
|
|
||||||
|
import URLs from './urls'
|
||||||
|
|
||||||
import "bootstrap/dist/css/bootstrap.css";
|
import "bootstrap/dist/css/bootstrap.css";
|
||||||
import "bootstrap-vue/dist/bootstrap-vue.css";
|
import "bootstrap-vue/dist/bootstrap-vue.css";
|
||||||
|
|
||||||
let url = new URL(window.location);
|
// let flamencoManager = require('flamenco-manager');
|
||||||
url.port = "8080";
|
// let apiClient = new flamencoManager.ApiClient(URLs.api);
|
||||||
const flamencoAPIURL = url.href;
|
|
||||||
url.protocol = "ws:";
|
|
||||||
const websocketURL = url.href;
|
|
||||||
console.log("Flamenco API:", flamencoAPIURL);
|
|
||||||
console.log("Websocket :", websocketURL);
|
|
||||||
|
|
||||||
let flamencoManager = require('flamenco-manager');
|
// let query = new flamencoManager.JobsQuery();
|
||||||
let apiClient = new flamencoManager.ApiClient(flamencoAPIURL);
|
// // query.status_in = ["active"];
|
||||||
|
// query.metadata = {project: "Heist"};
|
||||||
|
|
||||||
let query = new flamencoManager.JobsQuery();
|
// let JobsApi = new flamencoManager.JobsApi(apiClient);
|
||||||
// query.status_in = ["active"];
|
// JobsApi.queryJobs(query).then(function(data) {
|
||||||
query.metadata = {project: "Heist"};
|
// console.log('API called successfully.');
|
||||||
|
// console.log(data);
|
||||||
let JobsApi = new flamencoManager.JobsApi(apiClient);
|
// }, function(error) {
|
||||||
JobsApi.queryJobs(query).then(function(data) {
|
// console.error(error);
|
||||||
console.log('API called successfully.');
|
// });
|
||||||
console.log(data);
|
|
||||||
}, function(error) {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
Vue.config.serverUrl = websocketURL;
|
|
||||||
|
|
||||||
Vue.use(FormInputPlugin);
|
Vue.use(FormInputPlugin);
|
||||||
Vue.use(NavbarPlugin);
|
Vue.use(NavbarPlugin);
|
||||||
@ -47,8 +40,7 @@ Vue.component("b-input-group", BInputGroup);
|
|||||||
Vue.component("b-button", BButton);
|
Vue.component("b-button", BButton);
|
||||||
Vue.use(IconsPlugin);
|
Vue.use(IconsPlugin);
|
||||||
|
|
||||||
var vueApp = new Vue({
|
var vueApp = new Vue(App);
|
||||||
render: h => h(App),
|
vueApp.websocketURL = URLs.ws;
|
||||||
});
|
|
||||||
|
|
||||||
vueApp.$mount("#app");
|
vueApp.$mount("#app");
|
||||||
|
16
web/app/src/urls.js
Normal file
16
web/app/src/urls.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
let url = new URL(window.location);
|
||||||
|
url.port = "8080";
|
||||||
|
const flamencoAPIURL = url.href;
|
||||||
|
|
||||||
|
url.protocol = "ws:";
|
||||||
|
const websocketURL = url.href;
|
||||||
|
|
||||||
|
const URLs = {
|
||||||
|
api: flamencoAPIURL,
|
||||||
|
ws: websocketURL,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log("Flamenco API:", URLs.api);
|
||||||
|
console.log("Websocket :", URLs.ws);
|
||||||
|
|
||||||
|
export default URLs;
|
@ -152,6 +152,7 @@ Class | Method | HTTP request | Description
|
|||||||
- [flamencoManager.Job](docs/Job.md)
|
- [flamencoManager.Job](docs/Job.md)
|
||||||
- [flamencoManager.JobAllOf](docs/JobAllOf.md)
|
- [flamencoManager.JobAllOf](docs/JobAllOf.md)
|
||||||
- [flamencoManager.JobStatus](docs/JobStatus.md)
|
- [flamencoManager.JobStatus](docs/JobStatus.md)
|
||||||
|
- [flamencoManager.JobUpdate](docs/JobUpdate.md)
|
||||||
- [flamencoManager.JobsQuery](docs/JobsQuery.md)
|
- [flamencoManager.JobsQuery](docs/JobsQuery.md)
|
||||||
- [flamencoManager.JobsQueryResult](docs/JobsQueryResult.md)
|
- [flamencoManager.JobsQueryResult](docs/JobsQueryResult.md)
|
||||||
- [flamencoManager.ManagerConfiguration](docs/ManagerConfiguration.md)
|
- [flamencoManager.ManagerConfiguration](docs/ManagerConfiguration.md)
|
||||||
|
12
web/manager-api/docs/JobUpdate.md
Normal file
12
web/manager-api/docs/JobUpdate.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# flamencoManager.JobUpdate
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**id** | **String** | UUID of the Job |
|
||||||
|
**updated** | **Date** | Timestamp of last update |
|
||||||
|
**status** | [**JobStatus**](JobStatus.md) | |
|
||||||
|
**previous_status** | [**JobStatus**](JobStatus.md) | | [optional]
|
||||||
|
|
||||||
|
|
@ -55,7 +55,7 @@ class ApiClient {
|
|||||||
* @default {}
|
* @default {}
|
||||||
*/
|
*/
|
||||||
this.defaultHeaders = {
|
this.defaultHeaders = {
|
||||||
'User-Agent': 'Flamenco/c00cf8b0-dirty / webbrowser'
|
'User-Agent': 'Flamenco/c875745b-dirty / webbrowser'
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,6 +25,7 @@ import FlamencoVersion from './model/FlamencoVersion';
|
|||||||
import Job from './model/Job';
|
import Job from './model/Job';
|
||||||
import JobAllOf from './model/JobAllOf';
|
import JobAllOf from './model/JobAllOf';
|
||||||
import JobStatus from './model/JobStatus';
|
import JobStatus from './model/JobStatus';
|
||||||
|
import JobUpdate from './model/JobUpdate';
|
||||||
import JobsQuery from './model/JobsQuery';
|
import JobsQuery from './model/JobsQuery';
|
||||||
import JobsQueryResult from './model/JobsQueryResult';
|
import JobsQueryResult from './model/JobsQueryResult';
|
||||||
import ManagerConfiguration from './model/ManagerConfiguration';
|
import ManagerConfiguration from './model/ManagerConfiguration';
|
||||||
@ -162,6 +163,12 @@ export {
|
|||||||
*/
|
*/
|
||||||
JobStatus,
|
JobStatus,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The JobUpdate model constructor.
|
||||||
|
* @property {module:model/JobUpdate}
|
||||||
|
*/
|
||||||
|
JobUpdate,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The JobsQuery model constructor.
|
* The JobsQuery model constructor.
|
||||||
* @property {module:model/JobsQuery}
|
* @property {module:model/JobsQuery}
|
||||||
|
104
web/manager-api/src/model/JobUpdate.js
Normal file
104
web/manager-api/src/model/JobUpdate.js
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* Flamenco manager
|
||||||
|
* Render Farm manager API
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0.0
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
* https://openapi-generator.tech
|
||||||
|
* Do not edit the class manually.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ApiClient from '../ApiClient';
|
||||||
|
import JobStatus from './JobStatus';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The JobUpdate model module.
|
||||||
|
* @module model/JobUpdate
|
||||||
|
* @version 0.0.0
|
||||||
|
*/
|
||||||
|
class JobUpdate {
|
||||||
|
/**
|
||||||
|
* Constructs a new <code>JobUpdate</code>.
|
||||||
|
* @alias module:model/JobUpdate
|
||||||
|
* @param id {String} UUID of the Job
|
||||||
|
* @param updated {Date} Timestamp of last update
|
||||||
|
* @param status {module:model/JobStatus}
|
||||||
|
*/
|
||||||
|
constructor(id, updated, status) {
|
||||||
|
|
||||||
|
JobUpdate.initialize(this, id, updated, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the fields of this object.
|
||||||
|
* This method is used by the constructors of any subclasses, in order to implement multiple inheritance (mix-ins).
|
||||||
|
* Only for internal use.
|
||||||
|
*/
|
||||||
|
static initialize(obj, id, updated, status) {
|
||||||
|
obj['id'] = id;
|
||||||
|
obj['updated'] = updated;
|
||||||
|
obj['status'] = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a <code>JobUpdate</code> from a plain JavaScript object, optionally creating a new instance.
|
||||||
|
* Copies all relevant properties from <code>data</code> to <code>obj</code> if supplied or a new instance if not.
|
||||||
|
* @param {Object} data The plain JavaScript object bearing properties of interest.
|
||||||
|
* @param {module:model/JobUpdate} obj Optional instance to populate.
|
||||||
|
* @return {module:model/JobUpdate} The populated <code>JobUpdate</code> instance.
|
||||||
|
*/
|
||||||
|
static constructFromObject(data, obj) {
|
||||||
|
if (data) {
|
||||||
|
obj = obj || new JobUpdate();
|
||||||
|
|
||||||
|
if (data.hasOwnProperty('id')) {
|
||||||
|
obj['id'] = ApiClient.convertToType(data['id'], 'String');
|
||||||
|
}
|
||||||
|
if (data.hasOwnProperty('updated')) {
|
||||||
|
obj['updated'] = ApiClient.convertToType(data['updated'], 'Date');
|
||||||
|
}
|
||||||
|
if (data.hasOwnProperty('status')) {
|
||||||
|
obj['status'] = JobStatus.constructFromObject(data['status']);
|
||||||
|
}
|
||||||
|
if (data.hasOwnProperty('previous_status')) {
|
||||||
|
obj['previous_status'] = JobStatus.constructFromObject(data['previous_status']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UUID of the Job
|
||||||
|
* @member {String} id
|
||||||
|
*/
|
||||||
|
JobUpdate.prototype['id'] = undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timestamp of last update
|
||||||
|
* @member {Date} updated
|
||||||
|
*/
|
||||||
|
JobUpdate.prototype['updated'] = undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @member {module:model/JobStatus} status
|
||||||
|
*/
|
||||||
|
JobUpdate.prototype['status'] = undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @member {module:model/JobStatus} previous_status
|
||||||
|
*/
|
||||||
|
JobUpdate.prototype['previous_status'] = undefined;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default JobUpdate;
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user