)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"d7703e1ff629a226b8bde7674d87538c1d6f09ef","unresolved":false,"context_lines":[{"line_number":18,"context_line":"This patch moves the retrying wrapper to the upper layer,"},{"line_number":19,"context_line":"_set_aggregate(), to restart a new transaction when the"},{"line_number":20,"context_line":"DBDuplicateEntry error happens so that it can find the new entry"},{"line_number":21,"context_line":"another transaction has added."},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"Change-Id: I85ebc98502e9ca694ff07746e8e23c26e386df3c"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"9fdfeff1_c33be836","line":21,"updated":"2019-03-05 10:34:02.000000000","message":"Link the bug, perhaps?\n\nhttps://bugs.launchpad.net/nova/+bug/1818498","commit_id":"d0bf7c34cc409eb17afada8ebadefcf98cae9bfd"}],"placement/objects/resource_provider.py":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"d7703e1ff629a226b8bde7674d87538c1d6f09ef","unresolved":false,"context_lines":[{"line_number":583,"context_line":""},{"line_number":584,"context_line":""},{"line_number":585,"context_line":"# _ensure_aggregate() can raise DBDuplicateEntry. Then we must start a new"},{"line_number":586,"context_line":"# transaction because the new aggregate entry can be found by no means in"},{"line_number":587,"context_line":"# the old transaction if the isolation level is set to \"REPEATABLE_READ\""},{"line_number":588,"context_line":"@oslo_db_api.wrap_db_retry("},{"line_number":589,"context_line":"    max_retries\u003d10, inc_retry_interval\u003dFalse,"}],"source_content_type":"text/x-python","patch_set":1,"id":"9fdfeff1_2310b4a8","line":586,"range":{"start_line":586,"start_character":46,"end_line":586,"end_character":70},"updated":"2019-03-05 10:34:02.000000000","message":"I think you may want \"cannot be found\"","commit_id":"d0bf7c34cc409eb17afada8ebadefcf98cae9bfd"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"f582fb7e1fbb03de599761c19242d24ed9707270","unresolved":false,"context_lines":[{"line_number":574,"context_line":"                  agg_uuid, agg_id)"},{"line_number":575,"context_line":"        return agg_id"},{"line_number":576,"context_line":"    except db_exc.DBDuplicateEntry:"},{"line_number":577,"context_line":"        # Something else added this agg_uuid in between our initial"},{"line_number":578,"context_line":"        # fetch above and when we tried flushing this session."},{"line_number":579,"context_line":"        LOG.debug(\"_ensure_provider() failed to create new aggregate %s. \""},{"line_number":580,"context_line":"                  \"Another thread already created an aggregate record. \","},{"line_number":581,"context_line":"                  agg_uuid)"},{"line_number":582,"context_line":"        raise"},{"line_number":583,"context_line":""},{"line_number":584,"context_line":""},{"line_number":585,"context_line":"# _ensure_aggregate() can raise DBDuplicateEntry. Then we must start a new"}],"source_content_type":"text/x-python","patch_set":2,"id":"9fdfeff1_e60ab577","line":582,"range":{"start_line":577,"start_character":0,"end_line":582,"end_character":13},"updated":"2019-03-05 15:20:18.000000000","message":"This should use oslo_utils.excutils.save_and_reraise_exception","commit_id":"a6f0285778d565595603a08176a7ae2213f2a378"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"c997ad91aa3fd2b0cd7478971484d356a8653b9e","unresolved":false,"context_lines":[{"line_number":584,"context_line":""},{"line_number":585,"context_line":"# _ensure_aggregate() can raise DBDuplicateEntry. Then we must start a new"},{"line_number":586,"context_line":"# transaction because the new aggregate entry can\u0027t be found in the old"},{"line_number":587,"context_line":"# transaction if the isolation level is set to \"REPEATABLE_READ\""},{"line_number":588,"context_line":"@oslo_db_api.wrap_db_retry("},{"line_number":589,"context_line":"    max_retries\u003d10, inc_retry_interval\u003dFalse,"},{"line_number":590,"context_line":"    exception_checker\u003dlambda exc: isinstance(exc, db_exc.DBDuplicateEntry))"}],"source_content_type":"text/x-python","patch_set":2,"id":"9fdfeff1_c9d462be","line":587,"updated":"2019-03-05 15:50:10.000000000","message":"erm, kinda.\n\nA better way of describing why moving the wrap_db_entry() to here is a correct solution is that the db_api.placement_context_manager.writer decorator manages the lifecycle of the DB transaction in use for all functions contained in the decorated function.\n\nAny time any exception is raised through to the placement_context_manager.writer decorator, a ROLLBACK is issued and the current transaction context is torn down. Because we had the wrap_db_retry decorator on the inner function, that ROLLBACK and teardown of the DB transaction was not occurring and therefore the read on line 562 kept returning the same information (no agg record with UUID) but attempting to insert a record on line 572 resulted in the duplicate key error being returned. The wrap_db_error swallowed that exception and re-ran the _ensure_aggregate() function using the original transaction context that had not been ROLLBACK\u0027d torn down because the wrap_db_error decorator was \"underneath\" the placement_context_manager.writer decorator.","commit_id":"a6f0285778d565595603a08176a7ae2213f2a378"}]}
