)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"a5b309ea4883ea5a1a5f85746da246e2e8d37bdb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"4968f895_15cd46c7","updated":"2026-07-09 10:51:15.000000000","message":"recheck flaky test?","commit_id":"933973dc2c5ac7d4b23cd98bc48a883d6246403d"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"2069df861acbabced9c819416b9f648d5669ae47","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"ac39e88f_44c5cba1","updated":"2026-07-17 08:41:05.000000000","message":"recheck flaky tests?","commit_id":"ef810b16d55c0bf027da73e69bee090a390a87c6"}],"futurist/_futures.py":[{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"b389dab535fabb9415bd0d7ff262f42ce7c235a0","unresolved":true,"context_lines":[{"line_number":224,"context_line":"    def _get_workers_for_shutdown(self) -\u003e list[_thread.ThreadWorker]:"},{"line_number":225,"context_line":"        return list(self._workers)"},{"line_number":226,"context_line":""},{"line_number":227,"context_line":"    def _cancel_pending_futures(self) -\u003e None:"},{"line_number":228,"context_line":"        while True:"},{"line_number":229,"context_line":"            try:"},{"line_number":230,"context_line":"                work \u003d self._work_queue.get_nowait()"}],"source_content_type":"text/x-python","patch_set":1,"id":"5be6cb30_0c858145","line":227,"updated":"2026-07-09 11:58:38.000000000","message":"https://docs.python.org/3/library/queue.html#queue.Queue.shutdown implements draining in safe way regarding parallel put() and get() calls. So we might need to think about such a problem.","commit_id":"933973dc2c5ac7d4b23cd98bc48a883d6246403d"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"1a11b3863b148ecdcc2d64031cc217e48186d69a","unresolved":true,"context_lines":[{"line_number":224,"context_line":"    def _get_workers_for_shutdown(self) -\u003e list[_thread.ThreadWorker]:"},{"line_number":225,"context_line":"        return list(self._workers)"},{"line_number":226,"context_line":""},{"line_number":227,"context_line":"    def _cancel_pending_futures(self) -\u003e None:"},{"line_number":228,"context_line":"        while True:"},{"line_number":229,"context_line":"            try:"},{"line_number":230,"context_line":"                work \u003d self._work_queue.get_nowait()"}],"source_content_type":"text/x-python","patch_set":1,"id":"bfd94a9e_61e1ca3e","line":227,"in_reply_to":"5be6cb30_0c858145","updated":"2026-07-09 12:27:25.000000000","message":"i can split this into a followup but yes i was thinking we would use this in nova to further reduce the shutdown time.","commit_id":"933973dc2c5ac7d4b23cd98bc48a883d6246403d"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"d5eb6dd7f4c10fd1f44b37d34bdfe5fa36109f68","unresolved":false,"context_lines":[{"line_number":224,"context_line":"    def _get_workers_for_shutdown(self) -\u003e list[_thread.ThreadWorker]:"},{"line_number":225,"context_line":"        return list(self._workers)"},{"line_number":226,"context_line":""},{"line_number":227,"context_line":"    def _cancel_pending_futures(self) -\u003e None:"},{"line_number":228,"context_line":"        while True:"},{"line_number":229,"context_line":"            try:"},{"line_number":230,"context_line":"                work \u003d self._work_queue.get_nowait()"}],"source_content_type":"text/x-python","patch_set":1,"id":"3038499d_f16b7f4a","line":227,"in_reply_to":"bfd94a9e_61e1ca3e","updated":"2026-07-10 14:59:54.000000000","message":"Done","commit_id":"933973dc2c5ac7d4b23cd98bc48a883d6246403d"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"b389dab535fabb9415bd0d7ff262f42ce7c235a0","unresolved":true,"context_lines":[{"line_number":251,"context_line":"            workers \u003d self._get_workers_for_shutdown()"},{"line_number":252,"context_line":"            if not self._shutdown:"},{"line_number":253,"context_line":"                self._shutdown \u003d True"},{"line_number":254,"context_line":"                if cancel_futures:"},{"line_number":255,"context_line":"                    for w in workers:"},{"line_number":256,"context_line":"                        w.stop()"},{"line_number":257,"context_line":"                    self._cancel_pending_futures()"}],"source_content_type":"text/x-python","patch_set":1,"id":"82adb142_8366152a","line":254,"updated":"2026-07-09 11:58:38.000000000","message":"this seems like an extra missing feature added to the code. I would rather not mix that into the bugfix","commit_id":"933973dc2c5ac7d4b23cd98bc48a883d6246403d"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"d5eb6dd7f4c10fd1f44b37d34bdfe5fa36109f68","unresolved":false,"context_lines":[{"line_number":251,"context_line":"            workers \u003d self._get_workers_for_shutdown()"},{"line_number":252,"context_line":"            if not self._shutdown:"},{"line_number":253,"context_line":"                self._shutdown \u003d True"},{"line_number":254,"context_line":"                if cancel_futures:"},{"line_number":255,"context_line":"                    for w in workers:"},{"line_number":256,"context_line":"                        w.stop()"},{"line_number":257,"context_line":"                    self._cancel_pending_futures()"}],"source_content_type":"text/x-python","patch_set":1,"id":"0eff7ca1_40585893","line":254,"in_reply_to":"82adb142_8366152a","updated":"2026-07-10 14:59:54.000000000","message":"Acknowledged","commit_id":"933973dc2c5ac7d4b23cd98bc48a883d6246403d"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"b389dab535fabb9415bd0d7ff262f42ce7c235a0","unresolved":true,"context_lines":[{"line_number":263,"context_line":"                        # for each."},{"line_number":264,"context_line":"                        self._work_queue.join()"},{"line_number":265,"context_line":"                    for w in workers:"},{"line_number":266,"context_line":"                        w.stop()"},{"line_number":267,"context_line":"                for w in workers:"},{"line_number":268,"context_line":"                    w.wake()"},{"line_number":269,"context_line":"        if wait:"},{"line_number":270,"context_line":"            for w in workers:"},{"line_number":271,"context_line":"                w.join()"}],"source_content_type":"text/x-python","patch_set":1,"id":"3a4a3531_d90d9f1e","line":268,"range":{"start_line":266,"start_character":0,"end_line":268,"end_character":28},"updated":"2026-07-09 11:58:38.000000000","message":"this feels like should be a single step. As the intention is to stop the implementation is: mark as stopped, and wake so it notices that it is stopped. So wake is an implementation detail of stop.\n\nI suggest to move wake into stop","commit_id":"933973dc2c5ac7d4b23cd98bc48a883d6246403d"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"1a11b3863b148ecdcc2d64031cc217e48186d69a","unresolved":true,"context_lines":[{"line_number":263,"context_line":"                        # for each."},{"line_number":264,"context_line":"                        self._work_queue.join()"},{"line_number":265,"context_line":"                    for w in workers:"},{"line_number":266,"context_line":"                        w.stop()"},{"line_number":267,"context_line":"                for w in workers:"},{"line_number":268,"context_line":"                    w.wake()"},{"line_number":269,"context_line":"        if wait:"},{"line_number":270,"context_line":"            for w in workers:"},{"line_number":271,"context_line":"                w.join()"}],"source_content_type":"text/x-python","patch_set":1,"id":"6f645502_8fe0762f","line":268,"range":{"start_line":266,"start_character":0,"end_line":268,"end_character":28},"in_reply_to":"3a4a3531_d90d9f1e","updated":"2026-07-09 12:27:25.000000000","message":"its two steps becaue of the way the DynmicThreadpool srinks in _drop_thread\nhttps://review.opendev.org/c/openstack/futurist/+/996568/1/futurist/_futures.py#405","commit_id":"933973dc2c5ac7d4b23cd98bc48a883d6246403d"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"d5eb6dd7f4c10fd1f44b37d34bdfe5fa36109f68","unresolved":false,"context_lines":[{"line_number":263,"context_line":"                        # for each."},{"line_number":264,"context_line":"                        self._work_queue.join()"},{"line_number":265,"context_line":"                    for w in workers:"},{"line_number":266,"context_line":"                        w.stop()"},{"line_number":267,"context_line":"                for w in workers:"},{"line_number":268,"context_line":"                    w.wake()"},{"line_number":269,"context_line":"        if wait:"},{"line_number":270,"context_line":"            for w in workers:"},{"line_number":271,"context_line":"                w.join()"}],"source_content_type":"text/x-python","patch_set":1,"id":"1f867861_f5a04576","line":268,"range":{"start_line":266,"start_character":0,"end_line":268,"end_character":28},"in_reply_to":"6f645502_8fe0762f","updated":"2026-07-10 14:59:54.000000000","message":"Done","commit_id":"933973dc2c5ac7d4b23cd98bc48a883d6246403d"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"d5eb6dd7f4c10fd1f44b37d34bdfe5fa36109f68","unresolved":true,"context_lines":[{"line_number":241,"context_line":"                # continue processing work during shutdown."},{"line_number":242,"context_line":"                for w in workers:"},{"line_number":243,"context_line":"                    w.request_stop()"},{"line_number":244,"context_line":"                for w in workers:"},{"line_number":245,"context_line":"                    w.stop()"},{"line_number":246,"context_line":"        if wait:"},{"line_number":247,"context_line":"            for w in workers:"},{"line_number":248,"context_line":"                w.join()"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"    def _submit("},{"line_number":251,"context_line":"        self, fn: Callable[_P, _R], *args: _P.args, **kwargs: _P.kwargs"}],"source_content_type":"text/x-python","patch_set":2,"id":"1bf870d0_efb26208","line":248,"range":{"start_line":244,"start_character":0,"end_line":248,"end_character":24},"updated":"2026-07-10 14:59:54.000000000","message":"i coudl maybe combine these \nbut i dont know if we really want the join under the lock but i dont see that really having a negitive side effect.\nif we are in this code and have premarked all the works to stop then blocking if wait is requested does not hurt.","commit_id":"ef810b16d55c0bf027da73e69bee090a390a87c6"}],"futurist/_thread.py":[{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"b389dab535fabb9415bd0d7ff262f42ce7c235a0","unresolved":true,"context_lines":[{"line_number":53,"context_line":"    pass"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"class _Wakeup:"},{"line_number":57,"context_line":"    pass"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"773d7262_fcd12e41","line":56,"updated":"2026-07-09 11:58:38.000000000","message":"Im wondering why we are defining and independent class and then extend the accepted types. I think we can use the null object pattern to keep the type as is.\n```\nclass _Sentinel(_utils.WorkItem):\n    def __init__(self):\n        super().__init__(Future(), lambda:True)\n    def run(self):\n        raise ValueError(\"Sentinel never expected to be run\")\n```","commit_id":"933973dc2c5ac7d4b23cd98bc48a883d6246403d"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"b389dab535fabb9415bd0d7ff262f42ce7c235a0","unresolved":true,"context_lines":[{"line_number":57,"context_line":"    pass"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"_WAKEUP \u003d _Wakeup()"},{"line_number":61,"context_line":"_WorkQueueItem: TypeAlias \u003d _utils.WorkItem | _Wakeup"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"c5f8c619_35618030","line":60,"updated":"2026-07-09 11:58:38.000000000","message":"yeah that is a sentinel to wake up the worker so that it can notice the shutdown state.","commit_id":"933973dc2c5ac7d4b23cd98bc48a883d6246403d"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"10c20e2c76b56437e71a16c01069cd119f56fd3d","unresolved":true,"context_lines":[{"line_number":126,"context_line":"                if self._is_dying():"},{"line_number":127,"context_line":"                    raise _Stopping()"},{"line_number":128,"context_line":"                continue"},{"line_number":129,"context_line":"            if isinstance(work, _Sentinel):"},{"line_number":130,"context_line":"                self.work_queue.task_done()"},{"line_number":131,"context_line":"                if work.is_for(self):"},{"line_number":132,"context_line":"                    if self._is_dying():"}],"source_content_type":"text/x-python","patch_set":2,"id":"04bc84f6_7ffb1ee0","line":129,"updated":"2026-07-17 08:50:26.000000000","message":"we have now self._sentinel should we just see if it is the one queued?","commit_id":"ef810b16d55c0bf027da73e69bee090a390a87c6"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"2b80c57a52b8ef7ee71a22bf994fdd299cbc9efa","unresolved":true,"context_lines":[{"line_number":126,"context_line":"                if self._is_dying():"},{"line_number":127,"context_line":"                    raise _Stopping()"},{"line_number":128,"context_line":"                continue"},{"line_number":129,"context_line":"            if isinstance(work, _Sentinel):"},{"line_number":130,"context_line":"                self.work_queue.task_done()"},{"line_number":131,"context_line":"                if work.is_for(self):"},{"line_number":132,"context_line":"                    if self._is_dying():"}],"source_content_type":"text/x-python","patch_set":2,"id":"46f47a58_37f4a101","line":129,"in_reply_to":"04bc84f6_7ffb1ee0","updated":"2026-07-17 14:58:03.000000000","message":"honestly i kind of preferred how i did this in v1 it was simpler.\n\ninstead of per worker sentinels i think i can simply this so we shoudl still check if its an instance of the sentinel and then have that set.should_stop\u003dtrue and raise _Stopping()","commit_id":"ef810b16d55c0bf027da73e69bee090a390a87c6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"10c20e2c76b56437e71a16c01069cd119f56fd3d","unresolved":true,"context_lines":[{"line_number":128,"context_line":"                continue"},{"line_number":129,"context_line":"            if isinstance(work, _Sentinel):"},{"line_number":130,"context_line":"                self.work_queue.task_done()"},{"line_number":131,"context_line":"                if work.is_for(self):"},{"line_number":132,"context_line":"                    if self._is_dying():"},{"line_number":133,"context_line":"                        raise _Stopping()"},{"line_number":134,"context_line":"                elif work.target_exists:"},{"line_number":135,"context_line":"                    # All workers share one queue. Preserve another worker\u0027s"},{"line_number":136,"context_line":"                    # wakeup so that worker can claim it."},{"line_number":137,"context_line":"                    self.work_queue.put(work)"},{"line_number":138,"context_line":"                    if self._is_dying():"},{"line_number":139,"context_line":"                        raise _Stopping()"},{"line_number":140,"context_line":"                    time.sleep(0)"}],"source_content_type":"text/x-python","patch_set":2,"id":"2a281028_e94e17eb","line":137,"range":{"start_line":131,"start_character":0,"end_line":137,"end_character":45},"updated":"2026-07-17 08:50:26.000000000","message":"this feels complicated.\n\nWe have one queue and we have N threads consuming form that queue. We want to wake all of them. We know that once a thread wakes due to this type of work it will stop consuming new work as it stops. Can we just queue N generic wake up task and let each worker consume one and die?","commit_id":"ef810b16d55c0bf027da73e69bee090a390a87c6"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"2b80c57a52b8ef7ee71a22bf994fdd299cbc9efa","unresolved":true,"context_lines":[{"line_number":128,"context_line":"                continue"},{"line_number":129,"context_line":"            if isinstance(work, _Sentinel):"},{"line_number":130,"context_line":"                self.work_queue.task_done()"},{"line_number":131,"context_line":"                if work.is_for(self):"},{"line_number":132,"context_line":"                    if self._is_dying():"},{"line_number":133,"context_line":"                        raise _Stopping()"},{"line_number":134,"context_line":"                elif work.target_exists:"},{"line_number":135,"context_line":"                    # All workers share one queue. Preserve another worker\u0027s"},{"line_number":136,"context_line":"                    # wakeup so that worker can claim it."},{"line_number":137,"context_line":"                    self.work_queue.put(work)"},{"line_number":138,"context_line":"                    if self._is_dying():"},{"line_number":139,"context_line":"                        raise _Stopping()"},{"line_number":140,"context_line":"                    time.sleep(0)"}],"source_content_type":"text/x-python","patch_set":2,"id":"f7bc32cc_742a5565","line":137,"range":{"start_line":131,"start_character":0,"end_line":137,"end_character":45},"in_reply_to":"2a281028_e94e17eb","updated":"2026-07-17 14:58:03.000000000","message":"yes so if i change the behvioe to have the presence of the sentenal set self.should_stop\u003dtrue and raise _Stopping() then we can simpley encure 1 per worker and remove self._sentinel \u003d _Sentinel(self) and remove the need for the sentenal object ot even refence the worker\n\ninfact i might be able to relase it with\n```\n_Sentinel \u003d object()\n```\nand \n```\nif isinstance(work, _Sentinel):\n```\nwith\n``` \nif work is _Sentinel:\n```","commit_id":"ef810b16d55c0bf027da73e69bee090a390a87c6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"10c20e2c76b56437e71a16c01069cd119f56fd3d","unresolved":true,"context_lines":[{"line_number":137,"context_line":"                    self.work_queue.put(work)"},{"line_number":138,"context_line":"                    if self._is_dying():"},{"line_number":139,"context_line":"                        raise _Stopping()"},{"line_number":140,"context_line":"                    time.sleep(0)"},{"line_number":141,"context_line":"                continue"},{"line_number":142,"context_line":"            self.idle \u003d False"},{"line_number":143,"context_line":"            return work"}],"source_content_type":"text/x-python","patch_set":2,"id":"17ef222e_493c8708","line":140,"updated":"2026-07-17 08:50:26.000000000","message":"this feels like a workaround for something.","commit_id":"ef810b16d55c0bf027da73e69bee090a390a87c6"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"2b80c57a52b8ef7ee71a22bf994fdd299cbc9efa","unresolved":true,"context_lines":[{"line_number":137,"context_line":"                    self.work_queue.put(work)"},{"line_number":138,"context_line":"                    if self._is_dying():"},{"line_number":139,"context_line":"                        raise _Stopping()"},{"line_number":140,"context_line":"                    time.sleep(0)"},{"line_number":141,"context_line":"                continue"},{"line_number":142,"context_line":"            self.idle \u003d False"},{"line_number":143,"context_line":"            return work"}],"source_content_type":"text/x-python","patch_set":2,"id":"67523718_cbcb88e4","line":140,"in_reply_to":"17ef222e_493c8708","updated":"2026-07-17 14:58:03.000000000","message":"actully this shoudl not be needed it just allowint the thread to yeild to he kernel but we dont need to do that when not using evently as the kernel can just prement the thread.","commit_id":"ef810b16d55c0bf027da73e69bee090a390a87c6"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"10c20e2c76b56437e71a16c01069cd119f56fd3d","unresolved":true,"context_lines":[{"line_number":147,"context_line":"            self.should_stop \u003d True"},{"line_number":148,"context_line":""},{"line_number":149,"context_line":"    def stop(self, wake: bool \u003d True) -\u003e None:"},{"line_number":150,"context_line":"        self.request_stop()"},{"line_number":151,"context_line":"        # Wake the worker immediately instead of leaving it blocked until its"},{"line_number":152,"context_line":"        # next queue.get() timeout expires. A previously requested stop may"},{"line_number":153,"context_line":"        # still need waking during executor shutdown."}],"source_content_type":"text/x-python","patch_set":2,"id":"5cdebb79_673ea9e6","line":150,"updated":"2026-07-17 08:50:26.000000000","message":"hm this request_stop is now called form outside as well. Can we remove the external call and rely on the fact that when the external party calls stop it will do all the things needed to stop?","commit_id":"ef810b16d55c0bf027da73e69bee090a390a87c6"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"2b80c57a52b8ef7ee71a22bf994fdd299cbc9efa","unresolved":true,"context_lines":[{"line_number":147,"context_line":"            self.should_stop \u003d True"},{"line_number":148,"context_line":""},{"line_number":149,"context_line":"    def stop(self, wake: bool \u003d True) -\u003e None:"},{"line_number":150,"context_line":"        self.request_stop()"},{"line_number":151,"context_line":"        # Wake the worker immediately instead of leaving it blocked until its"},{"line_number":152,"context_line":"        # next queue.get() timeout expires. A previously requested stop may"},{"line_number":153,"context_line":"        # still need waking during executor shutdown."}],"source_content_type":"text/x-python","patch_set":2,"id":"afa249dd_51a8b4da","line":150,"in_reply_to":"5cdebb79_673ea9e6","updated":"2026-07-17 14:58:03.000000000","message":"This is done in 3 phases partly for speed but also correctness\n\nThe first request_stop pass tell the workers not to start new work and will be noticed when they either complete there current task or the idle timeout passes\n\nthe second pass in stop make sure that that is set again and inject the wake sentinel\n\nthe finally pass over the worker optionally wait in the shutdown case or is mandatory in the process atexit path\n\n\nbut yes i can simplfy it and make the sentenical object triger all the side effect so stop will basiclly jsut enqueu the stop senential which will wake and or stop the worker when its dequeue.","commit_id":"ef810b16d55c0bf027da73e69bee090a390a87c6"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"d5eb6dd7f4c10fd1f44b37d34bdfe5fa36109f68","unresolved":true,"context_lines":[{"line_number":180,"context_line":"        worker, _work_val \u003d _to_be_cleaned.popitem()"},{"line_number":181,"context_line":"        worker.request_stop()"},{"line_number":182,"context_line":"        threads_to_wait_for.append(worker)"},{"line_number":183,"context_line":"    for worker in threads_to_wait_for:"},{"line_number":184,"context_line":"        worker.stop()"},{"line_number":185,"context_line":"    while threads_to_wait_for:"},{"line_number":186,"context_line":"        worker \u003d threads_to_wait_for.pop()"},{"line_number":187,"context_line":"        try:"},{"line_number":188,"context_line":"            worker.join()"}],"source_content_type":"text/x-python","patch_set":2,"id":"b72b4149_4acc8a21","line":185,"range":{"start_line":183,"start_character":2,"end_line":185,"end_character":30},"updated":"2026-07-10 14:59:54.000000000","message":"same here\nonce we have notified them to stop with request stop\n\ni think we can jsut call stop before join\nbut this shoudl also work as is","commit_id":"ef810b16d55c0bf027da73e69bee090a390a87c6"}]}
