)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":28522,"name":"Hervé Beraud","email":"herveberaud.pro@gmail.com","username":"hberaud"},"change_message_id":"22b3c32d76663a49d28dbe31d962808b86a6823c","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"1c5cf140_d72fad3f","updated":"2025-10-20 11:22:09.000000000","message":"hey folks, if you do not mind I rename the topic to \"eventlet-removal\" to have your works tracked into the official dashboard https://review.opendev.org/q/prefixtopic:eventlet-removal","commit_id":"40c67ef50777167f161b9148b5b4f7ba5e8927e9"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"4c6358e8b8f185cc93b9fedfb94baf2460eb5b8c","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":16,"id":"fcf0fba0_1e7a410a","updated":"2026-04-01 05:02:09.000000000","message":"recheck","commit_id":"ce0128caa0a3cf732a969fbedc7e3cfe393988fa"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"d5ab509824d903d25de7291102c6f8f2258eba85","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":16,"id":"de816751_0fecb2df","in_reply_to":"c7f1efa6_65c81d50","updated":"2026-04-18 09:15:13.000000000","message":"Sorry for the delay — I’ll review this later this month.","commit_id":"ce0128caa0a3cf732a969fbedc7e3cfe393988fa"},{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"3ad8c97fb08fe4519d7613a4b9fe61dd73f810b0","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":16,"id":"c7f1efa6_65c81d50","in_reply_to":"fcf0fba0_1e7a410a","updated":"2026-04-09 08:27:10.000000000","message":"hello, Hirotaka, Could you take time to fix this?","commit_id":"ce0128caa0a3cf732a969fbedc7e3cfe393988fa"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"0fad6b52cec947b41262701740592d6f31514bf1","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":26,"id":"e2f21547_84907318","updated":"2026-08-22 04:32:06.000000000","message":"Hello Wu and Eric, Could you please check this?","commit_id":"3281094cca2e305c99ca68546cc2cf3f9ca0d333"},{"author":{"_account_id":36080,"name":"Erkin Mussurmankulov","display_name":"Eric","email":"erkin.mussurmankulov@ps.kz","username":"mongoose404","status":"PS Cloud services employee"},"change_message_id":"6b950626c68aaa4c90b080c55f1923eabc4b0e0f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":26,"id":"f097b7fd_bdbb8a0e","updated":"2026-08-25 12:05:43.000000000","message":"LGTM.\n\nI think we should merge it ASAP so we will have more time for testing these changes against a real OpenStack setup in our clouds.\nI didn\u0027t see any activity from Wu for a while, so I propose to merge this at the end of next week if he does not appear until that time. But let\u0027s hope that he will appear soon.","commit_id":"3281094cca2e305c99ca68546cc2cf3f9ca0d333"},{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"c2c4ad1d294cda781cea51b8b7ae20b09a905ef0","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":26,"id":"8a460916_56bc7c52","in_reply_to":"f097b7fd_bdbb8a0e","updated":"2026-09-06 07:17:43.000000000","message":"Sorry for the late response. I\u0027ve been really busy over the last few days.","commit_id":"3281094cca2e305c99ca68546cc2cf3f9ca0d333"},{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"78efe92e720b4be957c1755ae573a0a17c367a01","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":28,"id":"402fd034_15a62e53","updated":"2026-09-06 07:16:43.000000000","message":"Hello @erkin.mussurmankulov@ps.kz\n\nIt looks like the implementation of `TroveLauncher` and `async_run_with_timeout` are not tested at all, so I prefer to remove them.\n\nThe reasons are:\n1. Remove the custom `TroveLauncher`. Deployment tools such as kolla-ansible, openstack-ansible and devstack use uwsgi directly, so this custom launcher provides little value. We can use wsgiref directly, as Octavia has already done.\n\n2. Remove the timeout control. This timeout control is only used for cluster functions, which are experimental features. And `_create_cluster` / `_reset_cluster` already have automatic timeouts for each step, so removing this timeout logic is acceptable. If we still need timeout capability later, I think `oslo_utils.StopWatch` should be sufficient.\n\nIf there are no objections, I will update this patch soon.","commit_id":"567e6c9791ae574857bc9f17a0fc3a54d9b988ad"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"ebec1683d4178cbaee811e5b7a5105ea67b87e70","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":28,"id":"1a9e4613_2986b1b1","updated":"2026-09-18 15:22:13.000000000","message":"Hello Wu, Thanks for the review! I will update the patch this weekend.","commit_id":"567e6c9791ae574857bc9f17a0fc3a54d9b988ad"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"b7d513e988e14d8d2aba12b538d5a20a8e4b9968","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":30,"id":"cb59ef23_a2fd2e58","updated":"2026-09-22 12:10:28.000000000","message":"Hello Wu and Eric, Could you please check this again?","commit_id":"52d780656f046202b561f29253a998e3637ae15b"},{"author":{"_account_id":36080,"name":"Erkin Mussurmankulov","display_name":"Eric","email":"erkin.mussurmankulov@ps.kz","username":"mongoose404","status":"PS Cloud services employee"},"change_message_id":"aa4928803e79404d961a6f44d60782ac7fc0d631","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":30,"id":"174b5414_fda32011","updated":"2026-09-22 13:20:32.000000000","message":"Hello, Hirotaka! Thank you for your work. I really appreciate it.\n\nRight now, we\u0027re in the \"feature freeze\" stage, which means that only bug fixes are allowed to be merged until the final release.\n\nI will return to this MR after 2026.2 is released because we need to run more tests against it in addition to the synthetic Tempest scenarios. We will run these tests in our cloud, first in the DEV environment and then in production.\n\nI think this is the best way to make sure that everything works as expected. However, I hope that Wu will find time to review it before then.","commit_id":"52d780656f046202b561f29253a998e3637ae15b"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"fc78cc0fe7784539dd7006b829d84b6f86e4d9f0","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":30,"id":"bbe288e1_9aca20c7","updated":"2026-09-20 20:31:07.000000000","message":"Hello, Sorry for the late response... I added the unittests and fixed the problems.\n\nJust to clarify, Trove originally allowed users to run the API server directly without mod_wsgi or uwsgi. This patch is meant to preserve that existing capability without relying on eventlet. It is not intended to replace or restrict the use of uwsgi/mod_wsgi.\n\nThanks in advance,","commit_id":"52d780656f046202b561f29253a998e3637ae15b"}],"requirements.txt":[{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"046a93e7e64d04c2dae94683507b776b75c7db00","unresolved":true,"context_lines":[{"line_number":29,"context_line":"oslo.i18n\u003e\u003d3.15.3 # Apache-2.0"},{"line_number":30,"context_line":"oslo.middleware\u003e\u003d3.31.0 # Apache-2.0"},{"line_number":31,"context_line":"oslo.serialization!\u003d2.19.1,\u003e\u003d2.18.0 # Apache-2.0"},{"line_number":32,"context_line":"oslo.service[threading]!\u003d1.28.1,\u003e\u003d4.3.0 # Apache-2.0"},{"line_number":33,"context_line":"oslo.upgradecheck\u003e\u003d1.3.0 # Apache-2.0"},{"line_number":34,"context_line":"oslo.utils\u003e\u003d7.0.0 # Apache-2.0"},{"line_number":35,"context_line":"oslo.concurrency\u003e\u003d3.26.0 # Apache-2.0"}],"source_content_type":"text/plain","patch_set":17,"id":"fc51f661_7586223d","line":32,"range":{"start_line":32,"start_character":23,"end_line":32,"end_character":31},"updated":"2026-05-26 04:07:18.000000000","message":"this is not needed any more.","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"f4a09fe468c7c2ee1472395dc10560ef4a7de5a5","unresolved":false,"context_lines":[{"line_number":29,"context_line":"oslo.i18n\u003e\u003d3.15.3 # Apache-2.0"},{"line_number":30,"context_line":"oslo.middleware\u003e\u003d3.31.0 # Apache-2.0"},{"line_number":31,"context_line":"oslo.serialization!\u003d2.19.1,\u003e\u003d2.18.0 # Apache-2.0"},{"line_number":32,"context_line":"oslo.service[threading]!\u003d1.28.1,\u003e\u003d4.3.0 # Apache-2.0"},{"line_number":33,"context_line":"oslo.upgradecheck\u003e\u003d1.3.0 # Apache-2.0"},{"line_number":34,"context_line":"oslo.utils\u003e\u003d7.0.0 # Apache-2.0"},{"line_number":35,"context_line":"oslo.concurrency\u003e\u003d3.26.0 # Apache-2.0"}],"source_content_type":"text/plain","patch_set":17,"id":"ede9d816_0462e278","line":32,"range":{"start_line":32,"start_character":23,"end_line":32,"end_character":31},"in_reply_to":"fc51f661_7586223d","updated":"2026-08-21 15:59:05.000000000","message":"Done","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"}],"trove/cmd/api.py":[{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"4dac14d4c7cfdcc41d9f67aa501d25c89712c98e","unresolved":true,"context_lines":[{"line_number":33,"context_line":"    profile.setup_profiler(\u0027api\u0027, CONF.host)"},{"line_number":34,"context_line":"    conf_file \u003d CONF.find_file(CONF.api_paste_config)"},{"line_number":35,"context_line":"    workers \u003d CONF.trove_api_workers or processutils.get_worker_count()"},{"line_number":36,"context_line":"    launcher \u003d wsgi.launch(\u0027trove\u0027, CONF.bind_port, conf_file,"},{"line_number":37,"context_line":"                           host\u003dCONF.bind_host, workers\u003dworkers)"},{"line_number":38,"context_line":"    launcher.wait()"}],"source_content_type":"text/x-python","patch_set":26,"id":"5a5aeadc_6527a6b1","line":38,"range":{"start_line":36,"start_character":0,"end_line":38,"end_character":19},"updated":"2026-09-06 06:03:12.000000000","message":"`wsgi.launch` function already executes launcher.wait() inside the function and doesn\u0027t return a launcher object.","commit_id":"3281094cca2e305c99ca68546cc2cf3f9ca0d333"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"fc78cc0fe7784539dd7006b829d84b6f86e4d9f0","unresolved":false,"context_lines":[{"line_number":33,"context_line":"    profile.setup_profiler(\u0027api\u0027, CONF.host)"},{"line_number":34,"context_line":"    conf_file \u003d CONF.find_file(CONF.api_paste_config)"},{"line_number":35,"context_line":"    workers \u003d CONF.trove_api_workers or processutils.get_worker_count()"},{"line_number":36,"context_line":"    launcher \u003d wsgi.launch(\u0027trove\u0027, CONF.bind_port, conf_file,"},{"line_number":37,"context_line":"                           host\u003dCONF.bind_host, workers\u003dworkers)"},{"line_number":38,"context_line":"    launcher.wait()"}],"source_content_type":"text/x-python","patch_set":26,"id":"e5e8cd11_ef824afc","line":38,"range":{"start_line":36,"start_character":0,"end_line":38,"end_character":19},"in_reply_to":"5a5aeadc_6527a6b1","updated":"2026-09-20 20:31:07.000000000","message":"wsgi.launch function returns launcher object and fixed to make launcher.wait() not to call inside the function.","commit_id":"3281094cca2e305c99ca68546cc2cf3f9ca0d333"}],"trove/cmd/guest.py":[{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"78efe92e720b4be957c1755ae573a0a17c367a01","unresolved":true,"context_lines":[{"line_number":107,"context_line":"        operating_system.chown("},{"line_number":108,"context_line":"            mount_point, uid, gid, recursive\u003dTrue, as_root\u003dTrue)"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    # rpc module must be loaded after decision about thread monkeypatching"},{"line_number":111,"context_line":"    # because if thread module is not monkeypatched we can\u0027t use eventlet"},{"line_number":112,"context_line":"    # executor from oslo_messaging library."},{"line_number":113,"context_line":"    from trove import rpc"},{"line_number":114,"context_line":"    rpc.init(CONF)"},{"line_number":115,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"5f53a83b_de85f95c","line":112,"range":{"start_line":110,"start_character":0,"end_line":112,"end_character":43},"updated":"2026-09-06 07:16:43.000000000","message":"remove this comment,\nalso need to remove from : https://github.com/openstack/trove/blob/master/trove/cmd/common.py#L38","commit_id":"567e6c9791ae574857bc9f17a0fc3a54d9b988ad"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"fc78cc0fe7784539dd7006b829d84b6f86e4d9f0","unresolved":false,"context_lines":[{"line_number":107,"context_line":"        operating_system.chown("},{"line_number":108,"context_line":"            mount_point, uid, gid, recursive\u003dTrue, as_root\u003dTrue)"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    # rpc module must be loaded after decision about thread monkeypatching"},{"line_number":111,"context_line":"    # because if thread module is not monkeypatched we can\u0027t use eventlet"},{"line_number":112,"context_line":"    # executor from oslo_messaging library."},{"line_number":113,"context_line":"    from trove import rpc"},{"line_number":114,"context_line":"    rpc.init(CONF)"},{"line_number":115,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"99dc7dca_2e2977f4","line":112,"range":{"start_line":110,"start_character":0,"end_line":112,"end_character":43},"in_reply_to":"5f53a83b_de85f95c","updated":"2026-09-20 20:31:07.000000000","message":"Fixed to remove the comment.","commit_id":"567e6c9791ae574857bc9f17a0fc3a54d9b988ad"}],"trove/common/exception.py":[{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"046a93e7e64d04c2dae94683507b776b75c7db00","unresolved":true,"context_lines":[{"line_number":50,"context_line":"        self.message \u003d safe_fmt_string(self.message)"},{"line_number":51,"context_line":"        super(TroveError, self).__init__(**kwargs)"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"class TimeoutError(TroveError):"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    message \u003d _(\"Timeout.\")"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"class DBConstraintError(TroveError):"},{"line_number":60,"context_line":""}],"source_content_type":"text/x-python","patch_set":17,"id":"a3e48e2a_0e91d19c","line":57,"range":{"start_line":53,"start_character":0,"end_line":57,"end_character":0},"updated":"2026-05-26 04:07:18.000000000","message":"This may be redundant.","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"f4a09fe468c7c2ee1472395dc10560ef4a7de5a5","unresolved":false,"context_lines":[{"line_number":50,"context_line":"        self.message \u003d safe_fmt_string(self.message)"},{"line_number":51,"context_line":"        super(TroveError, self).__init__(**kwargs)"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"class TimeoutError(TroveError):"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    message \u003d _(\"Timeout.\")"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"class DBConstraintError(TroveError):"},{"line_number":60,"context_line":""}],"source_content_type":"text/x-python","patch_set":17,"id":"8fca6799_a09d52a7","line":57,"range":{"start_line":53,"start_character":0,"end_line":57,"end_character":0},"in_reply_to":"a3e48e2a_0e91d19c","updated":"2026-08-21 15:59:05.000000000","message":"For better readability, I introduced the trove.common.exception.TimeoutError class as a replacement for eventlet.timeout.Timeout.","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"}],"trove/common/strategies/cluster/experimental/cassandra/taskmanager.py":[{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"046a93e7e64d04c2dae94683507b776b75c7db00","unresolved":true,"context_lines":[{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":251,"context_line":"        try:"},{"line_number":252,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":253,"context_line":"                _grow_cluster, timeout))"},{"line_number":254,"context_line":"            self.reset_task()"},{"line_number":255,"context_line":"        except exception.TimeoutError:"},{"line_number":256,"context_line":"            LOG.exception(\"Timeout for growing cluster.\")"},{"line_number":257,"context_line":"            self.update_statuses_on_failure("},{"line_number":258,"context_line":"                cluster_id, status\u003dinst_tasks.InstanceTasks.GROWING_ERROR)"}],"source_content_type":"text/x-python","patch_set":17,"id":"696a689f_4db5a9e7","line":255,"range":{"start_line":252,"start_character":0,"end_line":255,"end_character":38},"updated":"2026-05-26 04:07:18.000000000","message":"Hello, I don’t prefer to use `asyncio.run` here because `asyncio` is too heavy for this scenario.\nOnce a timeout occurs, the process in the `asyncio` event loop will not receive SIGHUP, so it cannot be gracefully killed.\nI’ve checked the `_grow_cluster` and `_create_cluster` functions, and every step already has its own timeout mechanism.\nTherefore, the top-level timeout control doesn’t need to be too strict.\nUsing `watch \u003d otimeutils.StopWatch(duration\u003dCONF.cluster_usage_timeout)` like [this example](https://review.opendev.org/c/openstack/trove/+/952625/29/trove/taskmanager/models.py#352) is sufficient.","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"3bb6d408bae95cada40c043d210fa5be7cb428bf","unresolved":true,"context_lines":[{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":251,"context_line":"        try:"},{"line_number":252,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":253,"context_line":"                _grow_cluster, timeout))"},{"line_number":254,"context_line":"            self.reset_task()"},{"line_number":255,"context_line":"        except exception.TimeoutError:"},{"line_number":256,"context_line":"            LOG.exception(\"Timeout for growing cluster.\")"},{"line_number":257,"context_line":"            self.update_statuses_on_failure("},{"line_number":258,"context_line":"                cluster_id, status\u003dinst_tasks.InstanceTasks.GROWING_ERROR)"}],"source_content_type":"text/x-python","patch_set":17,"id":"83e2931d_200b96de","line":255,"range":{"start_line":252,"start_character":0,"end_line":255,"end_character":38},"in_reply_to":"696a689f_4db5a9e7","updated":"2026-05-28 09:29:44.000000000","message":"Hi Wu, thanks a lot for the comment!\n\nI checked the current logic in `trove/common/strategies/cluster/experimental/cassandra/taskmanager.py`, and it looks like it only handles timeout management without any signal handling to stop running functions. So, basically, I think our main goal right now should be keeping the behavior as close to `eventlet` as possible.\n\nIf we go with `oslo_utils.timeutils.StopWatch`, it wouldn\u0027t be enough because it can\u0027t forcefully stop a running function when the timeout hits. On the other hand, migrating to `asyncio` gives us behavior that\u0027s very similar to `eventlet`, which I think perfectly meets the requirements for this migration patch.\n\nRegarding the signal-driven interruption, that\u0027s a great point, but it\u0027s probably best handled as a separate, future fix. My thought for that is to run the `_grow_cluster` function using `ProcessPoolExecutor`. That way, when the main thread catches a signal via `loop.add_signal_handler`, we can safely terminate the subprocess.\n\nLet me know what you think!\n\nThanks,\nHirotaka","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"b654e4472edbbff5a7353024074ad636da3d0b1b","unresolved":true,"context_lines":[{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":251,"context_line":"        try:"},{"line_number":252,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":253,"context_line":"                _grow_cluster, timeout))"},{"line_number":254,"context_line":"            self.reset_task()"},{"line_number":255,"context_line":"        except exception.TimeoutError:"},{"line_number":256,"context_line":"            LOG.exception(\"Timeout for growing cluster.\")"},{"line_number":257,"context_line":"            self.update_statuses_on_failure("},{"line_number":258,"context_line":"                cluster_id, status\u003dinst_tasks.InstanceTasks.GROWING_ERROR)"}],"source_content_type":"text/x-python","patch_set":17,"id":"cd684a5f_1c1122a5","line":255,"range":{"start_line":252,"start_character":0,"end_line":255,"end_character":38},"in_reply_to":"83e2931d_200b96de","updated":"2026-05-31 05:36:08.000000000","message":"Hi Hirotaka,\n\nSignal handling is mostly implemented by low-level libraries such as oslo.message and processutils. If we need to handle these signals, we will have to replicate the same logic in our codebase.\nSince eventlet will be removed soon, we should re-evaluate whether we still need to retain this timeout behavior.\nIMO, these cluster functions have not been maintained for a long time, so I don’t think we should spend effort on this. Additionally, every call within cluster actions already has its own timeout. The top-level timeout can be calculated as follows:\n`guest call count × timeout + oslo message calls × timeout`\n\nOverall, I think removing this top-level timeout control is acceptable. Even if we decide to keep the current behavior, a `threading + join(timeout)` implementation is simpler than the current `asyncio` approach.\n\nMaybe we should hear what Eric thinks?","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":36080,"name":"Erkin Mussurmankulov","display_name":"Eric","email":"erkin.mussurmankulov@ps.kz","username":"mongoose404","status":"PS Cloud services employee"},"change_message_id":"34cef3e1f9b59f26d9bc2b0fb69a7e46a498cf85","unresolved":true,"context_lines":[{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":251,"context_line":"        try:"},{"line_number":252,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":253,"context_line":"                _grow_cluster, timeout))"},{"line_number":254,"context_line":"            self.reset_task()"},{"line_number":255,"context_line":"        except exception.TimeoutError:"},{"line_number":256,"context_line":"            LOG.exception(\"Timeout for growing cluster.\")"},{"line_number":257,"context_line":"            self.update_statuses_on_failure("},{"line_number":258,"context_line":"                cluster_id, status\u003dinst_tasks.InstanceTasks.GROWING_ERROR)"}],"source_content_type":"text/x-python","patch_set":17,"id":"ea10e957_c20e51a2","line":255,"range":{"start_line":252,"start_character":0,"end_line":255,"end_character":38},"in_reply_to":"c51811cf_10afa5ab","updated":"2026-08-21 07:37:05.000000000","message":"Hello guys!\nLooks like we\u0027re trying to support dead code here. We can\u0027t even test it and check if it still works (I\u0027m 99% sure it doesn\u0027t).\nProbably we should remove the entire `trove/common/strategies/cluster/experimental` directory first in a separate MR? After that, this MR would be less controversial.\n[Here is](https://review.opendev.org/c/openstack/trove/+/1001764) the MR for removal","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":36080,"name":"Erkin Mussurmankulov","display_name":"Eric","email":"erkin.mussurmankulov@ps.kz","username":"mongoose404","status":"PS Cloud services employee"},"change_message_id":"a8f4114fc47bc10be95a65974c91a9f0c32777c2","unresolved":true,"context_lines":[{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":251,"context_line":"        try:"},{"line_number":252,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":253,"context_line":"                _grow_cluster, timeout))"},{"line_number":254,"context_line":"            self.reset_task()"},{"line_number":255,"context_line":"        except exception.TimeoutError:"},{"line_number":256,"context_line":"            LOG.exception(\"Timeout for growing cluster.\")"},{"line_number":257,"context_line":"            self.update_statuses_on_failure("},{"line_number":258,"context_line":"                cluster_id, status\u003dinst_tasks.InstanceTasks.GROWING_ERROR)"}],"source_content_type":"text/x-python","patch_set":17,"id":"c51811cf_10afa5ab","line":255,"range":{"start_line":252,"start_character":0,"end_line":255,"end_character":38},"in_reply_to":"cd684a5f_1c1122a5","updated":"2026-08-10 13:13:46.000000000","message":"Hello, Wu. Sorry, I just saw your message.\nI\u0027m not familiar with either Eventlet or Oslo message libraries, so I would prefer to trust the decision process to more competent people, you and Hirotaka 😄\n\nI can do a deep dive into the topic, though, but right now I have a lot of work to do in parallel. Nevertheless, I can do it as a last resort if required.\n\n_________\n\nPlease note that we have very little time left. Feature freeze is planned on 6th September, in less than a month.","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"f4a09fe468c7c2ee1472395dc10560ef4a7de5a5","unresolved":false,"context_lines":[{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":251,"context_line":"        try:"},{"line_number":252,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":253,"context_line":"                _grow_cluster, timeout))"},{"line_number":254,"context_line":"            self.reset_task()"},{"line_number":255,"context_line":"        except exception.TimeoutError:"},{"line_number":256,"context_line":"            LOG.exception(\"Timeout for growing cluster.\")"},{"line_number":257,"context_line":"            self.update_statuses_on_failure("},{"line_number":258,"context_line":"                cluster_id, status\u003dinst_tasks.InstanceTasks.GROWING_ERROR)"}],"source_content_type":"text/x-python","patch_set":17,"id":"107d6604_d754e61a","line":255,"range":{"start_line":252,"start_character":0,"end_line":255,"end_character":38},"in_reply_to":"ea10e957_c20e51a2","updated":"2026-08-21 15:59:05.000000000","message":"Hello Eric and Wu, thanks for the comments!\n\nI have updated the patch. The new implementation uses `ProcessPoolExecutor` for the timeout control, which allows us to forcefully terminate the running process on timeout and prevent resource leaks.\n\nRegarding Eric\u0027s suggestion to remove the `experimental` cluster code: \nI don\u0027t think we should remove this feature at this timing. There might still be users relying on it in their environments. If we want to remove it, we should properly follow the standard OpenStack deprecation process [1] rather than dropping it as part of this migration effort.\n\n[1] https://docs.openstack.org/project-team-guide/deprecation.html","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"046a93e7e64d04c2dae94683507b776b75c7db00","unresolved":true,"context_lines":[{"line_number":324,"context_line":"                    status\u003dinst_tasks.InstanceTasks.SHRINKING_ERROR)"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":327,"context_line":"        try:"},{"line_number":328,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":329,"context_line":"                _shrink_cluster, timeout))"},{"line_number":330,"context_line":"            self.reset_task()"},{"line_number":331,"context_line":"        except exception.TimeoutError:"},{"line_number":332,"context_line":"            LOG.exception(\"Timeout for shrinking cluster.\")"},{"line_number":333,"context_line":"            self.update_statuses_on_failure("},{"line_number":334,"context_line":"                cluster_id, status\u003dinst_tasks.InstanceTasks.SHRINKING_ERROR)"}],"source_content_type":"text/x-python","patch_set":17,"id":"8783a7b0_2ee84ec7","line":331,"range":{"start_line":327,"start_character":0,"end_line":331,"end_character":38},"updated":"2026-05-26 04:07:18.000000000","message":"ditto","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"f4a09fe468c7c2ee1472395dc10560ef4a7de5a5","unresolved":false,"context_lines":[{"line_number":324,"context_line":"                    status\u003dinst_tasks.InstanceTasks.SHRINKING_ERROR)"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":327,"context_line":"        try:"},{"line_number":328,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":329,"context_line":"                _shrink_cluster, timeout))"},{"line_number":330,"context_line":"            self.reset_task()"},{"line_number":331,"context_line":"        except exception.TimeoutError:"},{"line_number":332,"context_line":"            LOG.exception(\"Timeout for shrinking cluster.\")"},{"line_number":333,"context_line":"            self.update_statuses_on_failure("},{"line_number":334,"context_line":"                cluster_id, status\u003dinst_tasks.InstanceTasks.SHRINKING_ERROR)"}],"source_content_type":"text/x-python","patch_set":17,"id":"24f2aa8c_5b8e5c48","line":331,"range":{"start_line":327,"start_character":0,"end_line":331,"end_character":38},"in_reply_to":"8783a7b0_2ee84ec7","updated":"2026-08-21 15:59:05.000000000","message":"Please see the comment in the cluster_utils.async_run_with_timeout function.","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"}],"trove/common/strategies/cluster/experimental/galera_common/taskmanager.py":[{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"046a93e7e64d04c2dae94683507b776b75c7db00","unresolved":true,"context_lines":[{"line_number":236,"context_line":""},{"line_number":237,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":238,"context_line":"        try:"},{"line_number":239,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":240,"context_line":"                _grow_cluster, timeout))"},{"line_number":241,"context_line":"            self.reset_task()"},{"line_number":242,"context_line":"        except exception.TimeoutError:"}],"source_content_type":"text/x-python","patch_set":17,"id":"04163430_e06ed0a4","line":239,"updated":"2026-05-26 04:07:18.000000000","message":"ditto","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"f4a09fe468c7c2ee1472395dc10560ef4a7de5a5","unresolved":false,"context_lines":[{"line_number":236,"context_line":""},{"line_number":237,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":238,"context_line":"        try:"},{"line_number":239,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":240,"context_line":"                _grow_cluster, timeout))"},{"line_number":241,"context_line":"            self.reset_task()"},{"line_number":242,"context_line":"        except exception.TimeoutError:"}],"source_content_type":"text/x-python","patch_set":17,"id":"7765a443_ad7903c0","line":239,"in_reply_to":"04163430_e06ed0a4","updated":"2026-08-21 15:59:05.000000000","message":"Please see the comment in the `cluster_utils.async_run_with_timeout` function.","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"}],"trove/common/strategies/cluster/experimental/mongodb/taskmanager.py":[{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"046a93e7e64d04c2dae94683507b776b75c7db00","unresolved":true,"context_lines":[{"line_number":237,"context_line":""},{"line_number":238,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":239,"context_line":"        try:"},{"line_number":240,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":241,"context_line":"                _grow_cluster, timeout))"},{"line_number":242,"context_line":"            self.reset_task()"},{"line_number":243,"context_line":"        except exception.TimeoutError:"}],"source_content_type":"text/x-python","patch_set":17,"id":"02c6bdf1_8a537382","line":240,"updated":"2026-05-26 04:07:18.000000000","message":"ditto","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"f4a09fe468c7c2ee1472395dc10560ef4a7de5a5","unresolved":false,"context_lines":[{"line_number":237,"context_line":""},{"line_number":238,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":239,"context_line":"        try:"},{"line_number":240,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":241,"context_line":"                _grow_cluster, timeout))"},{"line_number":242,"context_line":"            self.reset_task()"},{"line_number":243,"context_line":"        except exception.TimeoutError:"}],"source_content_type":"text/x-python","patch_set":17,"id":"f31ff1a1_5586f155","line":240,"in_reply_to":"02c6bdf1_8a537382","updated":"2026-08-21 15:59:05.000000000","message":"Please see the comment in the `cluster_utils.async_run_with_timeout` function.","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"}],"trove/common/strategies/cluster/experimental/redis/taskmanager.py":[{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"046a93e7e64d04c2dae94683507b776b75c7db00","unresolved":true,"context_lines":[{"line_number":137,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":138,"context_line":"        try:"},{"line_number":139,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":140,"context_line":"                _grow_cluster, timeout))"},{"line_number":141,"context_line":"            self.reset_task()"},{"line_number":142,"context_line":"        except exception.TimeoutError:"},{"line_number":143,"context_line":"            LOG.exception(\"Timeout for growing cluster.\")"}],"source_content_type":"text/x-python","patch_set":17,"id":"71d73f4f_88d075b7","line":140,"updated":"2026-05-26 04:07:18.000000000","message":"ditto","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"f4a09fe468c7c2ee1472395dc10560ef4a7de5a5","unresolved":false,"context_lines":[{"line_number":137,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":138,"context_line":"        try:"},{"line_number":139,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":140,"context_line":"                _grow_cluster, timeout))"},{"line_number":141,"context_line":"            self.reset_task()"},{"line_number":142,"context_line":"        except exception.TimeoutError:"},{"line_number":143,"context_line":"            LOG.exception(\"Timeout for growing cluster.\")"}],"source_content_type":"text/x-python","patch_set":17,"id":"c575b0ca_053920df","line":140,"in_reply_to":"71d73f4f_88d075b7","updated":"2026-08-21 15:59:05.000000000","message":"Please see the comment in the `cluster_utils.async_run_with_timeout` function.","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"}],"trove/common/strategies/cluster/experimental/vertica/taskmanager.py":[{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"046a93e7e64d04c2dae94683507b776b75c7db00","unresolved":true,"context_lines":[{"line_number":156,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"        try:"},{"line_number":159,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":160,"context_line":"                _grow_cluster, timeout))"},{"line_number":161,"context_line":"            self.reset_task()"},{"line_number":162,"context_line":"        except exception.TimeoutError:"}],"source_content_type":"text/x-python","patch_set":17,"id":"3cf8d363_85df9c2e","line":159,"updated":"2026-05-26 04:07:18.000000000","message":"ditto","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"f4a09fe468c7c2ee1472395dc10560ef4a7de5a5","unresolved":false,"context_lines":[{"line_number":156,"context_line":"        timeout \u003d CONF.cluster_usage_timeout"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"        try:"},{"line_number":159,"context_line":"            asyncio.run(cluster_utils.async_run_with_timeout("},{"line_number":160,"context_line":"                _grow_cluster, timeout))"},{"line_number":161,"context_line":"            self.reset_task()"},{"line_number":162,"context_line":"        except exception.TimeoutError:"}],"source_content_type":"text/x-python","patch_set":17,"id":"a1623d59_6b7239a2","line":159,"in_reply_to":"3cf8d363_85df9c2e","updated":"2026-08-21 15:59:05.000000000","message":"Please see the comment in the `cluster_utils.async_run_with_timeout` function.","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"}],"trove/common/strategies/cluster/utils.py":[{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"046a93e7e64d04c2dae94683507b776b75c7db00","unresolved":true,"context_lines":[{"line_number":22,"context_line":"    # make a thread to execute the task"},{"line_number":23,"context_line":"    coro \u003d asyncio.to_thread(func)"},{"line_number":24,"context_line":"    try:"},{"line_number":25,"context_line":"        await asyncio.wait_for(coro, timeout)"},{"line_number":26,"context_line":"    except asyncio.TimeoutError:"},{"line_number":27,"context_line":"        exc_fmt \u003d _(\"time out after waiting \""},{"line_number":28,"context_line":"                    \"%(time)s seconds when running %(func)s.\")"}],"source_content_type":"text/x-python","patch_set":17,"id":"e1a975d4_86387225","line":25,"updated":"2026-05-26 04:07:18.000000000","message":"maybe we can add timeout control in this function.","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"f4a09fe468c7c2ee1472395dc10560ef4a7de5a5","unresolved":false,"context_lines":[{"line_number":22,"context_line":"    # make a thread to execute the task"},{"line_number":23,"context_line":"    coro \u003d asyncio.to_thread(func)"},{"line_number":24,"context_line":"    try:"},{"line_number":25,"context_line":"        await asyncio.wait_for(coro, timeout)"},{"line_number":26,"context_line":"    except asyncio.TimeoutError:"},{"line_number":27,"context_line":"        exc_fmt \u003d _(\"time out after waiting \""},{"line_number":28,"context_line":"                    \"%(time)s seconds when running %(func)s.\")"}],"source_content_type":"text/x-python","patch_set":17,"id":"b4b7d9df_cb0ca7c4","line":25,"in_reply_to":"833d4244_182a204d","updated":"2026-08-21 15:59:05.000000000","message":"I decided to add the timeout control here. I used ProcessPoolExecutor so that we can forcefully terminate the process on timeout and prevent resource leaks.","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"0ba6a77cad99dd3b22ddadaadc5348ed541553b2","unresolved":true,"context_lines":[{"line_number":22,"context_line":"    # make a thread to execute the task"},{"line_number":23,"context_line":"    coro \u003d asyncio.to_thread(func)"},{"line_number":24,"context_line":"    try:"},{"line_number":25,"context_line":"        await asyncio.wait_for(coro, timeout)"},{"line_number":26,"context_line":"    except asyncio.TimeoutError:"},{"line_number":27,"context_line":"        exc_fmt \u003d _(\"time out after waiting \""},{"line_number":28,"context_line":"                    \"%(time)s seconds when running %(func)s.\")"}],"source_content_type":"text/x-python","patch_set":17,"id":"833d4244_182a204d","line":25,"in_reply_to":"e1a975d4_86387225","updated":"2026-05-26 04:09:21.000000000","message":"or we just remove this top-level timeout control","commit_id":"30cca5bceaac5fd59a34eb5edbe8780300a0513d"},{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"78efe92e720b4be957c1755ae573a0a17c367a01","unresolved":true,"context_lines":[{"line_number":31,"context_line":"            for pid, process in pool._processes.items():"},{"line_number":32,"context_line":"                process.terminate()"},{"line_number":33,"context_line":"            pool.shutdown(wait\u003dFalse, cancel_futures\u003dTrue)"},{"line_number":34,"context_line":"            exc_fmt \u003d _(\"time out after waiting \""},{"line_number":35,"context_line":"                        \"%(time)s seconds when running %(func)s.\")"},{"line_number":36,"context_line":"            msg_content \u003d {\u0027time\u0027: timeout, \u0027func\u0027: func.__name__}"},{"line_number":37,"context_line":"            raise exception.TimeoutError(exc_fmt % msg_content)"}],"source_content_type":"text/x-python","patch_set":28,"id":"c7e5418b_214e5a04","line":34,"range":{"start_line":34,"start_character":22,"end_line":34,"end_character":24},"updated":"2026-09-06 07:16:43.000000000","message":"It is not imported.","commit_id":"567e6c9791ae574857bc9f17a0fc3a54d9b988ad"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"fc78cc0fe7784539dd7006b829d84b6f86e4d9f0","unresolved":false,"context_lines":[{"line_number":31,"context_line":"            for pid, process in pool._processes.items():"},{"line_number":32,"context_line":"                process.terminate()"},{"line_number":33,"context_line":"            pool.shutdown(wait\u003dFalse, cancel_futures\u003dTrue)"},{"line_number":34,"context_line":"            exc_fmt \u003d _(\"time out after waiting \""},{"line_number":35,"context_line":"                        \"%(time)s seconds when running %(func)s.\")"},{"line_number":36,"context_line":"            msg_content \u003d {\u0027time\u0027: timeout, \u0027func\u0027: func.__name__}"},{"line_number":37,"context_line":"            raise exception.TimeoutError(exc_fmt % msg_content)"}],"source_content_type":"text/x-python","patch_set":28,"id":"8c26c099_4c4940d5","line":34,"range":{"start_line":34,"start_character":22,"end_line":34,"end_character":24},"in_reply_to":"c7e5418b_214e5a04","updated":"2026-09-20 20:31:07.000000000","message":"Fixed to add the import.","commit_id":"567e6c9791ae574857bc9f17a0fc3a54d9b988ad"},{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"78efe92e720b4be957c1755ae573a0a17c367a01","unresolved":true,"context_lines":[{"line_number":19,"context_line":"from trove.common import exception"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"async def async_run_with_timeout(func, timeout):"},{"line_number":23,"context_line":"    # make a process to execute the task"},{"line_number":24,"context_line":"    loop \u003d asyncio.get_running_loop()"},{"line_number":25,"context_line":"    with ProcessPoolExecutor(max_workers\u003d1) as pool:"},{"line_number":26,"context_line":"        try:"},{"line_number":27,"context_line":"            coro \u003d loop.run_in_executor(pool, func)"},{"line_number":28,"context_line":"            await asyncio.wait_for(coro, timeout\u003dtimeout)"},{"line_number":29,"context_line":"        except asyncio.TimeoutError:"},{"line_number":30,"context_line":"            # stop the process on timeout to prevent from leaking resources."},{"line_number":31,"context_line":"            for pid, process in pool._processes.items():"},{"line_number":32,"context_line":"                process.terminate()"},{"line_number":33,"context_line":"            pool.shutdown(wait\u003dFalse, cancel_futures\u003dTrue)"},{"line_number":34,"context_line":"            exc_fmt \u003d _(\"time out after waiting \""},{"line_number":35,"context_line":"                        \"%(time)s seconds when running %(func)s.\")"},{"line_number":36,"context_line":"            msg_content \u003d {\u0027time\u0027: timeout, \u0027func\u0027: func.__name__}"},{"line_number":37,"context_line":"            raise exception.TimeoutError(exc_fmt % msg_content)"}],"source_content_type":"text/x-python","patch_set":28,"id":"2e5182c6_c30dae16","line":37,"range":{"start_line":22,"start_character":0,"end_line":37,"end_character":63},"updated":"2026-09-06 07:16:43.000000000","message":"I tested it with the following code:\n\n```\nif __name__ \u003d\u003d \"__main__\":\n    async def test():\n        await async_run_with_timeout(lambda: time.sleep(10), 1)\n    asyncio.run(test())\n```\nIt looks like this function is not tested. \n\n```\npython trove/common/strategies/cluster/utils.py\nconcurrent.futures.process._RemoteTraceback: \n\"\"\"\nTraceback (most recent call last):\n  File \"/opt/miniconda3/envs/openstack-env/lib/python3.11/multiprocessing/queues.py\", line 244, in _feed\n    obj \u003d _ForkingPickler.dumps(obj)\n          ^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/opt/miniconda3/envs/openstack-env/lib/python3.11/multiprocessing/reduction.py\", line 51, in dumps\n    cls(buf, protocol).dump(obj)\nAttributeError: Can\u0027t pickle local object \u0027test.\u003clocals\u003e.\u003clambda\u003e\u0027\n\"\"\"\n\nThe above exception was the direct cause of the following exception:\n\nTraceback (most recent call last):\n  File \"/Users/wuchunyang/codes/trove/trove/common/strategies/cluster/utils.py\", line 43, in \u003cmodule\u003e\n    asyncio.run(test())\n  File \"/opt/miniconda3/envs/openstack-env/lib/python3.11/asyncio/runners.py\", line 190, in run\n    return runner.run(main)\n           ^^^^^^^^^^^^^^^^\n  File \"/opt/miniconda3/envs/openstack-env/lib/python3.11/asyncio/runners.py\", line 118, in run\n    return self._loop.run_until_complete(task)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/opt/miniconda3/envs/openstack-env/lib/python3.11/asyncio/base_events.py\", line 654, in run_until_complete\n    return future.result()\n           ^^^^^^^^^^^^^^^\n  File \"/Users/wuchunyang/codes/trove/trove/common/strategies/cluster/utils.py\", line 42, in test\n    await async_run_with_timeout(lambda: time.sleep(10), 1)\n  File \"/Users/wuchunyang/codes/trove/trove/common/strategies/cluster/utils.py\", line 28, in async_run_with_timeout\n    await asyncio.wait_for(coro, timeout\u003dtimeout)\n  File \"/opt/miniconda3/envs/openstack-env/lib/python3.11/asyncio/tasks.py\", line 489, in wait_for\n    return fut.result()\n           ^^^^^^^^^^^^\n  File \"/opt/miniconda3/envs/openstack-env/lib/python3.11/multiprocessing/queues.py\", line 244, in _feed\n    obj \u003d _ForkingPickler.dumps(obj)\n          ^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/opt/miniconda3/envs/openstack-env/lib/python3.11/multiprocessing/reduction.py\", line 51, in dumps\n    cls(buf, protocol).dump(obj)\nAttributeError: Can\u0027t pickle local object \u0027test.\u003clocals\u003e.\u003clambda\u003e\u0027\n```","commit_id":"567e6c9791ae574857bc9f17a0fc3a54d9b988ad"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"fc78cc0fe7784539dd7006b829d84b6f86e4d9f0","unresolved":false,"context_lines":[{"line_number":19,"context_line":"from trove.common import exception"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"async def async_run_with_timeout(func, timeout):"},{"line_number":23,"context_line":"    # make a process to execute the task"},{"line_number":24,"context_line":"    loop \u003d asyncio.get_running_loop()"},{"line_number":25,"context_line":"    with ProcessPoolExecutor(max_workers\u003d1) as pool:"},{"line_number":26,"context_line":"        try:"},{"line_number":27,"context_line":"            coro \u003d loop.run_in_executor(pool, func)"},{"line_number":28,"context_line":"            await asyncio.wait_for(coro, timeout\u003dtimeout)"},{"line_number":29,"context_line":"        except asyncio.TimeoutError:"},{"line_number":30,"context_line":"            # stop the process on timeout to prevent from leaking resources."},{"line_number":31,"context_line":"            for pid, process in pool._processes.items():"},{"line_number":32,"context_line":"                process.terminate()"},{"line_number":33,"context_line":"            pool.shutdown(wait\u003dFalse, cancel_futures\u003dTrue)"},{"line_number":34,"context_line":"            exc_fmt \u003d _(\"time out after waiting \""},{"line_number":35,"context_line":"                        \"%(time)s seconds when running %(func)s.\")"},{"line_number":36,"context_line":"            msg_content \u003d {\u0027time\u0027: timeout, \u0027func\u0027: func.__name__}"},{"line_number":37,"context_line":"            raise exception.TimeoutError(exc_fmt % msg_content)"}],"source_content_type":"text/x-python","patch_set":28,"id":"94d23125_04cb95a4","line":37,"range":{"start_line":22,"start_character":0,"end_line":37,"end_character":63},"in_reply_to":"2e5182c6_c30dae16","updated":"2026-09-20 20:31:07.000000000","message":"Since this feature is experimental, there might be errors in some corner cases. Could we prioritize the eventlet migration first and address this in a follow-up patch after the migration?\n\nI have confirmed that basic operations such as starting and stopping work without any issues.\n```\nstack@devstack:~/trove$ sudo systemctl stop devstack@tr-api\nstack@devstack:~/trove$ sudo systemctl status devstack@tr-api\n○ devstack@tr-api.service - Devstack devstack@tr-api.service\n     Loaded: loaded (/etc/systemd/system/devstack@tr-api.service; enabled; preset: enabled)\n     Active: inactive (dead) since Sun 2026-09-20 16:01:15 UTC; 23s ago\n   Duration: 1h 43min 22.367s\n    Process: 131889 ExecStart\u003d/opt/stack/data/venv/bin/trove-api --config-file /etc/trove/trove.conf (code\u003dexited, status\u003d0/SUCCESS)\n   Main PID: 131889 (code\u003dexited, status\u003d0/SUCCESS)\n        CPU: 3.152s\n\nSep 20 15:56:41 devstack trove-api[131889]: 127.0.0.1 - - [20/Sep/2026 15:56:41] \"GET /v1.0/6be2cf13a1244f03a4bea8cb21aaa4be/instances?include_clustered\u003dFalse HTTP/1.1\" 200 891\nSep 20 15:56:51 devstack trove-api[131889]: 2026-09-20 15:56:51.964 131889 DEBUG dbcounter [-] [131889] Writing DB stats trove:SELECT\u003d8 stat_writer /opt/stack/data/venv/lib/python3.12/site-pa\u003e\nSep 20 16:01:15 devstack systemd[1]: Stopping devstack@tr-api.service - Devstack devstack@tr-api.service...\nSep 20 16:01:15 devstack trove-api[131889]: 2026-09-20 16:01:15.246 131889 INFO trove.common.wsgi [-] wsgi.TroveLauncher.wait.handler\nSep 20 16:01:15 devstack trove-api[131889]: 2026-09-20 16:01:15.246 131889 INFO trove.common.wsgi [-] wsgi.TroveLauncher.stop\nSep 20 16:01:15 devstack trove-api[131889]: 2026-09-20 16:01:15.246 131889 INFO trove.common.base_wsgi [-] base_wsgi.Service.stop\nSep 20 16:01:15 devstack trove-api[131889]: 2026-09-20 16:01:15.246 131889 INFO trove.common.wsgi [-] wsgi.TroveLauncher.stop exit\nSep 20 16:01:15 devstack systemd[1]: devstack@tr-api.service: Deactivated successfully.\nSep 20 16:01:15 devstack systemd[1]: Stopped devstack@tr-api.service - Devstack devstack@tr-api.service.\nSep 20 16:01:15 devstack systemd[1]: devstack@tr-api.service: Consumed 3.152s CPU time.\n```\n\n```\nstack@devstack:~/trove$ sudo systemctl start devstack@tr-api                                                                                                                                                                                                     \nstack@devstack:~/trove$ sudo systemctl status devstack@tr-api                                                                                                                                                                                                    \n● devstack@tr-api.service - Devstack devstack@tr-api.service                                                                    \n     Loaded: loaded (/etc/systemd/system/devstack@tr-api.service; enabled; preset: enabled)                                     \n     Active: active (running) since Sun 2026-09-20 16:01:55 UTC; 31s ago                                                        \n   Main PID: 154007 (trove-api)                                 \n      Tasks: 3 (limit: 19094)                                   \n     Memory: 110.4M (peak: 110.9M)                              \n        CPU: 1.690s                                             \n     CGroup: /system.slice/system-devstack.slice/devstack@tr-api.service                                                        \n             └─154007 /opt/stack/data/venv/bin/python3.12 /opt/stack/data/venv/bin/trove-api --config-file /etc/trove/trove.conf                                                                                                                                 \n\nSep 20 16:01:57 devstack trove-api[154007]: 2026-09-20 16:01:57.217 154007 DEBUG trove.common.extensions [-] Extended resource: {tenant_id}/mgmt/datastore-versions __init__ /opt/stack/trove/trove/common/extensions.py:524                                     \nSep 20 16:01:57 devstack trove-api[154007]: 2026-09-20 16:01:57.218 154007 DEBUG trove.common.extensions [-] Extended resource: databases __init__ /opt/stack/trove/trove/common/extensions.py:524                                                               \nSep 20 16:01:57 devstack trove-api[154007]: 2026-09-20 16:01:57.218 154007 DEBUG trove.common.extensions [-] Extended resource: users __init__ /opt/stack/trove/trove/common/extensions.py:524                                                                   \nSep 20 16:01:57 devstack trove-api[154007]: 2026-09-20 16:01:57.219 154007 DEBUG trove.common.extensions [-] Extended resource: databases __init__ /opt/stack/trove/trove/common/extensions.py:524                                                               \nSep 20 16:01:57 devstack trove-api[154007]: 2026-09-20 16:01:57.220 154007 DEBUG trove.common.extensions [-] Extended resource: root __init__ /opt/stack/trove/trove/common/extensions.py:524                                                                    \nSep 20 16:01:57 devstack trove-api[154007]: 2026-09-20 16:01:57.221 154007 DEBUG trove.common.extensions [-] Extended resource: root __init__ /opt/stack/trove/trove/common/extensions.py:524                                                                    \nSep 20 16:01:57 devstack trove-api[154007]: 2026-09-20 16:01:57.222 154007 DEBUG trove.common.wsgi [-] Created context middleware with config: {} _factory /opt/stack/trove/trove/common/wsgi.py:576                                                             \nSep 20 16:01:57 devstack trove-api[154007]: 2026-09-20 16:01:57.222 154007 DEBUG trove.common.auth [-] Created auth middleware with config: {} _factory /opt/stack/trove/trove/common/auth.py:49                                                                 \nSep 20 16:01:57 devstack trove-api[154007]: 2026-09-20 16:01:57.222 154007 DEBUG trove.common.auth [-] Auth middleware providers: [\u003ctrove.common.auth.TenantBasedAuth object at 0x732b81403ec0\u003e] __init__ /opt/stack/trove/trove/com\u003e                            \nSep 20 16:02:07 devstack trove-api[154007]: 2026-09-20 16:02:07.097 154007 DEBUG dbcounter [-] [154007] Writing DB stats trove:SHOW\u003d26 stat_writer /opt/stack/data/venv/lib/python3.12/site-packages/dbcounter.py:115\n```","commit_id":"567e6c9791ae574857bc9f17a0fc3a54d9b988ad"}],"trove/common/wsgi.py":[{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"78efe92e720b4be957c1755ae573a0a17c367a01","unresolved":true,"context_lines":[{"line_number":83,"context_line":"    server \u003d base_wsgi.Service(app, port, host\u003dhost,"},{"line_number":84,"context_line":"                               server\u003d\u0027wsgiref\u0027)"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"    if workers is not None and not isinstance(workers, int):"},{"line_number":87,"context_line":"        raise TypeError(_(\"Type of workers should be int!\"))"},{"line_number":88,"context_line":"    if workers is not None and workers \u003c\u003d 0:"},{"line_number":89,"context_line":"        raise ValueError(_(\"Number of workers should be positive!\"))"},{"line_number":90,"context_line":""},{"line_number":91,"context_line":"    launcher \u003d TroveLauncher(CONF, restart_method\u003d\u0027mutate\u0027)"},{"line_number":92,"context_line":"    launcher.launch_service(server, workers\u003d1)"},{"line_number":93,"context_line":"    launcher.wait()"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"# Note: taken from Nova"},{"line_number":97,"context_line":"def serializers(**serializers):"}],"source_content_type":"text/x-python","patch_set":28,"id":"b01c2afa_0e5b11fc","line":94,"range":{"start_line":86,"start_character":0,"end_line":94,"end_character":0},"updated":"2026-09-06 07:16:43.000000000","message":"I\u0027d prefer to remove the whole TroveLauncher implementation. Deployment tools such as kolla-ansible, openstack-ansible and devstack use uwsgi to run the app directly, so it\u0027s not worth maintaining such a launcher.\n\nWe can use `server.serve_forever` from the current codebase for development scenarios only.\n\nWe should do this same as [Octavia project](https://github.com/openstack/octavia/blob/master/octavia/cmd/api.py#L49)","commit_id":"567e6c9791ae574857bc9f17a0fc3a54d9b988ad"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"fc78cc0fe7784539dd7006b829d84b6f86e4d9f0","unresolved":false,"context_lines":[{"line_number":83,"context_line":"    server \u003d base_wsgi.Service(app, port, host\u003dhost,"},{"line_number":84,"context_line":"                               server\u003d\u0027wsgiref\u0027)"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"    if workers is not None and not isinstance(workers, int):"},{"line_number":87,"context_line":"        raise TypeError(_(\"Type of workers should be int!\"))"},{"line_number":88,"context_line":"    if workers is not None and workers \u003c\u003d 0:"},{"line_number":89,"context_line":"        raise ValueError(_(\"Number of workers should be positive!\"))"},{"line_number":90,"context_line":""},{"line_number":91,"context_line":"    launcher \u003d TroveLauncher(CONF, restart_method\u003d\u0027mutate\u0027)"},{"line_number":92,"context_line":"    launcher.launch_service(server, workers\u003d1)"},{"line_number":93,"context_line":"    launcher.wait()"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"# Note: taken from Nova"},{"line_number":97,"context_line":"def serializers(**serializers):"}],"source_content_type":"text/x-python","patch_set":28,"id":"fca70e16_29aae480","line":94,"range":{"start_line":86,"start_character":0,"end_line":94,"end_character":0},"in_reply_to":"b01c2afa_0e5b11fc","updated":"2026-09-20 20:31:07.000000000","message":"I understand that major deployment tools use uwsgi. However, TroveLauncher was added as an optional fallback to maintain backward compatibility for users running the API without uwsgi (uwsgi remains the default).\nSince it works as an option, I don\u0027t think it is strictly necessary to remove it. That said, if we do decide to drop support for non-uwsgi deployments, I think we should follow the standard OpenStack deprecation process [1] rather than dropping it as part of this migration effort.\n--\n[1] https://docs.openstack.org/project-team-guide/deprecation.html","commit_id":"567e6c9791ae574857bc9f17a0fc3a54d9b988ad"},{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"78efe92e720b4be957c1755ae573a0a17c367a01","unresolved":true,"context_lines":[{"line_number":759,"context_line":"        if self.restart_method \u003d\u003d \u0027reload\u0027:"},{"line_number":760,"context_line":"            self.stop()"},{"line_number":761,"context_line":"            self.done \u003d threading.Event()"},{"line_number":762,"context_line":"        for restart_service in self.services:"},{"line_number":763,"context_line":"            restart_service.reset()"},{"line_number":764,"context_line":"            if self.restart_method \u003d\u003d \u0027reload\u0027:"},{"line_number":765,"context_line":"                self.tg.add_thread(self.run_service,"}],"source_content_type":"text/x-python","patch_set":28,"id":"44aab277_e82702b9","line":762,"range":{"start_line":762,"start_character":31,"end_line":762,"end_character":45},"updated":"2026-09-06 07:16:43.000000000","message":"self.services is not defined?","commit_id":"567e6c9791ae574857bc9f17a0fc3a54d9b988ad"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"fc78cc0fe7784539dd7006b829d84b6f86e4d9f0","unresolved":false,"context_lines":[{"line_number":759,"context_line":"        if self.restart_method \u003d\u003d \u0027reload\u0027:"},{"line_number":760,"context_line":"            self.stop()"},{"line_number":761,"context_line":"            self.done \u003d threading.Event()"},{"line_number":762,"context_line":"        for restart_service in self.services:"},{"line_number":763,"context_line":"            restart_service.reset()"},{"line_number":764,"context_line":"            if self.restart_method \u003d\u003d \u0027reload\u0027:"},{"line_number":765,"context_line":"                self.tg.add_thread(self.run_service,"}],"source_content_type":"text/x-python","patch_set":28,"id":"40e6d6b4_0331a9bd","line":762,"range":{"start_line":762,"start_character":31,"end_line":762,"end_character":45},"in_reply_to":"44aab277_e82702b9","updated":"2026-09-20 20:31:07.000000000","message":"Fixed.","commit_id":"567e6c9791ae574857bc9f17a0fc3a54d9b988ad"}],"trove/rpc.py":[{"author":{"_account_id":26285,"name":"wu.chunyang","email":"wchy1001@gmail.com","username":"wu.chunyang"},"change_message_id":"78efe92e720b4be957c1755ae573a0a17c367a01","unresolved":true,"context_lines":[{"line_number":112,"context_line":"               secure_serializer\u003dssz.SecureSerializer):"},{"line_number":113,"context_line":"    assert TRANSPORT is not None"},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"    # Thread module is not monkeypatched if remote debugging is enabled."},{"line_number":116,"context_line":"    # Using eventlet executor without monkepatching thread module will"},{"line_number":117,"context_line":"    # lead to unpredictable results."},{"line_number":118,"context_line":"    from trove.common import debug_utils"},{"line_number":119,"context_line":"    debug_utils.setup()"},{"line_number":120,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"63dbb0db_096aa5d2","line":117,"range":{"start_line":115,"start_character":0,"end_line":117,"end_character":36},"updated":"2026-09-06 07:16:43.000000000","message":"remove this comment","commit_id":"567e6c9791ae574857bc9f17a0fc3a54d9b988ad"},{"author":{"_account_id":31737,"name":"Hirotaka Wakabayashi","email":"hiwkby@yahoo.com","username":"hiwkby"},"change_message_id":"fc78cc0fe7784539dd7006b829d84b6f86e4d9f0","unresolved":false,"context_lines":[{"line_number":112,"context_line":"               secure_serializer\u003dssz.SecureSerializer):"},{"line_number":113,"context_line":"    assert TRANSPORT is not None"},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"    # Thread module is not monkeypatched if remote debugging is enabled."},{"line_number":116,"context_line":"    # Using eventlet executor without monkepatching thread module will"},{"line_number":117,"context_line":"    # lead to unpredictable results."},{"line_number":118,"context_line":"    from trove.common import debug_utils"},{"line_number":119,"context_line":"    debug_utils.setup()"},{"line_number":120,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"7a883ede_61512d7e","line":117,"range":{"start_line":115,"start_character":0,"end_line":117,"end_character":36},"in_reply_to":"63dbb0db_096aa5d2","updated":"2026-09-20 20:31:07.000000000","message":"Fixed.","commit_id":"567e6c9791ae574857bc9f17a0fc3a54d9b988ad"}]}
