![Renat Akhmerov](/assets/img/avatar_default.png)
* 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
79 lines
2.4 KiB
Python
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())
|