)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"448f470b30796c54ab7819b39e662813e83d0dc9","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Stanislav Kudriashev \u003cskudriashev@griddynamics.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2014-03-12 18:02:23 +0200"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"[WBE] Collect information from workers"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Change-Id: I4a810b1ddb0b04c11d12b47afc5f9cdf77d070be"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"AAAAWH%2F%2F6k8%3D","line":7,"updated":"2014-03-13 00:06:46.000000000","message":"What kind of information ;)","commit_id":"c2cbad5d510fa65192842a5fce79ca44dbd3523b"},{"author":{"_account_id":8895,"name":"Stanislav Kudriashev","email":"stas.kudriashev@gmail.com","username":"skudriashev"},"change_message_id":"a9c7ada1ef37c7e77bc4401a2e8be43eab63069d","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Stanislav Kudriashev \u003cskudriashev@griddynamics.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2014-03-12 18:02:23 +0200"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"[WBE] Collect information from workers"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Change-Id: I4a810b1ddb0b04c11d12b47afc5f9cdf77d070be"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"AAAAWH%2F%2F04g%3D","line":7,"in_reply_to":"AAAAWH%2F%2F6k8%3D","updated":"2014-03-13 15:08:11.000000000","message":"Done","commit_id":"c2cbad5d510fa65192842a5fce79ca44dbd3523b"}],"taskflow/engines/worker_based/cache.py":[{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"448f470b30796c54ab7819b39e662813e83d0dc9","unresolved":false,"context_lines":[{"line_number":68,"context_line":"        with self._lock.read_lock():"},{"line_number":69,"context_line":"            for request in six.itervalues(self._data):"},{"line_number":70,"context_line":"                if request.state \u003d\u003d pr.WAITING:"},{"line_number":71,"context_line":"                    yield request"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"class WorkersCache(Cache):"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAWH%2F%2F6kk%3D","line":71,"updated":"2014-03-13 00:06:46.000000000","message":"Yielding while holding a read lock worries me :-/\n\nCan u hold the read lock, grab all the current values, then yield them back instead of holding the lock while yielding (this may basically hold the lock for a very long time).","commit_id":"c2cbad5d510fa65192842a5fce79ca44dbd3523b"},{"author":{"_account_id":8895,"name":"Stanislav Kudriashev","email":"stas.kudriashev@gmail.com","username":"skudriashev"},"change_message_id":"a9c7ada1ef37c7e77bc4401a2e8be43eab63069d","unresolved":false,"context_lines":[{"line_number":68,"context_line":"        with self._lock.read_lock():"},{"line_number":69,"context_line":"            for request in six.itervalues(self._data):"},{"line_number":70,"context_line":"                if request.state \u003d\u003d pr.WAITING:"},{"line_number":71,"context_line":"                    yield request"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"class WorkersCache(Cache):"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAWH%2F%2F1GY%3D","line":71,"in_reply_to":"AAAAWH%2F%2F6kk%3D","updated":"2014-03-13 15:08:11.000000000","message":"Done","commit_id":"c2cbad5d510fa65192842a5fce79ca44dbd3523b"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"448f470b30796c54ab7819b39e662813e83d0dc9","unresolved":false,"context_lines":[{"line_number":71,"context_line":"                    yield request"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"class WorkersCache(Cache):"},{"line_number":75,"context_line":"    \"\"\"Represents thread-safe workers cache.\"\"\""},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def get_topic_by_task(self, task):"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAWH%2F%2F6jk%3D","line":74,"updated":"2014-03-13 00:06:46.000000000","message":"This is really getting into the matchmaker territory that oslo.messaging provides. \n\nhttps://github.com/openstack/oslo.messaging/blob/master/oslo/messaging/_drivers/matchmaker.py\n\nWe should probably seriously start thinking about how to use oslo.messaging to avoid recreating our own version of it.\n\nI\u0027ve started experimenting with it @ https://review.openstack.org/#/c/79825/","commit_id":"c2cbad5d510fa65192842a5fce79ca44dbd3523b"},{"author":{"_account_id":8895,"name":"Stanislav Kudriashev","email":"stas.kudriashev@gmail.com","username":"skudriashev"},"change_message_id":"a9c7ada1ef37c7e77bc4401a2e8be43eab63069d","unresolved":false,"context_lines":[{"line_number":71,"context_line":"                    yield request"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"class WorkersCache(Cache):"},{"line_number":75,"context_line":"    \"\"\"Represents thread-safe workers cache.\"\"\""},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def get_topic_by_task(self, task):"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAWH%2F%2F088%3D","line":74,"in_reply_to":"AAAAWH%2F%2F6jk%3D","updated":"2014-03-13 15:08:11.000000000","message":"Probably, but  this patch is not about heartbeats, this is just improvement of the existing architecture (without having to specify list of tasks for executor, so it get\u0027s that list during runtime).","commit_id":"c2cbad5d510fa65192842a5fce79ca44dbd3523b"}],"taskflow/engines/worker_based/executor.py":[{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"448f470b30796c54ab7819b39e662813e83d0dc9","unresolved":false,"context_lines":[{"line_number":44,"context_line":"        self._proxy_thread \u003d None"},{"line_number":45,"context_line":"        self._notify_thread \u003d None"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def _get_thread(self, target):"},{"line_number":48,"context_line":"        thread \u003d threading.Thread(target\u003dtarget)"},{"line_number":49,"context_line":"        # NOTE(skudriashev): When the main thread is terminated unexpectedly"},{"line_number":50,"context_line":"        # and thread is still alive - it will prevent main thread from exiting"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAWH%2F%2F6is%3D","line":47,"updated":"2014-03-13 00:06:46.000000000","message":"_get -\u003e _make seems to make more sense.","commit_id":"c2cbad5d510fa65192842a5fce79ca44dbd3523b"},{"author":{"_account_id":8895,"name":"Stanislav Kudriashev","email":"stas.kudriashev@gmail.com","username":"skudriashev"},"change_message_id":"a9c7ada1ef37c7e77bc4401a2e8be43eab63069d","unresolved":false,"context_lines":[{"line_number":44,"context_line":"        self._proxy_thread \u003d None"},{"line_number":45,"context_line":"        self._notify_thread \u003d None"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    def _get_thread(self, target):"},{"line_number":48,"context_line":"        thread \u003d threading.Thread(target\u003dtarget)"},{"line_number":49,"context_line":"        # NOTE(skudriashev): When the main thread is terminated unexpectedly"},{"line_number":50,"context_line":"        # and thread is still alive - it will prevent main thread from exiting"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAWH%2F%2F1IY%3D","line":47,"in_reply_to":"AAAAWH%2F%2F6is%3D","updated":"2014-03-13 15:08:11.000000000","message":"Done","commit_id":"c2cbad5d510fa65192842a5fce79ca44dbd3523b"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"ccfd24473ffa3081de58634e165bbf5ecbe07eec","unresolved":false,"context_lines":[{"line_number":189,"context_line":"                self._proxy.stop()"},{"line_number":190,"context_line":"                self._proxy_thread.join()"},{"line_number":191,"context_line":"            self._proxy_thread \u003d None"},{"line_number":192,"context_line":"            self._notify_thread \u003d None"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAWH%2F%2Fy3M%3D","line":192,"updated":"2014-03-13 19:07:30.000000000","message":"Where is the self._notify_thread join?","commit_id":"135a77b215fab30d5e3c7f8f7be612fbc00e6ad0"},{"author":{"_account_id":8895,"name":"Stanislav Kudriashev","email":"stas.kudriashev@gmail.com","username":"skudriashev"},"change_message_id":"c4e266837f4fec669719774d32b39b82add7677f","unresolved":false,"context_lines":[{"line_number":189,"context_line":"                self._proxy.stop()"},{"line_number":190,"context_line":"                self._proxy_thread.join()"},{"line_number":191,"context_line":"            self._proxy_thread \u003d None"},{"line_number":192,"context_line":"            self._notify_thread \u003d None"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAWH%2F%2Frj4%3D","line":192,"in_reply_to":"AAAAWH%2F%2Fy3M%3D","updated":"2014-03-14 14:36:27.000000000","message":"I forgot it intentionally to terminate the notify thread as fast as possible, and don\u0027t wait up to pr.NOTIFY_PERIOD (since join() will block execution). By the way, currently the NOTIFY_PERIOD is set to 5 seconds, but it can be even longer.\n\nI know this is not the best solution, but what is the other way?","commit_id":"135a77b215fab30d5e3c7f8f7be612fbc00e6ad0"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"07a0466b831d959027f23b38abdf68d205c3e94a","unresolved":false,"context_lines":[{"line_number":192,"context_line":"                self._proxy.stop()"},{"line_number":193,"context_line":"                self._proxy_thread.join()"},{"line_number":194,"context_line":"            self._proxy_thread \u003d None"},{"line_number":195,"context_line":"            self._notify_thread \u003d None"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAWH%2F%2FpCY%3D","line":195,"updated":"2014-03-14 19:49:57.000000000","message":"Still would be nice to join on this, just to make sure no crap is left behind. I know this thread is connected to the proxy thread running but it seems good behavior to join on both (first the proxy thread, then the notify thread). An even better way, instead of using time.sleep(pr.NOTIFY_PERIOD) from above, using a http://docs.python.org/2.7/library/threading.html#threading.Event event object, and everytime u need to sleep do self._notify_event.wait(timeout\u003dpr.NOTIFY_PERIOD), then u can immediatly (mostly immediate) signal the notify_thread to die by just setting that event  (via set()) after u stop the proxy thread.","commit_id":"6e913fd7ebfc8977b4f53b71ad2a63b4ce6dba61"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"0b78c46aff6efac6df3c1263fadf1ab86b62a240","unresolved":false,"context_lines":[{"line_number":192,"context_line":"                self._proxy.stop()"},{"line_number":193,"context_line":"                self._proxy_thread.join()"},{"line_number":194,"context_line":"            self._proxy_thread \u003d None"},{"line_number":195,"context_line":"            self._notify_thread \u003d None"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAWH%2F%2Fn%2Fc%3D","line":195,"in_reply_to":"AAAAWH%2F%2Fn%2F0%3D","updated":"2014-03-14 22:17:14.000000000","message":"Meant the notify thread, not the proxy one.","commit_id":"6e913fd7ebfc8977b4f53b71ad2a63b4ce6dba61"},{"author":{"_account_id":8895,"name":"Stanislav Kudriashev","email":"stas.kudriashev@gmail.com","username":"skudriashev"},"change_message_id":"a07085ff6c1bc5bf57241f5f960c53c82e6b3e81","unresolved":false,"context_lines":[{"line_number":192,"context_line":"                self._proxy.stop()"},{"line_number":193,"context_line":"                self._proxy_thread.join()"},{"line_number":194,"context_line":"            self._proxy_thread \u003d None"},{"line_number":195,"context_line":"            self._notify_thread \u003d None"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAWH%2F%2Fblo%3D","line":195,"in_reply_to":"AAAAWH%2F%2Fn%2Fc%3D","updated":"2014-03-17 23:12:32.000000000","message":"Done","commit_id":"6e913fd7ebfc8977b4f53b71ad2a63b4ce6dba61"},{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"6ccba1c5437a443e44abe8bd0d9adacd2bed3ddf","unresolved":false,"context_lines":[{"line_number":192,"context_line":"                self._proxy.stop()"},{"line_number":193,"context_line":"                self._proxy_thread.join()"},{"line_number":194,"context_line":"            self._proxy_thread \u003d None"},{"line_number":195,"context_line":"            self._notify_thread \u003d None"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAWH%2F%2Fn%2F0%3D","line":195,"in_reply_to":"AAAAWH%2F%2FpCY%3D","updated":"2014-03-14 22:16:35.000000000","message":"In fact, in the proxy thread, u can probably replace the loop condition.\n\n  while self._proxy.is_running:\n     do stuff\n\nAnd instead use:\n   \n   while not self._notify_event.set():\n      do stuff","commit_id":"6e913fd7ebfc8977b4f53b71ad2a63b4ce6dba61"}],"taskflow/engines/worker_based/protocol.py":[{"author":{"_account_id":7366,"name":"Ivan Melnikov","email":"imelnikov@griddynamics.com","username":"imelnikov"},"change_message_id":"dbd083f574d8e8ca787e8d6ffbc9ae4b7079b467","unresolved":false,"context_lines":[{"line_number":123,"context_line":"    def expired(self):"},{"line_number":124,"context_line":"        \"\"\"Check if request is expired."},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"        When new request is created its state is set to the PENDING, creation"},{"line_number":127,"context_line":"        time is stored and timeout is given via constructor arguments."},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"        Request is considered to be expired when it is in the PENDING state"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAWH%2F%2Ftdk%3D","line":126,"updated":"2014-03-14 12:18:55.000000000","message":"Docstring looks outdated.","commit_id":"135a77b215fab30d5e3c7f8f7be612fbc00e6ad0"},{"author":{"_account_id":8895,"name":"Stanislav Kudriashev","email":"stas.kudriashev@gmail.com","username":"skudriashev"},"change_message_id":"c4e266837f4fec669719774d32b39b82add7677f","unresolved":false,"context_lines":[{"line_number":123,"context_line":"    def expired(self):"},{"line_number":124,"context_line":"        \"\"\"Check if request is expired."},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"        When new request is created its state is set to the PENDING, creation"},{"line_number":127,"context_line":"        time is stored and timeout is given via constructor arguments."},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"        Request is considered to be expired when it is in the PENDING state"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAWH%2F%2FrqU%3D","line":126,"in_reply_to":"AAAAWH%2F%2Ftdk%3D","updated":"2014-03-14 14:36:27.000000000","message":"Done","commit_id":"135a77b215fab30d5e3c7f8f7be612fbc00e6ad0"}],"taskflow/engines/worker_based/server.py":[{"author":{"_account_id":1297,"name":"Joshua Harlow","email":"jxharlow@godaddy.com","username":"harlowja"},"change_message_id":"448f470b30796c54ab7819b39e662813e83d0dc9","unresolved":false,"context_lines":[{"line_number":52,"context_line":"                LOG.exception(\"Failed to acknowledge AMQP message.\")"},{"line_number":53,"context_line":"            else:"},{"line_number":54,"context_line":"                LOG.debug(\"AMQP message acknowledged.\")"},{"line_number":55,"context_line":"                msg_type \u003d data.pop(\u0027type\u0027, None)"},{"line_number":56,"context_line":"                if msg_type is not None:"},{"line_number":57,"context_line":"                    if msg_type \u003d\u003d pr.NOTIFY:"},{"line_number":58,"context_line":"                        handler \u003d self._process_notify"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAWH%2F%2F6h0%3D","line":55,"updated":"2014-03-13 00:06:46.000000000","message":"Same question is other review, use the messages own properties or content_type ?","commit_id":"c2cbad5d510fa65192842a5fce79ca44dbd3523b"},{"author":{"_account_id":8895,"name":"Stanislav Kudriashev","email":"stas.kudriashev@gmail.com","username":"skudriashev"},"change_message_id":"a9c7ada1ef37c7e77bc4401a2e8be43eab63069d","unresolved":false,"context_lines":[{"line_number":52,"context_line":"                LOG.exception(\"Failed to acknowledge AMQP message.\")"},{"line_number":53,"context_line":"            else:"},{"line_number":54,"context_line":"                LOG.debug(\"AMQP message acknowledged.\")"},{"line_number":55,"context_line":"                msg_type \u003d data.pop(\u0027type\u0027, None)"},{"line_number":56,"context_line":"                if msg_type is not None:"},{"line_number":57,"context_line":"                    if msg_type \u003d\u003d pr.NOTIFY:"},{"line_number":58,"context_line":"                        handler \u003d self._process_notify"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAWH%2F%2F08Q%3D","line":55,"in_reply_to":"AAAAWH%2F%2F6h0%3D","updated":"2014-03-13 15:08:11.000000000","message":"Same answer as on other review.","commit_id":"c2cbad5d510fa65192842a5fce79ca44dbd3523b"}]}
