From 2832d6e677413d08bd1645bb8bd8067b3ab665d6 Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Fri, 21 Nov 2014 13:07:47 -0800 Subject: [PATCH] Ensure that the zookeeper backend creates missing atoms When 'create_missing' is true the atom should be created instead of raising an exception; this is used when a flow detail is updated with a new detail and then saved. This also adds test cases that verify this happens so that we verify this on an ongoing basis. Fixes bug 1395812 Change-Id: I4851a08ff1ab4101dbec4a6656177908095c3c52 --- .../persistence/backends/impl_zookeeper.py | 6 ++- taskflow/tests/unit/persistence/base.py | 43 ++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/taskflow/persistence/backends/impl_zookeeper.py b/taskflow/persistence/backends/impl_zookeeper.py index 948c54dc..3cacffec 100644 --- a/taskflow/persistence/backends/impl_zookeeper.py +++ b/taskflow/persistence/backends/impl_zookeeper.py @@ -169,7 +169,11 @@ class ZkConnection(base.Connection): ad_data, _zstat = self._client.get(ad_path) except k_exc.NoNodeError: # Not-existent: create or raise exception. - raise exc.NotFound("No atom details found with id: %s" % ad.uuid) + if not create_missing: + raise exc.NotFound("No atom details found with" + " id: %s" % ad.uuid) + else: + txn.create(ad_path) else: # Existent: read it out. try: diff --git a/taskflow/tests/unit/persistence/base.py b/taskflow/tests/unit/persistence/base.py index 6d96df66..50bb3b3f 100644 --- a/taskflow/tests/unit/persistence/base.py +++ b/taskflow/tests/unit/persistence/base.py @@ -25,7 +25,48 @@ from taskflow.types import failure class PersistenceTestMixin(object): def _get_connection(self): - raise NotImplementedError() + raise NotImplementedError('_get_connection() implementation required') + + def test_task_detail_update_not_existing(self): + lb_id = uuidutils.generate_uuid() + lb_name = 'lb-%s' % (lb_id) + lb = logbook.LogBook(name=lb_name, uuid=lb_id) + fd = logbook.FlowDetail('test', uuid=uuidutils.generate_uuid()) + lb.add(fd) + td = logbook.TaskDetail("detail-1", uuid=uuidutils.generate_uuid()) + fd.add(td) + with contextlib.closing(self._get_connection()) as conn: + conn.save_logbook(lb) + + td2 = logbook.TaskDetail("detail-1", uuid=uuidutils.generate_uuid()) + fd.add(td2) + with contextlib.closing(self._get_connection()) as conn: + conn.update_flow_details(fd) + + with contextlib.closing(self._get_connection()) as conn: + lb2 = conn.get_logbook(lb.uuid) + fd2 = lb2.find(fd.uuid) + self.assertIsNotNone(fd2.find(td.uuid)) + self.assertIsNotNone(fd2.find(td2.uuid)) + + def test_flow_detail_update_not_existing(self): + lb_id = uuidutils.generate_uuid() + lb_name = 'lb-%s' % (lb_id) + lb = logbook.LogBook(name=lb_name, uuid=lb_id) + fd = logbook.FlowDetail('test', uuid=uuidutils.generate_uuid()) + lb.add(fd) + with contextlib.closing(self._get_connection()) as conn: + conn.save_logbook(lb) + + fd2 = logbook.FlowDetail('test-2', uuid=uuidutils.generate_uuid()) + lb.add(fd2) + with contextlib.closing(self._get_connection()) as conn: + conn.save_logbook(lb) + + with contextlib.closing(self._get_connection()) as conn: + lb2 = conn.get_logbook(lb.uuid) + self.assertIsNotNone(lb2.find(fd.uuid)) + self.assertIsNotNone(lb2.find(fd2.uuid)) def test_logbook_save_retrieve(self): lb_id = uuidutils.generate_uuid()