deb-mistral/mistral/workflow/utils.py
Renat Akhmerov 93ed2099d1 Refactor RPC serialization: add polymophic serializer
* The initial driver of this effort was that, as it turned out,
  it was impossible to have custom serialization for a custom
  type. For example, we had class Result and even had
  ResultSerializer but it wasn't used. So after taking a closer
  look it became clear that our serialization subsystem did not
  allow to register any alternative serializers by design.
  Because we had to use one serializer implementation registered
  in RPC. The solution is to make it more flexible by adding
  a special router-like serializer that knows to which specific
  serializer it needs to switch depending on an object type.
* Refactored serialization subsystem so that it's more flexible
  and manageble
* Added polymorphic entity serializer that can work as a router
  and switch between different serializers depending on their type
* Used Result and ResultSerializer in RPC instead of decomposing
  result object into primitive fields explicitly

Co-Authored-By: Dawid Deja <dawid.deja@intel.com>
Change-Id: I29d40a0b1b68a5410f3db2f7280c9c6244d55a84
2017-02-14 13:19:43 +07:00

79 lines
2.4 KiB
Python

# Copyright 2014 - Mirantis, Inc.
# Copyright 2015 - StackStorm, Inc.
# Copyright 2016 - Brocade Communications Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from mistral import serialization
from mistral import utils
class Result(serialization.MistralSerializable):
"""Explicit data structure containing a result of task execution."""
def __init__(self, data=None, error=None, cancel=False):
self.data = data
self.error = error
self.cancel = cancel
def __repr__(self):
return 'Result [data=%s, error=%s, cancel=%s]' % (
repr(self.data), repr(self.error), str(self.cancel)
)
def cut_repr(self):
return 'Result [data=%s, error=%s, cancel=%s]' % (
utils.cut(self.data), utils.cut(self.error), str(self.cancel)
)
def is_cancel(self):
return self.cancel
def is_error(self):
return self.error is not None and not self.is_cancel()
def is_success(self):
return not self.is_error() and not self.is_cancel()
def __eq__(self, other):
return (
self.data == other.data and
self.error == other.error and
self.cancel == other.cancel
)
def __ne__(self, other):
return not self.__eq__(other)
def to_dict(self):
return ({'result': self.data}
if self.is_success() else {'result': self.error})
class ResultSerializer(serialization.DictBasedSerializer):
def serialize_to_dict(self, entity):
return {
'data': entity.data,
'error': entity.error,
'cancel': entity.cancel
}
def deserialize_from_dict(self, entity_dict):
return Result(
entity_dict['data'],
entity_dict['error'],
entity_dict.get('cancel', False)
)
serialization.register_serializer(Result, ResultSerializer())