)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":11655,"name":"Julia Kreger","email":"juliaashleykreger@gmail.com","username":"jkreger","status":"Flying to the moon with a Jetpack!"},"change_message_id":"a418bcfd9620a9dae9fa67e11acc5699dad1515b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"f4e072a1_b08a48ef","updated":"2025-07-17 17:54:30.000000000","message":"First things first, we\u0027ll need to add an entry in __init__.py. 😊","commit_id":"610c94de13da41cbe515b3c79136d2e50744fb66"},{"author":{"_account_id":11655,"name":"Julia Kreger","email":"juliaashleykreger@gmail.com","username":"jkreger","status":"Flying to the moon with a Jetpack!"},"change_message_id":"ec9e2e6a5e7e50937c2f7e2c899600fb37143019","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"b188f02c_91783345","updated":"2025-07-17 18:00:22.000000000","message":"Furthermore, definitely doesn\u0027t work. :(\n\nPerodics fail to work and trigger with this code path.\n\nFailed to submit periodic callback \u0027ironic.drivers.modules.redfish.firmware.RedfishFirmware._query_update_status\u0027, retrying after 0.96 sec. Error: Current backlog 1 is not allowed to go beyond 1: futurist._futures.RejectedSubmission: Current backlog 1 is not allowed to go beyond 1","commit_id":"610c94de13da41cbe515b3c79136d2e50744fb66"},{"author":{"_account_id":11655,"name":"Julia Kreger","email":"juliaashleykreger@gmail.com","username":"jkreger","status":"Flying to the moon with a Jetpack!"},"change_message_id":"94a1a15b2c6dcae9b49b481a378acc0795db47fb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"9b60f843_bacc6607","updated":"2025-07-21 17:30:32.000000000","message":"I have this running locally with an ironic deployment and and have been repeatedly testing this as it has been developed. Overall, Looks good to me and fits the needful. If we need to further optimize, it can be done as part of a separate patch.","commit_id":"610c94de13da41cbe515b3c79136d2e50744fb66"},{"author":{"_account_id":28522,"name":"Hervé Beraud","email":"herveberaud.pro@gmail.com","username":"hberaud"},"change_message_id":"6b7204b725b66cfad5cb4236f71d529bb2b9d4f7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"27efa3f6_a92c7428","updated":"2025-07-16 18:56:53.000000000","message":"Would be good to attach this patch to the eventlet removal topic. That would help other maintainers to be aware of that.","commit_id":"610c94de13da41cbe515b3c79136d2e50744fb66"},{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"3a3c277fd63a335d2634d14957b6fa7981937043","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"981ce2d0_2097d948","in_reply_to":"a424cd8a_7a1b553d","updated":"2025-07-18 11:27:57.000000000","message":"Yeah, rejection is weird in futurist.\n\nMy intention with rejecting after 1 was specifically to prevent tasks from getting queued because it makes little sense with green threads. It does, however, makes sense with normal threads to queue tasks. So we might be good.","commit_id":"610c94de13da41cbe515b3c79136d2e50744fb66"},{"author":{"_account_id":11655,"name":"Julia Kreger","email":"juliaashleykreger@gmail.com","username":"jkreger","status":"Flying to the moon with a Jetpack!"},"change_message_id":"3d47e4d9f78ee9f52cb832acd7558f8412c32134","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"a424cd8a_7a1b553d","in_reply_to":"b188f02c_91783345","updated":"2025-07-17 18:55:50.000000000","message":"Okay, this is the rejection, I had to flip it around in the code calling so instead of reject if there is one, reject at a maximum of 275 in ironic\u0027s case.\n\nOtherwise, seems to actually work then!","commit_id":"610c94de13da41cbe515b3c79136d2e50744fb66"},{"author":{"_account_id":28522,"name":"Hervé Beraud","email":"herveberaud.pro@gmail.com","username":"hberaud"},"change_message_id":"0a341337321428dc2efe003454b3462fbb062307","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"3e287808_16d7775a","updated":"2025-07-22 09:29:14.000000000","message":"Nice works, thank you Dmitry. I just have one suggestion concerning the release note","commit_id":"d387a2459ece939299c7aef43c34b6ca7ec6ce69"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"1bb03cf0f360333a210c4c4cda55e5286d25c148","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"34c22619_d1f7720c","updated":"2025-07-22 11:33:55.000000000","message":"It might be good to decouple the change the exports the properties of the existing pool from the new pool type. I would use the former without the latter.\n\nI only reviewed the new properties but had not type to dig into the new DynamicPool impl.","commit_id":"6cd2979da177a90aa0a27d2423b496b4810dcd92"},{"author":{"_account_id":28522,"name":"Hervé Beraud","email":"herveberaud.pro@gmail.com","username":"hberaud"},"change_message_id":"619818b042ef8dd29fec29c1a50ae9a20cf3d2f0","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"01ab3354_5b5b451e","updated":"2025-07-22 10:04:11.000000000","message":"Perfect, thanks","commit_id":"6cd2979da177a90aa0a27d2423b496b4810dcd92"},{"author":{"_account_id":11655,"name":"Julia Kreger","email":"juliaashleykreger@gmail.com","username":"jkreger","status":"Flying to the moon with a Jetpack!"},"change_message_id":"31a5d85d84a4cbc28d5f8242168c8c69c5113f01","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"5f29ddcf_8da51fc6","updated":"2025-07-31 13:25:46.000000000","message":"I tested this with Ironic yesterday, and it is still good.","commit_id":"679355a3351b73bc60c1cea55e708d68f6b1f2d7"},{"author":{"_account_id":28522,"name":"Hervé Beraud","email":"herveberaud.pro@gmail.com","username":"hberaud"},"change_message_id":"39fec9fd537a767dace9ab2f8be68fd1eb753d85","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"5915bc12_a69e74a3","in_reply_to":"5f29ddcf_8da51fc6","updated":"2025-07-31 13:58:46.000000000","message":"Perfect, thanks for the heads up","commit_id":"679355a3351b73bc60c1cea55e708d68f6b1f2d7"}],"futurist/_futures.py":[{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"1bb03cf0f360333a210c4c4cda55e5286d25c148","unresolved":true,"context_lines":[{"line_number":165,"context_line":"        \"\"\""},{"line_number":166,"context_line":"        return self._work_queue.qsize()"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"    @property"},{"line_number":169,"context_line":"    def current_size(self):"},{"line_number":170,"context_line":"        \"\"\"The current number of worker threads.\"\"\""},{"line_number":171,"context_line":"        return len(self._workers)"},{"line_number":172,"context_line":""},{"line_number":173,"context_line":"    @property"},{"line_number":174,"context_line":"    def idle_threads(self):"},{"line_number":175,"context_line":"        \"\"\"The number of currently idle threads."},{"line_number":176,"context_line":""},{"line_number":177,"context_line":"        A thread is idle if it\u0027s waiting for new tasks from the queue."},{"line_number":178,"context_line":"        \"\"\""},{"line_number":179,"context_line":"        return sum(1 for w in self._workers if w.idle)"},{"line_number":180,"context_line":""},{"line_number":181,"context_line":"    def _add_thread(self):"},{"line_number":182,"context_line":"        w \u003d _thread.ThreadWorker.create_and_register("}],"source_content_type":"text/x-python","patch_set":6,"id":"7d3f7fb6_d30f7005","line":179,"range":{"start_line":168,"start_character":0,"end_line":179,"end_character":54},"updated":"2025-07-22 11:33:55.000000000","message":"are these thread safe without a lock? As they are only reading data it cannot directly break the pool itself, but we need to figure out if these can return inconsistent data (and that can cause problem e.g. in the DynamicPool) if the Pool is changing while we are collecting these property values.","commit_id":"6cd2979da177a90aa0a27d2423b496b4810dcd92"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"85ed2d2913351412a28423c158c8ccffb09f0951","unresolved":false,"context_lines":[{"line_number":165,"context_line":"        \"\"\""},{"line_number":166,"context_line":"        return self._work_queue.qsize()"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"    @property"},{"line_number":169,"context_line":"    def current_size(self):"},{"line_number":170,"context_line":"        \"\"\"The current number of worker threads.\"\"\""},{"line_number":171,"context_line":"        return len(self._workers)"},{"line_number":172,"context_line":""},{"line_number":173,"context_line":"    @property"},{"line_number":174,"context_line":"    def idle_threads(self):"},{"line_number":175,"context_line":"        \"\"\"The number of currently idle threads."},{"line_number":176,"context_line":""},{"line_number":177,"context_line":"        A thread is idle if it\u0027s waiting for new tasks from the queue."},{"line_number":178,"context_line":"        \"\"\""},{"line_number":179,"context_line":"        return sum(1 for w in self._workers if w.idle)"},{"line_number":180,"context_line":""},{"line_number":181,"context_line":"    def _add_thread(self):"},{"line_number":182,"context_line":"        w \u003d _thread.ThreadWorker.create_and_register("}],"source_content_type":"text/x-python","patch_set":6,"id":"fd9352e5_b90e8370","line":179,"range":{"start_line":168,"start_character":0,"end_line":179,"end_character":54},"in_reply_to":"0888d565_79e549ff","updated":"2025-07-22 12:42:02.000000000","message":"Acknowledged","commit_id":"6cd2979da177a90aa0a27d2423b496b4810dcd92"},{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"da5c0425c0db06fe6e3f40c22b41a4958165224f","unresolved":true,"context_lines":[{"line_number":165,"context_line":"        \"\"\""},{"line_number":166,"context_line":"        return self._work_queue.qsize()"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"    @property"},{"line_number":169,"context_line":"    def current_size(self):"},{"line_number":170,"context_line":"        \"\"\"The current number of worker threads.\"\"\""},{"line_number":171,"context_line":"        return len(self._workers)"},{"line_number":172,"context_line":""},{"line_number":173,"context_line":"    @property"},{"line_number":174,"context_line":"    def idle_threads(self):"},{"line_number":175,"context_line":"        \"\"\"The number of currently idle threads."},{"line_number":176,"context_line":""},{"line_number":177,"context_line":"        A thread is idle if it\u0027s waiting for new tasks from the queue."},{"line_number":178,"context_line":"        \"\"\""},{"line_number":179,"context_line":"        return sum(1 for w in self._workers if w.idle)"},{"line_number":180,"context_line":""},{"line_number":181,"context_line":"    def _add_thread(self):"},{"line_number":182,"context_line":"        w \u003d _thread.ThreadWorker.create_and_register("}],"source_content_type":"text/x-python","patch_set":6,"id":"0888d565_79e549ff","line":179,"range":{"start_line":168,"start_character":0,"end_line":179,"end_character":54},"in_reply_to":"7d3f7fb6_d30f7005","updated":"2025-07-22 11:36:32.000000000","message":"DynamicPool works under the lock.\n\nIt probably makes sense to copy self._workers before iterating over it to make sure it does not change the size under the iterator.","commit_id":"6cd2979da177a90aa0a27d2423b496b4810dcd92"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"f80d442c599d1e9e121231ddb90a984e528cf698","unresolved":false,"context_lines":[{"line_number":291,"context_line":"        super().__init__(max_workers\u003dmax_workers,"},{"line_number":292,"context_line":"                         check_and_reject\u003dcheck_and_reject)"},{"line_number":293,"context_line":"        if min_workers \u003c\u003d 0:"},{"line_number":294,"context_line":"            raise ValueError(\u0027min_workers must be positive\u0027)"},{"line_number":295,"context_line":"        if max_workers and min_workers \u003e\u003d max_workers:"},{"line_number":296,"context_line":"            raise ValueError(\u0027min_workers must be less than max_workers\u0027)"},{"line_number":297,"context_line":"        self._min_workers \u003d min_workers"}],"source_content_type":"text/x-python","patch_set":9,"id":"dd3f664d_d6dfba6c","line":294,"range":{"start_line":294,"start_character":30,"end_line":294,"end_character":58},"updated":"2025-08-04 14:39:42.000000000","message":"We probably want this message consistent with ThreadPoolExecutor, but that can be done in a follow-up.","commit_id":"679355a3351b73bc60c1cea55e708d68f6b1f2d7"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"f80d442c599d1e9e121231ddb90a984e528cf698","unresolved":false,"context_lines":[{"line_number":318,"context_line":"                break"},{"line_number":319,"context_line":"            new_workers.append(w)"},{"line_number":320,"context_line":""},{"line_number":321,"context_line":"        if idle_worker is None:"},{"line_number":322,"context_line":"            # Should not actually happen but races are possible; do nothing"},{"line_number":323,"context_line":"            LOG.warning("},{"line_number":324,"context_line":"                \u0027No idle worker thread to delete when shrinking pool %r\u0027, self)"}],"source_content_type":"text/x-python","patch_set":9,"id":"cd135178_3e82a29f","line":321,"range":{"start_line":321,"start_character":8,"end_line":321,"end_character":31},"updated":"2025-08-04 14:39:42.000000000","message":"Using else may result in a same behavior but I\u0027m ok with the proposed logic.","commit_id":"679355a3351b73bc60c1cea55e708d68f6b1f2d7"}],"futurist/tests/test_executors.py":[{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"2c766b917dcb27d06ed4f21c0d5fdd625255befd","unresolved":false,"context_lines":[{"line_number":224,"context_line":""},{"line_number":225,"context_line":"        for _i in range(10):"},{"line_number":226,"context_line":"            executor.submit(task)"},{"line_number":227,"context_line":"            time.sleep(0.1)  # without this threads don\u0027t start"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"        started.wait()"},{"line_number":230,"context_line":"        self.assertEqual(0, executor.queue_size)"}],"source_content_type":"text/x-python","patch_set":7,"id":"4ba87030_0df7c00e","line":227,"updated":"2025-07-24 09:13:56.000000000","message":"Removed in https://review.opendev.org/c/openstack/futurist/+/955758","commit_id":"7d3066fa42c0477000dcfd8cf0d4d88d09c11e6c"},{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"2c766b917dcb27d06ed4f21c0d5fdd625255befd","unresolved":false,"context_lines":[{"line_number":234,"context_line":"        self.assertEqual(10, mock_add_thread.call_count)"},{"line_number":235,"context_line":""},{"line_number":236,"context_line":"        done.set()"},{"line_number":237,"context_line":"        time.sleep(0.1)"},{"line_number":238,"context_line":"        executor.maintain()"},{"line_number":239,"context_line":"        self.assertEqual(0, executor.queue_size)"},{"line_number":240,"context_line":"        self.assertEqual(1, executor.current_size)"}],"source_content_type":"text/x-python","patch_set":7,"id":"9ec43f58_f1745015","line":237,"updated":"2025-07-24 09:13:56.000000000","message":"ditto","commit_id":"7d3066fa42c0477000dcfd8cf0d4d88d09c11e6c"}],"releasenotes/notes/dynamic-pool-ae8811eecd5f9009.yaml":[{"author":{"_account_id":28522,"name":"Hervé Beraud","email":"herveberaud.pro@gmail.com","username":"hberaud"},"change_message_id":"a11d5fafc0ecad1589441267e381870a52fccd47","unresolved":true,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    Adds a new ``DynamicThreadPoolExecutor`` that can resize (grow or shrink) its pool"},{"line_number":5,"context_line":"    based on demand."}],"source_content_type":"text/x-yaml","patch_set":5,"id":"ceb4b17b_42b6c7ca","line":5,"range":{"start_line":4,"start_character":4,"end_line":5,"end_character":20},"updated":"2025-07-22 09:28:27.000000000","message":"I\u0027d suggest to put some words about the fact that greenpool are scalable pools and this eventlet behaviour is one of the reasons that motivated the implementation of this new feature. Thoughts?","commit_id":"d387a2459ece939299c7aef43c34b6ca7ec6ce69"},{"author":{"_account_id":28522,"name":"Hervé Beraud","email":"herveberaud.pro@gmail.com","username":"hberaud"},"change_message_id":"ef7533293713b4c2af92693bd4c628befadf28aa","unresolved":false,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    Adds a new ``DynamicThreadPoolExecutor`` that can resize (grow or shrink) its pool"},{"line_number":5,"context_line":"    based on demand."}],"source_content_type":"text/x-yaml","patch_set":5,"id":"80fe662b_eba84996","line":5,"range":{"start_line":4,"start_character":4,"end_line":5,"end_character":20},"in_reply_to":"ceb4b17b_42b6c7ca","updated":"2025-07-22 10:09:00.000000000","message":"Done","commit_id":"d387a2459ece939299c7aef43c34b6ca7ec6ce69"}]}
