)]}'
{"/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"}],"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"}],"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"}],"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":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"}],"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"}],"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"}],"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"}],"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"}],"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":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"}]}
