Codebase list python-taskflow / 3e1f150
Use custom JSONType columns the JSONType from sqlalchemy_utils is quite brittle as it only does primitive json.dumps on values. This leads to various sorts of StorageFailure exceptions in taskflow when, for example, an unserializable exception bubbles up to the 'failure' field of AtomDetails. This patch sublclasses the JSONType from sqlalchemy_utils and overrides two of its methods that do (de)serialization to work via oslo.serialization functions. They deal with such occurencies much better, for example, by providing 'str' as a fallback default. Change-Id: I3b9e9498b155199a4e707006a0cf22cda0567c06 Related-Bug: #1935957 Pavlo Shchelokovskyy authored 2 years ago Pavlo Shchelokovskyy committed 2 years ago
1 changed file(s) with 27 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
1515
1616 import collections
1717
18 from oslo_serialization import jsonutils
1819 from oslo_utils import timeutils
1920 from oslo_utils import uuidutils
2021 from sqlalchemy import Table, Column, String, ForeignKey, DateTime, Enum
21 import sqlalchemy_utils as su
22 from sqlalchemy_utils.types import json as json_type
2223
2324 from taskflow.persistence import models
2425 from taskflow import states
3334 VERSION_LENGTH = 64
3435
3536
37 class JSONType(json_type.JSONType):
38 """Customized JSONType using oslo.serialization for json operations"""
39
40 def process_bind_param(self, value, dialect):
41 if dialect.name == 'postgresql' and json_type.has_postgres_json:
42 return value
43 if value is not None:
44 value = jsonutils.dumps(value)
45 return value
46
47 def process_result_value(self, value, dialect):
48 if dialect.name == 'postgresql':
49 return value
50 if value is not None:
51 value = jsonutils.loads(value)
52 return value
53
54
3655 def fetch(metadata):
3756 """Returns the master set of table objects (which is also there schema)."""
3857 logbooks = Table('logbooks', metadata,
4059 default=timeutils.utcnow),
4160 Column('updated_at', DateTime,
4261 onupdate=timeutils.utcnow),
43 Column('meta', su.JSONType),
62 Column('meta', JSONType),
4463 Column('name', String(length=NAME_LENGTH)),
4564 Column('uuid', String(length=UUID_LENGTH),
4665 primary_key=True, nullable=False, unique=True,
5372 Column('parent_uuid', String(length=UUID_LENGTH),
5473 ForeignKey('logbooks.uuid',
5574 ondelete='CASCADE')),
56 Column('meta', su.JSONType),
75 Column('meta', JSONType),
5776 Column('name', String(length=NAME_LENGTH)),
5877 Column('state', String(length=STATE_LENGTH)),
5978 Column('uuid', String(length=UUID_LENGTH),
6483 default=timeutils.utcnow),
6584 Column('updated_at', DateTime,
6685 onupdate=timeutils.utcnow),
67 Column('meta', su.JSONType),
86 Column('meta', JSONType),
6887 Column('parent_uuid', String(length=UUID_LENGTH),
6988 ForeignKey('flowdetails.uuid',
7089 ondelete='CASCADE')),
7493 Column('uuid', String(length=UUID_LENGTH),
7594 primary_key=True, nullable=False, unique=True,
7695 default=uuidutils.generate_uuid),
77 Column('failure', su.JSONType),
78 Column('results', su.JSONType),
79 Column('revert_results', su.JSONType),
80 Column('revert_failure', su.JSONType),
96 Column('failure', JSONType),
97 Column('results', JSONType),
98 Column('revert_results', JSONType),
99 Column('revert_failure', JSONType),
81100 Column('atom_type', Enum(*models.ATOM_TYPES,
82101 name='atom_types')),
83102 Column('intention', Enum(*states.INTENTIONS,