)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"0904fbb9ab92a349b05315f9415d9f59760dda73","unresolved":true,"context_lines":[{"line_number":24,"context_line":"the eventlet and threading backends."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"Also add an exclude list for functional tests that are currently causing"},{"line_number":27,"context_line":"hangs"},{"line_number":28,"context_line":"Co-Authored-By: Sean Mooney \u003csmooney@redhat.com\u003e"},{"line_number":29,"context_line":"Change-Id: Ia1463734c347f908b93d8659edbf5cadf05ab5d8"},{"line_number":30,"context_line":"Signed-off-by: Ashish Gupta \u003cashigupt@redhat.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"5adfded7_8e9cf19e","line":27,"updated":"2026-05-25 09:10:40.000000000","message":"nit:\n\n```suggestion\nhangs\n\n```","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"b18322a919a2e45712562a07d4a604aeac2acd97","unresolved":false,"context_lines":[{"line_number":24,"context_line":"the eventlet and threading backends."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"Also add an exclude list for functional tests that are currently causing"},{"line_number":27,"context_line":"hangs"},{"line_number":28,"context_line":"Co-Authored-By: Sean Mooney \u003csmooney@redhat.com\u003e"},{"line_number":29,"context_line":"Change-Id: Ia1463734c347f908b93d8659edbf5cadf05ab5d8"},{"line_number":30,"context_line":"Signed-off-by: Ashish Gupta \u003cashigupt@redhat.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"256aab7d_81fbe815","line":27,"in_reply_to":"5adfded7_8e9cf19e","updated":"2026-06-08 13:56:43.000000000","message":"Done","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"185388e937e3999315e65da73a70c4cc723b6348","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"e897b386_cde78400","updated":"2026-05-14 13:00:40.000000000","message":"Let\u0027s establish a set of tests that are passing with this change in place. It is interesting how much of the test suite runs stable with this.","commit_id":"1fc14b80ff42d2be42621cb21be59281ee838919"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"18652fa5e5a41337a68053e55bb49fef164ee251","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":1,"id":"efc6f9a1_55970a1d","in_reply_to":"6f89b39d_9b990956","updated":"2026-05-14 14:01:09.000000000","message":"@gibizer@gmail.com sure, I agree there are lots of failing tests with database is locked but the execution is never finishing because I am seeing below error in live migrations tests\n\n```\n\u0027oslo_db.exception.DBNonExistentDatabase: (sqlite3.OperationalError) unable to open database file\\n(Background on this error at: https://sqlalche.me/e/20/e3q8)\\n\u0027]: oslo_db.exception.DBNonExistentDatabase: (sqlite3.OperationalError) unable to open database file\n```\n\nI am still trying to figure out what\u0027s causing this but because of this the run keep getting stuck","commit_id":"1fc14b80ff42d2be42621cb21be59281ee838919"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"36aa59a4990bdaeb274a1675d8231cc12ac58138","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":1,"id":"6f89b39d_9b990956","in_reply_to":"e897b386_cde78400","updated":"2026-05-14 13:11:56.000000000","message":"I tried to run this locally and it seems there is plenty of hanging or close to hanging tests cases as the execution never finishes.\n\nMost of the failing test fails with `sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) database is locked.` I see it in UPDATE statements so either WAL does not get applied properly or two write transactions are happening in parallel and therefore the second gets rejected and we need the DB write serialization from https://review.opendev.org/c/openstack/nova/+/983069/1/nova/tests/fixtures/nova.py#659\n\nMaybe add one more patch top of this with that write serialization and then see what tests can be run in a stable way","commit_id":"1fc14b80ff42d2be42621cb21be59281ee838919"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"aca8a522e286f51653d55795576c8ad2dd767a2e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"35a5500c_ce98cc9a","in_reply_to":"efc6f9a1_55970a1d","updated":"2026-07-05 21:51:29.000000000","message":"Done","commit_id":"1fc14b80ff42d2be42621cb21be59281ee838919"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"af880a95ac3665737e523b528b58073f14b23da0","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":4,"id":"286ca6b8_f77823e7","updated":"2026-05-26 15:13:26.000000000","message":"I run it couple of times locally and I saw:\n\n* nova.tests.functional.test_nova_manage.TestDBArchiveDeletedRowsMultiCell.test_archive_deleted_rows\n```\nnova.exception.AllocationDeleteFailed: Failed to delete allocations for consumer f2b3882e-b72d-4ae2-8aa6-df701c6e426d. Error: {\"errors\": [{\"status\": 500, \"title\": \"Internal Server Error\", \"detail\": \"The server has either erred or is incapable of performing the requested operation.\\n\\n (sqlite3.OperationalError) cannot start a transaction within a transaction [SQL: BEGIN] (Background on this error at: https://sqlalche.me/e/20/e3q8)  \", \"request_id\": \"req-e7af2afd-1856-4b4b-85f4-809fc1770109\"}]}\n```\nThis is probably due to placement still uses in memory SQLite. So I suggest to try to apply the SQLite pattern to placement via PlacementFixture in nova/tests/functional/fixtures.py\n\n* nova.tests.functional.api_sample_tests.test_fixed_ips.FixedIpTest.test_fixed_ip_reserve [ multipart\n```\n2026-05-26 14:52:45,485 INFO [nova.db.migration] Applying migration(s)\n2026-05-26 14:52:45,523 INFO [nova.db.migration] Migration(s) applied\n2026-05-26 14:52:45,545 INFO [nova.db.migration] Applying migration(s)\n2026-05-26 14:52:45,704 INFO [nova.db.migration] Migration(s) applied\n0\nContent-Type: text/x-traceback;charset\u003dutf8,language\u003dpython\ntraceback\n365\nTraceback (most recent call last):\n  File \"/home/gibi/upstream/git/openstack/nova/nova/tests/functional/integrated_helpers.py\", line 1393, in setUp\n    super(_IntegratedTestBase, self).setUp()\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^\n  File \"/home/gibi/upstream/git/openstack/nova/nova/test.py\", line 261, in setUp\n    self._setup_cells()\n    ~~~~~~~~~~~~~~~~~^^\n  File \"/home/gibi/upstream/git/openstack/nova/nova/test.py\", line 365, in _setup_cells\n    celldbs.add_cell_database(objects.CellMapping.CELL0_UUID)\n    ~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/gibi/upstream/git/openstack/nova/nova/tests/fixtures/nova.py\", line 700, in add_cell_database\n    conn.connection.executescript(DB_SCHEMA[(\u0027main\u0027, None)])\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^\nsqlite3.OperationalError: table agent_builds already exists\n```\nThis seems to be some race with the DB schema application to the DB. It tries to apply the schema to a DB that already has one.\n\n* nova.tests.functional.test_servers_resource_request.ServerMoveWithPortResourceRequestTest.test_live_migrate_with_qos_port_reschedule_success\n```\n  File \"/home/gibi/upstream/git/openstack/nova/nova/tests/functional/test_servers_resource_request.py\", line 2325, in test_live_migrate_with_qos_port_reschedule_success\n    self._delete_server_and_check_allocations(\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^\n        server, qos_normal_port, qos_sriov_port)\n        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/gibi/upstream/git/openstack/nova/nova/tests/functional/test_servers_resource_request.py\", line 629, in _delete_server_and_check_allocations\n    self._delete_and_check_allocations(server)\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^\n  File \"/home/gibi/upstream/git/openstack/nova/nova/tests/functional/integrated_helpers.py\", line 1204, in _delete_and_check_allocations\n    self.assertRequestMatchesUsage(\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^\n        {\u0027VCPU\u0027: 0, \u0027MEMORY_MB\u0027: 0, \u0027DISK_GB\u0027: 0}, rp_uuid)\n        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/gibi/upstream/git/openstack/nova/nova/tests/functional/integrated_helpers.py\", line 978, in assertRequestMatchesUsage\n    self.assertEqual(\n    ~~~~~~~~~~~~~~~~^\n        value,\n        ^^^^^^\n        total_usage[rc],\n        ^^^^^^^^^^^^^^^^\n        \u0027The requested resource amount does not match with the total \u0027\n        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n        \u0027resource usage of the RP tree\u0027)\n        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/testtools/testcase.py\", line 513, in assertEqual\n    self.assertThat(observed, matcher, message)\n    ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/testtools/testcase.py\", line 704, in assertThat\n    raise mismatch_error\ntesttools.matchers._impl.MismatchError: 0 !\u003d 1: The requested resource amount does not match with the total resource usage of the RP tree\n```\nSeems like a test case failure, probably a racy test case that now has different timing due to threading or the file based DB.\n\n* nova.tests.functional.regressions.test_bug_1781710.AntiAffinityMultiCreateRequest.test_anti_affinity_multi_create\n```\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/placement/objects/allocation.py\", line 533, in get_all_by_consumer_id\n    resource_class\u003dcontext.rc_cache.string_from_id(\n                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^\n        rec[\u0027resource_class_id\u0027]),\n        ^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/placement/attribute_cache.py\", line 129, in string_from_id\n    self._refresh_from_db(self._ctx)\n    ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/oslo_db/sqlalchemy/enginefacade.py\", line 1159, in wrapper\n    return fn(*args, **kwargs)\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/placement/attribute_cache.py\", line 159, in _refresh_from_db\n    res \u003d ctx.session.execute(sel).fetchall()\n          ~~~~~~~~~~~~~~~~~~~^^^^^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/orm/session.py\", line 2351, in execute\n    return self._execute_internal(\n           ~~~~~~~~~~~~~~~~~~~~~~^\n        statement,\n        ^^^^^^^^^^\n    ...\u003c4 lines\u003e...\n        _add_event\u003d_add_event,\n        ^^^^^^^^^^^^^^^^^^^^^^\n    )\n    ^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/orm/session.py\", line 2239, in _execute_internal\n    conn \u003d self._connection_for_bind(bind)\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/orm/session.py\", line 2108, in _connection_for_bind\n    return trans._connection_for_bind(engine, execution_options)\n           ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"\u003cstring\u003e\", line 2, in _connection_for_bind\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py\", line 137, in _go\n    ret_value \u003d \n    fn(self, *arg, **kw)\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/orm/session.py\", line 1240, in _connection_for_bind\n    transaction \u003d conn.begin()\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/engine/base.py\", line 856, in begin\n    self._transaction \u003d RootTransaction(self)\n                        ~~~~~~~~~~~~~~~^^^^^^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/engine/base.py\", line 2692, in __init__\n    self._connection_begin_impl()\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/engine/base.py\", line 2710, in _connection_begin_impl\n    self.connection._begin_impl(self)\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/engine/base.py\", line 1099, in _begin_impl\n    self.dispatch.begin(self)\n    ~~~~~~~~~~~~~~~~~~~^^^^^^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/event/attr.py\", line 515, in __call__\n    fn(*args, **kw)\n    ~~^^^^^^^^^^^^^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/oslo_db/sqlalchemy/engines.py\", line 376, in _sqlite_emit_begin\n    conn.execute(sqlalchemy.text(\"BEGIN\"))\n    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/engine/base.py\", line 1419, in execute\n    return meth(\n        self,\n        distilled_parameters,\n        execution_options or NO_OPTIONS,\n    )\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/sql/elements.py\", line 527, in _execute_on_connection\n    return connection._execute_clauseelement(\n           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^\n        self, distilled_params, execution_options\n        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    )\n    ^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/engine/base.py\", line 1641, in _execute_clauseelement\n    ret \u003d self._execute_context(\n        dialect,\n    ...\u003c8 lines\u003e...\n        cache_hit\u003dcache_hit,\n    )\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/engine/base.py\", line 1846, in _execute_context\n    return self._exec_single_context(\n           ~~~~~~~~~~~~~~~~~~~~~~~~~^\n        dialect, context, statement, parameters\n        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    )\n    ^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/engine/base.py\", line 1986, in _exec_single_context\n    self._handle_dbapi_exception(\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^\n        e, str_statement, effective_parameters, cursor, context\n        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    )\n    ^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/engine/base.py\", line 2360, in _handle_dbapi_exception\n    raise newraise.with_traceback(exc_info[2]) from e\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/engine/base.py\", line 1967, in _exec_single_context\n    self.dialect.do_execute(\n    ~~~~~~~~~~~~~~~~~~~~~~~^\n        cursor, str_statement, effective_parameters, context\n        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    )\n    ^\n  File \"/home/gibi/upstream/git/openstack/nova/.tox/functional-py313-threading/lib/python3.13/site-packages/sqlalchemy/engine/default.py\", line 952, in do_execute\n    cursor.execute(statement, parameters)\n    ~~~~~~~~~~~~~~^^^^^^^^\n    ^^^^^^^^^^^^^^^\nsqlalchemy.exc.OperationalError: (sqlite3.OperationalError) cannot start a transaction within a transaction\n[SQL: BEGIN]\n```\nThis also due to placement using in memory SQLite\n\n*  nova.tests.functional.libvirt.test_vgpu.VGPUTests.test_multiple_instance_create\nAlso failed on placement transaction within transaction issues.\n\n---\n\nBottom line we need a patch to make at least PlacementFixture use placement with a file based DB as well because potentially all our functional tests can fail with a Placement transation issue if we are unlucky.","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"0904fbb9ab92a349b05315f9415d9f59760dda73","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"840fa036_a71dbdf3","updated":"2026-05-25 09:10:40.000000000","message":"My main question is whether this belongs here or in oslo.db","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"22b39b06c51c79c6d4e7b20e6cca528eda0c76d6","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"5fd690e6_f00936da","updated":"2026-05-26 06:05:50.000000000","message":"recheck, testing if failure is consistent","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"e79dd0d4a21c1b488b487980eaea3ea936a215c8","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":4,"id":"f480f089_60eefdf5","in_reply_to":"286ca6b8_f77823e7","updated":"2026-05-26 15:35:41.000000000","message":"The duplicate table issue should be fixed with the latest patchset but yeah I am also seeing (sqlite3.OperationalError) cannot start a transaction within a transaction issues due to placement. Let me create another patch as per your suggestion.","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"aca8a522e286f51653d55795576c8ad2dd767a2e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"180fd4b6_0ce7f530","in_reply_to":"f480f089_60eefdf5","updated":"2026-07-05 21:51:29.000000000","message":"Done","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"8f6ec558d4abd69ab3ce4cc063a93c60a1940535","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":18,"id":"c7b0086f_6fffaa78","updated":"2026-07-07 16:45:52.000000000","message":"I haven\u0027t finished the review yet but publishing what I have","commit_id":"fc444e23cb1adb3a43c3a751a000c9298e398c7c"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"f812ae90bdf02581878a31c45fae34ba7994efe2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":20,"id":"9a7d4395_d89df546","updated":"2026-07-09 10:49:43.000000000","message":"Looks good","commit_id":"baa54dbd7e4e20e67afa3c51ea1089f1b5b66460"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"6fcc56b88078c92cba631ebb819a9113ac4846a3","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":20,"id":"550c79b6_d4484528","updated":"2026-07-09 18:42:41.000000000","message":"lgtm","commit_id":"baa54dbd7e4e20e67afa3c51ea1089f1b5b66460"}],"nova/tests/fixtures/nova.py":[{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"185388e937e3999315e65da73a70c4cc723b6348","unresolved":true,"context_lines":[{"line_number":89,"context_line":"    empty; WAL is set on the file with :mod:`sqlite3` before SQLAlchemy opens"},{"line_number":90,"context_line":"    it."},{"line_number":91,"context_line":"    \"\"\""},{"line_number":92,"context_line":"    safe \u003d \u0027\u0027.join(c if c.isalnum() or c in \u0027-_\u0027 else \u0027-\u0027 for c in name)"},{"line_number":93,"context_line":"    fd, path \u003d tempfile.mkstemp("},{"line_number":94,"context_line":"        prefix\u003d\u0027nova-test-%s-\u0027 % safe,"},{"line_number":95,"context_line":"        suffix\u003d\u0027.sqlite\u0027,"}],"source_content_type":"text/x-python","patch_set":1,"id":"ff3131f5_302ae70e","line":92,"updated":"2026-05-14 13:00:40.000000000","message":"this is unnecessary complexity. We are calling this with \"main\" and \"api\" which are correct filenames.","commit_id":"1fc14b80ff42d2be42621cb21be59281ee838919"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"0904fbb9ab92a349b05315f9415d9f59760dda73","unresolved":false,"context_lines":[{"line_number":89,"context_line":"    empty; WAL is set on the file with :mod:`sqlite3` before SQLAlchemy opens"},{"line_number":90,"context_line":"    it."},{"line_number":91,"context_line":"    \"\"\""},{"line_number":92,"context_line":"    safe \u003d \u0027\u0027.join(c if c.isalnum() or c in \u0027-_\u0027 else \u0027-\u0027 for c in name)"},{"line_number":93,"context_line":"    fd, path \u003d tempfile.mkstemp("},{"line_number":94,"context_line":"        prefix\u003d\u0027nova-test-%s-\u0027 % safe,"},{"line_number":95,"context_line":"        suffix\u003d\u0027.sqlite\u0027,"}],"source_content_type":"text/x-python","patch_set":1,"id":"b336aee5_727741d6","line":92,"in_reply_to":"c086ed39_fefa0c8a","updated":"2026-05-25 09:10:40.000000000","message":"Done","commit_id":"1fc14b80ff42d2be42621cb21be59281ee838919"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"18652fa5e5a41337a68053e55bb49fef164ee251","unresolved":true,"context_lines":[{"line_number":89,"context_line":"    empty; WAL is set on the file with :mod:`sqlite3` before SQLAlchemy opens"},{"line_number":90,"context_line":"    it."},{"line_number":91,"context_line":"    \"\"\""},{"line_number":92,"context_line":"    safe \u003d \u0027\u0027.join(c if c.isalnum() or c in \u0027-_\u0027 else \u0027-\u0027 for c in name)"},{"line_number":93,"context_line":"    fd, path \u003d tempfile.mkstemp("},{"line_number":94,"context_line":"        prefix\u003d\u0027nova-test-%s-\u0027 % safe,"},{"line_number":95,"context_line":"        suffix\u003d\u0027.sqlite\u0027,"}],"source_content_type":"text/x-python","patch_set":1,"id":"c086ed39_fefa0c8a","line":92,"in_reply_to":"ff3131f5_302ae70e","updated":"2026-05-14 14:01:09.000000000","message":"sorry,This is not required and I meant to remove this but looks like it got added from my stash. I will remove it in next patch","commit_id":"1fc14b80ff42d2be42621cb21be59281ee838919"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"185388e937e3999315e65da73a70c4cc723b6348","unresolved":true,"context_lines":[{"line_number":101,"context_line":"    return \u0027sqlite:///%s\u0027 % abs_path, abs_path"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"def _unlink_sqlite_db_files(base_paths):"},{"line_number":105,"context_line":"    \"\"\"Remove each SQLite DB file and any -wal / -shm sidecars.\"\"\""},{"line_number":106,"context_line":"    for base in base_paths:"},{"line_number":107,"context_line":"        for suffix in (\u0027\u0027, \u0027-wal\u0027, \u0027-shm\u0027):"}],"source_content_type":"text/x-python","patch_set":1,"id":"618a343b_a691cd12","line":104,"updated":"2026-05-14 13:00:40.000000000","message":"If we store everything in a temp directory that is deleted at the end of the test case then we don\u0027t need to track and explicitly delete files from that temp directory.","commit_id":"1fc14b80ff42d2be42621cb21be59281ee838919"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"18652fa5e5a41337a68053e55bb49fef164ee251","unresolved":true,"context_lines":[{"line_number":101,"context_line":"    return \u0027sqlite:///%s\u0027 % abs_path, abs_path"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"def _unlink_sqlite_db_files(base_paths):"},{"line_number":105,"context_line":"    \"\"\"Remove each SQLite DB file and any -wal / -shm sidecars.\"\"\""},{"line_number":106,"context_line":"    for base in base_paths:"},{"line_number":107,"context_line":"        for suffix in (\u0027\u0027, \u0027-wal\u0027, \u0027-shm\u0027):"}],"source_content_type":"text/x-python","patch_set":1,"id":"a511cc60_f1408dfd","line":104,"in_reply_to":"618a343b_a691cd12","updated":"2026-05-14 14:01:09.000000000","message":"Acknowledged","commit_id":"1fc14b80ff42d2be42621cb21be59281ee838919"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"0904fbb9ab92a349b05315f9415d9f59760dda73","unresolved":false,"context_lines":[{"line_number":101,"context_line":"    return \u0027sqlite:///%s\u0027 % abs_path, abs_path"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"def _unlink_sqlite_db_files(base_paths):"},{"line_number":105,"context_line":"    \"\"\"Remove each SQLite DB file and any -wal / -shm sidecars.\"\"\""},{"line_number":106,"context_line":"    for base in base_paths:"},{"line_number":107,"context_line":"        for suffix in (\u0027\u0027, \u0027-wal\u0027, \u0027-shm\u0027):"}],"source_content_type":"text/x-python","patch_set":1,"id":"cca57061_9a3954bd","line":104,"in_reply_to":"a511cc60_f1408dfd","updated":"2026-05-25 09:10:40.000000000","message":"Done","commit_id":"1fc14b80ff42d2be42621cb21be59281ee838919"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"0904fbb9ab92a349b05315f9415d9f59760dda73","unresolved":true,"context_lines":[{"line_number":83,"context_line":""},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"def _use_file_backed_sqlite_with_wal(name):"},{"line_number":86,"context_line":"    \"\"\"Create a temp SQLite file with WAL; return (sqlalchemy_url, abs_path)."},{"line_number":87,"context_line":""},{"line_number":88,"context_line":"    Expects fixtures.NestedTempfile() so tempfile paths"},{"line_number":89,"context_line":"    live under a directory that is removed on test end. The file is created"}],"source_content_type":"text/x-python","patch_set":4,"id":"357c6cd2_9277b43b","line":86,"updated":"2026-05-25 09:10:40.000000000","message":"nit: you should probably expand WAL (write ahead logging?) at least once in this file","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"0a22789f0cc7670a46cda5a329c71975f6bc43f7","unresolved":false,"context_lines":[{"line_number":83,"context_line":""},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"def _use_file_backed_sqlite_with_wal(name):"},{"line_number":86,"context_line":"    \"\"\"Create a temp SQLite file with WAL; return (sqlalchemy_url, abs_path)."},{"line_number":87,"context_line":""},{"line_number":88,"context_line":"    Expects fixtures.NestedTempfile() so tempfile paths"},{"line_number":89,"context_line":"    live under a directory that is removed on test end. The file is created"}],"source_content_type":"text/x-python","patch_set":4,"id":"ed408767_cb1b67db","line":86,"in_reply_to":"357c6cd2_9277b43b","updated":"2026-05-26 15:29:55.000000000","message":"Done","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"0904fbb9ab92a349b05315f9415d9f59760dda73","unresolved":true,"context_lines":[{"line_number":430,"context_line":"_DB_WRITE_LOCK \u003d threading.RLock()"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":""},{"line_number":433,"context_line":"class DatabaseWriteLock(fixtures.Fixture):"},{"line_number":434,"context_line":"    \"\"\"Serialize writer transactions across threads in tests."},{"line_number":435,"context_line":""},{"line_number":436,"context_line":"    SQLite allows only a single writer at a time. Patches"}],"source_content_type":"text/x-python","patch_set":4,"id":"966679a2_58f87505","line":433,"updated":"2026-05-25 09:10:40.000000000","message":"Do these fixtures/helpers methods belong in oslo.db? I imagine every service is going to struggle with the same issue here?","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"af880a95ac3665737e523b528b58073f14b23da0","unresolved":true,"context_lines":[{"line_number":430,"context_line":"_DB_WRITE_LOCK \u003d threading.RLock()"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":""},{"line_number":433,"context_line":"class DatabaseWriteLock(fixtures.Fixture):"},{"line_number":434,"context_line":"    \"\"\"Serialize writer transactions across threads in tests."},{"line_number":435,"context_line":""},{"line_number":436,"context_line":"    SQLite allows only a single writer at a time. Patches"}],"source_content_type":"text/x-python","patch_set":4,"id":"870a27b0_3ee10a21","line":433,"in_reply_to":"966679a2_58f87505","updated":"2026-05-26 15:13:26.000000000","message":"I agree to put this into oslo.db. But I suggest to progress in parallel. So keeping a copy here while proposing it to oslo.db and removing the copy once oslo.db is released with the lock fixture. @ashigupt@redhat.com how does it sound?","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"0a22789f0cc7670a46cda5a329c71975f6bc43f7","unresolved":false,"context_lines":[{"line_number":430,"context_line":"_DB_WRITE_LOCK \u003d threading.RLock()"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":""},{"line_number":433,"context_line":"class DatabaseWriteLock(fixtures.Fixture):"},{"line_number":434,"context_line":"    \"\"\"Serialize writer transactions across threads in tests."},{"line_number":435,"context_line":""},{"line_number":436,"context_line":"    SQLite allows only a single writer at a time. Patches"}],"source_content_type":"text/x-python","patch_set":4,"id":"6132bd4e_9aa4a9b8","line":433,"in_reply_to":"966679a2_58f87505","updated":"2026-05-26 15:29:55.000000000","message":"That\u0027s a good point and I discussed it with @gibizer@gmail.com, We are currently working on stabilizing Nova test suite and as per your suggestion would work on to to move it to oslo.db","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"0904fbb9ab92a349b05315f9415d9f59760dda73","unresolved":true,"context_lines":[{"line_number":703,"context_line":"        super(CellDatabases, self).setUp()"},{"line_number":704,"context_line":"        if utils.concurrency_mode_threading():"},{"line_number":705,"context_line":"            self.useFixture(DatabaseWriteLock())"},{"line_number":706,"context_line":"        self.useFixture(fixtures.NestedTempfile())"},{"line_number":707,"context_line":"        self.addCleanup(self.cleanup)"},{"line_number":708,"context_line":"        self._real_target_cell \u003d context.target_cell"},{"line_number":709,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"24215950_1e7ec412","line":706,"updated":"2026-05-25 09:10:40.000000000","message":"We\u0027re already using `fixtures.TempDir` in a lot of places. I assume there\u0027s no interplay/conflicts between the two?","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"f71cc4b701babf3757dfd3ef22d1ab63e0f84425","unresolved":false,"context_lines":[{"line_number":703,"context_line":"        super(CellDatabases, self).setUp()"},{"line_number":704,"context_line":"        if utils.concurrency_mode_threading():"},{"line_number":705,"context_line":"            self.useFixture(DatabaseWriteLock())"},{"line_number":706,"context_line":"        self.useFixture(fixtures.NestedTempfile())"},{"line_number":707,"context_line":"        self.addCleanup(self.cleanup)"},{"line_number":708,"context_line":"        self._real_target_cell \u003d context.target_cell"},{"line_number":709,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"a5a0edbd_e73c76ae","line":706,"in_reply_to":"24215950_1e7ec412","updated":"2026-07-09 10:27:48.000000000","message":"There’s no conflict between them.\n\nNestedTempfile is basically a TempDir plus a patch to tempfile.tempdir so when _use_file_backed_sqlite_with_wal() calls mkstemp(), those sqlite files end up under one per-test directory that we tear down at the end.\n\nThe existing TempDir() fixtures are unchanged, tests still use .path when they need a directory. If both are active in the same test, another TempDir might end up under that nested tree but that should be fine as each fixture cleans up after itself on teardown.","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"dc31c9a7eaf7852079b496a36fa9ad434d6620da","unresolved":true,"context_lines":[{"line_number":452,"context_line":"            enginefacade._TransactionContextManager._transaction_scope)"},{"line_number":453,"context_line":""},{"line_number":454,"context_line":"        @contextmanager"},{"line_number":455,"context_line":"        def _locked_scope(tcm_self, context):"},{"line_number":456,"context_line":"            if tcm_self._mode is enginefacade._WRITER:"},{"line_number":457,"context_line":"                with _DB_WRITE_LOCK:"},{"line_number":458,"context_line":"                    with original(tcm_self, context) as resource:"},{"line_number":459,"context_line":"                        yield resource"},{"line_number":460,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":7,"id":"0035ac27_f4b3e6a2","line":457,"range":{"start_line":455,"start_character":0,"end_line":457,"end_character":36},"updated":"2026-05-28 11:17:00.000000000","message":"As far as I can see this serialize write transaction across all the different DBs we have in play. This is a bit excessive and probably a cause of some of the slowdown. We need to serialize write transaction within the same DB but we can allow two write transactions targeting two different DBs. I.e. two writes one for cell_0 and one for cell_1 can progress in parallel.\n\nLet\u0027s experiment with this in a follow up patch. Try to have a separate lock per DB and see if that helps speed things up.\n\nBTW, when you move this to olso.db you need to create a generic enough solution there so that nova can use it in this multi DB setup.","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"6b13a4d3774913aeec61f03670209c748225329c","unresolved":true,"context_lines":[{"line_number":452,"context_line":"            enginefacade._TransactionContextManager._transaction_scope)"},{"line_number":453,"context_line":""},{"line_number":454,"context_line":"        @contextmanager"},{"line_number":455,"context_line":"        def _locked_scope(tcm_self, context):"},{"line_number":456,"context_line":"            if tcm_self._mode is enginefacade._WRITER:"},{"line_number":457,"context_line":"                with _DB_WRITE_LOCK:"},{"line_number":458,"context_line":"                    with original(tcm_self, context) as resource:"},{"line_number":459,"context_line":"                        yield resource"},{"line_number":460,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":7,"id":"e9d89c89_cfee740a","line":457,"range":{"start_line":455,"start_character":0,"end_line":457,"end_character":36},"in_reply_to":"0035ac27_f4b3e6a2","updated":"2026-07-06 07:39:36.000000000","message":"I have implemented per DB lock in https://review.opendev.org/c/openstack/nova/+/992862/ as part of this series","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"f812ae90bdf02581878a31c45fae34ba7994efe2","unresolved":false,"context_lines":[{"line_number":452,"context_line":"            enginefacade._TransactionContextManager._transaction_scope)"},{"line_number":453,"context_line":""},{"line_number":454,"context_line":"        @contextmanager"},{"line_number":455,"context_line":"        def _locked_scope(tcm_self, context):"},{"line_number":456,"context_line":"            if tcm_self._mode is enginefacade._WRITER:"},{"line_number":457,"context_line":"                with _DB_WRITE_LOCK:"},{"line_number":458,"context_line":"                    with original(tcm_self, context) as resource:"},{"line_number":459,"context_line":"                        yield resource"},{"line_number":460,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":7,"id":"f3e2d28e_43e1f604","line":457,"range":{"start_line":455,"start_character":0,"end_line":457,"end_character":36},"in_reply_to":"e9d89c89_cfee740a","updated":"2026-07-09 10:49:43.000000000","message":"Done","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"dc31c9a7eaf7852079b496a36fa9ad434d6620da","unresolved":true,"context_lines":[{"line_number":696,"context_line":"        # schema). Replaying the same SQL via executescript would try to"},{"line_number":697,"context_line":"        # CREATE tables that already exist. Only clone from the cache when it"},{"line_number":698,"context_line":"        # was populated before this call (i.e. subsequent cells in this process)."},{"line_number":699,"context_line":"        main_schema_cached_before \u003d bool(DB_SCHEMA[(\u0027main\u0027, None)])"},{"line_number":700,"context_line":"        # NOTE(danms): This is a temporary MonkeyPatch just to get"},{"line_number":701,"context_line":"        # a new database created with the schema we need and the"},{"line_number":702,"context_line":"        # context manager for it stashed."}],"source_content_type":"text/x-python","patch_set":7,"id":"36ce2c7c_a2aac9c4","line":699,"updated":"2026-05-28 11:17:00.000000000","message":"this is already checked in _cache_schema can we have a single place to check for this?","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"6a0ae9d4edb4a53c039edced8039b80d254a7696","unresolved":false,"context_lines":[{"line_number":696,"context_line":"        # schema). Replaying the same SQL via executescript would try to"},{"line_number":697,"context_line":"        # CREATE tables that already exist. Only clone from the cache when it"},{"line_number":698,"context_line":"        # was populated before this call (i.e. subsequent cells in this process)."},{"line_number":699,"context_line":"        main_schema_cached_before \u003d bool(DB_SCHEMA[(\u0027main\u0027, None)])"},{"line_number":700,"context_line":"        # NOTE(danms): This is a temporary MonkeyPatch just to get"},{"line_number":701,"context_line":"        # a new database created with the schema we need and the"},{"line_number":702,"context_line":"        # context manager for it stashed."}],"source_content_type":"text/x-python","patch_set":7,"id":"91d7cb0f_fdb157d1","line":699,"in_reply_to":"36ce2c7c_a2aac9c4","updated":"2026-06-08 13:57:37.000000000","message":"Done","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"dc31c9a7eaf7852079b496a36fa9ad434d6620da","unresolved":true,"context_lines":[{"line_number":745,"context_line":"            engine.dispose()"},{"line_number":746,"context_line":""},{"line_number":747,"context_line":""},{"line_number":748,"context_line":"class Database(fixtures.Fixture):"},{"line_number":749,"context_line":""},{"line_number":750,"context_line":"    # TODO(stephenfin): The \u0027version\u0027 argument is unused and can be removed"},{"line_number":751,"context_line":"    def __init__(self, database\u003d\u0027main\u0027, version\u003dNone, connection\u003dNone):"}],"source_content_type":"text/x-python","patch_set":7,"id":"72f9e500_fe64a235","line":748,"updated":"2026-05-28 11:17:00.000000000","message":"I would love to get rid of the two separate DB fixtures eventually. But it is for a follow up for sure.","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"383f2c6b5ec758a6b4c82a11c0ce1b05fe4fc4ce","unresolved":false,"context_lines":[{"line_number":745,"context_line":"            engine.dispose()"},{"line_number":746,"context_line":""},{"line_number":747,"context_line":""},{"line_number":748,"context_line":"class Database(fixtures.Fixture):"},{"line_number":749,"context_line":""},{"line_number":750,"context_line":"    # TODO(stephenfin): The \u0027version\u0027 argument is unused and can be removed"},{"line_number":751,"context_line":"    def __init__(self, database\u003d\u0027main\u0027, version\u003dNone, connection\u003dNone):"}],"source_content_type":"text/x-python","patch_set":7,"id":"9293876a_b6d5080a","line":748,"in_reply_to":"72f9e500_fe64a235","updated":"2026-07-08 23:34:45.000000000","message":"Acknowledged","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"dc31c9a7eaf7852079b496a36fa9ad434d6620da","unresolved":true,"context_lines":[{"line_number":783,"context_line":"                ctxt_mgr \u003d main_db_api.create_context_manager("},{"line_number":784,"context_line":"                    connection\u003dself.connection)"},{"line_number":785,"context_line":"                self.get_engine \u003d ctxt_mgr.writer.get_engine"},{"line_number":786,"context_line":"            elif utils.concurrency_mode_threading():"},{"line_number":787,"context_line":"                _bind_database_fixture_to_file_wal_sqlite("},{"line_number":788,"context_line":"                    self, \u0027main\u0027, main_db_api)"},{"line_number":789,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":7,"id":"3d8ddde8_c0353265","line":786,"updated":"2026-05-28 11:17:00.000000000","message":"This branching feels wrong. \n* Could you check if we ever use this fixture by passing the connection? If so then in such case we need to check how that connection is created if that created to an in memory SQLite then we will have a problem.\n* if connection is not passed and we are in threading mode we still need to run at lest `main_db_api.configure(CONF)` as _bind_database_fixture_to_file_wal_sqlite only sets the url but not the rest of the DB parameters so if any test needs (or will need in the future) to change other configuration values then that will not be applied in threading mode.","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"b18322a919a2e45712562a07d4a604aeac2acd97","unresolved":true,"context_lines":[{"line_number":783,"context_line":"                ctxt_mgr \u003d main_db_api.create_context_manager("},{"line_number":784,"context_line":"                    connection\u003dself.connection)"},{"line_number":785,"context_line":"                self.get_engine \u003d ctxt_mgr.writer.get_engine"},{"line_number":786,"context_line":"            elif utils.concurrency_mode_threading():"},{"line_number":787,"context_line":"                _bind_database_fixture_to_file_wal_sqlite("},{"line_number":788,"context_line":"                    self, \u0027main\u0027, main_db_api)"},{"line_number":789,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":7,"id":"c38a50f5_46dddfbe","line":786,"in_reply_to":"3d8ddde8_c0353265","updated":"2026-06-08 13:56:43.000000000","message":"Checked Database(connection\u003d...), the only caller is test_connection_switch.py, which passes sqlite:///foo.db (file-backed SQLite not an in memory). That path uses create_context_manager(connection\u003d...), which applies full _get_db_conf(CONF.database, connection\u003d...) so all DB config from CONF is applied there.\n\nFor threading mode , _bind_database_fixture_to_file_wal_sqlite now calls db_api_module.configure(CONF) before overriding the connection URL matching the eventlet path.","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"f812ae90bdf02581878a31c45fae34ba7994efe2","unresolved":false,"context_lines":[{"line_number":783,"context_line":"                ctxt_mgr \u003d main_db_api.create_context_manager("},{"line_number":784,"context_line":"                    connection\u003dself.connection)"},{"line_number":785,"context_line":"                self.get_engine \u003d ctxt_mgr.writer.get_engine"},{"line_number":786,"context_line":"            elif utils.concurrency_mode_threading():"},{"line_number":787,"context_line":"                _bind_database_fixture_to_file_wal_sqlite("},{"line_number":788,"context_line":"                    self, \u0027main\u0027, main_db_api)"},{"line_number":789,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":7,"id":"2422b50f_1adceb98","line":786,"in_reply_to":"c38a50f5_46dddfbe","updated":"2026-07-09 10:49:43.000000000","message":"Acknowledged","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"dc31c9a7eaf7852079b496a36fa9ad434d6620da","unresolved":true,"context_lines":[{"line_number":799,"context_line":"                self.get_engine \u003d main_db_api.get_engine"},{"line_number":800,"context_line":"        elif self.database \u003d\u003d \u0027api\u0027:"},{"line_number":801,"context_line":"            if utils.concurrency_mode_threading():"},{"line_number":802,"context_line":"                _bind_database_fixture_to_file_wal_sqlite("},{"line_number":803,"context_line":"                    self, \u0027api\u0027, api_db_api)"},{"line_number":804,"context_line":"            else:"},{"line_number":805,"context_line":"                # NOTE(gibi): similar note applies here as for the main_db_api"}],"source_content_type":"text/x-python","patch_set":7,"id":"b6138cfd_83f8d155","line":802,"updated":"2026-05-28 11:17:00.000000000","message":"ditto we probably missing the api_db_api.configure(CONF) call in threading mode then","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"6a0ae9d4edb4a53c039edced8039b80d254a7696","unresolved":false,"context_lines":[{"line_number":799,"context_line":"                self.get_engine \u003d main_db_api.get_engine"},{"line_number":800,"context_line":"        elif self.database \u003d\u003d \u0027api\u0027:"},{"line_number":801,"context_line":"            if utils.concurrency_mode_threading():"},{"line_number":802,"context_line":"                _bind_database_fixture_to_file_wal_sqlite("},{"line_number":803,"context_line":"                    self, \u0027api\u0027, api_db_api)"},{"line_number":804,"context_line":"            else:"},{"line_number":805,"context_line":"                # NOTE(gibi): similar note applies here as for the main_db_api"}],"source_content_type":"text/x-python","patch_set":7,"id":"b94ae19a_354ad9fd","line":802,"in_reply_to":"b6138cfd_83f8d155","updated":"2026-06-08 13:57:37.000000000","message":"Done","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"dc31c9a7eaf7852079b496a36fa9ad434d6620da","unresolved":true,"context_lines":[{"line_number":836,"context_line":"    def cleanup(self):"},{"line_number":837,"context_line":"        engine \u003d self.get_engine()"},{"line_number":838,"context_line":"        engine.dispose()"},{"line_number":839,"context_line":"        # Delete the temp DB file (and any WAL/SHM sidecars) so that a"},{"line_number":840,"context_line":"        # subsequent connection via the still-active ReplaceEngineFacadeFixture"},{"line_number":841,"context_line":"        # sees a fresh empty database, matching the contract that in-memory"},{"line_number":842,"context_line":"        # SQLite provided implicitly. With in-memory SQLite, reconnecting to"}],"source_content_type":"text/x-python","patch_set":7,"id":"a06b86f6_1cc7301c","line":839,"updated":"2026-05-28 11:17:00.000000000","message":"Can we just store everything in a single self._temp_dir \u003d fixtures.TempDir() and then let the TempDir fixture\u0027s cleanup delete the whole directory? It feels like that would be a lot simpler than manually deleting files.\n\nOr is this cleanup already done by the NestedTempfile fixture? If so then why we need to cleanup here explicitly?","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"b26f494c0a7aaf9397203978ec44f69a3d6e6d63","unresolved":false,"context_lines":[{"line_number":836,"context_line":"    def cleanup(self):"},{"line_number":837,"context_line":"        engine \u003d self.get_engine()"},{"line_number":838,"context_line":"        engine.dispose()"},{"line_number":839,"context_line":"        # Delete the temp DB file (and any WAL/SHM sidecars) so that a"},{"line_number":840,"context_line":"        # subsequent connection via the still-active ReplaceEngineFacadeFixture"},{"line_number":841,"context_line":"        # sees a fresh empty database, matching the contract that in-memory"},{"line_number":842,"context_line":"        # SQLite provided implicitly. With in-memory SQLite, reconnecting to"}],"source_content_type":"text/x-python","patch_set":7,"id":"f015ab85_e4d995d5","line":839,"in_reply_to":"85d660f6_11d09ee1","updated":"2026-07-06 07:37:19.000000000","message":"Removed manual sqlite unlink from Database.cleanup(), it only disposes the engine now. Temp files are removed by NestedTempfile at end of test. We are now Skipping test_fixture_cleanup and test_api_fixture_cleanup in threading mode per your suggestion.","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"6176643750fb6d823c64252413eef09640654c6e","unresolved":true,"context_lines":[{"line_number":836,"context_line":"    def cleanup(self):"},{"line_number":837,"context_line":"        engine \u003d self.get_engine()"},{"line_number":838,"context_line":"        engine.dispose()"},{"line_number":839,"context_line":"        # Delete the temp DB file (and any WAL/SHM sidecars) so that a"},{"line_number":840,"context_line":"        # subsequent connection via the still-active ReplaceEngineFacadeFixture"},{"line_number":841,"context_line":"        # sees a fresh empty database, matching the contract that in-memory"},{"line_number":842,"context_line":"        # SQLite provided implicitly. With in-memory SQLite, reconnecting to"}],"source_content_type":"text/x-python","patch_set":7,"id":"f1107cfb_902bc717","line":839,"in_reply_to":"a06b86f6_1cc7301c","updated":"2026-06-09 08:43:01.000000000","message":"NestedTempfile removes the temp directory when the test finishes so that handles end-of-test cleanup.\n\nThe explicit unlink in cleanup() is for a different case because unit tests such as test_fixture_cleanup and test_fixture_reset call cleanup() or reset() mid-test while ReplaceEngineFacadeFixture is still active with the same connection URL. With in-memory SQLite, reconnecting after cleanup gave a blank DB but with file-backed SQLite, reconnecting to the same path would reopen the existing file with tables still present unless we delete it (and WAL/SHM sidecars). I tried removing this earlier but that ended up failing the unit tests I mentioned so it was the unit test failure this addresses.","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"8f5bf17387918128d238d8020638f91340da12eb","unresolved":true,"context_lines":[{"line_number":836,"context_line":"    def cleanup(self):"},{"line_number":837,"context_line":"        engine \u003d self.get_engine()"},{"line_number":838,"context_line":"        engine.dispose()"},{"line_number":839,"context_line":"        # Delete the temp DB file (and any WAL/SHM sidecars) so that a"},{"line_number":840,"context_line":"        # subsequent connection via the still-active ReplaceEngineFacadeFixture"},{"line_number":841,"context_line":"        # sees a fresh empty database, matching the contract that in-memory"},{"line_number":842,"context_line":"        # SQLite provided implicitly. With in-memory SQLite, reconnecting to"}],"source_content_type":"text/x-python","patch_set":7,"id":"85d660f6_11d09ee1","line":839,"in_reply_to":"f1107cfb_902bc717","updated":"2026-06-24 13:01:21.000000000","message":"Hm, those test_fixture_cleanup test_fixture_reset sounds like test case for this fixture. As we changing how our fixture behaves e.g. now using file based SQLite it is OK that the test cases are failing too. I would rather adapt the those test cases (or remove them if they does not make sense any more) then keep code in the fixture just to pass the test cases testing the fixture.","commit_id":"fc065aefe74464dd18c39569a16efe47f9e240c0"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"3707085c72e6b31cdbb9ca87873588113019ca9f","unresolved":false,"context_lines":[{"line_number":711,"context_line":"            # When the global schema cache is empty, _cache_schema runs"},{"line_number":712,"context_line":"            # migration.db_sync on this cell\u0027s engine (applying the full main"},{"line_number":713,"context_line":"            # schema). Replaying the same SQL via executescript would try to"},{"line_number":714,"context_line":"            # CREATE tables that already exist. Only clone from the cache when it"},{"line_number":715,"context_line":"            # was populated before this call (i.e. subsequent cells in this process)."},{"line_number":716,"context_line":"            if self._cache_schema(connection_str):"},{"line_number":717,"context_line":"                conn \u003d engine.connect()"}],"source_content_type":"text/x-python","patch_set":9,"id":"71ce84da_385ce025","line":714,"updated":"2026-06-08 16:23:15.000000000","message":"pep8: E501 line too long (81 \u003e 79 characters)","commit_id":"5760461a597b8c4bf4613562ff21951275ca2565"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"4f67dd2dda4e879b79ee5d99fad8cd439d020f2e","unresolved":false,"context_lines":[{"line_number":710,"context_line":"            engine.dispose()"},{"line_number":711,"context_line":"            # When the global schema cache is empty, _cache_schema runs"},{"line_number":712,"context_line":"            # migration.db_sync on this cell\u0027s engine (applying the full main"},{"line_number":713,"context_line":"            # schema). Replaying the same SQL via executescript on a file-backed"},{"line_number":714,"context_line":"            # DB would try to CREATE tables that already exist. Only clone from"},{"line_number":715,"context_line":"            # the cache when it was populated before this call (i.e. subsequent"},{"line_number":716,"context_line":"            # cells in this process), or when using in-memory SQLite (eventlet"}],"source_content_type":"text/x-python","patch_set":10,"id":"6eee7d4b_6dcee4fc","line":713,"updated":"2026-06-09 09:32:02.000000000","message":"pep8: E501 line too long (80 \u003e 79 characters)","commit_id":"3c6421a071755c38058d8a566f40bbae641e7f83"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"66830fd2aeebac799afca54e69c687ce244442df","unresolved":false,"context_lines":[{"line_number":705,"context_line":"            engine \u003d ctxt_mgr.writer.get_engine()"},{"line_number":706,"context_line":"            engine.dispose()"},{"line_number":707,"context_line":"            self._cache_schema(connection_str)"},{"line_number":708,"context_line":"            if main_schema_cached_before or not utils.concurrency_mode_threading():"},{"line_number":709,"context_line":"                conn \u003d engine.connect()"},{"line_number":710,"context_line":"                conn.connection.executescript(DB_SCHEMA[(\u0027main\u0027, None)])"},{"line_number":711,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"3cfeb91c_7ade006d","line":708,"updated":"2026-06-10 14:29:56.000000000","message":"pep8: E501 line too long (83 \u003e 79 characters)","commit_id":"f374cf63faf28f960299ccec1376d72dd7e4a772"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"8f6ec558d4abd69ab3ce4cc063a93c60a1940535","unresolved":true,"context_lines":[{"line_number":709,"context_line":"            engine.dispose()"},{"line_number":710,"context_line":"            # When the global schema cache is empty, _cache_schema runs"},{"line_number":711,"context_line":"            # migration.db_sync on this cell\u0027s engine (applying the full main"},{"line_number":712,"context_line":"            # schema). Replaying the same SQL via executescript on a"},{"line_number":713,"context_line":"            # file-backed DB would try to CREATE tables that already exist."},{"line_number":714,"context_line":"            # Only clone from the cache when it was populated before this"},{"line_number":715,"context_line":"            # call (i.e. subsequent cells in this process), or when using"},{"line_number":716,"context_line":"            # in-memory SQLite (eventlet mode) where dispose() above destroyed"}],"source_content_type":"text/x-python","patch_set":18,"id":"826dd68c_12c41ee9","line":713,"range":{"start_line":712,"start_character":23,"end_line":713,"end_character":75},"updated":"2026-07-07 16:45:52.000000000","message":"But why the schema already exists in the DB? Don\u0027t we initialize a new DB for each test case?\n\nHow I understand this. \n1) we create an empty DB for each test for each cell (either by not having a connection to the in memory DB, or by deleting the file based DB from disk)\n2) the first test case that runs in the worker and creates a cell DB needs to use `migration.db_sync(database\u003d\u0027main\u0027)` to apply the schema for the empty DB and caches the schema into DB_SCHEMA global. (we do this caching as db_sync is slower than `executescript`)\n3) each subsequent cell creation in that test case or any subsequent test case  in the same worker just `executescript`s the schema from the DB_SCHEMA global on the empty cell DB.\n\nThe eventlet case is more complicated as when the connection is closed the DB is lost. But strangely at L709 we forcefully closing the connection then reopening it at L720 and reapplying the DB schema. I don\u0027t really care about this logic in the eventlet case as it will be deleted in the future. So we can keep that as is. But can we separate the threading mode better from it so we don\u0027t need to carry over this complication? Or is there a reason we need to do all this in threading mode too?\n\nSomething like this seems to work for me and it is a lot cleaner to me:\n```\n❯ git --no-pager  diff\ndiff --git a/nova/tests/fixtures/nova.py b/nova/tests/fixtures/nova.py\nindex e6c0d6c99d..c219903218 100644\n--- a/nova/tests/fixtures/nova.py\n+++ b/nova/tests/fixtures/nova.py\n@@ -505,16 +505,19 @@ class CellDatabases(fixtures.Fixture):\n         \"\"\"\n         # NOTE(melwitt): See the regular Database fixture for why\n         # we do this.\n-        if DB_SCHEMA[(\u0027main\u0027, None)]:\n-            return True\n-        ctxt_mgr \u003d self._ctxt_mgrs[connection_str]\n-        engine \u003d ctxt_mgr.writer.get_engine()\n-        conn \u003d engine.connect()\n-        migration.db_sync(database\u003d\u0027main\u0027)\n-        DB_SCHEMA[(\u0027main\u0027, None)] \u003d \"\".join(line for line\n-                                    in conn.connection.iterdump())\n-        engine.dispose()\n-        return False\n+        if not DB_SCHEMA[(\u0027main\u0027, None)]:\n+            ctxt_mgr \u003d self._ctxt_mgrs[connection_str]\n+            engine \u003d ctxt_mgr.writer.get_engine()\n+            conn \u003d engine.connect()\n+            migration.db_sync(database\u003d\u0027main\u0027)\n+            DB_SCHEMA[(\u0027main\u0027, None)] \u003d \"\".join(line for line\n+                                        in conn.connection.iterdump())\n+        else:\n+            ctxt_mgr \u003d self._ctxt_mgrs[connection_str]\n+            engine \u003d ctxt_mgr.writer.get_engine()\n+            conn \u003d engine.connect()\n+            conn.connection.executescript(DB_SCHEMA[(\u0027main\u0027, None)])\n+\n \n     @contextmanager\n     def _wrap_target_cell(self, context, cell_mapping):\n@@ -707,18 +710,7 @@ class CellDatabases(fixtures.Fixture):\n         ):\n             engine \u003d ctxt_mgr.writer.get_engine()\n             engine.dispose()\n-            # When the global schema cache is empty, _cache_schema runs\n-            # migration.db_sync on this cell\u0027s engine (applying the full main\n-            # schema). Replaying the same SQL via executescript on a\n-            # file-backed DB would try to CREATE tables that already exist.\n-            # Only clone from the cache when it was populated before this\n-            # call (i.e. subsequent cells in this process), or when using\n-            # in-memory SQLite (eventlet mode) where dispose() above destroyed\n-            # the DB and executescript is required to repopulate from cache.\n-            schema_cached \u003d self._cache_schema(connection_str)\n-            if schema_cached or not utils.concurrency_mode_threading():\n-                conn \u003d engine.connect()\n-                conn.connection.executescript(DB_SCHEMA[(\u0027main\u0027, None)])\n+            self._cache_schema(connection_str)\n \n     def setUp(self):\n         super(CellDatabases, self).setUp()\n```","commit_id":"fc444e23cb1adb3a43c3a751a000c9298e398c7c"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"8e40df5d81624a8d50adbee45e9e873341d3dac6","unresolved":false,"context_lines":[{"line_number":709,"context_line":"            engine.dispose()"},{"line_number":710,"context_line":"            # When the global schema cache is empty, _cache_schema runs"},{"line_number":711,"context_line":"            # migration.db_sync on this cell\u0027s engine (applying the full main"},{"line_number":712,"context_line":"            # schema). Replaying the same SQL via executescript on a"},{"line_number":713,"context_line":"            # file-backed DB would try to CREATE tables that already exist."},{"line_number":714,"context_line":"            # Only clone from the cache when it was populated before this"},{"line_number":715,"context_line":"            # call (i.e. subsequent cells in this process), or when using"},{"line_number":716,"context_line":"            # in-memory SQLite (eventlet mode) where dispose() above destroyed"}],"source_content_type":"text/x-python","patch_set":18,"id":"10855b92_fde7a823","line":713,"range":{"start_line":712,"start_character":23,"end_line":713,"end_character":75},"in_reply_to":"2811fa3e_4eb88676","updated":"2026-07-08 23:20:20.000000000","message":"Makes sense, Thanks. Done","commit_id":"fc444e23cb1adb3a43c3a751a000c9298e398c7c"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"3b3894875ddbd9fd68d1a0b10a703728296ad115","unresolved":true,"context_lines":[{"line_number":709,"context_line":"            engine.dispose()"},{"line_number":710,"context_line":"            # When the global schema cache is empty, _cache_schema runs"},{"line_number":711,"context_line":"            # migration.db_sync on this cell\u0027s engine (applying the full main"},{"line_number":712,"context_line":"            # schema). Replaying the same SQL via executescript on a"},{"line_number":713,"context_line":"            # file-backed DB would try to CREATE tables that already exist."},{"line_number":714,"context_line":"            # Only clone from the cache when it was populated before this"},{"line_number":715,"context_line":"            # call (i.e. subsequent cells in this process), or when using"},{"line_number":716,"context_line":"            # in-memory SQLite (eventlet mode) where dispose() above destroyed"}],"source_content_type":"text/x-python","patch_set":18,"id":"2811fa3e_4eb88676","line":713,"range":{"start_line":712,"start_character":23,"end_line":713,"end_character":75},"in_reply_to":"826dd68c_12c41ee9","updated":"2026-07-08 11:08:15.000000000","message":"and of course the _cache_schema can be simplified to \n```\n        ctxt_mgr \u003d self._ctxt_mgrs[connection_str]\n        engine \u003d ctxt_mgr.writer.get_engine()\n        conn \u003d engine.connect()\n        if not DB_SCHEMA[(\u0027main\u0027, None)]:\n            migration.db_sync(database\u003d\u0027main\u0027)\n            DB_SCHEMA[(\u0027main\u0027, None)] \u003d \"\".join(line for line\n                                        in conn.connection.iterdump())\n        else:\n            conn.connection.executescript(DB_SCHEMA[(\u0027main\u0027, None)])\n```\nby pulling the common code of both if and else out","commit_id":"fc444e23cb1adb3a43c3a751a000c9298e398c7c"}],"nova/tests/unit/test_fixtures.py":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"0904fbb9ab92a349b05315f9415d9f59760dda73","unresolved":true,"context_lines":[{"line_number":246,"context_line":"        self.useFixture(fixtures.Database())"},{"line_number":247,"context_line":"        self.useFixture(fixtures.Database(database\u003d\u0027api\u0027))"},{"line_number":248,"context_line":""},{"line_number":249,"context_line":"        engine \u003d api_db_api.get_engine()"},{"line_number":250,"context_line":"        conn \u003d engine.connect()"},{"line_number":251,"context_line":"        result \u003d conn.execute(sa.text(\"SELECT * FROM flavors\"))"},{"line_number":252,"context_line":"        rows \u003d result.fetchall()"},{"line_number":253,"context_line":"        self.assertEqual(0, len(rows), \"Rows %s\" % rows)"},{"line_number":254,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"18f71b19_a43e9dd3","line":251,"range":{"start_line":249,"start_character":40,"end_line":251,"end_character":63},"updated":"2026-05-25 09:10:40.000000000","message":"per below\n\n```suggestion\n        engine \u003d api_db_api.get_engine()\n        with engine.connect() as conn:\n            result \u003d conn.execute(sa.text(\"SELECT * FROM flavors\"))\n```","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"0a22789f0cc7670a46cda5a329c71975f6bc43f7","unresolved":false,"context_lines":[{"line_number":246,"context_line":"        self.useFixture(fixtures.Database())"},{"line_number":247,"context_line":"        self.useFixture(fixtures.Database(database\u003d\u0027api\u0027))"},{"line_number":248,"context_line":""},{"line_number":249,"context_line":"        engine \u003d api_db_api.get_engine()"},{"line_number":250,"context_line":"        conn \u003d engine.connect()"},{"line_number":251,"context_line":"        result \u003d conn.execute(sa.text(\"SELECT * FROM flavors\"))"},{"line_number":252,"context_line":"        rows \u003d result.fetchall()"},{"line_number":253,"context_line":"        self.assertEqual(0, len(rows), \"Rows %s\" % rows)"},{"line_number":254,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"d8d83958_dea60882","line":251,"range":{"start_line":249,"start_character":40,"end_line":251,"end_character":63},"in_reply_to":"18f71b19_a43e9dd3","updated":"2026-05-26 15:29:55.000000000","message":"Done","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"0904fbb9ab92a349b05315f9415d9f59760dda73","unresolved":true,"context_lines":[{"line_number":257,"context_line":"        # File-backed SQLite (threading) uses a new connection per checkout;"},{"line_number":258,"context_line":"        # start a new connection so the flavors insert is visible."},{"line_number":259,"context_line":"        conn.close()"},{"line_number":260,"context_line":"        conn \u003d engine.connect()"},{"line_number":261,"context_line":"        result \u003d conn.execute(sa.text(\"SELECT * FROM flavors\"))"},{"line_number":262,"context_line":"        rows \u003d result.fetchall()"},{"line_number":263,"context_line":"        self.assertEqual(6, len(rows), \"Rows %s\" % rows)"}],"source_content_type":"text/x-python","patch_set":4,"id":"43b45936_171123cf","line":260,"updated":"2026-05-25 09:10:40.000000000","message":"Should we switch to a context-manager style so, rather than doing manual connection management? I suspect we\u0027re now leaving an connection open here at the end of this test?","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"0a22789f0cc7670a46cda5a329c71975f6bc43f7","unresolved":false,"context_lines":[{"line_number":257,"context_line":"        # File-backed SQLite (threading) uses a new connection per checkout;"},{"line_number":258,"context_line":"        # start a new connection so the flavors insert is visible."},{"line_number":259,"context_line":"        conn.close()"},{"line_number":260,"context_line":"        conn \u003d engine.connect()"},{"line_number":261,"context_line":"        result \u003d conn.execute(sa.text(\"SELECT * FROM flavors\"))"},{"line_number":262,"context_line":"        rows \u003d result.fetchall()"},{"line_number":263,"context_line":"        self.assertEqual(6, len(rows), \"Rows %s\" % rows)"}],"source_content_type":"text/x-python","patch_set":4,"id":"262531bf_b514234f","line":260,"in_reply_to":"43b45936_171123cf","updated":"2026-05-26 15:29:55.000000000","message":"yes sounds good","commit_id":"6ce29012ebace5a88c17a4207d04bce91cc4395e"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"d83905413eca6730a16f66cc7f6e6022f10dc293","unresolved":false,"context_lines":[{"line_number":18,"context_line":"import datetime"},{"line_number":19,"context_line":"import io"},{"line_number":20,"context_line":"from unittest import mock"},{"line_number":21,"context_line":"import unittest"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"import fixtures as fx"},{"line_number":24,"context_line":"from oslo_config import cfg"}],"source_content_type":"text/x-python","patch_set":17,"id":"4a3d4a0a_3fe35fdc","line":21,"updated":"2026-07-06 12:11:15.000000000","message":"pep8: H306: imports not in alphabetical order (unittest.mock, unittest)","commit_id":"81d1356f25d330890c10c2d245272fad2772ffa3"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"8f6ec558d4abd69ab3ce4cc063a93c60a1940535","unresolved":true,"context_lines":[{"line_number":202,"context_line":"    @unittest.skipIf("},{"line_number":203,"context_line":"        utils.concurrency_mode_threading(),"},{"line_number":204,"context_line":"        \u0027file-backed SQLite keeps data at the same path after cleanup(); \u0027"},{"line_number":205,"context_line":"        \u0027use db_fixture.reset() for a fresh database in threading mode\u0027)"},{"line_number":206,"context_line":"    def test_fixture_cleanup(self):"},{"line_number":207,"context_line":"        # In-memory SQLite only: cleanup() disposes the engine and reconnecting"},{"line_number":208,"context_line":"        # yields an empty database. File-backed temp files are removed when"}],"source_content_type":"text/x-python","patch_set":18,"id":"67e5235f_e58f0fed","line":205,"updated":"2026-07-07 16:45:52.000000000","message":"This test case can be reformulate to pass in both modes. If you use the fixture in a context manager mode then after the exit of the context manager we expect that the cleanup of the fixture runs. So something like\n\n```\nwith fixtures.Database():\n    # write something to the DB\n    \nwith fixtures.Database():\n    # check that the DB does not have what you wrote to it\n``` \n\nshould work in both modes to prove that to subsequent test cases don\u0027t see DB content of the previous one.\n\nI\u0027m fine to do this in a follow up and keep the disabling here for the time being.","commit_id":"fc444e23cb1adb3a43c3a751a000c9298e398c7c"},{"author":{"_account_id":35153,"name":"Ashish Gupta","email":"ashigupt@redhat.com","username":"ashigupt","status":"Redhat"},"change_message_id":"f71cc4b701babf3757dfd3ef22d1ab63e0f84425","unresolved":true,"context_lines":[{"line_number":202,"context_line":"    @unittest.skipIf("},{"line_number":203,"context_line":"        utils.concurrency_mode_threading(),"},{"line_number":204,"context_line":"        \u0027file-backed SQLite keeps data at the same path after cleanup(); \u0027"},{"line_number":205,"context_line":"        \u0027use db_fixture.reset() for a fresh database in threading mode\u0027)"},{"line_number":206,"context_line":"    def test_fixture_cleanup(self):"},{"line_number":207,"context_line":"        # In-memory SQLite only: cleanup() disposes the engine and reconnecting"},{"line_number":208,"context_line":"        # yields an empty database. File-backed temp files are removed when"}],"source_content_type":"text/x-python","patch_set":18,"id":"5fc86d3a_cd071f83","line":205,"in_reply_to":"67e5235f_e58f0fed","updated":"2026-07-09 10:27:48.000000000","message":"Sure, I will do this in a follow-up","commit_id":"fc444e23cb1adb3a43c3a751a000c9298e398c7c"},{"author":{"_account_id":8556,"name":"Ghanshyam Maan","display_name":"Ghanshyam Maan","email":"gmaan.os14@gmail.com","username":"ghanshyam"},"change_message_id":"6fcc56b88078c92cba631ebb819a9113ac4846a3","unresolved":true,"context_lines":[{"line_number":221,"context_line":"        schema \u003d \"\".join(line for line in conn.connection.iterdump())"},{"line_number":222,"context_line":"        self.assertEqual(schema, \"BEGIN TRANSACTION;COMMIT;\")"},{"line_number":223,"context_line":""},{"line_number":224,"context_line":"    @unittest.skipIf("},{"line_number":225,"context_line":"        utils.concurrency_mode_threading(),"},{"line_number":226,"context_line":"        \u0027file-backed SQLite keeps data at the same path after cleanup(); \u0027"},{"line_number":227,"context_line":"        \u0027use db_fixture.reset() for a fresh database in threading mode\u0027)"},{"line_number":228,"context_line":"    def test_api_fixture_cleanup(self):"},{"line_number":229,"context_line":"        # This sets up reasonable db connection strings"},{"line_number":230,"context_line":"        self.useFixture(fixtures.ConfFixture())"}],"source_content_type":"text/x-python","patch_set":20,"id":"b947dcce_1e7e1b99","line":227,"range":{"start_line":224,"start_character":0,"end_line":227,"end_character":72},"updated":"2026-07-09 18:42:41.000000000","message":"i think same for this, can be modified for both mode verification.","commit_id":"baa54dbd7e4e20e67afa3c51ea1089f1b5b66460"}]}
