)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"964dbb2bcee2ecd570a4863d2cfee04d7fddad6a","unresolved":false,"context_lines":[{"line_number":23,"context_line":"** If a forth SIGHUP will be triggered after 11 seconds, it will be sent"},{"line_number":24,"context_line":"immediately without delay."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"Closes-Bug: 1647432"},{"line_number":27,"context_line":"Change-Id: I2955e0de835458a2eea4dd088addf33b656f8670"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":16,"id":"ba5201f7_c1d21b34","line":26,"updated":"2017-01-10 21:27:39.000000000","message":"I\u0027ve read the bug report, and it sounds like a bug in keepalived. Have we reported it to the project?","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":23,"context_line":"** If a forth SIGHUP will be triggered after 11 seconds, it will be sent"},{"line_number":24,"context_line":"immediately without delay."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"Closes-Bug: 1647432"},{"line_number":27,"context_line":"Change-Id: I2955e0de835458a2eea4dd088addf33b656f8670"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":16,"id":"ba5201f7_759e73b9","line":26,"in_reply_to":"ba5201f7_c1d21b34","updated":"2017-01-16 13:22:12.000000000","message":"Will do.","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"11fb57c5bce316118d527ec3dc50f31dcc68cc7c","unresolved":false,"context_lines":[{"line_number":12,"context_line":"connectivity). This can happen when, for example, associating or"},{"line_number":13,"context_line":"disassociating multiple floatingips."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"The patch proposes an approach which throttles the SIGHUPs: the first"},{"line_number":16,"context_line":"SIGHUP is always sent, and subsequent SIGHUPs are delayed until a"},{"line_number":17,"context_line":"timeout has occurred. For example, when sending 3 SIGHUPs in a row (when"},{"line_number":18,"context_line":"the threshold value is 10 seconds), then:"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":44,"id":"ffe62b97_b8dccd74","line":15,"updated":"2017-03-24 14:43:18.000000000","message":"there were some tweaks to the commit message that are sadly lost","commit_id":"73ec88203400552cb7100677402bf146592ee996"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"5f6c4a83d0e78f0d36ee42c6df6b09c4f5041ca0","unresolved":false,"context_lines":[{"line_number":12,"context_line":"connectivity). This can happen when, for example, associating or"},{"line_number":13,"context_line":"disassociating multiple floatingips."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"The patch proposes an approach which throttles the SIGHUPs: the first"},{"line_number":16,"context_line":"SIGHUP is always sent, and subsequent SIGHUPs are delayed until a"},{"line_number":17,"context_line":"timeout has occurred. For example, when sending 3 SIGHUPs in a row (when"},{"line_number":18,"context_line":"the threshold value is 10 seconds), then:"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":44,"id":"ffe62b97_d88791d7","line":15,"in_reply_to":"ffe62b97_b8dccd74","updated":"2017-03-24 15:32:17.000000000","message":"Done","commit_id":"73ec88203400552cb7100677402bf146592ee996"}],"neutron/agent/common/utils.py":[{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"a15abb9a816f91fc629f8801a398b806e6bcdd4f","unresolved":false,"context_lines":[{"line_number":16,"context_line":"import os"},{"line_number":17,"context_line":"import time"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"import eventlet"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from oslo_config import cfg"},{"line_number":22,"context_line":"from oslo_log import log as logging"}],"source_content_type":"text/x-python","patch_set":1,"id":"3a71b18c_9ede760f","line":19,"updated":"2016-12-05 21:24:52.000000000","message":"why the new line?  should be in alphabetical","commit_id":"cbe30ae913b2fd39468ad9afe97c6649ba74ff3f"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"a0dffac189eaffefbf5d71148aa88aa8389e66a3","unresolved":false,"context_lines":[{"line_number":16,"context_line":"import os"},{"line_number":17,"context_line":"import time"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"import eventlet"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from oslo_config import cfg"},{"line_number":22,"context_line":"from oslo_log import log as logging"}],"source_content_type":"text/x-python","patch_set":1,"id":"3a71b18c_d5defd0f","line":19,"in_reply_to":"3a71b18c_9ede760f","updated":"2016-12-06 06:15:46.000000000","message":"Right - will remove line 20.","commit_id":"cbe30ae913b2fd39468ad9afe97c6649ba74ff3f"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"a15abb9a816f91fc629f8801a398b806e6bcdd4f","unresolved":false,"context_lines":[{"line_number":44,"context_line":"execute \u003d utils.execute"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"class Throttler(object):"},{"line_number":48,"context_line":"    \"\"\"Throttle number of calls to a function to only once per \u0027threshold\u0027.\"\"\""},{"line_number":49,"context_line":"    def __init__(self, threshold):"},{"line_number":50,"context_line":"        self.threshold \u003d threshold"}],"source_content_type":"text/x-python","patch_set":1,"id":"3a71b18c_591b1873","line":47,"updated":"2016-12-05 21:24:52.000000000","message":"Throttle (no \u0027r\u0027) ?\n\nThis could also be done as a decorator, I couldn\u0027t help but google and see https://gist.github.com/ChrisTM/5834503","commit_id":"cbe30ae913b2fd39468ad9afe97c6649ba74ff3f"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"a0dffac189eaffefbf5d71148aa88aa8389e66a3","unresolved":false,"context_lines":[{"line_number":44,"context_line":"execute \u003d utils.execute"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"class Throttler(object):"},{"line_number":48,"context_line":"    \"\"\"Throttle number of calls to a function to only once per \u0027threshold\u0027.\"\"\""},{"line_number":49,"context_line":"    def __init__(self, threshold):"},{"line_number":50,"context_line":"        self.threshold \u003d threshold"}],"source_content_type":"text/x-python","patch_set":1,"id":"3a71b18c_f50a1989","line":47,"in_reply_to":"3a71b18c_591b1873","updated":"2016-12-06 06:15:46.000000000","message":"Awesome code snippet, will convert this to a decorator and will try to simplify the code a bit.","commit_id":"cbe30ae913b2fd39468ad9afe97c6649ba74ff3f"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"9fc5ed99db433dcab3a0439df2cbd35f396ee327","unresolved":false,"context_lines":[{"line_number":44,"context_line":"execute \u003d utils.execute"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"class Throttler(object):"},{"line_number":48,"context_line":"    \"\"\"Throttle number of calls to a function to only once per \u0027threshold\u0027.\"\"\""},{"line_number":49,"context_line":"    def __init__(self, threshold):"},{"line_number":50,"context_line":"        self.threshold \u003d threshold"}],"source_content_type":"text/x-python","patch_set":1,"id":"3a71b18c_30b3bfea","line":47,"in_reply_to":"3a71b18c_f50a1989","updated":"2016-12-06 06:50:33.000000000","message":"Implementing this, it\u0027s a bit complicated since the timeout is a function of \"self.advert_int\", which is a configuration option. Unless I statically change \u0027self.spawn\u0027 in the constructor (which is ugly) a decorator doesn\u0027t work for this case.\n\nI will use datetime though, as it makes the code a lot more clear.","commit_id":"cbe30ae913b2fd39468ad9afe97c6649ba74ff3f"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"a15abb9a816f91fc629f8801a398b806e6bcdd4f","unresolved":false,"context_lines":[{"line_number":59,"context_line":"        now \u003d time.time()"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        if self.last_called_timestamp is None:"},{"line_number":62,"context_line":"            # \u0027function\u0027 wasn\u0027t called yet, so it\u0027s probably safe to call it."},{"line_number":63,"context_line":"            self.last_called_timestamp \u003d now"},{"line_number":64,"context_line":"            function(*args, **kwargs)"},{"line_number":65,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"3a71b18c_7e8efad0","line":62,"updated":"2016-12-05 21:24:52.000000000","message":"proabably?  I hope it\u0027s safe :)","commit_id":"cbe30ae913b2fd39468ad9afe97c6649ba74ff3f"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"a0dffac189eaffefbf5d71148aa88aa8389e66a3","unresolved":false,"context_lines":[{"line_number":59,"context_line":"        now \u003d time.time()"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        if self.last_called_timestamp is None:"},{"line_number":62,"context_line":"            # \u0027function\u0027 wasn\u0027t called yet, so it\u0027s probably safe to call it."},{"line_number":63,"context_line":"            self.last_called_timestamp \u003d now"},{"line_number":64,"context_line":"            function(*args, **kwargs)"},{"line_number":65,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"3a71b18c_3501f16a","line":62,"in_reply_to":"3a71b18c_7e8efad0","updated":"2016-12-06 06:15:46.000000000","message":"Me too! :P","commit_id":"cbe30ae913b2fd39468ad9afe97c6649ba74ff3f"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"771cd8fb2fdefab14784a12ffd570704f29c26b5","unresolved":false,"context_lines":[{"line_number":56,"context_line":"        self.is_deferred \u003d False"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    def call(self, function, *args, **kwargs):"},{"line_number":59,"context_line":"        now \u003d datetime.datetime.now()"},{"line_number":60,"context_line":"        time_since_last_call \u003d now - self.time_of_last_call"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        if self.is_deferred:"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a71b18c_676731b7","line":59,"updated":"2016-12-06 12:29:23.000000000","message":"this is suspiciously close to https://github.com/openstack/neutron/blob/master/neutron/notifiers/batch_notifier.py\n\ncan we just use that instead?","commit_id":"743999886d458d3548faf1f3788b9b8234342091"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"797c2db0f9263749b295876a700b0554a59607b3","unresolved":false,"context_lines":[{"line_number":56,"context_line":"        self.is_deferred \u003d False"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    def call(self, function, *args, **kwargs):"},{"line_number":59,"context_line":"        now \u003d datetime.datetime.now()"},{"line_number":60,"context_line":"        time_since_last_call \u003d now - self.time_of_last_call"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        if self.is_deferred:"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a71b18c_c743a56a","line":59,"in_reply_to":"3a71b18c_676731b7","updated":"2016-12-06 12:49:19.000000000","message":"Ignore this comment. we need to keep this synchronous without additional spawn calls so the main processing logic can capture exceptions and schedule resyncs.","commit_id":"743999886d458d3548faf1f3788b9b8234342091"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"da8bb4be5aa6c02911d9a90dafd505821ce5a219","unresolved":false,"context_lines":[{"line_number":68,"context_line":"            # We\u0027re in timeout, so we should throttle future calls."},{"line_number":69,"context_line":"            self.is_deferred \u003d True"},{"line_number":70,"context_line":"            time_to_wait \u003d self.throttle_period - time_since_last_call"},{"line_number":71,"context_line":"            eventlet.sleep(time_to_wait.total_seconds())"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"            self.time_of_last_call \u003d now"},{"line_number":74,"context_line":"            function(*args, **kwargs)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3a71b18c_a23777fd","line":71,"updated":"2016-12-06 13:16:29.000000000","message":"I think you want to recalculate \u0027now\u0027 after the sleep, otherwise \u0027time_of_last_call\u0027 will be set to a time way before the last call.","commit_id":"3066ce93f92985d541b7a66d07600d1e45b70806"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"d69a0e68be94ac2e738e95cef198c96c5e38afa3","unresolved":false,"context_lines":[{"line_number":68,"context_line":"            # We\u0027re in timeout, so we should throttle future calls."},{"line_number":69,"context_line":"            self.is_deferred \u003d True"},{"line_number":70,"context_line":"            time_to_wait \u003d self.throttle_period - time_since_last_call"},{"line_number":71,"context_line":"            eventlet.sleep(time_to_wait.total_seconds())"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"            self.time_of_last_call \u003d now"},{"line_number":74,"context_line":"            function(*args, **kwargs)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3a71b18c_bde6b8e5","line":71,"in_reply_to":"3a71b18c_a23777fd","updated":"2016-12-06 13:29:29.000000000","message":"Done","commit_id":"3066ce93f92985d541b7a66d07600d1e45b70806"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"da8bb4be5aa6c02911d9a90dafd505821ce5a219","unresolved":false,"context_lines":[{"line_number":70,"context_line":"            time_to_wait \u003d self.throttle_period - time_since_last_call"},{"line_number":71,"context_line":"            eventlet.sleep(time_to_wait.total_seconds())"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"            self.time_of_last_call \u003d now"},{"line_number":74,"context_line":"            function(*args, **kwargs)"},{"line_number":75,"context_line":"            self.is_deferred \u003d False"},{"line_number":76,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"3a71b18c_222447c3","line":73,"updated":"2016-12-06 13:16:29.000000000","message":"i think you can move these 3 lines outside of the conditional, then completely get rid of the else block to shorten this up...","commit_id":"3066ce93f92985d541b7a66d07600d1e45b70806"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"d69a0e68be94ac2e738e95cef198c96c5e38afa3","unresolved":false,"context_lines":[{"line_number":70,"context_line":"            time_to_wait \u003d self.throttle_period - time_since_last_call"},{"line_number":71,"context_line":"            eventlet.sleep(time_to_wait.total_seconds())"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"            self.time_of_last_call \u003d now"},{"line_number":74,"context_line":"            function(*args, **kwargs)"},{"line_number":75,"context_line":"            self.is_deferred \u003d False"},{"line_number":76,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"3a71b18c_9de3bcd8","line":73,"in_reply_to":"3a71b18c_222447c3","updated":"2016-12-06 13:29:29.000000000","message":"Done","commit_id":"3066ce93f92985d541b7a66d07600d1e45b70806"},{"author":{"_account_id":10267,"name":"venkata anil","email":"anilvenkata@redhat.com","username":"anil"},"change_message_id":"b5ec6f6a3257ea993160a4d37dc6c20ae78ec6e0","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        # If it has been, then it will do so in less than"},{"line_number":63,"context_line":"        # \u0027self.throttle_period\u0027 seconds."},{"line_number":64,"context_line":"        if not self.is_deferred:"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"            if time_since_last_call \u003c self.throttle_period:"},{"line_number":67,"context_line":"                # We\u0027re in timeout, so we should throttle future calls."},{"line_number":68,"context_line":"                self.is_deferred \u003d True"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a71b18c_ed66bbb9","line":65,"updated":"2016-12-06 16:00:41.000000000","message":"can we move line 59 to here?","commit_id":"86f65e5c7941563d53731d9a9407d97d79151ef0"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"74ec4104f8f1d97720c1305c168ba4285f9bd82b","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        # If it has been, then it will do so in less than"},{"line_number":63,"context_line":"        # \u0027self.throttle_period\u0027 seconds."},{"line_number":64,"context_line":"        if not self.is_deferred:"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"            if time_since_last_call \u003c self.throttle_period:"},{"line_number":67,"context_line":"                # We\u0027re in timeout, so we should throttle future calls."},{"line_number":68,"context_line":"                self.is_deferred \u003d True"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a71b18c_58e76bab","line":65,"in_reply_to":"3a71b18c_ed66bbb9","updated":"2016-12-06 16:11:57.000000000","message":"sure.","commit_id":"86f65e5c7941563d53731d9a9407d97d79151ef0"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"7b4a8ed8aea69a50e84748d85cfec3cc35cf6a8f","unresolved":false,"context_lines":[{"line_number":46,"context_line":"class Throttler(object):"},{"line_number":47,"context_line":"    \"\"\"Throttle number of calls to a function to only once per \u0027threshold\u0027."},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"    Loosly based on https://gist.github.com/ChrisTM/5834503."},{"line_number":50,"context_line":"    \"\"\""},{"line_number":51,"context_line":"    def __init__(self, seconds\u003d0):"},{"line_number":52,"context_line":"        self.throttle_period \u003d datetime.timedelta(seconds\u003dseconds)"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6eadb0_af30db57","line":49,"updated":"2016-12-13 13:13:56.000000000","message":"what\u0027s the license of the code?","commit_id":"3adc12fdc957b517449823f134c6478032e67caf"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"129bc938df43926d5622ff10d4cf93cb8283979c","unresolved":false,"context_lines":[{"line_number":46,"context_line":"class Throttler(object):"},{"line_number":47,"context_line":"    \"\"\"Throttle number of calls to a function to only once per \u0027threshold\u0027."},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"    Loosly based on https://gist.github.com/ChrisTM/5834503."},{"line_number":50,"context_line":"    \"\"\""},{"line_number":51,"context_line":"    def __init__(self, seconds\u003d0):"},{"line_number":52,"context_line":"        self.throttle_period \u003d datetime.timedelta(seconds\u003dseconds)"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6eadb0_f2d638c4","line":49,"in_reply_to":"1a6eadb0_52ae0c86","updated":"2016-12-13 13:39:49.000000000","message":"Meaning you don\u0027t have any right to share it.","commit_id":"3adc12fdc957b517449823f134c6478032e67caf"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"44194216d2f1db893502170aa663c41a9239e479","unresolved":false,"context_lines":[{"line_number":46,"context_line":"class Throttler(object):"},{"line_number":47,"context_line":"    \"\"\"Throttle number of calls to a function to only once per \u0027threshold\u0027."},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"    Loosly based on https://gist.github.com/ChrisTM/5834503."},{"line_number":50,"context_line":"    \"\"\""},{"line_number":51,"context_line":"    def __init__(self, seconds\u003d0):"},{"line_number":52,"context_line":"        self.throttle_period \u003d datetime.timedelta(seconds\u003dseconds)"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6eadb0_52ae0c86","line":49,"in_reply_to":"1a6eadb0_af30db57","updated":"2016-12-13 13:35:06.000000000","message":"I don\u0027t think that code has any license...","commit_id":"3adc12fdc957b517449823f134c6478032e67caf"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"d138d1716ef6c535fae6ecb63a8e8cc6df493003","unresolved":false,"context_lines":[{"line_number":49,"context_line":"    Loosly based on https://gist.github.com/ChrisTM/5834503."},{"line_number":50,"context_line":"    \"\"\""},{"line_number":51,"context_line":"    def __init__(self, seconds\u003d0):"},{"line_number":52,"context_line":"        self.throttle_period \u003d datetime.timedelta(seconds\u003dseconds)"},{"line_number":53,"context_line":"        self.time_of_last_call \u003d datetime.datetime.min"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"        # Is the function already running and should future calls be deferred?"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6eadb0_617a21f3","line":52,"range":{"start_line":52,"start_character":31,"end_line":52,"end_character":66},"updated":"2016-12-14 12:51:58.000000000","message":"You use datetime but then you work with order of seconds. You should be fine storing the seconds instead of using datetime objects.","commit_id":"3adc12fdc957b517449823f134c6478032e67caf"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"efabe88fe89f7051bce0bf1d59d44fc25badda80","unresolved":false,"context_lines":[{"line_number":49,"context_line":"    Loosly based on https://gist.github.com/ChrisTM/5834503."},{"line_number":50,"context_line":"    \"\"\""},{"line_number":51,"context_line":"    def __init__(self, seconds\u003d0):"},{"line_number":52,"context_line":"        self.throttle_period \u003d datetime.timedelta(seconds\u003dseconds)"},{"line_number":53,"context_line":"        self.time_of_last_call \u003d datetime.datetime.min"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"        # Is the function already running and should future calls be deferred?"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6eadb0_1c7470cd","line":52,"range":{"start_line":52,"start_character":31,"end_line":52,"end_character":66},"in_reply_to":"1a6eadb0_617a21f3","updated":"2016-12-14 13:11:09.000000000","message":"Done","commit_id":"3adc12fdc957b517449823f134c6478032e67caf"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"d138d1716ef6c535fae6ecb63a8e8cc6df493003","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        if not self.is_deferred:"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"            time_since_last_call \u003d ("},{"line_number":65,"context_line":"                datetime.datetime.now() - self.time_of_last_call)"},{"line_number":66,"context_line":"            if time_since_last_call \u003c self.throttle_period:"},{"line_number":67,"context_line":"                # We\u0027re in timeout, so we should throttle future calls."},{"line_number":68,"context_line":"                self.is_deferred \u003d True"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6eadb0_61c86123","line":65,"range":{"start_line":65,"start_character":16,"end_line":65,"end_character":39},"updated":"2016-12-14 12:51:58.000000000","message":"time.time()","commit_id":"3adc12fdc957b517449823f134c6478032e67caf"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"efabe88fe89f7051bce0bf1d59d44fc25badda80","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        if not self.is_deferred:"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"            time_since_last_call \u003d ("},{"line_number":65,"context_line":"                datetime.datetime.now() - self.time_of_last_call)"},{"line_number":66,"context_line":"            if time_since_last_call \u003c self.throttle_period:"},{"line_number":67,"context_line":"                # We\u0027re in timeout, so we should throttle future calls."},{"line_number":68,"context_line":"                self.is_deferred \u003d True"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6eadb0_fc7894c6","line":65,"range":{"start_line":65,"start_character":16,"end_line":65,"end_character":39},"in_reply_to":"1a6eadb0_61c86123","updated":"2016-12-14 13:11:09.000000000","message":"Done","commit_id":"3adc12fdc957b517449823f134c6478032e67caf"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"d138d1716ef6c535fae6ecb63a8e8cc6df493003","unresolved":false,"context_lines":[{"line_number":70,"context_line":"                eventlet.sleep(time_to_wait.total_seconds())"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"            self.time_of_last_call \u003d datetime.datetime.now()"},{"line_number":73,"context_line":"            function(*args, **kwargs)"},{"line_number":74,"context_line":"            self.is_deferred \u003d False"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6eadb0_e1f9d181","line":73,"range":{"start_line":73,"start_character":12,"end_line":73,"end_character":20},"updated":"2016-12-14 12:51:58.000000000","message":"What if function raises an exception here. Then you leave is_deferred in True state. I suggest to implement this with context manager.","commit_id":"3adc12fdc957b517449823f134c6478032e67caf"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"efabe88fe89f7051bce0bf1d59d44fc25badda80","unresolved":false,"context_lines":[{"line_number":70,"context_line":"                eventlet.sleep(time_to_wait.total_seconds())"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"            self.time_of_last_call \u003d datetime.datetime.now()"},{"line_number":73,"context_line":"            function(*args, **kwargs)"},{"line_number":74,"context_line":"            self.is_deferred \u003d False"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6eadb0_bcd29cd0","line":73,"range":{"start_line":73,"start_character":12,"end_line":73,"end_character":20},"in_reply_to":"1a6eadb0_e1f9d181","updated":"2016-12-14 13:11:09.000000000","message":"Done","commit_id":"3adc12fdc957b517449823f134c6478032e67caf"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"a89bb51a850d073a1a721adf0871f115a5d485c8","unresolved":false,"context_lines":[{"line_number":46,"context_line":"class Throttler(object):"},{"line_number":47,"context_line":"    \"\"\"Throttle number of calls to a function to only once per \u0027threshold\u0027."},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"    :param threshold: minimum time betwen 2 \u0027function\u0027 calls, in seconds."},{"line_number":50,"context_line":"    \"\"\""},{"line_number":51,"context_line":"    def __init__(self, threshold\u003d0):"},{"line_number":52,"context_line":"        self.threshold \u003d threshold"}],"source_content_type":"text/x-python","patch_set":15,"id":"1a6eadb0_12ac59ec","line":49,"range":{"start_line":49,"start_character":4,"end_line":49,"end_character":73},"updated":"2016-12-14 13:51:16.000000000","message":"This docstring belongs to __init__","commit_id":"d6945e59db27ce0ef51abfa93977d3788b48a52a"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"11c17f01fcba4cd34d1e093c7158eccea65ff82b","unresolved":false,"context_lines":[{"line_number":46,"context_line":"class Throttler(object):"},{"line_number":47,"context_line":"    \"\"\"Throttle number of calls to a function to only once per \u0027threshold\u0027."},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"    :param threshold: minimum time betwen 2 \u0027function\u0027 calls, in seconds."},{"line_number":50,"context_line":"    \"\"\""},{"line_number":51,"context_line":"    def __init__(self, threshold\u003d0):"},{"line_number":52,"context_line":"        self.threshold \u003d threshold"}],"source_content_type":"text/x-python","patch_set":15,"id":"1a6eadb0_0d458516","line":49,"range":{"start_line":49,"start_character":4,"end_line":49,"end_character":73},"in_reply_to":"1a6eadb0_12ac59ec","updated":"2016-12-18 09:31:38.000000000","message":"Done","commit_id":"d6945e59db27ce0ef51abfa93977d3788b48a52a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"a89bb51a850d073a1a721adf0871f115a5d485c8","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        # seconds."},{"line_number":62,"context_line":"        if not self.is_deferred:"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"            time_since_last_call \u003d ("},{"line_number":65,"context_line":"                time.time() - self.last_time_called)"},{"line_number":66,"context_line":"            if time_since_last_call \u003c self.threshold:"},{"line_number":67,"context_line":"                # We\u0027re in timeout, so we should throttle future calls."}],"source_content_type":"text/x-python","patch_set":15,"id":"1a6eadb0_32f4f584","line":64,"range":{"start_line":64,"start_character":35,"end_line":64,"end_character":36},"updated":"2016-12-14 13:51:16.000000000","message":"Why is it wrapped? It can fit this line.","commit_id":"d6945e59db27ce0ef51abfa93977d3788b48a52a"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"11c17f01fcba4cd34d1e093c7158eccea65ff82b","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        # seconds."},{"line_number":62,"context_line":"        if not self.is_deferred:"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"            time_since_last_call \u003d ("},{"line_number":65,"context_line":"                time.time() - self.last_time_called)"},{"line_number":66,"context_line":"            if time_since_last_call \u003c self.threshold:"},{"line_number":67,"context_line":"                # We\u0027re in timeout, so we should throttle future calls."}],"source_content_type":"text/x-python","patch_set":15,"id":"1a6eadb0_2d4a4128","line":64,"range":{"start_line":64,"start_character":35,"end_line":64,"end_character":36},"in_reply_to":"1a6eadb0_32f4f584","updated":"2016-12-18 09:31:38.000000000","message":"Done","commit_id":"d6945e59db27ce0ef51abfa93977d3788b48a52a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"a89bb51a850d073a1a721adf0871f115a5d485c8","unresolved":false,"context_lines":[{"line_number":67,"context_line":"                # We\u0027re in timeout, so we should throttle future calls."},{"line_number":68,"context_line":"                self.is_deferred \u003d True"},{"line_number":69,"context_line":"                time_to_wait \u003d self.threshold - time_since_last_call"},{"line_number":70,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"            self.last_time_called \u003d time.time()"},{"line_number":73,"context_line":"            try:"}],"source_content_type":"text/x-python","patch_set":15,"id":"1a6eadb0_72eaed10","line":70,"range":{"start_line":70,"start_character":16,"end_line":70,"end_character":44},"updated":"2016-12-14 13:51:16.000000000","message":"Being paranoid, what if this raises an exception like KeyboardInterrupt? I\u0027d either implement the context manager or put the whole function to try block.","commit_id":"d6945e59db27ce0ef51abfa93977d3788b48a52a"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"11c17f01fcba4cd34d1e093c7158eccea65ff82b","unresolved":false,"context_lines":[{"line_number":67,"context_line":"                # We\u0027re in timeout, so we should throttle future calls."},{"line_number":68,"context_line":"                self.is_deferred \u003d True"},{"line_number":69,"context_line":"                time_to_wait \u003d self.threshold - time_since_last_call"},{"line_number":70,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"            self.last_time_called \u003d time.time()"},{"line_number":73,"context_line":"            try:"}],"source_content_type":"text/x-python","patch_set":15,"id":"1a6eadb0_cd2f0d3d","line":70,"range":{"start_line":70,"start_character":16,"end_line":70,"end_character":44},"in_reply_to":"1a6eadb0_72eaed10","updated":"2016-12-18 09:31:38.000000000","message":"Done, though I think it complicated the code a bit. What do you think?","commit_id":"d6945e59db27ce0ef51abfa93977d3788b48a52a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"a89bb51a850d073a1a721adf0871f115a5d485c8","unresolved":false,"context_lines":[{"line_number":73,"context_line":"            try:"},{"line_number":74,"context_line":"                function(*args, **kwargs)"},{"line_number":75,"context_line":"            finally:"},{"line_number":76,"context_line":"                self.is_deferred \u003d False"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":""},{"line_number":79,"context_line":"def load_interface_driver(conf):"}],"source_content_type":"text/x-python","patch_set":15,"id":"1a6eadb0_ed73807e","line":76,"range":{"start_line":76,"start_character":0,"end_line":76,"end_character":40},"updated":"2016-12-14 13:51:16.000000000","message":"I think this is race-y. Let\u0027s say we have a three coroutines scheduled to call function. First one gets to L74 and function yields. Second coroutine gets in before threshold and gets to L68, sets is_deferred and sleeps on L70 -\u003e yields. First coroutine is finished and unsets on L76. Third coroutine enters still before threshold so L62 doesn\u0027t influence it as planned and gets to L70, sleeps similar time as second coroutine. Then both, second and third coroutines call function in very short time difference.","commit_id":"d6945e59db27ce0ef51abfa93977d3788b48a52a"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"11c17f01fcba4cd34d1e093c7158eccea65ff82b","unresolved":false,"context_lines":[{"line_number":73,"context_line":"            try:"},{"line_number":74,"context_line":"                function(*args, **kwargs)"},{"line_number":75,"context_line":"            finally:"},{"line_number":76,"context_line":"                self.is_deferred \u003d False"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":""},{"line_number":79,"context_line":"def load_interface_driver(conf):"}],"source_content_type":"text/x-python","patch_set":15,"id":"1a6eadb0_4d477d1d","line":76,"range":{"start_line":76,"start_character":0,"end_line":76,"end_character":40},"in_reply_to":"1a6eadb0_ed73807e","updated":"2016-12-18 09:31:38.000000000","message":"Give that man a cookie! Nice catch.","commit_id":"d6945e59db27ce0ef51abfa93977d3788b48a52a"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"964dbb2bcee2ecd570a4863d2cfee04d7fddad6a","unresolved":false,"context_lines":[{"line_number":49,"context_line":"    def __init__(self, threshold\u003d0):"},{"line_number":50,"context_line":"        \"\"\"Initialize a new Throttler."},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        :param threshold: minimum time betwen 2 \u0027function\u0027 calls, in seconds."},{"line_number":53,"context_line":"        \"\"\""},{"line_number":54,"context_line":"        self.threshold \u003d threshold"},{"line_number":55,"context_line":"        self.last_time_called \u003d time.time() - threshold"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_84902197","line":52,"range":{"start_line":52,"start_character":39,"end_line":52,"end_character":45},"updated":"2017-01-10 21:27:39.000000000","message":"between","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":49,"context_line":"    def __init__(self, threshold\u003d0):"},{"line_number":50,"context_line":"        \"\"\"Initialize a new Throttler."},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        :param threshold: minimum time betwen 2 \u0027function\u0027 calls, in seconds."},{"line_number":53,"context_line":"        \"\"\""},{"line_number":54,"context_line":"        self.threshold \u003d threshold"},{"line_number":55,"context_line":"        self.last_time_called \u003d time.time() - threshold"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_f5d8a381","line":52,"range":{"start_line":52,"start_character":39,"end_line":52,"end_character":45},"in_reply_to":"ba5201f7_84902197","updated":"2017-01-16 13:22:12.000000000","message":"Done","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"cc6f4c0694df1e03ea2b24014916fd38c602b2e1","unresolved":false,"context_lines":[{"line_number":57,"context_line":"        # Is the function already running and should future calls be deferred?"},{"line_number":58,"context_line":"        self.is_deferred \u003d False"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"    def sleep_until(self, time_to_sleep_until):"},{"line_number":61,"context_line":"        while True:"},{"line_number":62,"context_line":"            time_to_wait \u003d self.last_time_called - time.time() + self.threshold"},{"line_number":63,"context_line":"            if time_to_wait \u003c 0:"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_bfb30009","line":60,"range":{"start_line":60,"start_character":26,"end_line":60,"end_character":45},"updated":"2017-01-06 10:51:29.000000000","message":"It\u0027s unused","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":57,"context_line":"        # Is the function already running and should future calls be deferred?"},{"line_number":58,"context_line":"        self.is_deferred \u003d False"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"    def sleep_until(self, time_to_sleep_until):"},{"line_number":61,"context_line":"        while True:"},{"line_number":62,"context_line":"            time_to_wait \u003d self.last_time_called - time.time() + self.threshold"},{"line_number":63,"context_line":"            if time_to_wait \u003c 0:"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_15e8c70f","line":60,"range":{"start_line":60,"start_character":26,"end_line":60,"end_character":45},"in_reply_to":"ba5201f7_bfb30009","updated":"2017-01-16 13:22:12.000000000","message":"Done","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"964dbb2bcee2ecd570a4863d2cfee04d7fddad6a","unresolved":false,"context_lines":[{"line_number":62,"context_line":"            time_to_wait \u003d self.last_time_called - time.time() + self.threshold"},{"line_number":63,"context_line":"            if time_to_wait \u003c 0:"},{"line_number":64,"context_line":"                break"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"            try:"},{"line_number":67,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":68,"context_line":"                break"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_64c5fd3b","line":65,"updated":"2017-01-10 21:27:39.000000000","message":"unneeded line","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":62,"context_line":"            time_to_wait \u003d self.last_time_called - time.time() + self.threshold"},{"line_number":63,"context_line":"            if time_to_wait \u003c 0:"},{"line_number":64,"context_line":"                break"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"            try:"},{"line_number":67,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":68,"context_line":"                break"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a3c09a3_544b3d87","line":65,"in_reply_to":"ba5201f7_381e7fbb","updated":"2017-01-16 13:22:12.000000000","message":"Likewise, I also like spacing to make it more intuitive where the code goes from one logical segment to another.","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"10659b1513dd3ea38e6c68d23b2ca4f7fb1f1a6d","unresolved":false,"context_lines":[{"line_number":62,"context_line":"            time_to_wait \u003d self.last_time_called - time.time() + self.threshold"},{"line_number":63,"context_line":"            if time_to_wait \u003c 0:"},{"line_number":64,"context_line":"                break"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"            try:"},{"line_number":67,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":68,"context_line":"                break"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_381e7fbb","line":65,"in_reply_to":"ba5201f7_64c5fd3b","updated":"2017-01-11 19:43:54.000000000","message":"I personally like leaving some spacing for readability :P :)","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"cc6f4c0694df1e03ea2b24014916fd38c602b2e1","unresolved":false,"context_lines":[{"line_number":66,"context_line":"            try:"},{"line_number":67,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":68,"context_line":"                break"},{"line_number":69,"context_line":"            except KeyboardInterrupt:"},{"line_number":70,"context_line":"                pass"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    def call(self, function, *args, **kwargs):"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_3ff1d0cd","line":69,"range":{"start_line":69,"start_character":0,"end_line":69,"end_character":37},"updated":"2017-01-06 10:51:29.000000000","message":"In my previous comment I gave this only as an example. The point was to make a context manager. It doesn\u0027t make sense to catch this exception specifically.","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"26bbf357e833554255775cce6d6793dcdfae9b4d","unresolved":false,"context_lines":[{"line_number":66,"context_line":"            try:"},{"line_number":67,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":68,"context_line":"                break"},{"line_number":69,"context_line":"            except KeyboardInterrupt:"},{"line_number":70,"context_line":"                pass"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    def call(self, function, *args, **kwargs):"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_7534b3fa","line":69,"range":{"start_line":69,"start_character":0,"end_line":69,"end_character":37},"in_reply_to":"ba5201f7_3ff1d0cd","updated":"2017-01-11 09:36:05.000000000","message":"My concerns were about not leaving is_deferred set to True in case of exceptions raised between L81 and L88. To avoid that, I wanted something like:\n\n @contextlib.contextmanager\n def defer_call(self):\n     self.is_deffered \u003d True\n     try:\n         yield\n     finally:\n         self.is_deffered \u003d False\n\n\n def call():\n     if not self.is_deferred:\n         with self.defer_call():\n             do_your_business_here()","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":66,"context_line":"            try:"},{"line_number":67,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":68,"context_line":"                break"},{"line_number":69,"context_line":"            except KeyboardInterrupt:"},{"line_number":70,"context_line":"                pass"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    def call(self, function, *args, **kwargs):"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a3c09a3_c773fd7e","line":69,"range":{"start_line":69,"start_character":0,"end_line":69,"end_character":37},"in_reply_to":"ba5201f7_7534b3fa","updated":"2017-01-16 13:22:12.000000000","message":"Done","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"10659b1513dd3ea38e6c68d23b2ca4f7fb1f1a6d","unresolved":false,"context_lines":[{"line_number":73,"context_line":"        # Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":74,"context_line":"        # If it has been, then it will do so in less than \u0027self.threshold\u0027"},{"line_number":75,"context_line":"        # seconds."},{"line_number":76,"context_line":"        if not self.is_deferred:"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"            time_since_last_call \u003d time.time() - self.last_time_called"},{"line_number":79,"context_line":"            if time_since_last_call \u003c self.threshold:"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_98668b4f","line":76,"updated":"2017-01-11 19:43:54.000000000","message":"I\u0027d add a TODO here saying that if we ever stop using greenthreads we\u0027d need a mutex/locking here.","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":73,"context_line":"        # Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":74,"context_line":"        # If it has been, then it will do so in less than \u0027self.threshold\u0027"},{"line_number":75,"context_line":"        # seconds."},{"line_number":76,"context_line":"        if not self.is_deferred:"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"            time_since_last_call \u003d time.time() - self.last_time_called"},{"line_number":79,"context_line":"            if time_since_last_call \u003c self.threshold:"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a3c09a3_1431b505","line":76,"in_reply_to":"ba5201f7_98668b4f","updated":"2017-01-16 13:22:12.000000000","message":"Done","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"964dbb2bcee2ecd570a4863d2cfee04d7fddad6a","unresolved":false,"context_lines":[{"line_number":74,"context_line":"        # If it has been, then it will do so in less than \u0027self.threshold\u0027"},{"line_number":75,"context_line":"        # seconds."},{"line_number":76,"context_line":"        if not self.is_deferred:"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"            time_since_last_call \u003d time.time() - self.last_time_called"},{"line_number":79,"context_line":"            if time_since_last_call \u003c self.threshold:"},{"line_number":80,"context_line":"                # We\u0027re in timeout, so we should throttle future calls."}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_845581c7","line":77,"updated":"2017-01-10 21:27:39.000000000","message":"nit: what the line for?","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":74,"context_line":"        # If it has been, then it will do so in less than \u0027self.threshold\u0027"},{"line_number":75,"context_line":"        # seconds."},{"line_number":76,"context_line":"        if not self.is_deferred:"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"            time_since_last_call \u003d time.time() - self.last_time_called"},{"line_number":79,"context_line":"            if time_since_last_call \u003c self.threshold:"},{"line_number":80,"context_line":"                # We\u0027re in timeout, so we should throttle future calls."}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_75d67328","line":77,"in_reply_to":"ba5201f7_845581c7","updated":"2017-01-16 13:22:12.000000000","message":"ditto","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"cc6f4c0694df1e03ea2b24014916fd38c602b2e1","unresolved":false,"context_lines":[{"line_number":83,"context_line":"                self.last_time_called \u003d time.time()"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"                try:"},{"line_number":86,"context_line":"                    function(*args, **kwargs)"},{"line_number":87,"context_line":"                finally:"},{"line_number":88,"context_line":"                    self.is_deferred \u003d False"},{"line_number":89,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_9f955c34","line":86,"updated":"2017-01-06 10:51:29.000000000","message":"return function(*args, **kwargs)","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":83,"context_line":"                self.last_time_called \u003d time.time()"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"                try:"},{"line_number":86,"context_line":"                    function(*args, **kwargs)"},{"line_number":87,"context_line":"                finally:"},{"line_number":88,"context_line":"                    self.is_deferred \u003d False"},{"line_number":89,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_b5e0dbfb","line":86,"in_reply_to":"ba5201f7_9f955c34","updated":"2017-01-16 13:22:12.000000000","message":"Done","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"964dbb2bcee2ecd570a4863d2cfee04d7fddad6a","unresolved":false,"context_lines":[{"line_number":86,"context_line":"                    function(*args, **kwargs)"},{"line_number":87,"context_line":"                finally:"},{"line_number":88,"context_line":"                    self.is_deferred \u003d False"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"            else:"},{"line_number":91,"context_line":"                self.last_time_called \u003d time.time()"},{"line_number":92,"context_line":"                function(*args, **kwargs)"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_245bf5f7","line":89,"updated":"2017-01-10 21:27:39.000000000","message":"nit: what\u0027s the line for","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":86,"context_line":"                    function(*args, **kwargs)"},{"line_number":87,"context_line":"                finally:"},{"line_number":88,"context_line":"                    self.is_deferred \u003d False"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"            else:"},{"line_number":91,"context_line":"                self.last_time_called \u003d time.time()"},{"line_number":92,"context_line":"                function(*args, **kwargs)"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a3c09a3_d45f2d3f","line":89,"in_reply_to":"ba5201f7_245bf5f7","updated":"2017-01-16 13:22:12.000000000","message":"ditto","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"cc6f4c0694df1e03ea2b24014916fd38c602b2e1","unresolved":false,"context_lines":[{"line_number":89,"context_line":""},{"line_number":90,"context_line":"            else:"},{"line_number":91,"context_line":"                self.last_time_called \u003d time.time()"},{"line_number":92,"context_line":"                function(*args, **kwargs)"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"def load_interface_driver(conf):"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_bf98606b","line":92,"updated":"2017-01-06 10:51:29.000000000","message":"ditto","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":89,"context_line":""},{"line_number":90,"context_line":"            else:"},{"line_number":91,"context_line":"                self.last_time_called \u003d time.time()"},{"line_number":92,"context_line":"                function(*args, **kwargs)"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"def load_interface_driver(conf):"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_75bd93d6","line":92,"in_reply_to":"ba5201f7_bf98606b","updated":"2017-01-16 13:22:12.000000000","message":"Done","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"19e8292114541c49ca74ea521b08486d3c920e81","unresolved":false,"context_lines":[{"line_number":59,"context_line":"        self.is_deferred \u003d False"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"    @contextlib.contextmanager"},{"line_number":62,"context_line":"    def defer_call(self):"},{"line_number":63,"context_line":"        self.is_deffered \u003d True"},{"line_number":64,"context_line":"        try:"},{"line_number":65,"context_line":"            yield"}],"source_content_type":"text/x-python","patch_set":18,"id":"7a3c09a3_4cc009e1","line":62,"range":{"start_line":62,"start_character":0,"end_line":62,"end_character":18},"updated":"2017-01-16 15:59:48.000000000","message":"Nice!","commit_id":"1823eab3a81b18c36afb266db2ab8ca4db286d9d"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ad6839ba8ed0b310b177dfab09187b0f3a6e16ee","unresolved":false,"context_lines":[{"line_number":74,"context_line":""},{"line_number":75,"context_line":"            eventlet.sleep(time_to_wait)"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def call(self, function, *args, **kwargs):"},{"line_number":78,"context_line":"        # Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":79,"context_line":"        # If it has been, then it will do so in less than \u0027self.threshold\u0027"},{"line_number":80,"context_line":"        # seconds."}],"source_content_type":"text/x-python","patch_set":25,"id":"3a461143_3bcfea56","line":77,"range":{"start_line":77,"start_character":0,"end_line":77,"end_character":12},"updated":"2017-02-01 12:02:25.000000000","message":"Is there a reason we don\u0027t use it as decorator? Based on the usage I see, it\u0027s only wrapping the private _spawn call in public spawn() method.\n\nIf we consider \u0027threshold\u0027 instance attribute as configuration interface, we can decorate method and then set the threshold attribute on the method.","commit_id":"32d9b1441cefb6a497271106842667750c366e20"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"e12b286830e0c7601c5389cc75e880e2085465e8","unresolved":false,"context_lines":[{"line_number":74,"context_line":""},{"line_number":75,"context_line":"            eventlet.sleep(time_to_wait)"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def call(self, function, *args, **kwargs):"},{"line_number":78,"context_line":"        # Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":79,"context_line":"        # If it has been, then it will do so in less than \u0027self.threshold\u0027"},{"line_number":80,"context_line":"        # seconds."}],"source_content_type":"text/x-python","patch_set":25,"id":"3a461143_ba780a2d","line":77,"range":{"start_line":77,"start_character":0,"end_line":77,"end_character":12},"in_reply_to":"3a461143_3bcfea56","updated":"2017-02-02 11:11:16.000000000","message":"Ignorant question: Is there a way to have a decorator that it\u0027s a class/object wrapper instead of a simple function wrapper?.\n\nHere keeping the state somewhere for each throttler is fundamental.","commit_id":"32d9b1441cefb6a497271106842667750c366e20"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"552d0587ccbbb11c5b13ce80b63e9a7da1ee89c9","unresolved":false,"context_lines":[{"line_number":74,"context_line":""},{"line_number":75,"context_line":"            eventlet.sleep(time_to_wait)"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def call(self, function, *args, **kwargs):"},{"line_number":78,"context_line":"        # Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":79,"context_line":"        # If it has been, then it will do so in less than \u0027self.threshold\u0027"},{"line_number":80,"context_line":"        # seconds."}],"source_content_type":"text/x-python","patch_set":25,"id":"3a461143_d06135d5","line":77,"range":{"start_line":77,"start_character":0,"end_line":77,"end_character":12},"in_reply_to":"3a461143_ba780a2d","updated":"2017-02-02 11:47:09.000000000","message":"Yes, there is :) Take a look e.g. here https://review.openstack.org/#/c/72680/20/neutron/common/utils.py@46","commit_id":"32d9b1441cefb6a497271106842667750c366e20"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"bf373be5a421d28adce784bcf6f304797c046ce8","unresolved":false,"context_lines":[{"line_number":74,"context_line":""},{"line_number":75,"context_line":"            eventlet.sleep(time_to_wait)"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def call(self, function, *args, **kwargs):"},{"line_number":78,"context_line":"        # Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":79,"context_line":"        # If it has been, then it will do so in less than \u0027self.threshold\u0027"},{"line_number":80,"context_line":"        # seconds."}],"source_content_type":"text/x-python","patch_set":25,"id":"1a430d35_9aae5ee4","line":77,"range":{"start_line":77,"start_character":0,"end_line":77,"end_character":12},"in_reply_to":"3a461143_d06135d5","updated":"2017-02-08 11:41:57.000000000","message":"Done","commit_id":"32d9b1441cefb6a497271106842667750c366e20"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"73ad587187d95cc801b35599c2e0bab640c600bb","unresolved":false,"context_lines":[{"line_number":35,"context_line":"    from neutron.agent.linux import utils"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"# Should match cfg.CONF.ha_vrrp_advert_int."},{"line_number":38,"context_line":"#TODO(jschwarz): using cfg.CONF.ha_vrrp_advert_int necessitates an import,"},{"line_number":39,"context_line":"# which results in a recursive import. This should be fixed into being the"},{"line_number":40,"context_line":"# actual config value."},{"line_number":41,"context_line":"DEFAULT_THROTTLER_VALUE \u003d 2"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa31d9ce_75253d07","line":38,"updated":"2017-02-15 08:13:32.000000000","message":"necessitates \u003d\u003e requires?","commit_id":"a0ce54b4a0cfc5a640aff8ba6d72e0bcf279b0fe"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"dc6e07221a35b0bef1d21bd0a16ee0a332d10018","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        \"\"\"Decorate a function with throttler.\"\"\""},{"line_number":59,"context_line":"        self._threshold \u003d DEFAULT_THROTTLER_VALUE"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        self._last_time_called \u003d time.time() - self.throttle_threshold"},{"line_number":62,"context_line":"        self._func \u003d func"},{"line_number":63,"context_line":"        # Is the function already running and should future calls be deferred?"},{"line_number":64,"context_line":"        self._is_deferred \u003d False"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa31d9ce_b3d97f59","line":61,"updated":"2017-02-15 09:38:19.000000000","message":"why not: self._last_time_called \u003d 0","commit_id":"a0ce54b4a0cfc5a640aff8ba6d72e0bcf279b0fe"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"73ad587187d95cc801b35599c2e0bab640c600bb","unresolved":false,"context_lines":[{"line_number":81,"context_line":"            self._is_deferred \u003d False"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"    def sleep(self):"},{"line_number":84,"context_line":"        while True:"},{"line_number":85,"context_line":"            time_to_wait \u003d (self._last_time_called - time.time()"},{"line_number":86,"context_line":"                            + self.throttle_threshold)"},{"line_number":87,"context_line":"            if time_to_wait \u003c 0:"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa31d9ce_c5ad549c","line":84,"updated":"2017-02-15 08:13:32.000000000","message":"a comment would be great to explain that the \"while True:\" is required if self.throttle_threshold is increased during eventlet.sleep call.","commit_id":"a0ce54b4a0cfc5a640aff8ba6d72e0bcf279b0fe"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"73ad587187d95cc801b35599c2e0bab640c600bb","unresolved":false,"context_lines":[{"line_number":89,"context_line":""},{"line_number":90,"context_line":"            eventlet.sleep(time_to_wait)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    def __call__(self, *args, **kwargs):"},{"line_number":93,"context_line":"        \"\"\"Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        If it has been, then it will do so in less than"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa31d9ce_a5594090","line":92,"updated":"2017-02-15 08:13:32.000000000","message":"IMO the main property should ensure is that when __call__ is called then self._func will be executed by the greenthread or a concurrent one after __call__ call\n\nBUT this code ensures that when __call__ is called that:\n\n* self._func will be executed by the current greenthread \u003d\u003d\u003e OK\n* or self._func will be executed by a concurrent greenthread \u003d\u003d\u003e OK\n* or self._func is currently executed by a concurrent greenthread \u003d\u003d\u003e self._func is executed but perhaps with outdated data \u003d\u003d\u003e KO","commit_id":"a0ce54b4a0cfc5a640aff8ba6d72e0bcf279b0fe"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"26198b6ef588bd5b75fcd0a542b164ee3eeed096","unresolved":false,"context_lines":[{"line_number":89,"context_line":""},{"line_number":90,"context_line":"            eventlet.sleep(time_to_wait)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    def __call__(self, *args, **kwargs):"},{"line_number":93,"context_line":"        \"\"\"Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        If it has been, then it will do so in less than"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa31d9ce_c1b8c82c","line":92,"in_reply_to":"fa31d9ce_26f7fd59","updated":"2017-02-15 16:12:00.000000000","message":"a typical failing example:\n\n @utils.throttler\n def func():\n   data \u003d get_data()\n   commit_data(data)\n\n* gt1 calls func \u003d\u003e func is executed in gt1 without delay\n* gt2 calls func while gt1 is executing func and more precisely commit_data(data) \u003d\u003e gt2 does nothing because gt1 is already running func which implies get_data() is never called after gt2 \"requested\" to execute func and commited_data are perhaps outdated.\n\ngtX: greenthreadX","commit_id":"a0ce54b4a0cfc5a640aff8ba6d72e0bcf279b0fe"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"c3c0e8d50d5033b88b11a63f8e7fe017c4e0cd25","unresolved":false,"context_lines":[{"line_number":89,"context_line":""},{"line_number":90,"context_line":"            eventlet.sleep(time_to_wait)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    def __call__(self, *args, **kwargs):"},{"line_number":93,"context_line":"        \"\"\"Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        If it has been, then it will do so in less than"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa31d9ce_613d5cdc","line":92,"in_reply_to":"fa31d9ce_4134d848","updated":"2017-02-15 16:25:22.000000000","message":"I disagree, replacing:\n\n def func():\n  data \u003d get_data()\n  commit_data(data)\n\nwith:\n\n def func_lock():\n   with LOCK:\n     data \u003d get_data()\n     commit_data(data)\n\nsolves the race condition without utils.throttler but previous scenario is still failing with utils.throttler(func_lock)","commit_id":"a0ce54b4a0cfc5a640aff8ba6d72e0bcf279b0fe"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"af469840969f6ec745f1fc660272c3bc1f988577","unresolved":false,"context_lines":[{"line_number":89,"context_line":""},{"line_number":90,"context_line":"            eventlet.sleep(time_to_wait)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    def __call__(self, *args, **kwargs):"},{"line_number":93,"context_line":"        \"\"\"Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        If it has been, then it will do so in less than"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa31d9ce_11b4cbcf","line":92,"in_reply_to":"fa31d9ce_613d5cdc","updated":"2017-02-16 11:28:22.000000000","message":"I\u0027m a bit lost with the comments.\n\nI understand some of the comments, like, the data being old, etc.. but that\u0027s specific to every use case. As long as the limitation is documented and understood by the user of the class, that should be ok.","commit_id":"a0ce54b4a0cfc5a640aff8ba6d72e0bcf279b0fe"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"b9750cdd239586c9cd5e00f22f6a5b0d0ec532bb","unresolved":false,"context_lines":[{"line_number":89,"context_line":""},{"line_number":90,"context_line":"            eventlet.sleep(time_to_wait)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    def __call__(self, *args, **kwargs):"},{"line_number":93,"context_line":"        \"\"\"Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        If it has been, then it will do so in less than"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa31d9ce_26f7fd59","line":92,"in_reply_to":"fa31d9ce_739aa76f","updated":"2017-02-15 15:04:18.000000000","message":"The decorated function should be always called from the same greenthread as this __call__ (decorator) was called from. Maybe I don\u0027t get your question.","commit_id":"a0ce54b4a0cfc5a640aff8ba6d72e0bcf279b0fe"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"dc6e07221a35b0bef1d21bd0a16ee0a332d10018","unresolved":false,"context_lines":[{"line_number":89,"context_line":""},{"line_number":90,"context_line":"            eventlet.sleep(time_to_wait)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    def __call__(self, *args, **kwargs):"},{"line_number":93,"context_line":"        \"\"\"Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        If it has been, then it will do so in less than"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa31d9ce_739aa76f","line":92,"in_reply_to":"fa31d9ce_a5594090","updated":"2017-02-15 09:38:19.000000000","message":"Do we want to ensure that self._func is called by current greenthread or by a concurrent gt before exiting __call__?","commit_id":"a0ce54b4a0cfc5a640aff8ba6d72e0bcf279b0fe"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6d51044ce5de91edd92471e9177bf28a77490adc","unresolved":false,"context_lines":[{"line_number":89,"context_line":""},{"line_number":90,"context_line":"            eventlet.sleep(time_to_wait)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    def __call__(self, *args, **kwargs):"},{"line_number":93,"context_line":"        \"\"\"Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        If it has been, then it will do so in less than"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa31d9ce_4134d848","line":92,"in_reply_to":"fa31d9ce_c1b8c82c","updated":"2017-02-15 16:18:48.000000000","message":"This failing example comes from the race-y nature of func() itself, not from throttler. If we remove throttler, the race would still be there. Such case should be treated with locking mechanism of func(). Throttler\u0027s purpose is to defer calls not solving races.","commit_id":"a0ce54b4a0cfc5a640aff8ba6d72e0bcf279b0fe"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"ce74e312e4a01d4c118c2db2765d3c2db44e9a6c","unresolved":false,"context_lines":[{"line_number":90,"context_line":"            eventlet.sleep(time_to_wait)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    def __call__(self, *args, **kwargs):"},{"line_number":93,"context_line":"        \"\"\"Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        If it has been, then it will do so in less than"},{"line_number":96,"context_line":"        \u0027self.throttle_threshold\u0027 seconds."}],"source_content_type":"text/x-python","patch_set":27,"id":"1a1ced50_70407d57","line":93,"updated":"2017-03-17 15:16:43.000000000","message":"It\u0027s incorrect, it ensures that another thread has scheduled or is currently executing the decorated function.","commit_id":"a0ce54b4a0cfc5a640aff8ba6d72e0bcf279b0fe"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":33,"context_line":"else:"},{"line_number":34,"context_line":"    from neutron.agent.linux import utils"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"# Should match cfg.CONF.ha_vrrp_advert_int."},{"line_number":37,"context_line":"#TODO(jschwarz): using cfg.CONF.ha_vrrp_advert_int necessitates an import,"},{"line_number":38,"context_line":"# which results in a recursive import. This should be fixed into being the"},{"line_number":39,"context_line":"# actual config value."}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_5fcaaaa2","line":36,"range":{"start_line":36,"start_character":2,"end_line":36,"end_character":43},"updated":"2017-03-17 17:29:15.000000000","message":"why? isn\u0027t the throttler supposed to be independent of HA agent using it?","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":33,"context_line":"else:"},{"line_number":34,"context_line":"    from neutron.agent.linux import utils"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"# Should match cfg.CONF.ha_vrrp_advert_int."},{"line_number":37,"context_line":"#TODO(jschwarz): using cfg.CONF.ha_vrrp_advert_int necessitates an import,"},{"line_number":38,"context_line":"# which results in a recursive import. This should be fixed into being the"},{"line_number":39,"context_line":"# actual config value."}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_9c3082ea","line":36,"range":{"start_line":36,"start_character":2,"end_line":36,"end_character":43},"in_reply_to":"1a1ced50_5fcaaaa2","updated":"2017-03-20 14:09:13.000000000","message":"Done","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":50,"context_line":"execute \u003d utils.execute"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"class throttler(object):"},{"line_number":54,"context_line":"    \"\"\"Throttle number of calls to a function to only once per \u0027threshold\u0027.\"\"\""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def __init__(self, func):"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_9f7c2222","line":53,"updated":"2017-03-17 17:29:15.000000000","message":"I think you need some equivalent of functools.wraps here not to override name and  docstrings for the decorated function.","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":50,"context_line":"execute \u003d utils.execute"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"class throttler(object):"},{"line_number":54,"context_line":"    \"\"\"Throttle number of calls to a function to only once per \u0027threshold\u0027.\"\"\""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def __init__(self, func):"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_09429610","line":53,"in_reply_to":"1a1ced50_9f7c2222","updated":"2017-03-20 14:09:13.000000000","message":"Done","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":51,"context_line":""},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"class throttler(object):"},{"line_number":54,"context_line":"    \"\"\"Throttle number of calls to a function to only once per \u0027threshold\u0027.\"\"\""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def __init__(self, func):"},{"line_number":57,"context_line":"        \"\"\"Decorate a function with throttler.\"\"\""}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_bfac7eee","line":54,"range":{"start_line":54,"start_character":63,"end_line":54,"end_character":74},"updated":"2017-03-17 17:29:15.000000000","message":"quotes suggest it\u0027s a parameter or a property, but neither is the case.","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":51,"context_line":""},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"class throttler(object):"},{"line_number":54,"context_line":"    \"\"\"Throttle number of calls to a function to only once per \u0027threshold\u0027.\"\"\""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def __init__(self, func):"},{"line_number":57,"context_line":"        \"\"\"Decorate a function with throttler.\"\"\""}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_29803246","line":54,"range":{"start_line":54,"start_character":63,"end_line":54,"end_character":74},"in_reply_to":"1a1ced50_bfac7eee","updated":"2017-03-20 14:09:13.000000000","message":"Done","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":57,"context_line":"        \"\"\"Decorate a function with throttler.\"\"\""},{"line_number":58,"context_line":"        self._threshold \u003d DEFAULT_THROTTLER_VALUE"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"        self._last_time_called \u003d time.time() - self.throttle_threshold"},{"line_number":61,"context_line":"        self._func \u003d func"},{"line_number":62,"context_line":"        # Someone has already scheduled a func call"},{"line_number":63,"context_line":"        self._is_scheduled \u003d False"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_bf48fe2e","line":60,"range":{"start_line":60,"start_character":44,"end_line":60,"end_character":70},"updated":"2017-03-17 17:29:15.000000000","message":"that\u0027s not immediately clear from the code, so I suggest to add a comment explaining why you do that (to make the first call immediately trigger the function).","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":57,"context_line":"        \"\"\"Decorate a function with throttler.\"\"\""},{"line_number":58,"context_line":"        self._threshold \u003d DEFAULT_THROTTLER_VALUE"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"        self._last_time_called \u003d time.time() - self.throttle_threshold"},{"line_number":61,"context_line":"        self._func \u003d func"},{"line_number":62,"context_line":"        # Someone has already scheduled a func call"},{"line_number":63,"context_line":"        self._is_scheduled \u003d False"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_29459216","line":60,"range":{"start_line":60,"start_character":44,"end_line":60,"end_character":70},"in_reply_to":"1a1ced50_bf48fe2e","updated":"2017-03-20 14:09:13.000000000","message":"Done","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":59,"context_line":""},{"line_number":60,"context_line":"        self._last_time_called \u003d time.time() - self.throttle_threshold"},{"line_number":61,"context_line":"        self._func \u003d func"},{"line_number":62,"context_line":"        # Someone has already scheduled a func call"},{"line_number":63,"context_line":"        self._is_scheduled \u003d False"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_5f58eafa","line":62,"range":{"start_line":62,"start_character":8,"end_line":62,"end_character":51},"updated":"2017-03-17 17:29:15.000000000","message":"that comment is worded so that to suggest that the function was indeed scheduled at this point. I think what you want to say is that the attribute is to track whether it was scheduled though.","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":59,"context_line":""},{"line_number":60,"context_line":"        self._last_time_called \u003d time.time() - self.throttle_threshold"},{"line_number":61,"context_line":"        self._func \u003d func"},{"line_number":62,"context_line":"        # Someone has already scheduled a func call"},{"line_number":63,"context_line":"        self._is_scheduled \u003d False"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_494c8e42","line":62,"range":{"start_line":62,"start_character":8,"end_line":62,"end_character":51},"in_reply_to":"1a1ced50_5f58eafa","updated":"2017-03-20 14:09:13.000000000","message":"Done","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":68,"context_line":""},{"line_number":69,"context_line":"    @throttle_threshold.setter"},{"line_number":70,"context_line":"    def throttle_threshold(self, value):"},{"line_number":71,"context_line":"        self._last_time_called +\u003d self._threshold - value"},{"line_number":72,"context_line":"        self._threshold \u003d value"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def defer_call(self):"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_ff00b6ac","line":71,"range":{"start_line":71,"start_character":34,"end_line":71,"end_character":57},"updated":"2017-03-17 17:29:15.000000000","message":"explain the intent in a comment, I don\u0027t fully grasp that. is it to compensate for the line 60?","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":68,"context_line":""},{"line_number":69,"context_line":"    @throttle_threshold.setter"},{"line_number":70,"context_line":"    def throttle_threshold(self, value):"},{"line_number":71,"context_line":"        self._last_time_called +\u003d self._threshold - value"},{"line_number":72,"context_line":"        self._threshold \u003d value"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def defer_call(self):"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_0910d600","line":71,"range":{"start_line":71,"start_character":34,"end_line":71,"end_character":57},"in_reply_to":"1a1ced50_ff00b6ac","updated":"2017-03-20 14:09:13.000000000","message":"Done","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":77,"context_line":"            time_to_wait \u003d (self._last_time_called - time.time()"},{"line_number":78,"context_line":"                            + self.throttle_threshold)"},{"line_number":79,"context_line":"            if time_to_wait \u003e 0:"},{"line_number":80,"context_line":"            # We\u0027re in timeout, so we should throttle future calls."},{"line_number":81,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":82,"context_line":"            self._last_time_called \u003d time.time()"},{"line_number":83,"context_line":"        finally:"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_7f8846e8","line":80,"range":{"start_line":80,"start_character":23,"end_line":80,"end_character":30},"updated":"2017-03-17 17:29:15.000000000","message":"in timeout? I think this term is usually used for other things (like in case an operation was interrupted due to timing constraints). Maybe you mean \u0027we just triggered the function, wait\u0027","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":77,"context_line":"            time_to_wait \u003d (self._last_time_called - time.time()"},{"line_number":78,"context_line":"                            + self.throttle_threshold)"},{"line_number":79,"context_line":"            if time_to_wait \u003e 0:"},{"line_number":80,"context_line":"            # We\u0027re in timeout, so we should throttle future calls."},{"line_number":81,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":82,"context_line":"            self._last_time_called \u003d time.time()"},{"line_number":83,"context_line":"        finally:"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_a9eee2b1","line":80,"range":{"start_line":80,"start_character":23,"end_line":80,"end_character":30},"in_reply_to":"1a1ced50_7f8846e8","updated":"2017-03-20 14:09:13.000000000","message":"Done","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":86,"context_line":"    def __call__(self, *args, **kwargs):"},{"line_number":87,"context_line":"        \"\"\"Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"        If it has been, then it will do so in less than"},{"line_number":90,"context_line":"        \u0027self.throttle_threshold\u0027 seconds."},{"line_number":91,"context_line":"        \"\"\""},{"line_number":92,"context_line":"        #NOTE(jschwarz): If we ever stop using greenthreads, we\u0027d need some"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_9fa3429e","line":89,"range":{"start_line":89,"start_character":14,"end_line":89,"end_character":22},"updated":"2017-03-17 17:29:15.000000000","message":"has been what? the previous sentence said \u0027hasn\u0027t already *scheduled*. you mean \u0027If it hasn\u0027t scheduled\u0027?","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":86,"context_line":"    def __call__(self, *args, **kwargs):"},{"line_number":87,"context_line":"        \"\"\"Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"        If it has been, then it will do so in less than"},{"line_number":90,"context_line":"        \u0027self.throttle_threshold\u0027 seconds."},{"line_number":91,"context_line":"        \"\"\""},{"line_number":92,"context_line":"        #NOTE(jschwarz): If we ever stop using greenthreads, we\u0027d need some"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_7fb5a6cb","line":89,"range":{"start_line":89,"start_character":32,"end_line":89,"end_character":42},"updated":"2017-03-17 17:29:15.000000000","message":"will do what? be more specific, it\u0027s a documentation that can be read without access to the code","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":86,"context_line":"    def __call__(self, *args, **kwargs):"},{"line_number":87,"context_line":"        \"\"\"Check if another thread hasn\u0027t already scheduled \u0027function\u0027 to run."},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"        If it has been, then it will do so in less than"},{"line_number":90,"context_line":"        \u0027self.throttle_threshold\u0027 seconds."},{"line_number":91,"context_line":"        \"\"\""},{"line_number":92,"context_line":"        #NOTE(jschwarz): If we ever stop using greenthreads, we\u0027d need some"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_49264ecf","line":89,"range":{"start_line":89,"start_character":14,"end_line":89,"end_character":22},"in_reply_to":"1a1ced50_9fa3429e","updated":"2017-03-20 14:09:13.000000000","message":"Done","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":95,"context_line":"            self.defer_call()"},{"line_number":96,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":99,"context_line":"        return functools.partial(self.__call__, obj)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":""}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_1fdd9214","line":98,"updated":"2017-03-17 17:29:15.000000000","message":"explain the intent of the method","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":95,"context_line":"            self.defer_call()"},{"line_number":96,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":99,"context_line":"        return functools.partial(self.__call__, obj)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":""}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_1c2492ad","line":98,"in_reply_to":"1a1ced50_1fdd9214","updated":"2017-03-20 14:09:13.000000000","message":"Done","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"c85769e0c3c636196d11b385338fb075330ae1fd","unresolved":false,"context_lines":[{"line_number":60,"context_line":"        # Bool whether someone has already scheduled a func call."},{"line_number":61,"context_line":"        self._is_scheduled \u003d False"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        functools.update_wrapper(self, func)"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    @property"},{"line_number":66,"context_line":"    def throttle_threshold(self):"}],"source_content_type":"text/x-python","patch_set":32,"id":"1a1ced50_558df879","line":63,"updated":"2017-03-20 15:13:16.000000000","message":"it updates decorator if func is a function ... but not if func is a method","commit_id":"a1e3bf85d6973eccf73a5e3fb30eab1277481e1a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"b473e0c9e6e09ce887c12ce190eff7ee7688df46","unresolved":false,"context_lines":[{"line_number":60,"context_line":"        # Bool whether someone has already scheduled a func call."},{"line_number":61,"context_line":"        self._is_scheduled \u003d False"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        functools.update_wrapper(self, func)"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    @property"},{"line_number":66,"context_line":"    def throttle_threshold(self):"}],"source_content_type":"text/x-python","patch_set":32,"id":"1a1ced50_75191488","line":63,"in_reply_to":"1a1ced50_558df879","updated":"2017-03-20 15:26:31.000000000","message":"I should update the UT. Thanks","commit_id":"a1e3bf85d6973eccf73a5e3fb30eab1277481e1a"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"c85769e0c3c636196d11b385338fb075330ae1fd","unresolved":false,"context_lines":[{"line_number":99,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":102,"context_line":"        \"\"\"Descriptor to pass \u0027self\u0027 as a first parameter to decorated method."},{"line_number":103,"context_line":"        \"\"\""},{"line_number":104,"context_line":"        return functools.partial(self.__call__, obj)"},{"line_number":105,"context_line":""}],"source_content_type":"text/x-python","patch_set":32,"id":"1a1ced50_75003402","line":102,"updated":"2017-03-20 15:13:16.000000000","message":"nope:\n\n \"descriptor to pass \u0027obj\u0027 as first parameter to decorated  method\"","commit_id":"a1e3bf85d6973eccf73a5e3fb30eab1277481e1a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"b473e0c9e6e09ce887c12ce190eff7ee7688df46","unresolved":false,"context_lines":[{"line_number":99,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":102,"context_line":"        \"\"\"Descriptor to pass \u0027self\u0027 as a first parameter to decorated method."},{"line_number":103,"context_line":"        \"\"\""},{"line_number":104,"context_line":"        return functools.partial(self.__call__, obj)"},{"line_number":105,"context_line":""}],"source_content_type":"text/x-python","patch_set":32,"id":"1a1ced50_9535b0f8","line":102,"in_reply_to":"1a1ced50_75003402","updated":"2017-03-20 15:26:31.000000000","message":"My comment was vague, I should highlight it\u0027s the \u0027self\u0027 in decorated method - I think it\u0027s more clear than \u0027obj\u0027.","commit_id":"a1e3bf85d6973eccf73a5e3fb30eab1277481e1a"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"26deae25ac91d4f8547d208df282972b198577d9","unresolved":false,"context_lines":[{"line_number":99,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":102,"context_line":"        \"\"\"Descriptor to pass \u0027self\u0027 as a first parameter to decorated method."},{"line_number":103,"context_line":"        \"\"\""},{"line_number":104,"context_line":"        return functools.partial(self.__call__, obj)"},{"line_number":105,"context_line":""}],"source_content_type":"text/x-python","patch_set":32,"id":"1a1ced50_f86ed92d","line":102,"in_reply_to":"1a1ced50_9535b0f8","updated":"2017-03-20 15:40:40.000000000","message":"obj doesn\u0027t not always reference an instance: in the case of a classmethod, it references the class","commit_id":"a1e3bf85d6973eccf73a5e3fb30eab1277481e1a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"7635ff8f44b157400296fdf8cf08d2743df802c7","unresolved":false,"context_lines":[{"line_number":99,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":102,"context_line":"        \"\"\"Descriptor to pass \u0027self\u0027 as a first parameter to decorated method."},{"line_number":103,"context_line":"        \"\"\""},{"line_number":104,"context_line":"        return functools.partial(self.__call__, obj)"},{"line_number":105,"context_line":""}],"source_content_type":"text/x-python","patch_set":32,"id":"1a1ced50_58552d1b","line":102,"in_reply_to":"1a1ced50_f86ed92d","updated":"2017-03-20 15:44:49.000000000","message":"I\u0027ll still need another respin due to UT name, I\u0027ll change self to obj if that is clearer.","commit_id":"a1e3bf85d6973eccf73a5e3fb30eab1277481e1a"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"c85769e0c3c636196d11b385338fb075330ae1fd","unresolved":false,"context_lines":[{"line_number":101,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":102,"context_line":"        \"\"\"Descriptor to pass \u0027self\u0027 as a first parameter to decorated method."},{"line_number":103,"context_line":"        \"\"\""},{"line_number":104,"context_line":"        return functools.partial(self.__call__, obj)"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"def load_interface_driver(conf):"}],"source_content_type":"text/x-python","patch_set":32,"id":"1a1ced50_35bb1c29","line":104,"updated":"2017-03-20 15:13:16.000000000","message":"Prefer:\n\n funcpart \u003d functools.partial(self.__call__, obj)\n functools.update_wrapper(funcpart, self.func)\n return funcpart\n\nwhich updates decorator if func is a method","commit_id":"a1e3bf85d6973eccf73a5e3fb30eab1277481e1a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"b473e0c9e6e09ce887c12ce190eff7ee7688df46","unresolved":false,"context_lines":[{"line_number":101,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":102,"context_line":"        \"\"\"Descriptor to pass \u0027self\u0027 as a first parameter to decorated method."},{"line_number":103,"context_line":"        \"\"\""},{"line_number":104,"context_line":"        return functools.partial(self.__call__, obj)"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"def load_interface_driver(conf):"}],"source_content_type":"text/x-python","patch_set":32,"id":"1a1ced50_1522a0b9","line":104,"in_reply_to":"1a1ced50_35bb1c29","updated":"2017-03-20 15:26:31.000000000","message":"Done","commit_id":"a1e3bf85d6973eccf73a5e3fb30eab1277481e1a"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"dbcfe4cbb905be8b13c7f271285c0cd0c41cd028","unresolved":false,"context_lines":[{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    @throttle_threshold.setter"},{"line_number":68,"context_line":"    def throttle_threshold(self, value):"},{"line_number":69,"context_line":"        # After update we need to shift the time since lass call in order to"},{"line_number":70,"context_line":"        # have correct values for time_to_wait in defer_call() method."},{"line_number":71,"context_line":"        self._last_time_called +\u003d self._threshold - value"},{"line_number":72,"context_line":"        self._threshold \u003d value"}],"source_content_type":"text/x-python","patch_set":34,"id":"1a1ced50_bbb456d1","line":69,"range":{"start_line":69,"start_character":58,"end_line":69,"end_character":59},"updated":"2017-03-20 17:41:28.000000000","message":"t","commit_id":"6146fa7f7a1af72d4668b3018367158ef8680b0b"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"b7ccedd67e5121b7ab957a3e8bb46780438fc69d","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    from neutron.agent.linux import utils"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"DEFAULT_THROTTLER_VALUE \u003d 2"},{"line_number":37,"context_line":"DEFAULT_THROTTLER_MULTIPLIER \u003d 1.2"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":40,"context_line":"config.register_root_helper(cfg.CONF)"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_9d9a2a62","line":37,"updated":"2017-03-20 20:10:09.000000000","message":"This multiplier seems specific to HA usage, it should not live here.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"8e866169d8b4016bece9ec42c508d72a9207c705","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    from neutron.agent.linux import utils"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"DEFAULT_THROTTLER_VALUE \u003d 2"},{"line_number":37,"context_line":"DEFAULT_THROTTLER_MULTIPLIER \u003d 1.2"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":40,"context_line":"config.register_root_helper(cfg.CONF)"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_2880f58a","line":37,"in_reply_to":"1a1ced50_9cea14ab","updated":"2017-03-21 13:32:59.000000000","message":"It\u0027s used only in keepalived manager. Maybe we should move it out from there.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"935518c0e24a00158a99ad672f36e46374ec52c1","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    from neutron.agent.linux import utils"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"DEFAULT_THROTTLER_VALUE \u003d 2"},{"line_number":37,"context_line":"DEFAULT_THROTTLER_MULTIPLIER \u003d 1.2"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":40,"context_line":"config.register_root_helper(cfg.CONF)"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_9cea14ab","line":37,"in_reply_to":"1a1ced50_9d9a2a62","updated":"2017-03-21 10:24:00.000000000","message":"why is it specific to HA?","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"17cf712375cca036622be583165beaba8af6bd53","unresolved":false,"context_lines":[{"line_number":43,"context_line":"INTERFACE_NAMESPACE \u003d \u0027neutron.interface_drivers\u0027"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"execute \u003d utils.execute"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"class throttler(object):"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_974498b7","line":46,"range":{"start_line":46,"start_character":10,"end_line":46,"end_character":11},"updated":"2017-03-21 18:12:22.000000000","message":"btw why is the throttler in this file? what\u0027s so specific about agents here?","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"d8720d4c5cf734cfc34740ee369573a5663ffd7b","unresolved":false,"context_lines":[{"line_number":46,"context_line":"execute \u003d utils.execute"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"class throttler(object):"},{"line_number":50,"context_line":"    \"\"\"Throttle number of calls to a function to only once per"},{"line_number":51,"context_line":"       \u0027throttle_threshold\u0027."},{"line_number":52,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_0792689e","line":49,"updated":"2017-03-20 20:59:13.000000000","message":"there is already neutron/notifiers/batch_notifier.py that seems to cover a similar need. I understand we don\u0027t need to do code refactoring in a bug fix, so please just add a TODO for that.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"d97ca7b395755949f5133db109e934424688cfaf","unresolved":false,"context_lines":[{"line_number":46,"context_line":"execute \u003d utils.execute"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"class throttler(object):"},{"line_number":50,"context_line":"    \"\"\"Throttle number of calls to a function to only once per"},{"line_number":51,"context_line":"       \u0027throttle_threshold\u0027."},{"line_number":52,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_9ed216ff","line":49,"in_reply_to":"1a1ced50_0792689e","updated":"2017-03-21 04:10:53.000000000","message":"that being rewriting the code to use the existing batcher, potentially refactoring the latter first.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"8e866169d8b4016bece9ec42c508d72a9207c705","unresolved":false,"context_lines":[{"line_number":46,"context_line":"execute \u003d utils.execute"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"class throttler(object):"},{"line_number":50,"context_line":"    \"\"\"Throttle number of calls to a function to only once per"},{"line_number":51,"context_line":"       \u0027throttle_threshold\u0027."},{"line_number":52,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_e827bdc7","line":49,"in_reply_to":"1a1ced50_9ed216ff","updated":"2017-03-21 13:32:59.000000000","message":"It looks that batch notifier has a different use case. Not sure it would be worth refactoring. Maybe REVISIT note makes more sense than TODO? If I add TODO, then I would feel responsible for the refactoring :)","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"17cf712375cca036622be583165beaba8af6bd53","unresolved":false,"context_lines":[{"line_number":46,"context_line":"execute \u003d utils.execute"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"class throttler(object):"},{"line_number":50,"context_line":"    \"\"\"Throttle number of calls to a function to only once per"},{"line_number":51,"context_line":"       \u0027throttle_threshold\u0027."},{"line_number":52,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_1701886a","line":49,"in_reply_to":"1a1ced50_e827bdc7","updated":"2017-03-21 18:12:22.000000000","message":"Maybe. Kevin suggested that, he wanted to refactor the batcher to be reusable.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"b7ccedd67e5121b7ab957a3e8bb46780438fc69d","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    \"\"\""},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    def __init__(self, func):"},{"line_number":55,"context_line":"        self._threshold \u003d DEFAULT_THROTTLER_VALUE"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"        # First call should trigger the function."},{"line_number":58,"context_line":"        self._last_time_called \u003d time.time() - self.throttle_threshold"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_1dc63a48","line":55,"range":{"start_line":55,"start_character":26,"end_line":55,"end_character":49},"updated":"2017-03-20 20:10:09.000000000","message":"maybe allow to pass the value as a parameter, so that we don\u0027t need to later set the property.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"c07cd9a0aa0ec4d6cdaa02ad449c4a3bf444a20f","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    \"\"\""},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    def __init__(self, func):"},{"line_number":55,"context_line":"        self._threshold \u003d DEFAULT_THROTTLER_VALUE"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"        # First call should trigger the function."},{"line_number":58,"context_line":"        self._last_time_called \u003d time.time() - self.throttle_threshold"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_d2255509","line":55,"range":{"start_line":55,"start_character":26,"end_line":55,"end_character":49},"in_reply_to":"1a1ced50_1dc63a48","updated":"2017-03-21 11:08:38.000000000","message":"It seems impossible as decorators are executed during module load which could happen before oslo config files are loaded","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"935518c0e24a00158a99ad672f36e46374ec52c1","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    \"\"\""},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    def __init__(self, func):"},{"line_number":55,"context_line":"        self._threshold \u003d DEFAULT_THROTTLER_VALUE"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"        # First call should trigger the function."},{"line_number":58,"context_line":"        self._last_time_called \u003d time.time() - self.throttle_threshold"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_bcfa7073","line":55,"range":{"start_line":55,"start_character":26,"end_line":55,"end_character":49},"in_reply_to":"1a1ced50_1dc63a48","updated":"2017-03-21 10:24:00.000000000","message":"That makes sense.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"8e866169d8b4016bece9ec42c508d72a9207c705","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    \"\"\""},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    def __init__(self, func):"},{"line_number":55,"context_line":"        self._threshold \u003d DEFAULT_THROTTLER_VALUE"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"        # First call should trigger the function."},{"line_number":58,"context_line":"        self._last_time_called \u003d time.time() - self.throttle_threshold"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_4dc1cd53","line":55,"range":{"start_line":55,"start_character":26,"end_line":55,"end_character":49},"in_reply_to":"1a1ced50_1dc63a48","updated":"2017-03-21 13:32:59.000000000","message":"The problem with having it as a parameter is that class and its decorated method is created before we load config options into config object.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"17cf712375cca036622be583165beaba8af6bd53","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    \"\"\""},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    def __init__(self, func):"},{"line_number":55,"context_line":"        self._threshold \u003d DEFAULT_THROTTLER_VALUE"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"        # First call should trigger the function."},{"line_number":58,"context_line":"        self._last_time_called \u003d time.time() - self.throttle_threshold"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_f7322c5d","line":55,"range":{"start_line":55,"start_character":26,"end_line":55,"end_character":49},"in_reply_to":"1a1ced50_4dc1cd53","updated":"2017-03-21 18:12:22.000000000","message":"Which is a use case specific to HA, but not a general case for the throttler that is supposed to be untangled from HA.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"b7ccedd67e5121b7ab957a3e8bb46780438fc69d","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        try:"},{"line_number":77,"context_line":"            time_to_wait \u003d ("},{"line_number":78,"context_line":"                self._last_time_called - time.time() + self.throttle_threshold)"},{"line_number":79,"context_line":"            if time_to_wait \u003e 0:"},{"line_number":80,"context_line":"                # Decorated function has been called recently, wait."},{"line_number":81,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":82,"context_line":"            self._last_time_called \u003d time.time()"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_7d648e48","line":79,"updated":"2017-03-20 20:10:09.000000000","message":"we may want to add some debug logs here to ease reading logs and to give a clue to log readers why it takes more time to process a call than may be expected.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"17cf712375cca036622be583165beaba8af6bd53","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        try:"},{"line_number":77,"context_line":"            time_to_wait \u003d ("},{"line_number":78,"context_line":"                self._last_time_called - time.time() + self.throttle_threshold)"},{"line_number":79,"context_line":"            if time_to_wait \u003e 0:"},{"line_number":80,"context_line":"                # Decorated function has been called recently, wait."},{"line_number":81,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":82,"context_line":"            self._last_time_called \u003d time.time()"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_d77ff0dd","line":79,"in_reply_to":"1a1ced50_080c1940","updated":"2017-03-21 18:12:22.000000000","message":"Yes, smth like:\n\nLog1: X called but postponed for Y msec\nLog2: X triggered after Y msec wait","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"8e866169d8b4016bece9ec42c508d72a9207c705","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        try:"},{"line_number":77,"context_line":"            time_to_wait \u003d ("},{"line_number":78,"context_line":"                self._last_time_called - time.time() + self.throttle_threshold)"},{"line_number":79,"context_line":"            if time_to_wait \u003e 0:"},{"line_number":80,"context_line":"                # Decorated function has been called recently, wait."},{"line_number":81,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":82,"context_line":"            self._last_time_called \u003d time.time()"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_080c1940","line":79,"in_reply_to":"1a1ced50_529c050f","updated":"2017-03-21 13:32:59.000000000","message":"Maybe a debug logs when call is scheduled and when call is triggered?","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"935518c0e24a00158a99ad672f36e46374ec52c1","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        try:"},{"line_number":77,"context_line":"            time_to_wait \u003d ("},{"line_number":78,"context_line":"                self._last_time_called - time.time() + self.throttle_threshold)"},{"line_number":79,"context_line":"            if time_to_wait \u003e 0:"},{"line_number":80,"context_line":"                # Decorated function has been called recently, wait."},{"line_number":81,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":82,"context_line":"            self._last_time_called \u003d time.time()"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_3c2da0fe","line":79,"in_reply_to":"1a1ced50_7d648e48","updated":"2017-03-21 10:24:00.000000000","message":"+1","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"c07cd9a0aa0ec4d6cdaa02ad449c4a3bf444a20f","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        try:"},{"line_number":77,"context_line":"            time_to_wait \u003d ("},{"line_number":78,"context_line":"                self._last_time_called - time.time() + self.throttle_threshold)"},{"line_number":79,"context_line":"            if time_to_wait \u003e 0:"},{"line_number":80,"context_line":"                # Decorated function has been called recently, wait."},{"line_number":81,"context_line":"                eventlet.sleep(time_to_wait)"},{"line_number":82,"context_line":"            self._last_time_called \u003d time.time()"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_529c050f","line":79,"in_reply_to":"1a1ced50_7d648e48","updated":"2017-03-21 11:08:38.000000000","message":"What do you mean exactly? time_to_wait is not related to \"it takes more time to process a call than may be expected.\"","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"c07cd9a0aa0ec4d6cdaa02ad449c4a3bf444a20f","unresolved":false,"context_lines":[{"line_number":90,"context_line":"        won\u0027t be called. Otherwise the function will be called in at least"},{"line_number":91,"context_line":"        \u0027self.throttle_threshold\u0027 seconds from the last call."},{"line_number":92,"context_line":"        \"\"\""},{"line_number":93,"context_line":"        #NOTE(jschwarz): If we ever stop using greenthreads, we\u0027d need some"},{"line_number":94,"context_line":"        # sort of a locking mechanism here."},{"line_number":95,"context_line":"        if not self._is_scheduled:"},{"line_number":96,"context_line":"            self.defer_call()"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_726bc1f1","line":93,"updated":"2017-03-21 11:08:38.000000000","message":"We can update the code to remove this constraint","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"4e6e56bc1e75a8deff29361d34f32291d971b731","unresolved":false,"context_lines":[{"line_number":90,"context_line":"        won\u0027t be called. Otherwise the function will be called in at least"},{"line_number":91,"context_line":"        \u0027self.throttle_threshold\u0027 seconds from the last call."},{"line_number":92,"context_line":"        \"\"\""},{"line_number":93,"context_line":"        #NOTE(jschwarz): If we ever stop using greenthreads, we\u0027d need some"},{"line_number":94,"context_line":"        # sort of a locking mechanism here."},{"line_number":95,"context_line":"        if not self._is_scheduled:"},{"line_number":96,"context_line":"            self.defer_call()"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_6eb835c9","line":93,"in_reply_to":"1a1ced50_4b19ab78","updated":"2017-03-21 13:55:34.000000000","message":"yes, it can be done with:\n\n self._is_scheduled \u003d threading.Lock()\n ...\n\n if self._is_scheduled.acquire(False):\n   try:\n     ...\n   finally:\n     self._is_scheduled.release()\n   return self._func(...)","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"82cf298592e317de9bad1bd3021980908f3704da","unresolved":false,"context_lines":[{"line_number":90,"context_line":"        won\u0027t be called. Otherwise the function will be called in at least"},{"line_number":91,"context_line":"        \u0027self.throttle_threshold\u0027 seconds from the last call."},{"line_number":92,"context_line":"        \"\"\""},{"line_number":93,"context_line":"        #NOTE(jschwarz): If we ever stop using greenthreads, we\u0027d need some"},{"line_number":94,"context_line":"        # sort of a locking mechanism here."},{"line_number":95,"context_line":"        if not self._is_scheduled:"},{"line_number":96,"context_line":"            self.defer_call()"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_3a19137a","line":93,"in_reply_to":"1a1ced50_6eb835c9","updated":"2017-03-21 15:00:49.000000000","message":"Done","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"8e866169d8b4016bece9ec42c508d72a9207c705","unresolved":false,"context_lines":[{"line_number":90,"context_line":"        won\u0027t be called. Otherwise the function will be called in at least"},{"line_number":91,"context_line":"        \u0027self.throttle_threshold\u0027 seconds from the last call."},{"line_number":92,"context_line":"        \"\"\""},{"line_number":93,"context_line":"        #NOTE(jschwarz): If we ever stop using greenthreads, we\u0027d need some"},{"line_number":94,"context_line":"        # sort of a locking mechanism here."},{"line_number":95,"context_line":"        if not self._is_scheduled:"},{"line_number":96,"context_line":"            self.defer_call()"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_4b19ab78","line":93,"in_reply_to":"1a1ced50_726bc1f1","updated":"2017-03-21 13:32:59.000000000","message":"You mean adding locking regardless of using eventlet?","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"ed2dcd50f6cf6b35c02f88a94ecc686876715270","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        self._threshold \u003d DEFAULT_THROTTLER_VALUE"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"        # First call should trigger the function."},{"line_number":61,"context_line":"        self._last_time_called \u003d time.time() - self.throttle_threshold"},{"line_number":62,"context_line":"        self._func \u003d func"},{"line_number":63,"context_line":"        # Lock whether someone has already scheduled a func call."},{"line_number":64,"context_line":"        self._scheduled_l \u003d threading.Lock()"}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_ddc2afe8","line":61,"updated":"2017-03-21 19:05:54.000000000","message":"you can otherwise:\n\n self._last_time_called \u003d 0\n\nor:\n\n self._last_time_called \u003d float(\u0027-inf\u0027)","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"345c2fc9f6abd278ced7c5759427218f0f85703d","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        self._threshold \u003d DEFAULT_THROTTLER_VALUE"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"        # First call should trigger the function."},{"line_number":61,"context_line":"        self._last_time_called \u003d time.time() - self.throttle_threshold"},{"line_number":62,"context_line":"        self._func \u003d func"},{"line_number":63,"context_line":"        # Lock whether someone has already scheduled a func call."},{"line_number":64,"context_line":"        self._scheduled_l \u003d threading.Lock()"}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_5e34d9fa","line":61,"in_reply_to":"1a1ced50_ddc2afe8","updated":"2017-03-22 13:42:35.000000000","message":"Done","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"ed2dcd50f6cf6b35c02f88a94ecc686876715270","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        self._last_time_called \u003d time.time() - self.throttle_threshold"},{"line_number":62,"context_line":"        self._func \u003d func"},{"line_number":63,"context_line":"        # Lock whether someone has already scheduled a func call."},{"line_number":64,"context_line":"        self._scheduled_l \u003d threading.Lock()"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    @property"},{"line_number":67,"context_line":"    def throttle_threshold(self):"}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_1dea87ac","line":64,"updated":"2017-03-21 19:05:54.000000000","message":"\u0027_schedule_lock\u0027 seems a bit more readable","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"345c2fc9f6abd278ced7c5759427218f0f85703d","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        self._last_time_called \u003d time.time() - self.throttle_threshold"},{"line_number":62,"context_line":"        self._func \u003d func"},{"line_number":63,"context_line":"        # Lock whether someone has already scheduled a func call."},{"line_number":64,"context_line":"        self._scheduled_l \u003d threading.Lock()"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    @property"},{"line_number":67,"context_line":"    def throttle_threshold(self):"}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_9e43b16b","line":64,"in_reply_to":"1a1ced50_1dea87ac","updated":"2017-03-22 13:42:35.000000000","message":"Done","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"ed2dcd50f6cf6b35c02f88a94ecc686876715270","unresolved":false,"context_lines":[{"line_number":94,"context_line":"        won\u0027t be called. Otherwise the function will be called in at least"},{"line_number":95,"context_line":"        \u0027self.throttle_threshold\u0027 seconds from the last call."},{"line_number":96,"context_line":"        \"\"\""},{"line_number":97,"context_line":"        if self._scheduled_l.acquire(False):"},{"line_number":98,"context_line":"            self.defer_call()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_9d72f70f","line":97,"updated":"2017-03-21 19:05:54.000000000","message":"it seems a safer/cleaner pattern to acquire and release the lock in the same method:\n\n if self._schedule_lock.acquire(False):\n   try:\n     self.defer_call()\n   finally:\n     self._schedule_lock.release()","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"345c2fc9f6abd278ced7c5759427218f0f85703d","unresolved":false,"context_lines":[{"line_number":94,"context_line":"        won\u0027t be called. Otherwise the function will be called in at least"},{"line_number":95,"context_line":"        \u0027self.throttle_threshold\u0027 seconds from the last call."},{"line_number":96,"context_line":"        \"\"\""},{"line_number":97,"context_line":"        if self._scheduled_l.acquire(False):"},{"line_number":98,"context_line":"            self.defer_call()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_1e2fc1a1","line":97,"in_reply_to":"1a1ced50_9d72f70f","updated":"2017-03-22 13:42:35.000000000","message":"Done","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"87f888cc0f45a319350907cae284798c57e33f5b","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        if self._scheduled_l.acquire(False):"},{"line_number":98,"context_line":"            self.defer_call()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_3704c448","line":100,"updated":"2017-03-21 18:14:46.000000000","message":"should we update last_call_time here before returning and unlocking the is_scheduled lock.","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"fc58f4688f454a784458a7486587cb838216ef34","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        if self._scheduled_l.acquire(False):"},{"line_number":98,"context_line":"            self.defer_call()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_47ade986","line":100,"in_reply_to":"1a1ced50_0424cf5b","updated":"2017-03-22 15:03:06.000000000","message":"We still release the lock before self._func is called.","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"4cf55e07e826187c4c3ce6a1bcca416a682c2f9c","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        if self._scheduled_l.acquire(False):"},{"line_number":98,"context_line":"            self.defer_call()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_72fc3db8","line":100,"in_reply_to":"1a1ced50_22852e59","updated":"2017-03-23 09:01:47.000000000","message":"I got you, but that would introduce again the race from PS27, wouldn\u0027t it?","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"661f8ba335e9ef90a7b33a7f95dc395a24bf81ae","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        if self._scheduled_l.acquire(False):"},{"line_number":98,"context_line":"            self.defer_call()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_22852e59","line":100,"in_reply_to":"1a1ced50_3302e60a","updated":"2017-03-22 19:26:31.000000000","message":"Oh right. I was somehow reasoning about L97 as if it\u0027s a context manager. Should we use one here?","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"19398283bd3772313aceb0c092458cecad51a9e0","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        if self._scheduled_l.acquire(False):"},{"line_number":98,"context_line":"            self.defer_call()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_ea993fc5","line":100,"in_reply_to":"1a1ced50_3704c448","updated":"2017-03-22 13:43:48.000000000","message":"You mean updating it twice? Before and after call?","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"eca5b396c2e420792cca7cf1a415367ccffbb187","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        if self._scheduled_l.acquire(False):"},{"line_number":98,"context_line":"            self.defer_call()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_adc75794","line":100,"in_reply_to":"1a1ced50_47ade986","updated":"2017-03-22 16:57:24.000000000","message":"How come? Am I reading the code here incorrectly? Don\u0027t we unlock after block started at line 97 ends, which will happen after return in line 100 is done?","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"beb463f562b5a44ea7d43366c3f497e343209660","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        if self._scheduled_l.acquire(False):"},{"line_number":98,"context_line":"            self.defer_call()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_0424cf5b","line":100,"in_reply_to":"1a1ced50_8ae36bd8","updated":"2017-03-22 14:38:55.000000000","message":"Not sure. Since we keep the lock for the whole __call__ section, we should not be affected. I think Cedric\u0027s comment applied to a previous version of the patch where we were freeing the lock before func was executed.","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"e33dbc66d9351ae1a59ed6f03520c4548427fd81","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        if self._scheduled_l.acquire(False):"},{"line_number":98,"context_line":"            self.defer_call()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_3302e60a","line":100,"in_reply_to":"1a1ced50_adc75794","updated":"2017-03-22 17:28:30.000000000","message":"We lock the code in L97 (if acquire returns True) and unlock it at the end of L98 (more precisely in defer_call at L88)","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"c9f3e0a354040945ae69104e5a53f37bb47b19a2","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        if self._scheduled_l.acquire(False):"},{"line_number":98,"context_line":"            self.defer_call()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_8ae36bd8","line":100,"in_reply_to":"1a1ced50_ea4e9f39","updated":"2017-03-22 13:51:51.000000000","message":"That has a race: https://review.openstack.org/#/c/407099/35/neutron/agent/linux/keepalived.py@432","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"41a589d4c04ee53385593cb28e92209b68a0bb4b","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        if self._scheduled_l.acquire(False):"},{"line_number":98,"context_line":"            self.defer_call()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":37,"id":"1a1ced50_ea4e9f39","line":100,"in_reply_to":"1a1ced50_ea993fc5","updated":"2017-03-22 13:48:47.000000000","message":"No, just after the call. It should be enough to guarantee that there is at least threshold seconds between the end of the previous call and the start of the next one.","commit_id":"243189df0eff76c50d824e23dd3b80e6cb4a2c56"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"892816feac204103348d4084cceff23be83e6bed","unresolved":false,"context_lines":[{"line_number":97,"context_line":"            finally:"},{"line_number":98,"context_line":"                self._scheduled_lock.release()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":38,"id":"1a1ced50_4d0b43d6","line":100,"updated":"2017-03-22 16:59:05.000000000","message":"so, here, you call _func under lock. In which case we should have been safe to update the last_time_called just before returning from the __call__ method.","commit_id":"5dc9369ba7d4ce4e78fa32a608fd40b3fe1a5d10"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"03ac2c17ae048c0e9173adf717ea53f2c4420785","unresolved":false,"context_lines":[{"line_number":97,"context_line":"            finally:"},{"line_number":98,"context_line":"                self._scheduled_lock.release()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":38,"id":"1a1ced50_a2c75e94","line":100,"in_reply_to":"1a1ced50_4d0b43d6","updated":"2017-03-22 19:27:54.000000000","message":"ok now I get where misunderstanding from previous PSs came from. If we would transform line 94 into a context manager, (and remove unlock from defer_call), then we would be sure that _func is executed in scope of the lock, and we would then be able to store last_called at the end of _func execution.","commit_id":"5dc9369ba7d4ce4e78fa32a608fd40b3fe1a5d10"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"2c6a893f2f5e9ac090dcbea4d14deab89e063ae9","unresolved":false,"context_lines":[{"line_number":97,"context_line":"            finally:"},{"line_number":98,"context_line":"                self._scheduled_lock.release()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":38,"id":"1a1ced50_a2fcbeb8","line":100,"in_reply_to":"1a1ced50_a2c75e94","updated":"2017-03-22 19:29:33.000000000","message":"https://docs.python.org/2/library/threading.html#using-locks-conditions-and-semaphores-in-the-with-statement","commit_id":"5dc9369ba7d4ce4e78fa32a608fd40b3fe1a5d10"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"b5607148cf65f1c1cd7fb82b7c516900178bdc94","unresolved":false,"context_lines":[{"line_number":97,"context_line":"            finally:"},{"line_number":98,"context_line":"                self._scheduled_lock.release()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":38,"id":"1a1ced50_dadfc30a","line":100,"in_reply_to":"1a1ced50_a2fcbeb8","updated":"2017-03-23 10:53:42.000000000","message":"The with statement is not correct to use as we don\u0027t want the third call in a row to be scheduled. It will be replaced by second call being deferred. With statement would schedule all calls.\n\nSo I think we should agree what is the expected behavior. If self._func is a long running function we would throttle \"threshold + execution of self._func\". Which means in case of sending SIGHUPs, it can create a race where l3 agent change was scheduled but was skipped because there is some routine in place AFTER SIGHUP was sent by self._func leading to *not* loading new configuration for keepalived.","commit_id":"5dc9369ba7d4ce4e78fa32a608fd40b3fe1a5d10"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"48c46d94c66ee94bd025447214155de829a111e9","unresolved":false,"context_lines":[{"line_number":97,"context_line":"            finally:"},{"line_number":98,"context_line":"                self._scheduled_lock.release()"},{"line_number":99,"context_line":"            LOG.debug(\"Calling throttled function %s\", self._func.__name__)"},{"line_number":100,"context_line":"            return self._func(*args, **kwargs)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def __get__(self, obj, objtype):"},{"line_number":103,"context_line":"        \"\"\"Descriptor to pass \u0027obj\u0027 as a first parameter to decorated method."}],"source_content_type":"text/x-python","patch_set":38,"id":"1a1ced50_e3121209","line":100,"in_reply_to":"1a1ced50_dadfc30a","updated":"2017-03-23 15:17:49.000000000","message":"Oh now it makes sense to me, thanks for explanation.","commit_id":"5dc9369ba7d4ce4e78fa32a608fd40b3fe1a5d10"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"da5fb84bfa543d04f07551a5a5ee138e8fce44a2","unresolved":false,"context_lines":[{"line_number":103,"context_line":"        functools.update_wrapper(funcpart, self._func)"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"        # Propagate set_throttle_threshold setter to the partial function"},{"line_number":106,"context_line":"        setattr(funcpart, \u0027set_throttle_threshold\u0027,"},{"line_number":107,"context_line":"                self.set_throttle_threshold)"},{"line_number":108,"context_line":""},{"line_number":109,"context_line":"        return funcpart"}],"source_content_type":"text/x-python","patch_set":43,"id":"ffe62b97_c4120eb2","line":106,"updated":"2017-03-24 13:26:59.000000000","message":"funcpart.set_throttle_threshold \u003d ...","commit_id":"ce1a59b5912fb786837e1b2255e63fab487642d8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"11fb57c5bce316118d527ec3dc50f31dcc68cc7c","unresolved":false,"context_lines":[{"line_number":53,"context_line":"    \"\"\"Throttle number of calls to a function to only once per"},{"line_number":54,"context_line":"       \u0027_threshold\u0027."},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"       :param set_throttle_threshold: Setter for configuring custom threshold."},{"line_number":57,"context_line":"    \"\"\""},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"    def __init__(self, func):"}],"source_content_type":"text/x-python","patch_set":44,"id":"ffe62b97_0d1ff96c","line":56,"range":{"start_line":56,"start_character":7,"end_line":56,"end_character":78},"updated":"2017-03-24 14:43:18.000000000","message":"huh? I don\u0027t see such param. There is a method though?","commit_id":"73ec88203400552cb7100677402bf146592ee996"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"11fb57c5bce316118d527ec3dc50f31dcc68cc7c","unresolved":false,"context_lines":[{"line_number":57,"context_line":"    \"\"\""},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"    def __init__(self, func):"},{"line_number":60,"context_line":"        self._threshold \u003d DEFAULT_THROTTLER_VALUE"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        # First call should trigger the function."},{"line_number":63,"context_line":"        self._last_time_called \u003d 0"}],"source_content_type":"text/x-python","patch_set":44,"id":"ffe62b97_781c056a","line":60,"range":{"start_line":60,"start_character":7,"end_line":60,"end_character":49},"updated":"2017-03-24 14:43:18.000000000","message":"same old question, why we need to set it here, then reset it later, if we could make the class simpler by passing the value directly as a parameter...","commit_id":"73ec88203400552cb7100677402bf146592ee996"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"5f6c4a83d0e78f0d36ee42c6df6b09c4f5041ca0","unresolved":false,"context_lines":[{"line_number":57,"context_line":"    \"\"\""},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"    def __init__(self, func):"},{"line_number":60,"context_line":"        self._threshold \u003d DEFAULT_THROTTLER_VALUE"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        # First call should trigger the function."},{"line_number":63,"context_line":"        self._last_time_called \u003d 0"}],"source_content_type":"text/x-python","patch_set":44,"id":"ffe62b97_f8b7f585","line":60,"range":{"start_line":60,"start_character":7,"end_line":60,"end_character":49},"in_reply_to":"ffe62b97_781c056a","updated":"2017-03-24 15:32:17.000000000","message":"Passing a parameter is a YAGNI because we can\u0027t use it now. If we have a use, it would look as follows\n\n def param_throttler(threshold):\n    def inner(f):\n       return throttler(f, threshold)\n    return inner\n\nbut we don\u0027t need it now.","commit_id":"73ec88203400552cb7100677402bf146592ee996"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"972756dc8e767180a4b5d0e5c0afcd615cabc16d","unresolved":false,"context_lines":[{"line_number":57,"context_line":"    \"\"\""},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"    def __init__(self, func):"},{"line_number":60,"context_line":"        self._threshold \u003d DEFAULT_THROTTLER_VALUE"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        # First call should trigger the function."},{"line_number":63,"context_line":"        self._last_time_called \u003d 0"}],"source_content_type":"text/x-python","patch_set":44,"id":"ffe62b97_68cc3089","line":60,"range":{"start_line":60,"start_character":7,"end_line":60,"end_character":49},"in_reply_to":"ffe62b97_f8b7f585","updated":"2017-03-24 15:36:21.000000000","message":"If you would apply the decorator to instancemethod in __init__, you would know the value already. I even suspect that then your __get__ could be somewhat simpler. Sounds like a win controlling complexity of the throttler itself. It\u0027s keepalived manager problem that it can\u0027t get access to the value in time.","commit_id":"73ec88203400552cb7100677402bf146592ee996"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"11fb57c5bce316118d527ec3dc50f31dcc68cc7c","unresolved":false,"context_lines":[{"line_number":86,"context_line":""},{"line_number":87,"context_line":"        If call of the function has been already scheduled then the function"},{"line_number":88,"context_line":"        won\u0027t be called. Otherwise the function will be called in at least"},{"line_number":89,"context_line":"        \u0027self._threshold\u0027 seconds from the last call."},{"line_number":90,"context_line":"        \"\"\""},{"line_number":91,"context_line":"        if self._scheduled_lock.acquire(False):"},{"line_number":92,"context_line":"            try:"}],"source_content_type":"text/x-python","patch_set":44,"id":"ffe62b97_384d5d72","line":89,"range":{"start_line":89,"start_character":14,"end_line":89,"end_character":24},"updated":"2017-03-24 14:43:18.000000000","message":"it\u0027s not public, so you should not refer to it in docstring","commit_id":"73ec88203400552cb7100677402bf146592ee996"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"5f6c4a83d0e78f0d36ee42c6df6b09c4f5041ca0","unresolved":false,"context_lines":[{"line_number":86,"context_line":""},{"line_number":87,"context_line":"        If call of the function has been already scheduled then the function"},{"line_number":88,"context_line":"        won\u0027t be called. Otherwise the function will be called in at least"},{"line_number":89,"context_line":"        \u0027self._threshold\u0027 seconds from the last call."},{"line_number":90,"context_line":"        \"\"\""},{"line_number":91,"context_line":"        if self._scheduled_lock.acquire(False):"},{"line_number":92,"context_line":"            try:"}],"source_content_type":"text/x-python","patch_set":44,"id":"ffe62b97_38631d1d","line":89,"range":{"start_line":89,"start_character":14,"end_line":89,"end_character":24},"in_reply_to":"ffe62b97_384d5d72","updated":"2017-03-24 15:32:17.000000000","message":"Done","commit_id":"73ec88203400552cb7100677402bf146592ee996"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"11fb57c5bce316118d527ec3dc50f31dcc68cc7c","unresolved":false,"context_lines":[{"line_number":102,"context_line":"        Descriptors are not very widely used, please see"},{"line_number":103,"context_line":"https://docs.python.org/2.7/reference/datamodel.html#implementing-descriptors"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"        Basically this method is called whenever `dot` is invoked on an object"},{"line_number":106,"context_line":"        (instance.) and return value replaces the instance."},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":44,"id":"ffe62b97_187bb98c","line":105,"range":{"start_line":105,"start_character":50,"end_line":105,"end_character":53},"updated":"2017-03-24 14:43:18.000000000","message":".","commit_id":"73ec88203400552cb7100677402bf146592ee996"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"5f6c4a83d0e78f0d36ee42c6df6b09c4f5041ca0","unresolved":false,"context_lines":[{"line_number":102,"context_line":"        Descriptors are not very widely used, please see"},{"line_number":103,"context_line":"https://docs.python.org/2.7/reference/datamodel.html#implementing-descriptors"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"        Basically this method is called whenever `dot` is invoked on an object"},{"line_number":106,"context_line":"        (instance.) and return value replaces the instance."},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":44,"id":"ffe62b97_6538d9d2","line":105,"range":{"start_line":105,"start_character":50,"end_line":105,"end_character":53},"in_reply_to":"ffe62b97_187bb98c","updated":"2017-03-24 15:32:17.000000000","message":"Done","commit_id":"73ec88203400552cb7100677402bf146592ee996"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"c0bcaed1d60436110d1f09cbb5780db45be0e8bb","unresolved":false,"context_lines":[{"line_number":116,"context_line":"        # can be used on partial object."},{"line_number":117,"context_line":"        funcpart.set_throttle_threshold \u003d self.set_throttle_threshold"},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"        # Replace the parial object magical attributes with magical attributes"},{"line_number":120,"context_line":"        # of original decorated function/method \u0027self._func\u0027. Similar to"},{"line_number":121,"context_line":"        # functools.wraps."},{"line_number":122,"context_line":"        return functools.update_wrapper(funcpart, self._func)"}],"source_content_type":"text/x-python","patch_set":44,"id":"ffe62b97_d3b652da","line":119,"range":{"start_line":119,"start_character":22,"end_line":119,"end_character":28},"updated":"2017-03-24 15:03:57.000000000","message":"partial","commit_id":"73ec88203400552cb7100677402bf146592ee996"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"5f6c4a83d0e78f0d36ee42c6df6b09c4f5041ca0","unresolved":false,"context_lines":[{"line_number":116,"context_line":"        # can be used on partial object."},{"line_number":117,"context_line":"        funcpart.set_throttle_threshold \u003d self.set_throttle_threshold"},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"        # Replace the parial object magical attributes with magical attributes"},{"line_number":120,"context_line":"        # of original decorated function/method \u0027self._func\u0027. Similar to"},{"line_number":121,"context_line":"        # functools.wraps."},{"line_number":122,"context_line":"        return functools.update_wrapper(funcpart, self._func)"}],"source_content_type":"text/x-python","patch_set":44,"id":"ffe62b97_25d771f0","line":119,"range":{"start_line":119,"start_character":22,"end_line":119,"end_character":28},"in_reply_to":"ffe62b97_d3b652da","updated":"2017-03-24 15:32:17.000000000","message":"Done","commit_id":"73ec88203400552cb7100677402bf146592ee996"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"11fb57c5bce316118d527ec3dc50f31dcc68cc7c","unresolved":false,"context_lines":[{"line_number":106,"context_line":"        (instance.) and return value replaces the instance."},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"        \"\"\""},{"line_number":109,"context_line":"        # Make sure \u0027obj\u0027 (which could be cls for classmethod or self for"},{"line_number":110,"context_line":"        # instance methods) is passed to the self.__call__ *args as a first"},{"line_number":111,"context_line":"        # argument."},{"line_number":112,"context_line":"        funcpart \u003d functools.partial(self.__call__, obj)"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"        # Propagate set_throttle_threshold setter to the partial object as it\u0027s"},{"line_number":115,"context_line":"        # not part of magical attributes, so instance.set_throttle_threshold"},{"line_number":116,"context_line":"        # can be used on partial object."},{"line_number":117,"context_line":"        funcpart.set_throttle_threshold \u003d self.set_throttle_threshold"},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"        # Replace the parial object magical attributes with magical attributes"},{"line_number":120,"context_line":"        # of original decorated function/method \u0027self._func\u0027. Similar to"},{"line_number":121,"context_line":"        # functools.wraps."},{"line_number":122,"context_line":"        return functools.update_wrapper(funcpart, self._func)"},{"line_number":123,"context_line":""},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"def load_interface_driver(conf):"}],"source_content_type":"text/x-python","patch_set":44,"id":"ffe62b97_f8a4950a","line":122,"range":{"start_line":109,"start_character":8,"end_line":122,"end_character":61},"updated":"2017-03-24 14:43:18.000000000","message":"My belief is, if you need to document that, you better scratch that completely, as in PS42 where it\u0027s my belief the approach is a lot more simple.","commit_id":"73ec88203400552cb7100677402bf146592ee996"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"5f6c4a83d0e78f0d36ee42c6df6b09c4f5041ca0","unresolved":false,"context_lines":[{"line_number":106,"context_line":"        (instance.) and return value replaces the instance."},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"        \"\"\""},{"line_number":109,"context_line":"        # Make sure \u0027obj\u0027 (which could be cls for classmethod or self for"},{"line_number":110,"context_line":"        # instance methods) is passed to the self.__call__ *args as a first"},{"line_number":111,"context_line":"        # argument."},{"line_number":112,"context_line":"        funcpart \u003d functools.partial(self.__call__, obj)"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"        # Propagate set_throttle_threshold setter to the partial object as it\u0027s"},{"line_number":115,"context_line":"        # not part of magical attributes, so instance.set_throttle_threshold"},{"line_number":116,"context_line":"        # can be used on partial object."},{"line_number":117,"context_line":"        funcpart.set_throttle_threshold \u003d self.set_throttle_threshold"},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"        # Replace the parial object magical attributes with magical attributes"},{"line_number":120,"context_line":"        # of original decorated function/method \u0027self._func\u0027. Similar to"},{"line_number":121,"context_line":"        # functools.wraps."},{"line_number":122,"context_line":"        return functools.update_wrapper(funcpart, self._func)"},{"line_number":123,"context_line":""},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"def load_interface_driver(conf):"}],"source_content_type":"text/x-python","patch_set":44,"id":"ffe62b97_25b53132","line":122,"range":{"start_line":109,"start_character":8,"end_line":122,"end_character":61},"in_reply_to":"ffe62b97_f8a4950a","updated":"2017-03-24 15:32:17.000000000","message":"It still requires storing state to function object, which also requires different behaviors for different python versions, so there is still complexity. Also later you need to replace real method with wrapper ...","commit_id":"73ec88203400552cb7100677402bf146592ee996"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"981e9ed5250aad8e5e59c0173f5d711500d1a661","unresolved":false,"context_lines":[{"line_number":65,"context_line":"# REVISIT(jlibosva): Some parts of throttler may be similar to what"},{"line_number":66,"context_line":"#                    neutron.notifiers.batch_notifier.BatchNotifier does. They"},{"line_number":67,"context_line":"#                    could be refactored and unified."},{"line_number":68,"context_line":"def throttler(threshold\u003dDEFAULT_THROTTLER_VALUE):"},{"line_number":69,"context_line":"    \"\"\"Throttle number of calls to a function to only once per \u0027threshold\u0027."},{"line_number":70,"context_line":"    \"\"\""},{"line_number":71,"context_line":"    def decorator(f):"}],"source_content_type":"text/x-python","patch_set":46,"id":"ffe62b97_01d692c6","line":68,"updated":"2017-03-24 21:21:46.000000000","message":"btw there is nothing agent-specific with the throttler, could go into some more generic place.","commit_id":"81bf980b3ec10082dd5b71c4bb021e51d5c0c327"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"18f940f7cd7f4aa11db5712601feb6c841e0e90a","unresolved":false,"context_lines":[{"line_number":65,"context_line":"# REVISIT(jlibosva): Some parts of throttler may be similar to what"},{"line_number":66,"context_line":"#                    neutron.notifiers.batch_notifier.BatchNotifier does. They"},{"line_number":67,"context_line":"#                    could be refactored and unified."},{"line_number":68,"context_line":"def throttler(threshold\u003dDEFAULT_THROTTLER_VALUE):"},{"line_number":69,"context_line":"    \"\"\"Throttle number of calls to a function to only once per \u0027threshold\u0027."},{"line_number":70,"context_line":"    \"\"\""},{"line_number":71,"context_line":"    def decorator(f):"}],"source_content_type":"text/x-python","patch_set":46,"id":"ffe62b97_dd3e20d9","line":68,"in_reply_to":"ffe62b97_01d692c6","updated":"2017-03-27 12:42:56.000000000","message":"Done","commit_id":"81bf980b3ec10082dd5b71c4bb021e51d5c0c327"}],"neutron/agent/l3/ha_router.py":[{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"9b0724a0825080875f78e83f995d28b73ba8a0b6","unresolved":false,"context_lines":[{"line_number":33,"context_line":"HA_DEV_PREFIX \u003d \u0027ha-\u0027"},{"line_number":34,"context_line":"IP_MONITOR_PROCESS_SERVICE \u003d \u0027ip_monitor\u0027"},{"line_number":35,"context_line":"SIGTERM_TIMEOUT \u003d 10"},{"line_number":36,"context_line":"THROTTLER_MULTIPLIER \u003d 1.5"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"class HaRouterNamespace(namespaces.RouterNamespace):"}],"source_content_type":"text/x-python","patch_set":47,"id":"ffe62b97_01f1af6b","line":36,"updated":"2017-03-27 17:48:25.000000000","message":"Brian\u0027s comments suggest this constant may need some explanation in code.","commit_id":"34b22f1fe533032222172fd3c9c276f8d7c67e62"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"49bc6f8024370ff6f6db2e36dce9146b7cda2a5f","unresolved":false,"context_lines":[{"line_number":33,"context_line":"HA_DEV_PREFIX \u003d \u0027ha-\u0027"},{"line_number":34,"context_line":"IP_MONITOR_PROCESS_SERVICE \u003d \u0027ip_monitor\u0027"},{"line_number":35,"context_line":"SIGTERM_TIMEOUT \u003d 10"},{"line_number":36,"context_line":"THROTTLER_MULTIPLIER \u003d 1.5"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"class HaRouterNamespace(namespaces.RouterNamespace):"}],"source_content_type":"text/x-python","patch_set":47,"id":"ffe62b97_cef06f94","line":36,"in_reply_to":"ffe62b97_01f1af6b","updated":"2017-03-28 12:53:30.000000000","message":"Done","commit_id":"34b22f1fe533032222172fd3c9c276f8d7c67e62"}],"neutron/agent/linux/keepalived.py":[{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"a15abb9a816f91fc629f8801a398b806e6bcdd4f","unresolved":false,"context_lines":[{"line_number":15,"context_line":"import errno"},{"line_number":16,"context_line":"import itertools"},{"line_number":17,"context_line":"import os"},{"line_number":18,"context_line":"import time"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"import netaddr"},{"line_number":21,"context_line":"from neutron_lib import exceptions"}],"source_content_type":"text/x-python","patch_set":1,"id":"3a71b18c_f9f5c4ec","line":18,"updated":"2016-12-05 21:24:52.000000000","message":"not used","commit_id":"cbe30ae913b2fd39468ad9afe97c6649ba74ff3f"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"a0dffac189eaffefbf5d71148aa88aa8389e66a3","unresolved":false,"context_lines":[{"line_number":15,"context_line":"import errno"},{"line_number":16,"context_line":"import itertools"},{"line_number":17,"context_line":"import os"},{"line_number":18,"context_line":"import time"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"import netaddr"},{"line_number":21,"context_line":"from neutron_lib import exceptions"}],"source_content_type":"text/x-python","patch_set":1,"id":"3a71b18c_75f7e98a","line":18,"in_reply_to":"3a71b18c_f9f5c4ec","updated":"2016-12-06 06:15:46.000000000","message":"Done","commit_id":"cbe30ae913b2fd39468ad9afe97c6649ba74ff3f"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"797c2db0f9263749b295876a700b0554a59607b3","unresolved":false,"context_lines":[{"line_number":416,"context_line":"        LOG.debug(\u0027Keepalived spawned with config %s\u0027, config_path)"},{"line_number":417,"context_line":""},{"line_number":418,"context_line":"    def spawn(self):"},{"line_number":419,"context_line":"        eventlet.spawn(self.throttler.call, self._spawn)"},{"line_number":420,"context_line":""},{"line_number":421,"context_line":"    def disable(self):"},{"line_number":422,"context_line":"        self.process_monitor.unregister(uuid\u003dself.resource_id,"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a71b18c_275d3947","line":419,"updated":"2016-12-06 12:49:19.000000000","message":"drop this spawn and go back to the previous version so we can catch exceptions. We already use a pool of coroutines so we don\u0027t need to worry about blocking everything up. http://git.openstack.org/cgit/openstack/neutron/tree/neutron/agent/l3/agent.py#n528","commit_id":"743999886d458d3548faf1f3788b9b8234342091"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"a89bb51a850d073a1a721adf0871f115a5d485c8","unresolved":false,"context_lines":[{"line_number":348,"context_line":""},{"line_number":349,"context_line":"    \"\"\""},{"line_number":350,"context_line":""},{"line_number":351,"context_line":"    def __init__(self, resource_id, config, process_monitor, advert_int,"},{"line_number":352,"context_line":"                 conf_path\u003d\u0027/tmp\u0027, namespace\u003dNone):"},{"line_number":353,"context_line":"        self.resource_id \u003d resource_id"},{"line_number":354,"context_line":"        self.config \u003d config"}],"source_content_type":"text/x-python","patch_set":15,"id":"1a6eadb0_92d78922","line":351,"range":{"start_line":351,"start_character":61,"end_line":351,"end_character":72},"updated":"2016-12-14 13:51:16.000000000","message":"I checked that we don\u0027t have a consumer under big tent of KeepalivedManager though it\u0027s safer to put this as a last parameter of this method with default value of 2 to keep backward compatibility.","commit_id":"d6945e59db27ce0ef51abfa93977d3788b48a52a"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"11c17f01fcba4cd34d1e093c7158eccea65ff82b","unresolved":false,"context_lines":[{"line_number":348,"context_line":""},{"line_number":349,"context_line":"    \"\"\""},{"line_number":350,"context_line":""},{"line_number":351,"context_line":"    def __init__(self, resource_id, config, process_monitor, advert_int,"},{"line_number":352,"context_line":"                 conf_path\u003d\u0027/tmp\u0027, namespace\u003dNone):"},{"line_number":353,"context_line":"        self.resource_id \u003d resource_id"},{"line_number":354,"context_line":"        self.config \u003d config"}],"source_content_type":"text/x-python","patch_set":15,"id":"1a6eadb0_cd3aad98","line":351,"range":{"start_line":351,"start_character":61,"end_line":351,"end_character":72},"in_reply_to":"1a6eadb0_92d78922","updated":"2016-12-18 09:31:38.000000000","message":"Done, except I\u0027ve given it the default value that matches the one from the configuration option.","commit_id":"d6945e59db27ce0ef51abfa93977d3788b48a52a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"cc6f4c0694df1e03ea2b24014916fd38c602b2e1","unresolved":false,"context_lines":[{"line_number":356,"context_line":"        self.process_monitor \u003d process_monitor"},{"line_number":357,"context_line":"        self.conf_path \u003d conf_path"},{"line_number":358,"context_line":""},{"line_number":359,"context_line":"        if not advert_int:"},{"line_number":360,"context_line":"            advert_int \u003d cfg.CONF.ha_vrrp_advert_int"},{"line_number":361,"context_line":"        self.throttler \u003d utils.Throttler(threshold\u003dadvert_int)"},{"line_number":362,"context_line":""},{"line_number":363,"context_line":"    def get_conf_dir(self):"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_5f9a146f","line":360,"range":{"start_line":359,"start_character":0,"end_line":360,"end_character":52},"updated":"2017-01-06 10:51:29.000000000","message":"Nit: adver_int \u003d advert_int or cfg.CONF.ha_vrrp_advert_int","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"964dbb2bcee2ecd570a4863d2cfee04d7fddad6a","unresolved":false,"context_lines":[{"line_number":357,"context_line":"        self.conf_path \u003d conf_path"},{"line_number":358,"context_line":""},{"line_number":359,"context_line":"        if not advert_int:"},{"line_number":360,"context_line":"            advert_int \u003d cfg.CONF.ha_vrrp_advert_int"},{"line_number":361,"context_line":"        self.throttler \u003d utils.Throttler(threshold\u003dadvert_int)"},{"line_number":362,"context_line":""},{"line_number":363,"context_line":"    def get_conf_dir(self):"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_c18e9b26","line":360,"range":{"start_line":360,"start_character":25,"end_line":360,"end_character":52},"updated":"2017-01-10 21:27:39.000000000","message":"This value is 2 seconds by default. Is it always enough for keepalived to get ready to process the next signal without master switch?\n\nNot to mention that you probably reuse a configuration option that has a description that is very different from your intent. Currently it says: \"The advertisement interval in seconds\". How is operator supposed to figure out that this knob controls the throttler too?","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":357,"context_line":"        self.conf_path \u003d conf_path"},{"line_number":358,"context_line":""},{"line_number":359,"context_line":"        if not advert_int:"},{"line_number":360,"context_line":"            advert_int \u003d cfg.CONF.ha_vrrp_advert_int"},{"line_number":361,"context_line":"        self.throttler \u003d utils.Throttler(threshold\u003dadvert_int)"},{"line_number":362,"context_line":""},{"line_number":363,"context_line":"    def get_conf_dir(self):"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a3c09a3_c76e9d2e","line":360,"range":{"start_line":360,"start_character":25,"end_line":360,"end_character":52},"in_reply_to":"ba5201f7_98504b34","updated":"2017-01-16 13:22:12.000000000","message":"So, considering I\u0027d like to backport this patch, adding a new configuration option is not optimal. I\u0027m fine with making a function of ha_vrrp_advert_int and modify the documentation.\n\nAlso, 2*advert_int seems a bit much. It shouldn\u0027t take a C code 2 seconds to run a signal handler. 1.2 * advert_int sounds better.","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"10659b1513dd3ea38e6c68d23b2ca4f7fb1f1a6d","unresolved":false,"context_lines":[{"line_number":357,"context_line":"        self.conf_path \u003d conf_path"},{"line_number":358,"context_line":""},{"line_number":359,"context_line":"        if not advert_int:"},{"line_number":360,"context_line":"            advert_int \u003d cfg.CONF.ha_vrrp_advert_int"},{"line_number":361,"context_line":"        self.throttler \u003d utils.Throttler(threshold\u003dadvert_int)"},{"line_number":362,"context_line":""},{"line_number":363,"context_line":"    def get_conf_dir(self):"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_98504b34","line":360,"range":{"start_line":360,"start_character":25,"end_line":360,"end_character":52},"in_reply_to":"ba5201f7_c18e9b26","updated":"2017-01-11 19:43:54.000000000","message":"I believe we can auto-calculate the throttler and not add another knob.\n\nBut I\u0027d leave some extra time for master election, we may need to look into the VRRP protocol details, but I\u0027d guess that at least 2*advert_int, let\u0027s have a deeper look into the protocol and find the right proportion.","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"19e8292114541c49ca74ea521b08486d3c920e81","unresolved":false,"context_lines":[{"line_number":358,"context_line":""},{"line_number":359,"context_line":"        if not advert_int:"},{"line_number":360,"context_line":"            advert_int \u003d cfg.CONF.ha_vrrp_advert_int"},{"line_number":361,"context_line":"        self.throttler \u003d utils.Throttler(threshold\u003d(advert_int * 1.2))"},{"line_number":362,"context_line":""},{"line_number":363,"context_line":"    def get_conf_dir(self):"},{"line_number":364,"context_line":"        confs_dir \u003d os.path.abspath(os.path.normpath(self.conf_path))"}],"source_content_type":"text/x-python","patch_set":18,"id":"7a3c09a3_2c649d20","line":361,"range":{"start_line":361,"start_character":51,"end_line":361,"end_character":52},"updated":"2017-01-16 15:59:48.000000000","message":"Nit: Parenthesis are not needed.","commit_id":"1823eab3a81b18c36afb266db2ab8ca4db286d9d"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"19e8292114541c49ca74ea521b08486d3c920e81","unresolved":false,"context_lines":[{"line_number":358,"context_line":""},{"line_number":359,"context_line":"        if not advert_int:"},{"line_number":360,"context_line":"            advert_int \u003d cfg.CONF.ha_vrrp_advert_int"},{"line_number":361,"context_line":"        self.throttler \u003d utils.Throttler(threshold\u003d(advert_int * 1.2))"},{"line_number":362,"context_line":""},{"line_number":363,"context_line":"    def get_conf_dir(self):"},{"line_number":364,"context_line":"        confs_dir \u003d os.path.abspath(os.path.normpath(self.conf_path))"}],"source_content_type":"text/x-python","patch_set":18,"id":"7a3c09a3_ac8a4dbd","line":361,"range":{"start_line":361,"start_character":65,"end_line":361,"end_character":68},"updated":"2017-01-16 15:59:48.000000000","message":"This should be made a constant instead of magical number laying here. You can later also re-use that in the fullstack tests.","commit_id":"1823eab3a81b18c36afb266db2ab8ca4db286d9d"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"1c52503190e8164bb694a1ae3fab756ea20e8bcc","unresolved":false,"context_lines":[{"line_number":358,"context_line":""},{"line_number":359,"context_line":"        if not advert_int:"},{"line_number":360,"context_line":"            advert_int \u003d cfg.CONF.ha_vrrp_advert_int"},{"line_number":361,"context_line":"        self.throttler \u003d utils.Throttler(threshold\u003d(advert_int * 1.2))"},{"line_number":362,"context_line":""},{"line_number":363,"context_line":"    def get_conf_dir(self):"},{"line_number":364,"context_line":"        confs_dir \u003d os.path.abspath(os.path.normpath(self.conf_path))"}],"source_content_type":"text/x-python","patch_set":18,"id":"3a461143_8643496b","line":361,"range":{"start_line":361,"start_character":65,"end_line":361,"end_character":68},"in_reply_to":"7a3c09a3_ac8a4dbd","updated":"2017-01-31 16:13:05.000000000","message":"Done","commit_id":"1823eab3a81b18c36afb266db2ab8ca4db286d9d"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"02bd3c62d33d3f5bc80b8b891890898266ba417c","unresolved":false,"context_lines":[{"line_number":355,"context_line":"        self.namespace \u003d namespace"},{"line_number":356,"context_line":"        self.process_monitor \u003d process_monitor"},{"line_number":357,"context_line":"        self.conf_path \u003d conf_path"},{"line_number":358,"context_line":"        self.throttler \u003d utils.Throttler(threshold\u003d(advert_int * 1.2))"},{"line_number":359,"context_line":""},{"line_number":360,"context_line":"    def get_conf_dir(self):"},{"line_number":361,"context_line":"        confs_dir \u003d os.path.abspath(os.path.normpath(self.conf_path))"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a461143_e0cd0e32","line":358,"range":{"start_line":358,"start_character":65,"end_line":358,"end_character":68},"updated":"2017-01-30 09:43:09.000000000","message":"constant if you need to respin.","commit_id":"7479fea3992003594f8c26a3cda4f09e5827fec8"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"023151d18386104f7e172a391a3ec7b46779264c","unresolved":false,"context_lines":[{"line_number":355,"context_line":"        self.namespace \u003d namespace"},{"line_number":356,"context_line":"        self.process_monitor \u003d process_monitor"},{"line_number":357,"context_line":"        self.conf_path \u003d conf_path"},{"line_number":358,"context_line":"        self.throttler \u003d utils.Throttler(threshold\u003d(advert_int * 1.2))"},{"line_number":359,"context_line":""},{"line_number":360,"context_line":"    def get_conf_dir(self):"},{"line_number":361,"context_line":"        confs_dir \u003d os.path.abspath(os.path.normpath(self.conf_path))"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a461143_c1053b46","line":358,"range":{"start_line":358,"start_character":65,"end_line":358,"end_character":68},"in_reply_to":"3a461143_e0cd0e32","updated":"2017-01-31 16:29:04.000000000","message":"Done","commit_id":"7479fea3992003594f8c26a3cda4f09e5827fec8"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"69f0b0fc762df786f56afe274f1dd93900df23cf","unresolved":false,"context_lines":[{"line_number":39,"context_line":""},{"line_number":40,"context_line":"# Should match cfg.CONF.ha_vrrp_advert_int."},{"line_number":41,"context_line":"#TODO(jschwarz): using cfg.CONF.ha_vrrp_advert_int necessitates an import,"},{"line_number":42,"context_line":"# which results in a recursive import. This should be fixed into being the"},{"line_number":43,"context_line":"# actual config value."},{"line_number":44,"context_line":"DEFAULT_THROTTLER_VALUE \u003d 2"},{"line_number":45,"context_line":"DEFAULT_THROTTLER_MULTIPLIER \u003d 1.2"}],"source_content_type":"text/x-python","patch_set":25,"id":"3a461143_807b0dbd","line":42,"updated":"2017-02-01 11:39:23.000000000","message":"I\u0027ve been there, you can break recursive imports this way:\nhttps://github.com/openstack/neutron/blob/master/neutron/api/rpc/callbacks/version_manager.py#L29\n\nCould we use that to somehow, what\u0027s the nature of the circular import?","commit_id":"32d9b1441cefb6a497271106842667750c366e20"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"3605ce42bb02ac326537ecf7b65d3b8c5fcb8e4a","unresolved":false,"context_lines":[{"line_number":39,"context_line":""},{"line_number":40,"context_line":"# Should match cfg.CONF.ha_vrrp_advert_int."},{"line_number":41,"context_line":"#TODO(jschwarz): using cfg.CONF.ha_vrrp_advert_int necessitates an import,"},{"line_number":42,"context_line":"# which results in a recursive import. This should be fixed into being the"},{"line_number":43,"context_line":"# actual config value."},{"line_number":44,"context_line":"DEFAULT_THROTTLER_VALUE \u003d 2"},{"line_number":45,"context_line":"DEFAULT_THROTTLER_MULTIPLIER \u003d 1.2"}],"source_content_type":"text/x-python","patch_set":25,"id":"3a461143_c55dfc49","line":42,"in_reply_to":"3a461143_1bea2edb","updated":"2017-02-02 11:04:08.000000000","message":"I\u0027m ok with a follow up on this :)","commit_id":"32d9b1441cefb6a497271106842667750c366e20"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"b00cb6a4cebb6cb3f79b6c49ebbb0625609893e9","unresolved":false,"context_lines":[{"line_number":39,"context_line":""},{"line_number":40,"context_line":"# Should match cfg.CONF.ha_vrrp_advert_int."},{"line_number":41,"context_line":"#TODO(jschwarz): using cfg.CONF.ha_vrrp_advert_int necessitates an import,"},{"line_number":42,"context_line":"# which results in a recursive import. This should be fixed into being the"},{"line_number":43,"context_line":"# actual config value."},{"line_number":44,"context_line":"DEFAULT_THROTTLER_VALUE \u003d 2"},{"line_number":45,"context_line":"DEFAULT_THROTTLER_MULTIPLIER \u003d 1.2"}],"source_content_type":"text/x-python","patch_set":25,"id":"3a461143_1bea2edb","line":42,"in_reply_to":"3a461143_807b0dbd","updated":"2017-02-01 11:45:20.000000000","message":"the circular import is caused when this file imports conf.l3_ha (which in turn imports this file).\n\nWe can solve it in a followup patch :)","commit_id":"32d9b1441cefb6a497271106842667750c366e20"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":369,"context_line":""},{"line_number":370,"context_line":"    def __init__(self, resource_id, config, process_monitor,"},{"line_number":371,"context_line":"                 conf_path\u003d\u0027/tmp\u0027, namespace\u003dNone,"},{"line_number":372,"context_line":"                 advert_int\u003dutils.DEFAULT_THROTTLER_VALUE):"},{"line_number":373,"context_line":"        self.resource_id \u003d resource_id"},{"line_number":374,"context_line":"        self.config \u003d config"},{"line_number":375,"context_line":"        self.namespace \u003d namespace"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_df34dadf","line":372,"range":{"start_line":372,"start_character":17,"end_line":372,"end_character":57},"updated":"2017-03-17 17:29:15.000000000","message":"when do we want to use a value that is different from the one from the corresponding config option?","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":369,"context_line":""},{"line_number":370,"context_line":"    def __init__(self, resource_id, config, process_monitor,"},{"line_number":371,"context_line":"                 conf_path\u003d\u0027/tmp\u0027, namespace\u003dNone,"},{"line_number":372,"context_line":"                 advert_int\u003dutils.DEFAULT_THROTTLER_VALUE):"},{"line_number":373,"context_line":"        self.resource_id \u003d resource_id"},{"line_number":374,"context_line":"        self.config \u003d config"},{"line_number":375,"context_line":"        self.namespace \u003d namespace"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_5c644ae4","line":372,"range":{"start_line":372,"start_character":17,"end_line":372,"end_character":57},"in_reply_to":"1a1ced50_df34dadf","updated":"2017-03-20 14:09:13.000000000","message":"I believe this is just to separate config object from KeepalivedManager.","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"b7ccedd67e5121b7ab957a3e8bb46780438fc69d","unresolved":false,"context_lines":[{"line_number":429,"context_line":"        keepalived_pm.default_cmd_callback \u003d ("},{"line_number":430,"context_line":"            self._get_keepalived_process_callback(vrrp_pm, config_path))"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"        keepalived_pm.enable(reload_cfg\u003dTrue)"},{"line_number":433,"context_line":""},{"line_number":434,"context_line":"        for key, instance in six.iteritems(self.config.instances):"},{"line_number":435,"context_line":"            if instance.track_script:"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_6186ac66","line":432,"range":{"start_line":432,"start_character":8,"end_line":432,"end_character":45},"updated":"2017-03-20 20:10:09.000000000","message":"seems like what we should throttle is not the whole spawn, but this specific call. Otherwise time between consequent SIGHUPs may vary depending on how long other work done by the method takes.\n\nThe reason I suggest that is that it seems in fullstack test, SIGHUPs can be sent before the intended threshold is reached, see:\n\nhttp://logs.openstack.org/99/407099/34/check/gate-neutron-dsvm-fullstack-ubuntu-xenial/fa6d235/logs/dsvm-fullstack-logs/TestHAL3Agent.test_keepalived_multiple_sighups_does_not_forfeit_mastership/neutron-l3-agent--2017-03-20--16-09-10-762426.txt.gz#_2017-03-20_16_10_05_260\n\nhttp://logs.openstack.org/99/407099/34/check/gate-neutron-dsvm-fullstack-ubuntu-xenial/fa6d235/logs/dsvm-fullstack-logs/TestHAL3Agent.test_keepalived_multiple_sighups_does_not_forfeit_mastership/neutron-l3-agent--2017-03-20--16-09-10-762426.txt.gz#_2017-03-20_16_10_07_260\n\nTime between those two calls is 2 sec, not 2 sec * 1.2.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"4e6e56bc1e75a8deff29361d34f32291d971b731","unresolved":false,"context_lines":[{"line_number":429,"context_line":"        keepalived_pm.default_cmd_callback \u003d ("},{"line_number":430,"context_line":"            self._get_keepalived_process_callback(vrrp_pm, config_path))"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"        keepalived_pm.enable(reload_cfg\u003dTrue)"},{"line_number":433,"context_line":""},{"line_number":434,"context_line":"        for key, instance in six.iteritems(self.config.instances):"},{"line_number":435,"context_line":"            if instance.track_script:"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_aedb0d4e","line":432,"range":{"start_line":432,"start_character":8,"end_line":432,"end_character":45},"in_reply_to":"1a1ced50_0bddf36e","updated":"2017-03-21 13:55:34.000000000","message":"No, otherwise during function execution any execution request will be done without delay (because is_scheduled is False and last_time_called \u003c time.time() - threshold).","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"c07cd9a0aa0ec4d6cdaa02ad449c4a3bf444a20f","unresolved":false,"context_lines":[{"line_number":429,"context_line":"        keepalived_pm.default_cmd_callback \u003d ("},{"line_number":430,"context_line":"            self._get_keepalived_process_callback(vrrp_pm, config_path))"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"        keepalived_pm.enable(reload_cfg\u003dTrue)"},{"line_number":433,"context_line":""},{"line_number":434,"context_line":"        for key, instance in six.iteritems(self.config.instances):"},{"line_number":435,"context_line":"            if instance.track_script:"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_d2a2b598","line":432,"range":{"start_line":432,"start_character":8,"end_line":432,"end_character":45},"in_reply_to":"1a1ced50_3cf04067","updated":"2017-03-21 11:08:38.000000000","message":"If we throttle only this instruction then we no more ensure that keepalived_pm.enable(..) will be executed before L434-L442 ... indeed when decorated function is executed by a concurrent greenthread we don\u0027t wait for its execution (and it\u0027s a bit tricky to wait for it).","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"935518c0e24a00158a99ad672f36e46374ec52c1","unresolved":false,"context_lines":[{"line_number":429,"context_line":"        keepalived_pm.default_cmd_callback \u003d ("},{"line_number":430,"context_line":"            self._get_keepalived_process_callback(vrrp_pm, config_path))"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"        keepalived_pm.enable(reload_cfg\u003dTrue)"},{"line_number":433,"context_line":""},{"line_number":434,"context_line":"        for key, instance in six.iteritems(self.config.instances):"},{"line_number":435,"context_line":"            if instance.track_script:"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_3cf04067","line":432,"range":{"start_line":432,"start_character":8,"end_line":432,"end_character":45},"in_reply_to":"1a1ced50_6186ac66","updated":"2017-03-21 10:24:00.000000000","message":"Hmm, there shouldn\u0027t be a great difference between doing it specifically for this line, or the whole function, L423 to L429 execution should be very very short.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e788c13ba36781714a0d6fe042267d1ac411bc12","unresolved":false,"context_lines":[{"line_number":429,"context_line":"        keepalived_pm.default_cmd_callback \u003d ("},{"line_number":430,"context_line":"            self._get_keepalived_process_callback(vrrp_pm, config_path))"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"        keepalived_pm.enable(reload_cfg\u003dTrue)"},{"line_number":433,"context_line":""},{"line_number":434,"context_line":"        for key, instance in six.iteritems(self.config.instances):"},{"line_number":435,"context_line":"            if instance.track_script:"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_87a441ba","line":432,"range":{"start_line":432,"start_character":8,"end_line":432,"end_character":45},"in_reply_to":"1a1ced50_84619fab","updated":"2017-03-22 15:01:18.000000000","message":"Moving the lock after function would introduce the race from PS27, wouldn\u0027t it?","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8124,"name":"cbrandily","email":"zzelle@gmail.com","username":"cbrandily"},"change_message_id":"9fea17f04be313d35aef4cef3aa7a3c30958de4b","unresolved":false,"context_lines":[{"line_number":429,"context_line":"        keepalived_pm.default_cmd_callback \u003d ("},{"line_number":430,"context_line":"            self._get_keepalived_process_callback(vrrp_pm, config_path))"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"        keepalived_pm.enable(reload_cfg\u003dTrue)"},{"line_number":433,"context_line":""},{"line_number":434,"context_line":"        for key, instance in six.iteritems(self.config.instances):"},{"line_number":435,"context_line":"            if instance.track_script:"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_f8591036","line":432,"range":{"start_line":432,"start_character":8,"end_line":432,"end_character":45},"in_reply_to":"1a1ced50_87a441ba","updated":"2017-03-22 15:40:49.000000000","message":"Yes, it would.\n\nWe want to ensure that spawn will be executed AFTER a \"spawn execution request\".\n\nIf we release the lock after spawn execution, it implies that:\n* spawn will be executed AFTER a \"spawn execution request\" \u003d\u003d\u003e OK\n* or spawn is currently executed DURING a \"spawn execution request\" \u003d\u003d\u003e KO","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"763f77fcecd8e1ea5e9baf9ed1439e74f6f9b415","unresolved":false,"context_lines":[{"line_number":429,"context_line":"        keepalived_pm.default_cmd_callback \u003d ("},{"line_number":430,"context_line":"            self._get_keepalived_process_callback(vrrp_pm, config_path))"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"        keepalived_pm.enable(reload_cfg\u003dTrue)"},{"line_number":433,"context_line":""},{"line_number":434,"context_line":"        for key, instance in six.iteritems(self.config.instances):"},{"line_number":435,"context_line":"            if instance.track_script:"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_8dad1ceb","line":432,"range":{"start_line":432,"start_character":8,"end_line":432,"end_character":45},"in_reply_to":"1a1ced50_8d7e1b68","updated":"2017-03-23 09:19:56.000000000","message":"I think if we unlock after calling to _func(), it still would have that effect from PS27.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"ad5112d63a3232c9f509cf4ea9fb51591fd703f0","unresolved":false,"context_lines":[{"line_number":429,"context_line":"        keepalived_pm.default_cmd_callback \u003d ("},{"line_number":430,"context_line":"            self._get_keepalived_process_callback(vrrp_pm, config_path))"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"        keepalived_pm.enable(reload_cfg\u003dTrue)"},{"line_number":433,"context_line":""},{"line_number":434,"context_line":"        for key, instance in six.iteritems(self.config.instances):"},{"line_number":435,"context_line":"            if instance.track_script:"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_84619fab","line":432,"range":{"start_line":432,"start_character":8,"end_line":432,"end_character":45},"in_reply_to":"1a1ced50_aedb0d4e","updated":"2017-03-22 14:37:41.000000000","message":"The answer here would be keeping the lock for the time of func execution, and free it after function is completed, (and just after we update last time checked after the func call).","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"8e866169d8b4016bece9ec42c508d72a9207c705","unresolved":false,"context_lines":[{"line_number":429,"context_line":"        keepalived_pm.default_cmd_callback \u003d ("},{"line_number":430,"context_line":"            self._get_keepalived_process_callback(vrrp_pm, config_path))"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"        keepalived_pm.enable(reload_cfg\u003dTrue)"},{"line_number":433,"context_line":""},{"line_number":434,"context_line":"        for key, instance in six.iteritems(self.config.instances):"},{"line_number":435,"context_line":"            if instance.track_script:"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_0bddf36e","line":432,"range":{"start_line":432,"start_character":8,"end_line":432,"end_character":45},"in_reply_to":"1a1ced50_d2a2b598","updated":"2017-03-21 13:32:59.000000000","message":"Would updating the last_time_called AFTER the function has finished solve the issue?","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"fd968db913b4a047720275154976a49181949592","unresolved":false,"context_lines":[{"line_number":429,"context_line":"        keepalived_pm.default_cmd_callback \u003d ("},{"line_number":430,"context_line":"            self._get_keepalived_process_callback(vrrp_pm, config_path))"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"        keepalived_pm.enable(reload_cfg\u003dTrue)"},{"line_number":433,"context_line":""},{"line_number":434,"context_line":"        for key, instance in six.iteritems(self.config.instances):"},{"line_number":435,"context_line":"            if instance.track_script:"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_8d7e1b68","line":432,"range":{"start_line":432,"start_character":8,"end_line":432,"end_character":45},"in_reply_to":"1a1ced50_f8591036","updated":"2017-03-22 16:56:05.000000000","message":"I am not asking to lock on enable() only here. All I am saying now is that we may want to make the throttler guarantee that there is always at least 2 secs between calls, not just between STARTs of the calls.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"a275c8025a3a213eaa750087c454c0afa5a8f73d","unresolved":false,"context_lines":[{"line_number":376,"context_line":"        self.conf_path \u003d conf_path"},{"line_number":377,"context_line":"        if advert_int is not None:"},{"line_number":378,"context_line":"            # Configure throttler decorator"},{"line_number":379,"context_line":"            self.spawn.throttle_threshold \u003d advert_int"},{"line_number":380,"context_line":""},{"line_number":381,"context_line":"    def get_conf_dir(self):"},{"line_number":382,"context_line":"        confs_dir \u003d os.path.abspath(os.path.normpath(self.conf_path))"}],"source_content_type":"text/x-python","patch_set":40,"id":"ffe62b97_65e120d1","line":379,"updated":"2017-03-23 21:13:09.000000000","message":"I think there is an issue here, with this call, and __get__ implementation in throttler class, that make this line ineffective (it sets threshold on functools.partial object, not on throttler).","commit_id":"a624f6fb643d50608cf2e0b37746fc50b18bd238"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"11fb57c5bce316118d527ec3dc50f31dcc68cc7c","unresolved":false,"context_lines":[{"line_number":376,"context_line":"        self.conf_path \u003d conf_path"},{"line_number":377,"context_line":"        if advert_int is not None:"},{"line_number":378,"context_line":"            # Configure throttler decorator"},{"line_number":379,"context_line":"            self.spawn.set_throttle_threshold(advert_int)"},{"line_number":380,"context_line":""},{"line_number":381,"context_line":"    def get_conf_dir(self):"},{"line_number":382,"context_line":"        confs_dir \u003d os.path.abspath(os.path.normpath(self.conf_path))"}],"source_content_type":"text/x-python","patch_set":44,"id":"ffe62b97_98c22985","line":379,"updated":"2017-03-24 14:43:18.000000000","message":"note it won\u0027t allow to have two managers with different threshold","commit_id":"73ec88203400552cb7100677402bf146592ee996"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"5f6c4a83d0e78f0d36ee42c6df6b09c4f5041ca0","unresolved":false,"context_lines":[{"line_number":376,"context_line":"        self.conf_path \u003d conf_path"},{"line_number":377,"context_line":"        if advert_int is not None:"},{"line_number":378,"context_line":"            # Configure throttler decorator"},{"line_number":379,"context_line":"            self.spawn.set_throttle_threshold(advert_int)"},{"line_number":380,"context_line":""},{"line_number":381,"context_line":"    def get_conf_dir(self):"},{"line_number":382,"context_line":"        confs_dir \u003d os.path.abspath(os.path.normpath(self.conf_path))"}],"source_content_type":"text/x-python","patch_set":44,"id":"ffe62b97_0805a4c2","line":379,"in_reply_to":"ffe62b97_98c22985","updated":"2017-03-24 15:32:17.000000000","message":"not good.","commit_id":"73ec88203400552cb7100677402bf146592ee996"}],"neutron/cmd/sanity/checks.py":[{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"964dbb2bcee2ecd570a4863d2cfee04d7fddad6a","unresolved":false,"context_lines":[{"line_number":285,"context_line":"        # Instantiate keepalived manager with the IPv6 configuration."},{"line_number":286,"context_line":"        self.manager \u003d keepalived.KeepalivedManager(\u0027router1\u0027, self.config,"},{"line_number":287,"context_line":"            namespace\u003dself.nsname, process_monitor\u003dself.pm,"},{"line_number":288,"context_line":"            conf_path\u003dself.config_path, advert_int\u003d2)"},{"line_number":289,"context_line":"        self.manager.spawn()"},{"line_number":290,"context_line":""},{"line_number":291,"context_line":"    def verify_ipv6_address_assignment(self, gw_dev):"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_21a2074c","line":288,"range":{"start_line":288,"start_character":38,"end_line":288,"end_character":52},"updated":"2017-01-10 21:27:39.000000000","message":"Why do you need to pass it here? Doesn\u0027t default value work?","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":285,"context_line":"        # Instantiate keepalived manager with the IPv6 configuration."},{"line_number":286,"context_line":"        self.manager \u003d keepalived.KeepalivedManager(\u0027router1\u0027, self.config,"},{"line_number":287,"context_line":"            namespace\u003dself.nsname, process_monitor\u003dself.pm,"},{"line_number":288,"context_line":"            conf_path\u003dself.config_path, advert_int\u003d2)"},{"line_number":289,"context_line":"        self.manager.spawn()"},{"line_number":290,"context_line":""},{"line_number":291,"context_line":"    def verify_ipv6_address_assignment(self, gw_dev):"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_15a0c79e","line":288,"range":{"start_line":288,"start_character":38,"end_line":288,"end_character":52},"in_reply_to":"ba5201f7_21a2074c","updated":"2017-01-16 13:22:12.000000000","message":"Done","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"730424677b5daac1165cd28a812d8c8ddc9774a6","unresolved":false,"context_lines":[{"line_number":281,"context_line":"        cfg.CONF.set_override(\u0027check_child_processes_interval\u0027, 0, \u0027AGENT\u0027)"},{"line_number":282,"context_line":""},{"line_number":283,"context_line":"        # Make sure KeepalivedManager has the config options it needs"},{"line_number":284,"context_line":"        ha_conf.register_l3_agent_ha_opts()"},{"line_number":285,"context_line":""},{"line_number":286,"context_line":"        # Create a temp directory to store keepalived configuration."},{"line_number":287,"context_line":"        self.config_path \u003d tempfile.mkdtemp()"}],"source_content_type":"text/x-python","patch_set":20,"id":"7a3c09a3_c7b2eb05","line":284,"updated":"2017-01-17 09:56:05.000000000","message":"This is a workaround on a wrong place. If someone imports the KeepalivedManager and wants to use it, he\u0027ll get an exception. The fix should be either for KeepalivedManager or better make a default for KeepalivedManager and let the advert being configurable for agent only, who will pass the value down to KeepalivedManager","commit_id":"a53cc8b36d4093d894fdd9ad85c1f8eea6a6a83c"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"84423cd5637362f6303edd8318fd88f5598a0032","unresolved":false,"context_lines":[{"line_number":281,"context_line":"        cfg.CONF.set_override(\u0027check_child_processes_interval\u0027, 0, \u0027AGENT\u0027)"},{"line_number":282,"context_line":""},{"line_number":283,"context_line":"        # Make sure KeepalivedManager has the config options it needs"},{"line_number":284,"context_line":"        ha_conf.register_l3_agent_ha_opts()"},{"line_number":285,"context_line":""},{"line_number":286,"context_line":"        # Create a temp directory to store keepalived configuration."},{"line_number":287,"context_line":"        self.config_path \u003d tempfile.mkdtemp()"}],"source_content_type":"text/x-python","patch_set":20,"id":"3a461143_94c1fa56","line":284,"in_reply_to":"7a3c09a3_c7b2eb05","updated":"2017-01-29 10:20:20.000000000","message":"Done","commit_id":"a53cc8b36d4093d894fdd9ad85c1f8eea6a6a83c"}],"neutron/conf/agent/l3/ha.py":[{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":36,"context_line":"               default\u003d2,"},{"line_number":37,"context_line":"               help\u003d_(\u0027The advertisement interval in seconds. This value is \u0027"},{"line_number":38,"context_line":"                      \u0027also used to throttle SIGHUPs sent to the Keepalived \u0027"},{"line_number":39,"context_line":"                      \u0027processes, where at most one is sent per \u0027"},{"line_number":40,"context_line":"                      \u0027ha_vrrp_advert_int seconds.\u0027)),"},{"line_number":41,"context_line":"    cfg.IntOpt(\u0027ha_keepalived_state_change_server_threads\u0027,"},{"line_number":42,"context_line":"               default\u003d(1 + host.cpu_count()) // 2,"},{"line_number":43,"context_line":"               sample_default\u003d\u0027(1 + \u003cnum_of_cpus\u003e) / 2\u0027,"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_441743a3","line":40,"range":{"start_line":39,"start_character":48,"end_line":40,"end_character":49},"updated":"2017-03-17 17:29:15.000000000","message":"It\u0027s not exactly that, right? We apply a multiplier?.. Suggesting to make the wording a tad more vague not to refer to specific number of seconds. Also, you talk about SIGHUPs here, but does the consumer care about how exactly we reload configuration for the service? At least they should not if all works as intended.","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":34,"context_line":"               secret\u003dTrue),"},{"line_number":35,"context_line":"    cfg.IntOpt(\u0027ha_vrrp_advert_int\u0027,"},{"line_number":36,"context_line":"               default\u003d2,"},{"line_number":37,"context_line":"               help\u003d_(\u0027The advertisement interval in seconds. This value is \u0027"},{"line_number":38,"context_line":"                      \u0027also used to throttle SIGHUPs sent to the Keepalived \u0027"},{"line_number":39,"context_line":"                      \u0027processes, where at most one is sent per \u0027"},{"line_number":40,"context_line":"                      \u0027ha_vrrp_advert_int seconds.\u0027)),"},{"line_number":41,"context_line":"    cfg.IntOpt(\u0027ha_keepalived_state_change_server_threads\u0027,"},{"line_number":42,"context_line":"               default\u003d(1 + host.cpu_count()) // 2,"},{"line_number":43,"context_line":"               sample_default\u003d\u0027(1 + \u003cnum_of_cpus\u003e) / 2\u0027,"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_c43c1332","line":40,"range":{"start_line":37,"start_character":61,"end_line":40,"end_character":50},"updated":"2017-03-17 17:29:15.000000000","message":"does the change deserve a release note?","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":36,"context_line":"               default\u003d2,"},{"line_number":37,"context_line":"               help\u003d_(\u0027The advertisement interval in seconds. This value is \u0027"},{"line_number":38,"context_line":"                      \u0027also used to throttle SIGHUPs sent to the Keepalived \u0027"},{"line_number":39,"context_line":"                      \u0027processes, where at most one is sent per \u0027"},{"line_number":40,"context_line":"                      \u0027ha_vrrp_advert_int seconds.\u0027)),"},{"line_number":41,"context_line":"    cfg.IntOpt(\u0027ha_keepalived_state_change_server_threads\u0027,"},{"line_number":42,"context_line":"               default\u003d(1 + host.cpu_count()) // 2,"},{"line_number":43,"context_line":"               sample_default\u003d\u0027(1 + \u003cnum_of_cpus\u003e) / 2\u0027,"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_3f978091","line":40,"range":{"start_line":39,"start_character":48,"end_line":40,"end_character":49},"in_reply_to":"1a1ced50_441743a3","updated":"2017-03-20 14:09:13.000000000","message":"So the question is whether we want to use the multiplier or rather introduce a new config option? Is the advert_int option related to the timeframe where we are not allowed to send SIGHUP?","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":34,"context_line":"               secret\u003dTrue),"},{"line_number":35,"context_line":"    cfg.IntOpt(\u0027ha_vrrp_advert_int\u0027,"},{"line_number":36,"context_line":"               default\u003d2,"},{"line_number":37,"context_line":"               help\u003d_(\u0027The advertisement interval in seconds. This value is \u0027"},{"line_number":38,"context_line":"                      \u0027also used to throttle SIGHUPs sent to the Keepalived \u0027"},{"line_number":39,"context_line":"                      \u0027processes, where at most one is sent per \u0027"},{"line_number":40,"context_line":"                      \u0027ha_vrrp_advert_int seconds.\u0027)),"},{"line_number":41,"context_line":"    cfg.IntOpt(\u0027ha_keepalived_state_change_server_threads\u0027,"},{"line_number":42,"context_line":"               default\u003d(1 + host.cpu_count()) // 2,"},{"line_number":43,"context_line":"               sample_default\u003d\u0027(1 + \u003cnum_of_cpus\u003e) / 2\u0027,"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_9fe31433","line":40,"range":{"start_line":37,"start_character":61,"end_line":40,"end_character":50},"in_reply_to":"1a1ced50_c43c1332","updated":"2017-03-20 14:09:13.000000000","message":"I think the fact we throttle is an implementation detail/workaround for keepalived. The functionality should be kept, keepalived will be always SIGHUPed when configuration change was made.","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"8e268e3af09a1139c8073b0711ea09bf9dbdde3e","unresolved":false,"context_lines":[{"line_number":37,"context_line":"               help\u003d_(\u0027The advertisement interval in seconds. This value is \u0027"},{"line_number":38,"context_line":"                      \u0027also used to throttle SIGHUP signals sent to \u0027"},{"line_number":39,"context_line":"                      \u0027keepalived where at most one signal is sent per \u0027"},{"line_number":40,"context_line":"                      \u0027ha_vrrp_advert_int seconds multiplied by 1.5.\u0027)),"},{"line_number":41,"context_line":"    cfg.IntOpt(\u0027ha_keepalived_state_change_server_threads\u0027,"},{"line_number":42,"context_line":"               default\u003d(1 + host.cpu_count()) // 2,"},{"line_number":43,"context_line":"               sample_default\u003d\u0027(1 + \u003cnum_of_cpus\u003e) / 2\u0027,"}],"source_content_type":"text/x-python","patch_set":47,"id":"ffe62b97_82feeb34","line":40,"updated":"2017-03-27 15:33:04.000000000","message":"So this multiplication factor is the only thing I\u0027m stuck on.  Is this 1.5x something just learned from testing?  i.e. do we need another option or is having the throttler valued tied to this good enough?\n\nnit: would be good to use the 1.5 defined in ha_router.py if possible, since if someone changes that they will probably forget to change this.","commit_id":"34b22f1fe533032222172fd3c9c276f8d7c67e62"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"5329cd6edbf82e70a0a77e760319e8c1fb0008cf","unresolved":false,"context_lines":[{"line_number":37,"context_line":"               help\u003d_(\u0027The advertisement interval in seconds. This value is \u0027"},{"line_number":38,"context_line":"                      \u0027also used to throttle SIGHUP signals sent to \u0027"},{"line_number":39,"context_line":"                      \u0027keepalived where at most one signal is sent per \u0027"},{"line_number":40,"context_line":"                      \u0027ha_vrrp_advert_int seconds multiplied by 1.5.\u0027)),"},{"line_number":41,"context_line":"    cfg.IntOpt(\u0027ha_keepalived_state_change_server_threads\u0027,"},{"line_number":42,"context_line":"               default\u003d(1 + host.cpu_count()) // 2,"},{"line_number":43,"context_line":"               sample_default\u003d\u0027(1 + \u003cnum_of_cpus\u003e) / 2\u0027,"}],"source_content_type":"text/x-python","patch_set":47,"id":"ffe62b97_5a20c0b0","line":40,"in_reply_to":"ffe62b97_41ac5733","updated":"2017-03-27 18:35:50.000000000","message":"I agree that fewer options are better, as long as we know 1.5x is good enough, since otherwise there\u0027s no way to change the throttler value without changing advert_int, even if we didn\u0027t want to change advert_int.  A short explanation of the relationship might be enough.","commit_id":"34b22f1fe533032222172fd3c9c276f8d7c67e62"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"c276a17ca335bc428abd1863e8b1646cf3cae0b9","unresolved":false,"context_lines":[{"line_number":37,"context_line":"               help\u003d_(\u0027The advertisement interval in seconds. This value is \u0027"},{"line_number":38,"context_line":"                      \u0027also used to throttle SIGHUP signals sent to \u0027"},{"line_number":39,"context_line":"                      \u0027keepalived where at most one signal is sent per \u0027"},{"line_number":40,"context_line":"                      \u0027ha_vrrp_advert_int seconds multiplied by 1.5.\u0027)),"},{"line_number":41,"context_line":"    cfg.IntOpt(\u0027ha_keepalived_state_change_server_threads\u0027,"},{"line_number":42,"context_line":"               default\u003d(1 + host.cpu_count()) // 2,"},{"line_number":43,"context_line":"               sample_default\u003d\u0027(1 + \u003cnum_of_cpus\u003e) / 2\u0027,"}],"source_content_type":"text/x-python","patch_set":47,"id":"ffe62b97_41ac5733","line":40,"in_reply_to":"ffe62b97_4dc5b35a","updated":"2017-03-27 17:49:25.000000000","message":"Let\u0027s not introduce another option unless we see the need in the future.","commit_id":"34b22f1fe533032222172fd3c9c276f8d7c67e62"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"1c48a49e8b25bbe503c065d65d5010a6a375f622","unresolved":false,"context_lines":[{"line_number":37,"context_line":"               help\u003d_(\u0027The advertisement interval in seconds. This value is \u0027"},{"line_number":38,"context_line":"                      \u0027also used to throttle SIGHUP signals sent to \u0027"},{"line_number":39,"context_line":"                      \u0027keepalived where at most one signal is sent per \u0027"},{"line_number":40,"context_line":"                      \u0027ha_vrrp_advert_int seconds multiplied by 1.5.\u0027)),"},{"line_number":41,"context_line":"    cfg.IntOpt(\u0027ha_keepalived_state_change_server_threads\u0027,"},{"line_number":42,"context_line":"               default\u003d(1 + host.cpu_count()) // 2,"},{"line_number":43,"context_line":"               sample_default\u003d\u0027(1 + \u003cnum_of_cpus\u003e) / 2\u0027,"}],"source_content_type":"text/x-python","patch_set":47,"id":"ffe62b97_4dc5b35a","line":40,"in_reply_to":"ffe62b97_82feeb34","updated":"2017-03-27 15:44:28.000000000","message":"If I remember correctly it\u0027s to compensate the execution time of sending SIGHUP. And the magical constant came empirically, was 1.3 in previous patchsets ... we could create a new config option but maybe it\u0027s not necessary with this.\n\n+ for formatting the string with constant.","commit_id":"34b22f1fe533032222172fd3c9c276f8d7c67e62"},{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"58b536d8f8a3c3c66d55a6c11ba0e8ae11082f0f","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    cfg.IntOpt(\u0027ha_vrrp_advert_int\u0027,"},{"line_number":37,"context_line":"               default\u003d2,"},{"line_number":38,"context_line":"               help\u003d_(\u0027The advertisement interval in seconds. This value is \u0027"},{"line_number":39,"context_line":"                      \u0027also used to throttle SIGHUP signals sent to \u0027"},{"line_number":40,"context_line":"                      \u0027keepalived where at most one signal is sent per \u0027"},{"line_number":41,"context_line":"                      \u0027ha_vrrp_advert_int seconds multiplied by %d.\u0027) % ("},{"line_number":42,"context_line":"                          ha_router.THROTTLER_MULTIPLIER)),"}],"source_content_type":"text/x-python","patch_set":48,"id":"ffe62b97_f170a00a","line":39,"updated":"2017-03-28 20:06:28.000000000","message":"Is this implementation detail really relevant to operators?","commit_id":"9cc6d97a4dd47b6ffeb70a5d374d36bf9ea8ff9e"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"a41e665d1f7dcd0160de8c71e2d724aa569f856e","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    cfg.IntOpt(\u0027ha_vrrp_advert_int\u0027,"},{"line_number":37,"context_line":"               default\u003d2,"},{"line_number":38,"context_line":"               help\u003d_(\u0027The advertisement interval in seconds. This value is \u0027"},{"line_number":39,"context_line":"                      \u0027also used to throttle SIGHUP signals sent to \u0027"},{"line_number":40,"context_line":"                      \u0027keepalived where at most one signal is sent per \u0027"},{"line_number":41,"context_line":"                      \u0027ha_vrrp_advert_int seconds multiplied by %d.\u0027) % ("},{"line_number":42,"context_line":"                          ha_router.THROTTLER_MULTIPLIER)),"}],"source_content_type":"text/x-python","patch_set":48,"id":"ffe62b97_43de5f6d","line":39,"in_reply_to":"ffe62b97_f170a00a","updated":"2017-03-28 20:13:37.000000000","message":"No. Let me kill it.","commit_id":"9cc6d97a4dd47b6ffeb70a5d374d36bf9ea8ff9e"}],"neutron/tests/common/agents/l3_agent.py":[{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"964dbb2bcee2ecd570a4863d2cfee04d7fddad6a","unresolved":false,"context_lines":[{"line_number":80,"context_line":""},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"def get_internal_device_name(self, port_id):"},{"line_number":83,"context_line":"    #NOTE(jschwarz): \u0027self\u0027 is a subclass of RouterInfo."},{"line_number":84,"context_line":"    return _append_suffix("},{"line_number":85,"context_line":"        (namespaces.INTERNAL_DEV_PREFIX + port_id)"},{"line_number":86,"context_line":"        [:interface.LinuxInterfaceDriver.DEV_NAME_LEN])"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_2401356b","line":83,"updated":"2017-01-10 21:27:39.000000000","message":"rename self into ri then?","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":80,"context_line":""},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"def get_internal_device_name(self, port_id):"},{"line_number":83,"context_line":"    #NOTE(jschwarz): \u0027self\u0027 is a subclass of RouterInfo."},{"line_number":84,"context_line":"    return _append_suffix("},{"line_number":85,"context_line":"        (namespaces.INTERNAL_DEV_PREFIX + port_id)"},{"line_number":86,"context_line":"        [:interface.LinuxInterfaceDriver.DEV_NAME_LEN])"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_558faf22","line":83,"in_reply_to":"ba5201f7_2401356b","updated":"2017-01-16 13:22:12.000000000","message":"Done","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"964dbb2bcee2ecd570a4863d2cfee04d7fddad6a","unresolved":false,"context_lines":[{"line_number":87,"context_line":""},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"def get_external_device_name(self, port_id):"},{"line_number":90,"context_line":"    #NOTE(jschwarz): \u0027self\u0027 is a subclass of RouterInfo."},{"line_number":91,"context_line":"    return _append_suffix("},{"line_number":92,"context_line":"        (namespaces.EXTERNAL_DEV_PREFIX + port_id)"},{"line_number":93,"context_line":"        [:interface.LinuxInterfaceDriver.DEV_NAME_LEN])"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_e4064d84","line":90,"updated":"2017-01-10 21:27:39.000000000","message":"then maybe rename it into \u0027ri\u0027","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":87,"context_line":""},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"def get_external_device_name(self, port_id):"},{"line_number":90,"context_line":"    #NOTE(jschwarz): \u0027self\u0027 is a subclass of RouterInfo."},{"line_number":91,"context_line":"    return _append_suffix("},{"line_number":92,"context_line":"        (namespaces.EXTERNAL_DEV_PREFIX + port_id)"},{"line_number":93,"context_line":"        [:interface.LinuxInterfaceDriver.DEV_NAME_LEN])"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_35722b4a","line":90,"in_reply_to":"ba5201f7_e4064d84","updated":"2017-01-16 13:22:12.000000000","message":"Done","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        super(L3NATAgentForTest, self).__init__(host, conf)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def _create_router(self, router_id, router):"},{"line_number":65,"context_line":"        router \u003d ("},{"line_number":66,"context_line":"            super(L3NATAgentForTest, self)._create_router(router_id, router))"},{"line_number":67,"context_line":""}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_7f0e8635","line":64,"updated":"2017-03-17 17:29:15.000000000","message":"explain in a comment what you try to achieve here, and why","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        super(L3NATAgentForTest, self).__init__(host, conf)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def _create_router(self, router_id, router):"},{"line_number":65,"context_line":"        router \u003d ("},{"line_number":66,"context_line":"            super(L3NATAgentForTest, self)._create_router(router_id, router))"},{"line_number":67,"context_line":""}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_7ce82611","line":64,"in_reply_to":"1a1ced50_7f0e8635","updated":"2017-03-20 14:09:13.000000000","message":"Done","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"dbcfe4cbb905be8b13c7f271285c0cd0c41cd028","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        super(L3NATAgentForTest, self).__init__(host, conf)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def _create_router(self, router_id, router):"},{"line_number":65,"context_line":"        \"\"\"Create a router with suffix added to the router namespace name.\"\"\""},{"line_number":66,"context_line":"        router \u003d ("},{"line_number":67,"context_line":"            super(L3NATAgentForTest, self)._create_router(router_id, router))"},{"line_number":68,"context_line":""}],"source_content_type":"text/x-python","patch_set":34,"id":"1a1ced50_1b22ca00","line":65,"range":{"start_line":65,"start_character":8,"end_line":65,"end_character":77},"updated":"2017-03-20 17:41:28.000000000","message":"this describes what you do, but not why (I assume that\u0027s for fullstack to run multiple agents for the same router?)","commit_id":"6146fa7f7a1af72d4668b3018367158ef8680b0b"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"5b13daa5a527c73eea60ebf7dafd8ceef63804e4","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        super(L3NATAgentForTest, self).__init__(host, conf)"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def _create_router(self, router_id, router):"},{"line_number":65,"context_line":"        \"\"\"Create a router with suffix added to the router namespace name.\"\"\""},{"line_number":66,"context_line":"        router \u003d ("},{"line_number":67,"context_line":"            super(L3NATAgentForTest, self)._create_router(router_id, router))"},{"line_number":68,"context_line":""}],"source_content_type":"text/x-python","patch_set":34,"id":"1a1ced50_7b99fe1e","line":65,"range":{"start_line":65,"start_character":8,"end_line":65,"end_character":77},"in_reply_to":"1a1ced50_1b22ca00","updated":"2017-03-20 17:44:11.000000000","message":"Yes, that\u0027s to test HA routers as all would have the same namespace and because we run on a single machine, we need to distinguish the namespaces per node.","commit_id":"6146fa7f7a1af72d4668b3018367158ef8680b0b"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"8e268e3af09a1139c8073b0711ea09bf9dbdde3e","unresolved":false,"context_lines":[{"line_number":87,"context_line":"def get_internal_device_name(ri, port_id):"},{"line_number":88,"context_line":"    return _append_suffix("},{"line_number":89,"context_line":"        (namespaces.INTERNAL_DEV_PREFIX + port_id)"},{"line_number":90,"context_line":"        [:interface.LinuxInterfaceDriver.DEV_NAME_LEN])"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"def get_external_device_name(ri, port_id):"}],"source_content_type":"text/x-python","patch_set":47,"id":"ffe62b97_c213d35b","line":90,"updated":"2017-03-27 15:33:04.000000000","message":"I guess this could have just used the value from the constants file, but it\u0027s a nit.","commit_id":"34b22f1fe533032222172fd3c9c276f8d7c67e62"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"1c48a49e8b25bbe503c065d65d5010a6a375f622","unresolved":false,"context_lines":[{"line_number":87,"context_line":"def get_internal_device_name(ri, port_id):"},{"line_number":88,"context_line":"    return _append_suffix("},{"line_number":89,"context_line":"        (namespaces.INTERNAL_DEV_PREFIX + port_id)"},{"line_number":90,"context_line":"        [:interface.LinuxInterfaceDriver.DEV_NAME_LEN])"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"def get_external_device_name(ri, port_id):"}],"source_content_type":"text/x-python","patch_set":47,"id":"ffe62b97_cd87830f","line":90,"in_reply_to":"ffe62b97_c213d35b","updated":"2017-03-27 15:44:28.000000000","message":"If I\u0027ll respin with formatting config string, I\u0027ll update this as well.","commit_id":"34b22f1fe533032222172fd3c9c276f8d7c67e62"}],"neutron/tests/fullstack/resources/config.py":[{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"e42e20b2cdfb4a31ae4aa8e263a037e150fc8e93","unresolved":false,"context_lines":[{"line_number":89,"context_line":"            },"},{"line_number":90,"context_line":"        })"},{"line_number":91,"context_line":"        if env_desc.quota_port is not None:"},{"line_number":92,"context_line":"            self.config[\u0027quotas\u0027][\u0027quota_port\u0027] \u003d env_desc.quota_port"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"    def _setUp(self):"},{"line_number":95,"context_line":"        self.config[\u0027DEFAULT\u0027].update({"}],"source_content_type":"text/x-python","patch_set":38,"id":"1a1ced50_cdcc938b","line":92,"updated":"2017-03-22 16:59:40.000000000","message":"Traceback (most recent call last):\n  File \"/opt/stack/new/neutron/.tox/dsvm-fullstack/local/lib/python2.7/site-packages/fixtures/fixture.py\", line 197, in setUp\n    self._setUp()\n  File \"neutron/tests/fullstack/resources/environment.py\", line 382, in _setUp\n    cfg.CONF.database.connection, self.rabbitmq_environment))\n  File \"neutron/tests/fullstack/resources/config.py\", line 92, in __init__\n    self.config[\u0027quotas\u0027][\u0027quota_port\u0027] \u003d env_desc.quota_port\nKeyError: \u0027quotas\u0027","commit_id":"5dc9369ba7d4ce4e78fa32a608fd40b3fe1a5d10"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"80ca9f322322c27d92dc7e13cd5a11b025cde3df","unresolved":false,"context_lines":[{"line_number":89,"context_line":"            },"},{"line_number":90,"context_line":"        })"},{"line_number":91,"context_line":"        if env_desc.quota_port is not None:"},{"line_number":92,"context_line":"            self.config[\u0027quotas\u0027][\u0027quota_port\u0027] \u003d env_desc.quota_port"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"    def _setUp(self):"},{"line_number":95,"context_line":"        self.config[\u0027DEFAULT\u0027].update({"}],"source_content_type":"text/x-python","patch_set":38,"id":"1a1ced50_17505b31","line":92,"in_reply_to":"1a1ced50_cdcc938b","updated":"2017-03-23 09:18:56.000000000","message":"heh, I fixed it locally and didn\u0027t send the new PS ... I swear :)","commit_id":"5dc9369ba7d4ce4e78fa32a608fd40b3fe1a5d10"}],"neutron/tests/fullstack/test_l3_agent.py":[{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"964dbb2bcee2ecd570a4863d2cfee04d7fddad6a","unresolved":false,"context_lines":[{"line_number":216,"context_line":"            timeout\u003d90)"},{"line_number":217,"context_line":""},{"line_number":218,"context_line":"    def _get_keepalived_state(self, keepalived_state_file):"},{"line_number":219,"context_line":"        with open(keepalived_state_file, \"rb\") as fd:"},{"line_number":220,"context_line":"            return fd.read()"},{"line_number":221,"context_line":""},{"line_number":222,"context_line":"    def _get_state_file_for_master_agent(self, router_id):"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_64689d22","line":219,"range":{"start_line":219,"start_character":43,"end_line":219,"end_character":44},"updated":"2017-01-10 21:27:39.000000000","message":"why do we need binary mode here? isn\u0027t it text file?","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":216,"context_line":"            timeout\u003d90)"},{"line_number":217,"context_line":""},{"line_number":218,"context_line":"    def _get_keepalived_state(self, keepalived_state_file):"},{"line_number":219,"context_line":"        with open(keepalived_state_file, \"rb\") as fd:"},{"line_number":220,"context_line":"            return fd.read()"},{"line_number":221,"context_line":""},{"line_number":222,"context_line":"    def _get_state_file_for_master_agent(self, router_id):"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_15dc4711","line":219,"range":{"start_line":219,"start_character":43,"end_line":219,"end_character":44},"in_reply_to":"ba5201f7_64689d22","updated":"2017-01-16 13:22:12.000000000","message":"matter of habit to always open files in binary mode (some OSs tend to convert \\n to \\r\\n *ahem* if the file isn\u0027t binarily opened).","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"964dbb2bcee2ecd570a4863d2cfee04d7fddad6a","unresolved":false,"context_lines":[{"line_number":235,"context_line":"        router \u003d self.safe_client.create_router(tenant_id, ha\u003dTrue,"},{"line_number":236,"context_line":"                                                external_network\u003dext_net[\u0027id\u0027])"},{"line_number":237,"context_line":"        agents \u003d self.client.list_l3_agent_hosting_routers(router[\u0027id\u0027])"},{"line_number":238,"context_line":"        self.assertEqual(2, len(agents[\u0027agents\u0027]),"},{"line_number":239,"context_line":"                         \u0027HA router must be scheduled to both nodes\u0027)"},{"line_number":240,"context_line":"        common_utils.wait_until_true("},{"line_number":241,"context_line":"            functools.partial("}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_a4e0c597","line":238,"updated":"2017-01-10 21:27:39.000000000","message":"is there a chance that the router is not yet scheduled when we fetch the list of hosting agents?","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":235,"context_line":"        router \u003d self.safe_client.create_router(tenant_id, ha\u003dTrue,"},{"line_number":236,"context_line":"                                                external_network\u003dext_net[\u0027id\u0027])"},{"line_number":237,"context_line":"        agents \u003d self.client.list_l3_agent_hosting_routers(router[\u0027id\u0027])"},{"line_number":238,"context_line":"        self.assertEqual(2, len(agents[\u0027agents\u0027]),"},{"line_number":239,"context_line":"                         \u0027HA router must be scheduled to both nodes\u0027)"},{"line_number":240,"context_line":"        common_utils.wait_until_true("},{"line_number":241,"context_line":"            functools.partial("}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_15f3679f","line":238,"in_reply_to":"ba5201f7_a4e0c597","updated":"2017-01-16 13:22:12.000000000","message":"There is. Will put in a wait_until.","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":241,"context_line":"            functools.partial("},{"line_number":242,"context_line":"                self._is_ha_router_active_on_one_agent,"},{"line_number":243,"context_line":"                router[\u0027id\u0027]),"},{"line_number":244,"context_line":"            timeout\u003d9000)"},{"line_number":245,"context_line":"        keepalived_state_file \u003d self._get_state_file_for_master_agent("},{"line_number":246,"context_line":"            router[\u0027id\u0027])"},{"line_number":247,"context_line":"        self.assertIsNotNone(keepalived_state_file)"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_f5ab431c","line":244,"range":{"start_line":244,"start_character":20,"end_line":244,"end_character":24},"updated":"2017-01-16 13:22:12.000000000","message":"This shouldn\u0027t be this high.","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"964dbb2bcee2ecd570a4863d2cfee04d7fddad6a","unresolved":false,"context_lines":[{"line_number":253,"context_line":"        # Create 5 fake VMs, each with a floating ip. Each floating ip"},{"line_number":254,"context_line":"        # association should send a SIGHUP to the keepalived\u0027s parent process,"},{"line_number":255,"context_line":"        # unless the Throttler works."},{"line_number":256,"context_line":"        fips \u003d []"},{"line_number":257,"context_line":"        host \u003d self.environment.hosts[0]"},{"line_number":258,"context_line":"        for i in range(5):"},{"line_number":259,"context_line":"            vm \u003d self._boot_fake_vm_in_network(host, tenant_id, network[\u0027id\u0027])"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_a4536538","line":256,"range":{"start_line":256,"start_character":8,"end_line":256,"end_character":17},"updated":"2017-01-10 21:27:39.000000000","message":"why do we need to collect those? they are not used.","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":253,"context_line":"        # Create 5 fake VMs, each with a floating ip. Each floating ip"},{"line_number":254,"context_line":"        # association should send a SIGHUP to the keepalived\u0027s parent process,"},{"line_number":255,"context_line":"        # unless the Throttler works."},{"line_number":256,"context_line":"        fips \u003d []"},{"line_number":257,"context_line":"        host \u003d self.environment.hosts[0]"},{"line_number":258,"context_line":"        for i in range(5):"},{"line_number":259,"context_line":"            vm \u003d self._boot_fake_vm_in_network(host, tenant_id, network[\u0027id\u0027])"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_55632f1a","line":256,"range":{"start_line":256,"start_character":8,"end_line":256,"end_character":17},"in_reply_to":"ba5201f7_a4536538","updated":"2017-01-16 13:22:12.000000000","message":"Done","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"964dbb2bcee2ecd570a4863d2cfee04d7fddad6a","unresolved":false,"context_lines":[{"line_number":255,"context_line":"        # unless the Throttler works."},{"line_number":256,"context_line":"        fips \u003d []"},{"line_number":257,"context_line":"        host \u003d self.environment.hosts[0]"},{"line_number":258,"context_line":"        for i in range(5):"},{"line_number":259,"context_line":"            vm \u003d self._boot_fake_vm_in_network(host, tenant_id, network[\u0027id\u0027])"},{"line_number":260,"context_line":"            fips.append(self.safe_client.create_floatingip("},{"line_number":261,"context_line":"                tenant_id, ext_net[\u0027id\u0027], vm.ip, vm.neutron_port[\u0027id\u0027]))"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_442559c0","line":258,"range":{"start_line":258,"start_character":23,"end_line":258,"end_character":24},"updated":"2017-01-10 21:27:39.000000000","message":"you think 5 is enough to trigger that failure?","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":255,"context_line":"        # unless the Throttler works."},{"line_number":256,"context_line":"        fips \u003d []"},{"line_number":257,"context_line":"        host \u003d self.environment.hosts[0]"},{"line_number":258,"context_line":"        for i in range(5):"},{"line_number":259,"context_line":"            vm \u003d self._boot_fake_vm_in_network(host, tenant_id, network[\u0027id\u0027])"},{"line_number":260,"context_line":"            fips.append(self.safe_client.create_floatingip("},{"line_number":261,"context_line":"                tenant_id, ext_net[\u0027id\u0027], vm.ip, vm.neutron_port[\u0027id\u0027]))"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_3554eb1f","line":258,"range":{"start_line":258,"start_character":23,"end_line":258,"end_character":24},"in_reply_to":"ba5201f7_442559c0","updated":"2017-01-16 13:22:12.000000000","message":"It\u0027s a matter of balance - I don\u0027t want to create 100 because it might cause the test to timeout.","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"964dbb2bcee2ecd570a4863d2cfee04d7fddad6a","unresolved":false,"context_lines":[{"line_number":262,"context_line":"            # For each fip, we\u0027ll check that the keepalived\u0027s state file has"},{"line_number":263,"context_line":"            # not changed and is still master. This will indicate that the"},{"line_number":264,"context_line":"            # Throttler works."},{"line_number":265,"context_line":"            self.assertEqual(\"master\","},{"line_number":266,"context_line":"                             self._get_keepalived_state(keepalived_state_file))"}],"source_content_type":"text/x-python","patch_set":16,"id":"ba5201f7_573509d9","line":265,"updated":"2017-01-10 21:27:39.000000000","message":"there is a slight serialization here: you want on fake VM to be created before proceeding to the next VM. Shouldn\u0027t we parallelize the requests on one side and master state checks on the other side? Then we would be sure that serialization that occurs because of VM setup won\u0027t get in the way of multiple signals being sent.","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"5410ee1fe874c4ed46deff6c7a00c1da60988d69","unresolved":false,"context_lines":[{"line_number":262,"context_line":"            # For each fip, we\u0027ll check that the keepalived\u0027s state file has"},{"line_number":263,"context_line":"            # not changed and is still master. This will indicate that the"},{"line_number":264,"context_line":"            # Throttler works."},{"line_number":265,"context_line":"            self.assertEqual(\"master\","},{"line_number":266,"context_line":"                             self._get_keepalived_state(keepalived_state_file))"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a3c09a3_6abe90d5","line":265,"in_reply_to":"ba5201f7_573509d9","updated":"2017-01-16 13:22:12.000000000","message":"Starting a VM doesn\u0027t cause a SIGHUP, only creating a floatingip does, so paralleling the checks is counter-productive. I can add a \"make sure for X seconds that the state doesn\u0027t change\" but more than that isn\u0027t needed.","commit_id":"40c346d9d11278ea7c089ab8f1cae3eeb2691b6b"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"19e8292114541c49ca74ea521b08486d3c920e81","unresolved":false,"context_lines":[{"line_number":218,"context_line":""},{"line_number":219,"context_line":"    def _get_keepalived_state(self, keepalived_state_file):"},{"line_number":220,"context_line":"        with open(keepalived_state_file, \"r\") as fd:"},{"line_number":221,"context_line":"            return fd.read()"},{"line_number":222,"context_line":""},{"line_number":223,"context_line":"    def _get_state_file_for_master_agent(self, router_id):"},{"line_number":224,"context_line":"        for host in self.environment.hosts:"}],"source_content_type":"text/x-python","patch_set":18,"id":"7a3c09a3_e74c6e72","line":221,"range":{"start_line":221,"start_character":19,"end_line":221,"end_character":28},"updated":"2017-01-16 15:59:48.000000000","message":"Nit: Should you also call strip() here to be safe?","commit_id":"1823eab3a81b18c36afb266db2ab8ca4db286d9d"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"1c52503190e8164bb694a1ae3fab756ea20e8bcc","unresolved":false,"context_lines":[{"line_number":218,"context_line":""},{"line_number":219,"context_line":"    def _get_keepalived_state(self, keepalived_state_file):"},{"line_number":220,"context_line":"        with open(keepalived_state_file, \"r\") as fd:"},{"line_number":221,"context_line":"            return fd.read()"},{"line_number":222,"context_line":""},{"line_number":223,"context_line":"    def _get_state_file_for_master_agent(self, router_id):"},{"line_number":224,"context_line":"        for host in self.environment.hosts:"}],"source_content_type":"text/x-python","patch_set":18,"id":"3a461143_e687adb2","line":221,"range":{"start_line":221,"start_character":19,"end_line":221,"end_character":28},"in_reply_to":"7a3c09a3_e74c6e72","updated":"2017-01-31 16:13:05.000000000","message":"The string is dumped to file without newlines, so nope :)","commit_id":"1823eab3a81b18c36afb266db2ab8ca4db286d9d"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"19e8292114541c49ca74ea521b08486d3c920e81","unresolved":false,"context_lines":[{"line_number":225,"context_line":"            keepalived_state_file \u003d os.path.join("},{"line_number":226,"context_line":"                host.neutron_config.state_path, \"ha_confs\", router_id, \"state\")"},{"line_number":227,"context_line":""},{"line_number":228,"context_line":"            if self._get_keepalived_state(keepalived_state_file) \u003d\u003d \"master\":"},{"line_number":229,"context_line":"                return keepalived_state_file"},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"    def test_keepalived_multiple_sighups_does_not_forfeit_mastership(self):"}],"source_content_type":"text/x-python","patch_set":18,"id":"7a3c09a3_47d70223","line":228,"range":{"start_line":228,"start_character":68,"end_line":228,"end_character":76},"updated":"2017-01-16 15:59:48.000000000","message":"(No-action-required): !@#$%^\u0026","commit_id":"1823eab3a81b18c36afb266db2ab8ca4db286d9d"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"1c52503190e8164bb694a1ae3fab756ea20e8bcc","unresolved":false,"context_lines":[{"line_number":225,"context_line":"            keepalived_state_file \u003d os.path.join("},{"line_number":226,"context_line":"                host.neutron_config.state_path, \"ha_confs\", router_id, \"state\")"},{"line_number":227,"context_line":""},{"line_number":228,"context_line":"            if self._get_keepalived_state(keepalived_state_file) \u003d\u003d \"master\":"},{"line_number":229,"context_line":"                return keepalived_state_file"},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"    def test_keepalived_multiple_sighups_does_not_forfeit_mastership(self):"}],"source_content_type":"text/x-python","patch_set":18,"id":"3a461143_268e15d0","line":228,"range":{"start_line":228,"start_character":68,"end_line":228,"end_character":76},"in_reply_to":"7a3c09a3_47d70223","updated":"2017-01-31 16:13:05.000000000","message":"Done","commit_id":"1823eab3a81b18c36afb266db2ab8ca4db286d9d"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"19e8292114541c49ca74ea521b08486d3c920e81","unresolved":false,"context_lines":[{"line_number":238,"context_line":"        agents \u003d self.client.list_l3_agent_hosting_routers(router[\u0027id\u0027])"},{"line_number":239,"context_line":"        common_utils.wait_until_true("},{"line_number":240,"context_line":"            lambda:"},{"line_number":241,"context_line":"            len(self.client.list_l3_agent_hosting_routers(router[\u0027id\u0027])) \u003d\u003d 2,"},{"line_number":242,"context_line":"            timeout\u003d90)"},{"line_number":243,"context_line":"        common_utils.wait_until_true("},{"line_number":244,"context_line":"            functools.partial("}],"source_content_type":"text/x-python","patch_set":18,"id":"7a3c09a3_07733a4e","line":241,"range":{"start_line":241,"start_character":76,"end_line":241,"end_character":77},"updated":"2017-01-16 15:59:48.000000000","message":"What if I decide to change number of l3 agents ran in this test on L191? It\u0027ll be better to introduce a constant.","commit_id":"1823eab3a81b18c36afb266db2ab8ca4db286d9d"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"1c52503190e8164bb694a1ae3fab756ea20e8bcc","unresolved":false,"context_lines":[{"line_number":238,"context_line":"        agents \u003d self.client.list_l3_agent_hosting_routers(router[\u0027id\u0027])"},{"line_number":239,"context_line":"        common_utils.wait_until_true("},{"line_number":240,"context_line":"            lambda:"},{"line_number":241,"context_line":"            len(self.client.list_l3_agent_hosting_routers(router[\u0027id\u0027])) \u003d\u003d 2,"},{"line_number":242,"context_line":"            timeout\u003d90)"},{"line_number":243,"context_line":"        common_utils.wait_until_true("},{"line_number":244,"context_line":"            functools.partial("}],"source_content_type":"text/x-python","patch_set":18,"id":"3a461143_6669fdf8","line":241,"range":{"start_line":241,"start_character":76,"end_line":241,"end_character":77},"in_reply_to":"7a3c09a3_07733a4e","updated":"2017-01-31 16:13:05.000000000","message":"Constant is meaningless since in case someone changes the number of agents the constant will have to change.\n\nAlso, this is used elsewhere as well (line 210 comes to mind), so it\u0027s out of scope :P","commit_id":"1823eab3a81b18c36afb266db2ab8ca4db286d9d"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"19e8292114541c49ca74ea521b08486d3c920e81","unresolved":false,"context_lines":[{"line_number":265,"context_line":"            # not changed and is still master. This will indicate that the"},{"line_number":266,"context_line":"            # Throttler works. We want to check for ha_vrrp_advert_int (the"},{"line_number":267,"context_line":"            # default is 2 seconds), plus a bit more, so 3 seconds is ok."},{"line_number":268,"context_line":"            time_to_stop \u003d time.time() + (cfg.CONF.ha_vrrp_advert_int * 1.2)"},{"line_number":269,"context_line":"            while True:"},{"line_number":270,"context_line":"                if time.time() \u003e time_to_stop:"},{"line_number":271,"context_line":"                    break"},{"line_number":272,"context_line":"                self.assertEqual("},{"line_number":273,"context_line":"                    \"master\","},{"line_number":274,"context_line":"                    self._get_keepalived_state(keepalived_state_file))"}],"source_content_type":"text/x-python","patch_set":18,"id":"7a3c09a3_472f02f6","line":274,"range":{"start_line":268,"start_character":0,"end_line":274,"end_character":70},"updated":"2017-01-16 15:59:48.000000000","message":"This should be out of the for cycle. Otherwise you create floating ip, wait some time, create another fip. This way the throttler is not exercised but simulated similar behavior.","commit_id":"1823eab3a81b18c36afb266db2ab8ca4db286d9d"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"1c52503190e8164bb694a1ae3fab756ea20e8bcc","unresolved":false,"context_lines":[{"line_number":265,"context_line":"            # not changed and is still master. This will indicate that the"},{"line_number":266,"context_line":"            # Throttler works. We want to check for ha_vrrp_advert_int (the"},{"line_number":267,"context_line":"            # default is 2 seconds), plus a bit more, so 3 seconds is ok."},{"line_number":268,"context_line":"            time_to_stop \u003d time.time() + (cfg.CONF.ha_vrrp_advert_int * 1.2)"},{"line_number":269,"context_line":"            while True:"},{"line_number":270,"context_line":"                if time.time() \u003e time_to_stop:"},{"line_number":271,"context_line":"                    break"},{"line_number":272,"context_line":"                self.assertEqual("},{"line_number":273,"context_line":"                    \"master\","},{"line_number":274,"context_line":"                    self._get_keepalived_state(keepalived_state_file))"}],"source_content_type":"text/x-python","patch_set":18,"id":"3a461143_61a1e7f7","line":274,"range":{"start_line":268,"start_character":0,"end_line":274,"end_character":70},"in_reply_to":"7a3c09a3_472f02f6","updated":"2017-01-31 16:13:05.000000000","message":"Done","commit_id":"1823eab3a81b18c36afb266db2ab8ca4db286d9d"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"02bd3c62d33d3f5bc80b8b891890898266ba417c","unresolved":false,"context_lines":[{"line_number":238,"context_line":"                                                external_network\u003dext_net[\u0027id\u0027])"},{"line_number":239,"context_line":"        common_utils.wait_until_true("},{"line_number":240,"context_line":"            lambda:"},{"line_number":241,"context_line":"            len(self.client.list_l3_agent_hosting_routers("},{"line_number":242,"context_line":"                router[\u0027id\u0027])[\u0027agents\u0027]) \u003d\u003d 2,"},{"line_number":243,"context_line":"            timeout\u003d90)"},{"line_number":244,"context_line":"        common_utils.wait_until_true("}],"source_content_type":"text/x-python","patch_set":23,"id":"3a461143_60dafee9","line":241,"updated":"2017-01-30 09:43:09.000000000","message":"You\u0027re ignoring all jlibosva\u0027s comments, :-P","commit_id":"7479fea3992003594f8c26a3cda4f09e5827fec8"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"023151d18386104f7e172a391a3ec7b46779264c","unresolved":false,"context_lines":[{"line_number":238,"context_line":"                                                external_network\u003dext_net[\u0027id\u0027])"},{"line_number":239,"context_line":"        common_utils.wait_until_true("},{"line_number":240,"context_line":"            lambda:"},{"line_number":241,"context_line":"            len(self.client.list_l3_agent_hosting_routers("},{"line_number":242,"context_line":"                router[\u0027id\u0027])[\u0027agents\u0027]) \u003d\u003d 2,"},{"line_number":243,"context_line":"            timeout\u003d90)"},{"line_number":244,"context_line":"        common_utils.wait_until_true("}],"source_content_type":"text/x-python","patch_set":23,"id":"3a461143_e1007736","line":241,"in_reply_to":"3a461143_60dafee9","updated":"2017-01-31 16:29:04.000000000","message":"Done","commit_id":"7479fea3992003594f8c26a3cda4f09e5827fec8"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"02bd3c62d33d3f5bc80b8b891890898266ba417c","unresolved":false,"context_lines":[{"line_number":265,"context_line":"            # not changed and is still master. This will indicate that the"},{"line_number":266,"context_line":"            # Throttler works. We want to check for ha_vrrp_advert_int (the"},{"line_number":267,"context_line":"            # default is 2 seconds), plus a bit more."},{"line_number":268,"context_line":"            time_to_stop \u003d time.time() + (2 * 1.2)"},{"line_number":269,"context_line":"            while True:"},{"line_number":270,"context_line":"                if time.time() \u003e time_to_stop:"},{"line_number":271,"context_line":"                    break"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a461143_e0f42e5c","line":268,"range":{"start_line":268,"start_character":46,"end_line":268,"end_character":49},"updated":"2017-01-30 09:43:09.000000000","message":"constant :P","commit_id":"7479fea3992003594f8c26a3cda4f09e5827fec8"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"02bd3c62d33d3f5bc80b8b891890898266ba417c","unresolved":false,"context_lines":[{"line_number":265,"context_line":"            # not changed and is still master. This will indicate that the"},{"line_number":266,"context_line":"            # Throttler works. We want to check for ha_vrrp_advert_int (the"},{"line_number":267,"context_line":"            # default is 2 seconds), plus a bit more."},{"line_number":268,"context_line":"            time_to_stop \u003d time.time() + (2 * 1.2)"},{"line_number":269,"context_line":"            while True:"},{"line_number":270,"context_line":"                if time.time() \u003e time_to_stop:"},{"line_number":271,"context_line":"                    break"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a461143_c0ef3285","line":268,"updated":"2017-01-30 09:43:09.000000000","message":"why did you move from the config setting to an int? :?","commit_id":"7479fea3992003594f8c26a3cda4f09e5827fec8"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"023151d18386104f7e172a391a3ec7b46779264c","unresolved":false,"context_lines":[{"line_number":265,"context_line":"            # not changed and is still master. This will indicate that the"},{"line_number":266,"context_line":"            # Throttler works. We want to check for ha_vrrp_advert_int (the"},{"line_number":267,"context_line":"            # default is 2 seconds), plus a bit more."},{"line_number":268,"context_line":"            time_to_stop \u003d time.time() + (2 * 1.2)"},{"line_number":269,"context_line":"            while True:"},{"line_number":270,"context_line":"                if time.time() \u003e time_to_stop:"},{"line_number":271,"context_line":"                    break"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a461143_619ba718","line":268,"range":{"start_line":268,"start_character":46,"end_line":268,"end_character":49},"in_reply_to":"3a461143_e0f42e5c","updated":"2017-01-31 16:29:04.000000000","message":"Done.\n\nMoved because the config option isn\u0027t loaded here, and loading it in KeepalivedManager causes a recursive import. In short, there was no real good place to put it. I\u0027ve changed it into a constant instead.","commit_id":"7479fea3992003594f8c26a3cda4f09e5827fec8"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"02bd3c62d33d3f5bc80b8b891890898266ba417c","unresolved":false,"context_lines":[{"line_number":266,"context_line":"            # Throttler works. We want to check for ha_vrrp_advert_int (the"},{"line_number":267,"context_line":"            # default is 2 seconds), plus a bit more."},{"line_number":268,"context_line":"            time_to_stop \u003d time.time() + (2 * 1.2)"},{"line_number":269,"context_line":"            while True:"},{"line_number":270,"context_line":"                if time.time() \u003e time_to_stop:"},{"line_number":271,"context_line":"                    break"},{"line_number":272,"context_line":"                self.assertEqual("},{"line_number":273,"context_line":"                    \"master\","},{"line_number":274,"context_line":"                    self._get_keepalived_state(keepalived_state_file))"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a461143_80fa8a41","line":274,"range":{"start_line":269,"start_character":10,"end_line":274,"end_character":70},"updated":"2017-01-30 09:43:09.000000000","message":"jlibosva\u0027s comments on PS18","commit_id":"7479fea3992003594f8c26a3cda4f09e5827fec8"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"023151d18386104f7e172a391a3ec7b46779264c","unresolved":false,"context_lines":[{"line_number":266,"context_line":"            # Throttler works. We want to check for ha_vrrp_advert_int (the"},{"line_number":267,"context_line":"            # default is 2 seconds), plus a bit more."},{"line_number":268,"context_line":"            time_to_stop \u003d time.time() + (2 * 1.2)"},{"line_number":269,"context_line":"            while True:"},{"line_number":270,"context_line":"                if time.time() \u003e time_to_stop:"},{"line_number":271,"context_line":"                    break"},{"line_number":272,"context_line":"                self.assertEqual("},{"line_number":273,"context_line":"                    \"master\","},{"line_number":274,"context_line":"                    self._get_keepalived_state(keepalived_state_file))"}],"source_content_type":"text/x-python","patch_set":23,"id":"3a461143_61c2c7ea","line":274,"range":{"start_line":269,"start_character":10,"end_line":274,"end_character":70},"in_reply_to":"3a461143_80fa8a41","updated":"2017-01-31 16:29:04.000000000","message":"Done","commit_id":"7479fea3992003594f8c26a3cda4f09e5827fec8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ad6839ba8ed0b310b177dfab09187b0f3a6e16ee","unresolved":false,"context_lines":[{"line_number":230,"context_line":"                return keepalived_state_file"},{"line_number":231,"context_line":""},{"line_number":232,"context_line":"    def test_keepalived_multiple_sighups_does_not_forfeit_mastership(self):"},{"line_number":233,"context_line":"        # Setup a complete \"Neutron stack\" - both an internal and an external"},{"line_number":234,"context_line":"        # network+subnet, and a router connected to both."},{"line_number":235,"context_line":"        tenant_id \u003d uuidutils.generate_uuid()"},{"line_number":236,"context_line":"        ext_net, ext_sub \u003d self._create_external_network_and_subnet(tenant_id)"},{"line_number":237,"context_line":"        router \u003d self.safe_client.create_router(tenant_id, ha\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":25,"id":"3a461143_5b4d96c2","line":234,"range":{"start_line":233,"start_character":0,"end_line":234,"end_character":57},"updated":"2017-02-01 12:02:25.000000000","message":"This should be docstring","commit_id":"32d9b1441cefb6a497271106842667750c366e20"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"bf373be5a421d28adce784bcf6f304797c046ce8","unresolved":false,"context_lines":[{"line_number":230,"context_line":"                return keepalived_state_file"},{"line_number":231,"context_line":""},{"line_number":232,"context_line":"    def test_keepalived_multiple_sighups_does_not_forfeit_mastership(self):"},{"line_number":233,"context_line":"        # Setup a complete \"Neutron stack\" - both an internal and an external"},{"line_number":234,"context_line":"        # network+subnet, and a router connected to both."},{"line_number":235,"context_line":"        tenant_id \u003d uuidutils.generate_uuid()"},{"line_number":236,"context_line":"        ext_net, ext_sub \u003d self._create_external_network_and_subnet(tenant_id)"},{"line_number":237,"context_line":"        router \u003d self.safe_client.create_router(tenant_id, ha\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":25,"id":"1a430d35_b9ccffbb","line":234,"range":{"start_line":233,"start_character":0,"end_line":234,"end_character":57},"in_reply_to":"3a461143_5b4d96c2","updated":"2017-02-08 11:41:57.000000000","message":"Done","commit_id":"32d9b1441cefb6a497271106842667750c366e20"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ad6839ba8ed0b310b177dfab09187b0f3a6e16ee","unresolved":false,"context_lines":[{"line_number":258,"context_line":"        # unless the Throttler works."},{"line_number":259,"context_line":"        host \u003d self.environment.hosts[0]"},{"line_number":260,"context_line":"        for i in range(5):"},{"line_number":261,"context_line":"            vm \u003d self._boot_fake_vm_in_network(host, tenant_id, network[\u0027id\u0027])"},{"line_number":262,"context_line":"            self.safe_client.create_floatingip("},{"line_number":263,"context_line":"                tenant_id, ext_net[\u0027id\u0027], vm.ip, vm.neutron_port[\u0027id\u0027])"},{"line_number":264,"context_line":""}],"source_content_type":"text/x-python","patch_set":25,"id":"3a461143_dbb42683","line":261,"range":{"start_line":261,"start_character":22,"end_line":261,"end_character":46},"updated":"2017-02-01 12:02:25.000000000","message":"This call is gonna block on boot per machine. That means this is gonna take wait \u003cfake_boot_time\u003e and then add fip, which sends SIGHUP to keepalived. Then again it waits and sends SIGHUP. Given that there are these pauses, the calls to throttles seems unclear. How about either not waiting for boot as we really don\u0027t care about the connectivity to those instances or split it into two loops (first create servers, second create fips).","commit_id":"32d9b1441cefb6a497271106842667750c366e20"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"bf373be5a421d28adce784bcf6f304797c046ce8","unresolved":false,"context_lines":[{"line_number":258,"context_line":"        # unless the Throttler works."},{"line_number":259,"context_line":"        host \u003d self.environment.hosts[0]"},{"line_number":260,"context_line":"        for i in range(5):"},{"line_number":261,"context_line":"            vm \u003d self._boot_fake_vm_in_network(host, tenant_id, network[\u0027id\u0027])"},{"line_number":262,"context_line":"            self.safe_client.create_floatingip("},{"line_number":263,"context_line":"                tenant_id, ext_net[\u0027id\u0027], vm.ip, vm.neutron_port[\u0027id\u0027])"},{"line_number":264,"context_line":""}],"source_content_type":"text/x-python","patch_set":25,"id":"1a430d35_f6ae962c","line":261,"range":{"start_line":261,"start_character":22,"end_line":261,"end_character":46},"in_reply_to":"3a461143_dbb42683","updated":"2017-02-08 11:41:57.000000000","message":"Done","commit_id":"32d9b1441cefb6a497271106842667750c366e20"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ad6839ba8ed0b310b177dfab09187b0f3a6e16ee","unresolved":false,"context_lines":[{"line_number":269,"context_line":"                        (keepalived.DEFAULT_THROTTLER_VALUE *"},{"line_number":270,"context_line":"                         keepalived.DEFAULT_THROTTLER_MULTIPLIER))"},{"line_number":271,"context_line":"        while True:"},{"line_number":272,"context_line":"            if time.time() \u003e time_to_stop:"},{"line_number":273,"context_line":"                break"},{"line_number":274,"context_line":"            self.assertEqual("},{"line_number":275,"context_line":"                \"master\","}],"source_content_type":"text/x-python","patch_set":25,"id":"3a461143_9b337e13","line":272,"range":{"start_line":272,"start_character":29,"end_line":272,"end_character":41},"updated":"2017-02-01 12:02:25.000000000","message":"I think we should wait a lot more than what throttler waits as we\u0027re interested in the master state that should stay there during the whole fip process.","commit_id":"32d9b1441cefb6a497271106842667750c366e20"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"bf373be5a421d28adce784bcf6f304797c046ce8","unresolved":false,"context_lines":[{"line_number":269,"context_line":"                        (keepalived.DEFAULT_THROTTLER_VALUE *"},{"line_number":270,"context_line":"                         keepalived.DEFAULT_THROTTLER_MULTIPLIER))"},{"line_number":271,"context_line":"        while True:"},{"line_number":272,"context_line":"            if time.time() \u003e time_to_stop:"},{"line_number":273,"context_line":"                break"},{"line_number":274,"context_line":"            self.assertEqual("},{"line_number":275,"context_line":"                \"master\","}],"source_content_type":"text/x-python","patch_set":25,"id":"1a430d35_16aa4219","line":272,"range":{"start_line":272,"start_character":29,"end_line":272,"end_character":41},"in_reply_to":"3a461143_9b337e13","updated":"2017-02-08 11:41:57.000000000","message":"Done","commit_id":"32d9b1441cefb6a497271106842667750c366e20"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":53,"context_line":"            return port[\u0027port\u0027][\u0027status\u0027] \u003d\u003d \u0027ACTIVE\u0027"},{"line_number":54,"context_line":"        common_utils.wait_until_true(lambda: is_port_status_active(), sleep\u003d1)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def _create_subnet(self, tenant_id, subnet_cidr, network_id, router_id):"},{"line_number":57,"context_line":"        # For IPv6 subnets, enable_dhcp should be set to true."},{"line_number":58,"context_line":"        enable_dhcp \u003d (netaddr.IPNetwork(subnet_cidr).version \u003d\u003d"},{"line_number":59,"context_line":"            constants.IP_VERSION_6)"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_c9e50ca9","line":56,"range":{"start_line":56,"start_character":8,"end_line":56,"end_character":22},"updated":"2017-03-17 17:29:15.000000000","message":"nit: the name of the method doesn\u0027t reflect that it attaches the subnet to a router.","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":53,"context_line":"            return port[\u0027port\u0027][\u0027status\u0027] \u003d\u003d \u0027ACTIVE\u0027"},{"line_number":54,"context_line":"        common_utils.wait_until_true(lambda: is_port_status_active(), sleep\u003d1)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def _create_subnet(self, tenant_id, subnet_cidr, network_id, router_id):"},{"line_number":57,"context_line":"        # For IPv6 subnets, enable_dhcp should be set to true."},{"line_number":58,"context_line":"        enable_dhcp \u003d (netaddr.IPNetwork(subnet_cidr).version \u003d\u003d"},{"line_number":59,"context_line":"            constants.IP_VERSION_6)"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_bc5e1ee7","line":56,"range":{"start_line":56,"start_character":8,"end_line":56,"end_character":22},"in_reply_to":"1a1ced50_c9e50ca9","updated":"2017-03-20 14:09:13.000000000","message":"Done","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        self.block_until_port_status_active("},{"line_number":66,"context_line":"            router_interface_info[\u0027port_id\u0027])"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def _boot_fake_vm_in_network(self, host, tenant_id, network_id, wait\u003dTrue):"},{"line_number":69,"context_line":"        vm \u003d self.useFixture("},{"line_number":70,"context_line":"            machine.FakeFullstackMachine("},{"line_number":71,"context_line":"                host, network_id, tenant_id, self.safe_client))"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_09ee448b","line":68,"range":{"start_line":68,"start_character":68,"end_line":68,"end_character":77},"updated":"2017-03-17 17:29:15.000000000","message":"not used?","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        self.block_until_port_status_active("},{"line_number":66,"context_line":"            router_interface_info[\u0027port_id\u0027])"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def _boot_fake_vm_in_network(self, host, tenant_id, network_id, wait\u003dTrue):"},{"line_number":69,"context_line":"        vm \u003d self.useFixture("},{"line_number":70,"context_line":"            machine.FakeFullstackMachine("},{"line_number":71,"context_line":"                host, network_id, tenant_id, self.safe_client))"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_fc0fb6de","line":68,"range":{"start_line":68,"start_character":68,"end_line":68,"end_character":77},"in_reply_to":"1a1ced50_09ee448b","updated":"2017-03-20 14:09:13.000000000","message":"Done","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":259,"context_line":"        host \u003d self.environment.hosts[0]"},{"line_number":260,"context_line":"        for i in range(5):"},{"line_number":261,"context_line":"            vm \u003d self._boot_fake_vm_in_network("},{"line_number":262,"context_line":"                host, tenant_id, network[\u0027id\u0027], wait\u003dFalse)"},{"line_number":263,"context_line":"            self.safe_client.create_floatingip("},{"line_number":264,"context_line":"                tenant_id, ext_net[\u0027id\u0027], vm.ip, vm.neutron_port[\u0027id\u0027])"},{"line_number":265,"context_line":""}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_898954cd","line":262,"range":{"start_line":262,"start_character":46,"end_line":262,"end_character":58},"updated":"2017-03-17 17:29:15.000000000","message":"since the method in question ignores the argument, I think you still serialize boots.","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6817627c214f50b4451f195342cf06abb3c9f160","unresolved":false,"context_lines":[{"line_number":259,"context_line":"        host \u003d self.environment.hosts[0]"},{"line_number":260,"context_line":"        for i in range(5):"},{"line_number":261,"context_line":"            vm \u003d self._boot_fake_vm_in_network("},{"line_number":262,"context_line":"                host, tenant_id, network[\u0027id\u0027], wait\u003dFalse)"},{"line_number":263,"context_line":"            self.safe_client.create_floatingip("},{"line_number":264,"context_line":"                tenant_id, ext_net[\u0027id\u0027], vm.ip, vm.neutron_port[\u0027id\u0027])"},{"line_number":265,"context_line":""}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_9cc0822c","line":262,"range":{"start_line":262,"start_character":46,"end_line":262,"end_character":58},"in_reply_to":"1a1ced50_898954cd","updated":"2017-03-20 14:09:13.000000000","message":"Done","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":265,"context_line":""},{"line_number":266,"context_line":"        # Check that the keepalived\u0027s state file has not changed and is still"},{"line_number":267,"context_line":"        # master. This will indicate that the Throttler works. We want to check"},{"line_number":268,"context_line":"        # for ha_vrrp_advert_int (the default is 2 seconds), plus a bit more."},{"line_number":269,"context_line":"        time_to_stop \u003d (time.time() +"},{"line_number":270,"context_line":"                        (agent_utils.DEFAULT_THROTTLER_VALUE *"},{"line_number":271,"context_line":"                         agent_utils.DEFAULT_THROTTLER_MULTIPLIER * 1.3))"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_89b0748d","line":268,"range":{"start_line":268,"start_character":14,"end_line":268,"end_character":32},"updated":"2017-03-17 17:29:15.000000000","message":"do we still tangle that to the config option?","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"1e94c7735a998760b715ec8364914e9cfb175b77","unresolved":false,"context_lines":[{"line_number":265,"context_line":""},{"line_number":266,"context_line":"        # Check that the keepalived\u0027s state file has not changed and is still"},{"line_number":267,"context_line":"        # master. This will indicate that the Throttler works. We want to check"},{"line_number":268,"context_line":"        # for ha_vrrp_advert_int (the default is 2 seconds), plus a bit more."},{"line_number":269,"context_line":"        time_to_stop \u003d (time.time() +"},{"line_number":270,"context_line":"                        (agent_utils.DEFAULT_THROTTLER_VALUE *"},{"line_number":271,"context_line":"                         agent_utils.DEFAULT_THROTTLER_MULTIPLIER * 1.3))"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_fff9964e","line":268,"range":{"start_line":268,"start_character":14,"end_line":268,"end_character":32},"in_reply_to":"1a1ced50_89b0748d","updated":"2017-03-17 17:31:28.000000000","message":"FYI this comment is invalid.","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"b7ccedd67e5121b7ab957a3e8bb46780438fc69d","unresolved":false,"context_lines":[{"line_number":256,"context_line":"        self._create_and_attach_subnet("},{"line_number":257,"context_line":"            tenant_id, \u002713.37.0.0/24\u0027, network[\u0027id\u0027], router[\u0027id\u0027])"},{"line_number":258,"context_line":""},{"line_number":259,"context_line":"        # Create 5 fake VMs, each with a floating ip. Each floating ip"},{"line_number":260,"context_line":"        # association should send a SIGHUP to the keepalived\u0027s parent process,"},{"line_number":261,"context_line":"        # unless the Throttler works."},{"line_number":262,"context_line":"        host \u003d self.environment.hosts[0]"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_a113440c","line":259,"range":{"start_line":259,"start_character":17,"end_line":259,"end_character":18},"updated":"2017-03-20 20:10:09.000000000","message":"that seems rather low to consistently capture a regression. Can we bump it to something more agressive like 50? it doesn\u0027t boot a real VM, so that should be fine for test env, right?\n\nThe reason I suggest that is I see the test failed in gate once, while it was passing before. Apparently there is not enough brute force to hit the bug consistently.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"c1d8aca65e126e6a50c2a735220b934fd29191db","unresolved":false,"context_lines":[{"line_number":256,"context_line":"        self._create_and_attach_subnet("},{"line_number":257,"context_line":"            tenant_id, \u002713.37.0.0/24\u0027, network[\u0027id\u0027], router[\u0027id\u0027])"},{"line_number":258,"context_line":""},{"line_number":259,"context_line":"        # Create 5 fake VMs, each with a floating ip. Each floating ip"},{"line_number":260,"context_line":"        # association should send a SIGHUP to the keepalived\u0027s parent process,"},{"line_number":261,"context_line":"        # unless the Throttler works."},{"line_number":262,"context_line":"        host \u003d self.environment.hosts[0]"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_df71de77","line":259,"range":{"start_line":259,"start_character":17,"end_line":259,"end_character":18},"in_reply_to":"1a1ced50_a113440c","updated":"2017-03-21 12:27:47.000000000","message":"Yes, I\u0027d bump it, and also the throttler multiplier as it seems that mastership is lost sometimes yet.","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"8e866169d8b4016bece9ec42c508d72a9207c705","unresolved":false,"context_lines":[{"line_number":256,"context_line":"        self._create_and_attach_subnet("},{"line_number":257,"context_line":"            tenant_id, \u002713.37.0.0/24\u0027, network[\u0027id\u0027], router[\u0027id\u0027])"},{"line_number":258,"context_line":""},{"line_number":259,"context_line":"        # Create 5 fake VMs, each with a floating ip. Each floating ip"},{"line_number":260,"context_line":"        # association should send a SIGHUP to the keepalived\u0027s parent process,"},{"line_number":261,"context_line":"        # unless the Throttler works."},{"line_number":262,"context_line":"        host \u003d self.environment.hosts[0]"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a1ced50_4bba8b0b","line":259,"range":{"start_line":259,"start_character":17,"end_line":259,"end_character":18},"in_reply_to":"1a1ced50_df71de77","updated":"2017-03-21 13:32:59.000000000","message":"Done","commit_id":"5322a07ae619f28bb60c3cb450741c408c2146e0"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"8c842fc8757115463610830c7761340175a4cc1d","unresolved":false,"context_lines":[{"line_number":275,"context_line":"        # for ha_vrrp_advert_int (the default is 2 seconds), plus a bit more."},{"line_number":276,"context_line":"        time_to_stop \u003d (time.time() +"},{"line_number":277,"context_line":"                        (agent_utils.DEFAULT_THROTTLER_VALUE *"},{"line_number":278,"context_line":"                         agent_utils.DEFAULT_THROTTLER_MULTIPLIER * 1.3))"},{"line_number":279,"context_line":"        while True:"},{"line_number":280,"context_line":"            if time.time() \u003e time_to_stop:"},{"line_number":281,"context_line":"                break"}],"source_content_type":"text/x-python","patch_set":39,"id":"1a1ced50_ae7644a1","line":278,"range":{"start_line":278,"start_character":25,"end_line":278,"end_character":65},"updated":"2017-03-23 13:50:54.000000000","message":"Yikes","commit_id":"155ee23f60c296faa37b6e22df4e7a6c18b76517"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"909186789f5b239b533067d3defdfabe79304518","unresolved":false,"context_lines":[{"line_number":260,"context_line":"        self._create_and_attach_subnet("},{"line_number":261,"context_line":"            tenant_id, \u002713.37.0.0/24\u0027, network[\u0027id\u0027], router[\u0027id\u0027])"},{"line_number":262,"context_line":""},{"line_number":263,"context_line":"        # Create 10 fake VMs, each with a floating ip. Each floating ip"},{"line_number":264,"context_line":"        # association should send a SIGHUP to the keepalived\u0027s parent process,"},{"line_number":265,"context_line":"        # unless the Throttler works."},{"line_number":266,"context_line":"        host \u003d self.environment.hosts[0]"}],"source_content_type":"text/x-python","patch_set":42,"id":"ffe62b97_50dc8e73","line":263,"updated":"2017-03-24 05:31:43.000000000","message":"fyi I lowered the number of VMs because with 50 the time of the test becomes ridiculously long (5 minutes here)","commit_id":"1dd9b8c096ae1b4b7a9461649440dee04de3dfa2"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"653e98a1d5dbc021c2b520615622317a05af2894","unresolved":false,"context_lines":[{"line_number":271,"context_line":"            self.safe_client.create_floatingip("},{"line_number":272,"context_line":"                tenant_id, ext_net[\u0027id\u0027], vm.ip, vm.neutron_port[\u0027id\u0027])"},{"line_number":273,"context_line":""},{"line_number":274,"context_line":"        # Check that the keepalived\u0027s state file has not changed and is still"},{"line_number":275,"context_line":"        # master. This will indicate that the Throttler works. We want to check"},{"line_number":276,"context_line":"        # for ha_vrrp_advert_int (the default is 2 seconds), plus a bit more."},{"line_number":277,"context_line":"        time_to_stop \u003d (time.time() +"}],"source_content_type":"text/x-python","patch_set":45,"id":"ffe62b97_fe4b5a84","line":274,"updated":"2017-03-24 16:33:35.000000000","message":"I will look at making the check progressing while router updates are happening so that we don\u0027t miss flip when it happens even number of times.","commit_id":"ff25082a98508900125305612eec207af9e38600"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"653e98a1d5dbc021c2b520615622317a05af2894","unresolved":false,"context_lines":[{"line_number":274,"context_line":"        # Check that the keepalived\u0027s state file has not changed and is still"},{"line_number":275,"context_line":"        # master. This will indicate that the Throttler works. We want to check"},{"line_number":276,"context_line":"        # for ha_vrrp_advert_int (the default is 2 seconds), plus a bit more."},{"line_number":277,"context_line":"        time_to_stop \u003d (time.time() +"},{"line_number":278,"context_line":"                        (agent_utils.DEFAULT_THROTTLER_VALUE *"},{"line_number":279,"context_line":"                         ha_router.THROTTLER_MULTIPLIER * 1.3))"},{"line_number":280,"context_line":"        while True:"}],"source_content_type":"text/x-python","patch_set":45,"id":"ffe62b97_9e3faed5","line":277,"range":{"start_line":277,"start_character":8,"end_line":277,"end_character":20},"updated":"2017-03-24 16:33:35.000000000","message":"instead of a hard time limit, maybe we should wait for all FIPs up and working, then stop.","commit_id":"ff25082a98508900125305612eec207af9e38600"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"821cb045bd9b929c1ee35fbb7e3496493ea10204","unresolved":false,"context_lines":[{"line_number":193,"context_line":"        host_descriptions \u003d ["},{"line_number":194,"context_line":"            environment.HostDescription(l3_agent\u003dTrue) for _ in range(2)]"},{"line_number":195,"context_line":"        # REVISIT(jlibosva): Remove quota_port once they are bumped by"},{"line_number":196,"context_line":"        #                    https://review.openstack.org/#/c/444030/"},{"line_number":197,"context_line":"        env \u003d environment.Environment("},{"line_number":198,"context_line":"            environment.EnvironmentDescription("},{"line_number":199,"context_line":"                network_type\u003d\u0027vxlan\u0027, l2_pop\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":48,"id":"ffe62b97_111f84b7","line":196,"updated":"2017-03-28 20:01:18.000000000","message":"note to reviewers: this is now merged, but we want to backport.","commit_id":"9cc6d97a4dd47b6ffeb70a5d374d36bf9ea8ff9e"},{"author":{"_account_id":748,"name":"Armando Migliaccio","email":"armamig@gmail.com","username":"armando-migliaccio"},"change_message_id":"271a5e383eb02e193d829807631c02c6aa6cf1e5","unresolved":false,"context_lines":[{"line_number":193,"context_line":"        host_descriptions \u003d ["},{"line_number":194,"context_line":"            environment.HostDescription(l3_agent\u003dTrue) for _ in range(2)]"},{"line_number":195,"context_line":"        # REVISIT(jlibosva): Remove quota_port once they are bumped by"},{"line_number":196,"context_line":"        #                    https://review.openstack.org/#/c/444030/"},{"line_number":197,"context_line":"        env \u003d environment.Environment("},{"line_number":198,"context_line":"            environment.EnvironmentDescription("},{"line_number":199,"context_line":"                network_type\u003d\u0027vxlan\u0027, l2_pop\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":48,"id":"ffe62b97_919cb40e","line":196,"in_reply_to":"ffe62b97_111f84b7","updated":"2017-03-28 20:04:51.000000000","message":"does this mean that we can drop this code change?","commit_id":"9cc6d97a4dd47b6ffeb70a5d374d36bf9ea8ff9e"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"3901e202a79e1c8bcdcfd98851eda24503dd1dd2","unresolved":false,"context_lines":[{"line_number":193,"context_line":"        host_descriptions \u003d ["},{"line_number":194,"context_line":"            environment.HostDescription(l3_agent\u003dTrue) for _ in range(2)]"},{"line_number":195,"context_line":"        # REVISIT(jlibosva): Remove quota_port once they are bumped by"},{"line_number":196,"context_line":"        #                    https://review.openstack.org/#/c/444030/"},{"line_number":197,"context_line":"        env \u003d environment.Environment("},{"line_number":198,"context_line":"            environment.EnvironmentDescription("},{"line_number":199,"context_line":"                network_type\u003d\u0027vxlan\u0027, l2_pop\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":48,"id":"ffe62b97_3914ae43","line":196,"in_reply_to":"ffe62b97_83f0e7fe","updated":"2017-03-28 21:06:17.000000000","message":"Actually, now that we create just 10 FIPs, we may need not to bump quotas in backports either, because default port quota pre Pike was 50.","commit_id":"9cc6d97a4dd47b6ffeb70a5d374d36bf9ea8ff9e"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"a41e665d1f7dcd0160de8c71e2d724aa569f856e","unresolved":false,"context_lines":[{"line_number":193,"context_line":"        host_descriptions \u003d ["},{"line_number":194,"context_line":"            environment.HostDescription(l3_agent\u003dTrue) for _ in range(2)]"},{"line_number":195,"context_line":"        # REVISIT(jlibosva): Remove quota_port once they are bumped by"},{"line_number":196,"context_line":"        #                    https://review.openstack.org/#/c/444030/"},{"line_number":197,"context_line":"        env \u003d environment.Environment("},{"line_number":198,"context_line":"            environment.EnvironmentDescription("},{"line_number":199,"context_line":"                network_type\u003d\u0027vxlan\u0027, l2_pop\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":48,"id":"ffe62b97_83f0e7fe","line":196,"in_reply_to":"ffe62b97_919cb40e","updated":"2017-03-28 20:13:37.000000000","message":"OK will include in backports only.","commit_id":"9cc6d97a4dd47b6ffeb70a5d374d36bf9ea8ff9e"}],"neutron/tests/functional/agent/linux/test_keepalived.py":[{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ad6839ba8ed0b310b177dfab09187b0f3a6e16ee","unresolved":false,"context_lines":[{"line_number":37,"context_line":"                                                               \u0027router\u0027)"},{"line_number":38,"context_line":"        self.manager \u003d keepalived.KeepalivedManager("},{"line_number":39,"context_line":"            \u0027router1\u0027, self.expected_config, self.process_monitor,"},{"line_number":40,"context_line":"            conf_path\u003dcfg.CONF.state_path, advert_int\u003d2)"},{"line_number":41,"context_line":"        self.addCleanup(self.manager.disable)"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    def _spawn_keepalived(self, keepalived_manager):"}],"source_content_type":"text/x-python","patch_set":25,"id":"3a461143_9b1a9e7b","line":40,"range":{"start_line":40,"start_character":41,"end_line":40,"end_character":55},"updated":"2017-02-01 12:02:25.000000000","message":"Why do we need this?","commit_id":"32d9b1441cefb6a497271106842667750c366e20"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"bf373be5a421d28adce784bcf6f304797c046ce8","unresolved":false,"context_lines":[{"line_number":37,"context_line":"                                                               \u0027router\u0027)"},{"line_number":38,"context_line":"        self.manager \u003d keepalived.KeepalivedManager("},{"line_number":39,"context_line":"            \u0027router1\u0027, self.expected_config, self.process_monitor,"},{"line_number":40,"context_line":"            conf_path\u003dcfg.CONF.state_path, advert_int\u003d2)"},{"line_number":41,"context_line":"        self.addCleanup(self.manager.disable)"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    def _spawn_keepalived(self, keepalived_manager):"}],"source_content_type":"text/x-python","patch_set":25,"id":"1a430d35_1a334eac","line":40,"range":{"start_line":40,"start_character":41,"end_line":40,"end_character":55},"in_reply_to":"3a461143_9b1a9e7b","updated":"2017-02-08 11:41:57.000000000","message":"Done","commit_id":"32d9b1441cefb6a497271106842667750c366e20"}],"neutron/tests/unit/agent/common/test_utils.py":[{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":85,"context_line":""},{"line_number":86,"context_line":"class TestThrottler(base.BaseTestCase):"},{"line_number":87,"context_line":"    def test_throttler(self):"},{"line_number":88,"context_line":"        threshold \u003d 20"},{"line_number":89,"context_line":"        orig_function \u003d mock.Mock()"},{"line_number":90,"context_line":"        function \u003d utils.throttler(orig_function)"},{"line_number":91,"context_line":"        function.throttle_threshold \u003d threshold"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_04b70b3a","line":88,"range":{"start_line":88,"start_character":20,"end_line":88,"end_character":22},"updated":"2017-03-17 17:29:15.000000000","message":"It makes the test to waste 20 sec+. Can we pick a lower number?","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"8238a69ad2dc2f8aa2e233d79c24f43167b7a4e2","unresolved":false,"context_lines":[{"line_number":87,"context_line":"    def test_throttler(self):"},{"line_number":88,"context_line":"        threshold \u003d 20"},{"line_number":89,"context_line":"        orig_function \u003d mock.Mock()"},{"line_number":90,"context_line":"        function \u003d utils.throttler(orig_function)"},{"line_number":91,"context_line":"        function.throttle_threshold \u003d threshold"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"        function()"}],"source_content_type":"text/x-python","patch_set":30,"id":"1a1ced50_a95b7053","line":90,"range":{"start_line":90,"start_character":8,"end_line":90,"end_character":16},"updated":"2017-03-17 17:29:15.000000000","message":"how about a more specific name, like throttled_func[tion]?","commit_id":"5667718d07dc7302f3bd2a753944d50de50d6ed8"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"4a063341edbe604e62ea29931a51a84073b4c750","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        self.assertEqual(3, orig_function.call_count)"},{"line_number":116,"context_line":"        self.assertTrue(timestamp \u003c throttled_func._last_time_called)"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"    def test_function_docstring_is_preserved(self):"},{"line_number":119,"context_line":"        class Klass(object):"},{"line_number":120,"context_line":"            @utils.throttler"},{"line_number":121,"context_line":"            def method(self):"}],"source_content_type":"text/x-python","patch_set":34,"id":"1a1ced50_782d8945","line":118,"range":{"start_line":118,"start_character":13,"end_line":118,"end_character":21},"updated":"2017-03-20 15:34:51.000000000","message":"method","commit_id":"6146fa7f7a1af72d4668b3018367158ef8680b0b"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"dbcfe4cbb905be8b13c7f271285c0cd0c41cd028","unresolved":false,"context_lines":[{"line_number":120,"context_line":"            @utils.throttler"},{"line_number":121,"context_line":"            def method(self):"},{"line_number":122,"context_line":"                \"\"\"Docstring\"\"\""},{"line_number":123,"context_line":"                pass"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"        self.assertEqual(\"Docstring\", Klass.method.__doc__)"}],"source_content_type":"text/x-python","patch_set":34,"id":"1a1ced50_bb5e1674","line":123,"updated":"2017-03-20 17:41:28.000000000","message":"nit: redundant line","commit_id":"6146fa7f7a1af72d4668b3018367158ef8680b0b"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"151ee7e23e0cae84139c83c7697f66794971a2c2","unresolved":false,"context_lines":[{"line_number":88,"context_line":"        threshold \u003d 1"},{"line_number":89,"context_line":"        orig_function \u003d mock.Mock()"},{"line_number":90,"context_line":"        # Add this magic name as it\u0027s required by functools"},{"line_number":91,"context_line":"        # TODO(ihrachys) is it? ^"},{"line_number":92,"context_line":"        orig_function.__name__ \u003d \u0027mock_func\u0027"},{"line_number":93,"context_line":"        throttled_func \u003d utils.throttler(threshold)(orig_function)"},{"line_number":94,"context_line":""}],"source_content_type":"text/x-python","patch_set":42,"id":"ffe62b97_01190b78","line":91,"range":{"start_line":91,"start_character":25,"end_line":91,"end_character":31},"updated":"2017-03-24 11:38:24.000000000","message":"It is by update_wrapper() - not sure about wraps()","commit_id":"1dd9b8c096ae1b4b7a9461649440dee04de3dfa2"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"981e9ed5250aad8e5e59c0173f5d711500d1a661","unresolved":false,"context_lines":[{"line_number":87,"context_line":"class TestThrottler(base.BaseTestCase):"},{"line_number":88,"context_line":"    def test_throttler(self):"},{"line_number":89,"context_line":"        threshold \u003d 1"},{"line_number":90,"context_line":"        orig_function \u003d mock.Mock()"},{"line_number":91,"context_line":"        # Add this magic name as it\u0027s required by functools"},{"line_number":92,"context_line":"        orig_function.__name__ \u003d \u0027mock_func\u0027"},{"line_number":93,"context_line":"        throttled_func \u003d utils.throttler(threshold)(orig_function)"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        throttled_func()"}],"source_content_type":"text/x-python","patch_set":46,"id":"ffe62b97_c152ea67","line":92,"range":{"start_line":90,"start_character":8,"end_line":92,"end_character":44},"updated":"2017-03-24 21:21:46.000000000","message":"could use a proper (later mocked) function to avoid that.","commit_id":"81bf980b3ec10082dd5b71c4bb021e51d5c0c327"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"0f97bed31db4c5069ee47107695d1672b933ea84","unresolved":false,"context_lines":[{"line_number":87,"context_line":"class TestThrottler(base.BaseTestCase):"},{"line_number":88,"context_line":"    def test_throttler(self):"},{"line_number":89,"context_line":"        threshold \u003d 1"},{"line_number":90,"context_line":"        orig_function \u003d mock.Mock()"},{"line_number":91,"context_line":"        # Add this magic name as it\u0027s required by functools"},{"line_number":92,"context_line":"        orig_function.__name__ \u003d \u0027mock_func\u0027"},{"line_number":93,"context_line":"        throttled_func \u003d utils.throttler(threshold)(orig_function)"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        throttled_func()"}],"source_content_type":"text/x-python","patch_set":46,"id":"ffe62b97_163b459c","line":92,"range":{"start_line":90,"start_character":8,"end_line":92,"end_character":44},"in_reply_to":"ffe62b97_80e5cbaa","updated":"2017-03-27 13:08:59.000000000","message":"I see.","commit_id":"81bf980b3ec10082dd5b71c4bb021e51d5c0c327"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"18f940f7cd7f4aa11db5712601feb6c841e0e90a","unresolved":false,"context_lines":[{"line_number":87,"context_line":"class TestThrottler(base.BaseTestCase):"},{"line_number":88,"context_line":"    def test_throttler(self):"},{"line_number":89,"context_line":"        threshold \u003d 1"},{"line_number":90,"context_line":"        orig_function \u003d mock.Mock()"},{"line_number":91,"context_line":"        # Add this magic name as it\u0027s required by functools"},{"line_number":92,"context_line":"        orig_function.__name__ \u003d \u0027mock_func\u0027"},{"line_number":93,"context_line":"        throttled_func \u003d utils.throttler(threshold)(orig_function)"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        throttled_func()"}],"source_content_type":"text/x-python","patch_set":46,"id":"ffe62b97_80e5cbaa","line":92,"range":{"start_line":90,"start_character":8,"end_line":92,"end_character":44},"in_reply_to":"ffe62b97_c152ea67","updated":"2017-03-27 12:42:56.000000000","message":"I don\u0027t know how to do it. I tried to mock the cell in throttler\u0027s closure with the original function but cell is read only.\n\nI tried to create a function and the mock it but it\u0027s still replaced with Mock object.\n\nIf I create a function, decorate it and then mock, it won\u0027t get mocked inside of the decorator.","commit_id":"81bf980b3ec10082dd5b71c4bb021e51d5c0c327"}]}
