)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"120c285fd93d56d6601e473658068558a36d2375","unresolved":true,"context_lines":[{"line_number":23,"context_line":"sleep as required after each allowed request. For example, before a"},{"line_number":24,"context_line":"max_rate of 1 per second might result in 2 requests being allowed"},{"line_number":25,"context_line":"followed by a 2 second sleep. That is corrected to be a sleep of 1"},{"line_number":26,"context_line":"second after each request."},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"Change-Id: Ibcf4dbeb4332dee7e9e233473d4ceaf75a5a85c7"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":5,"id":"499e3cfe_85946f14","line":26,"updated":"2022-05-16 19:25:57.000000000","message":"it seems like the rate_buffer should have an effect on how this bunching/bursting behavior works - but I couldn\u0027t get any of the test churn to fall away playing with different default values for that kwarg","commit_id":"5227cb702b744bbe9aaecfff002604be45f64a8c"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1a510b9d4bff1990331002707366ce4c4fccbd11","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"83f5ee47_5a5da3ab","updated":"2022-03-23 18:37:51.000000000","message":"needs more tests","commit_id":"8777d9939ee86ca114ffe511c3c202e8d8391a1a"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fe8a9654c9be251917ee03021727eb24e73030c3","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"e3ec9a6b_9e0a7b94","updated":"2022-04-01 03:44:17.000000000","message":"Nice refactor Al. Love that we can use it all the places and seems like a nice starting point too.","commit_id":"6505b050563e2aebf235dcfdfe384ee75d22378d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"8a299e68_873ffdaf","updated":"2022-05-04 10:18:12.000000000","message":"Thanks for the great reviews! new patchset coming soon","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fe6b40597dafd75d7240bfcca906f1bef021b7a4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"dcbc03b4_a8f95810","updated":"2022-04-28 18:40:15.000000000","message":"recheck\n\nThis looks good!  Just a couple nits.  I\u0027m curious how confident you are in the general usefulness of sortability of ratelimiter instances - definately not a blocker for me.  I don\u0027t understand the test churn.","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"120c285fd93d56d6601e473658068558a36d2375","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"f062f2f1_049cac3d","updated":"2022-05-16 19:25:57.000000000","message":"I like encapsalating state with code - this seems like a win to me.","commit_id":"5227cb702b744bbe9aaecfff002604be45f64a8c"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"42617ab4c85bd5c8b32d9e1c187f64e13a461388","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"50d61e0a_5fe95daa","updated":"2022-05-04 21:38:39.000000000","message":"recheck\n\nStrange -- `Object returning 503 for []` yet I don\u0027t see any timeouts...","commit_id":"5227cb702b744bbe9aaecfff002604be45f64a8c"}],"swift/common/utils.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1a510b9d4bff1990331002707366ce4c4fccbd11","unresolved":true,"context_lines":[{"line_number":3454,"context_line":"    # 1,000 milliseconds \u003d 1 second"},{"line_number":3455,"context_line":"    clock_accuracy \u003d 1000.0"},{"line_number":3456,"context_line":""},{"line_number":3457,"context_line":"    def __init__(self, max_rate, rate_buffer\u003d5, running_time\u003d0):"},{"line_number":3458,"context_line":"        self.max_rate \u003d max_rate"},{"line_number":3459,"context_line":"        self.rate_buffer_ms \u003d rate_buffer * self.clock_accuracy"},{"line_number":3460,"context_line":"        self.running_time \u003d running_time"}],"source_content_type":"text/x-python","patch_set":1,"id":"eda85380_94b31a15","line":3457,"updated":"2022-03-23 18:37:51.000000000","message":"I might rename some of these args but for now leaving the same as the original implementation to ease review.","commit_id":"8777d9939ee86ca114ffe511c3c202e8d8391a1a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":3454,"context_line":"    # 1,000 milliseconds \u003d 1 second"},{"line_number":3455,"context_line":"    clock_accuracy \u003d 1000.0"},{"line_number":3456,"context_line":""},{"line_number":3457,"context_line":"    def __init__(self, max_rate, rate_buffer\u003d5, running_time\u003d0):"},{"line_number":3458,"context_line":"        self.max_rate \u003d max_rate"},{"line_number":3459,"context_line":"        self.rate_buffer_ms \u003d rate_buffer * self.clock_accuracy"},{"line_number":3460,"context_line":"        self.running_time \u003d running_time"}],"source_content_type":"text/x-python","patch_set":1,"id":"66d0211c_54ec8ec3","line":3457,"in_reply_to":"eda85380_94b31a15","updated":"2022-05-04 10:18:12.000000000","message":"Ack","commit_id":"8777d9939ee86ca114ffe511c3c202e8d8391a1a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1a510b9d4bff1990331002707366ce4c4fccbd11","unresolved":true,"context_lines":[{"line_number":3479,"context_line":""},{"line_number":3480,"context_line":"        # Convert rate_buffer to milliseconds and compare"},{"line_number":3481,"context_line":"        if now - self.running_time \u003e self.rate_buffer_ms:"},{"line_number":3482,"context_line":"            self.running_time \u003d now"},{"line_number":3483,"context_line":"        elif self.running_time \u003e now:"},{"line_number":3484,"context_line":"            if block:"},{"line_number":3485,"context_line":"                # Convert diff to a floating point number of seconds and sleep"}],"source_content_type":"text/x-python","patch_set":1,"id":"b2c649a2_71229779","line":3482,"range":{"start_line":3482,"start_character":12,"end_line":3482,"end_character":35},"updated":"2022-03-23 18:37:51.000000000","message":"I think this should be \n\n  self.running_time \u003d now - self.rate_buffer_ms\n\nso that the \"burst capacity\" is carried forwards and not lost at end of rate_buffer time","commit_id":"8777d9939ee86ca114ffe511c3c202e8d8391a1a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b640462b9284b36a655163074bff03a973e86d59","unresolved":true,"context_lines":[{"line_number":3479,"context_line":""},{"line_number":3480,"context_line":"        # Convert rate_buffer to milliseconds and compare"},{"line_number":3481,"context_line":"        if now - self.running_time \u003e self.rate_buffer_ms:"},{"line_number":3482,"context_line":"            self.running_time \u003d now"},{"line_number":3483,"context_line":"        elif self.running_time \u003e now:"},{"line_number":3484,"context_line":"            if block:"},{"line_number":3485,"context_line":"                # Convert diff to a floating point number of seconds and sleep"}],"source_content_type":"text/x-python","patch_set":1,"id":"b22a79af_8e233bd7","line":3482,"range":{"start_line":3482,"start_character":12,"end_line":3482,"end_character":35},"in_reply_to":"0139ff58_dda9a080","updated":"2022-04-04 09:11:45.000000000","message":"See. https://review.opendev.org/c/openstack/swift/+/835122\n\nIt struck me as odd that the capacity to burst is just lost completely once the rate buffer time has passed, rather than there always being capacity to burst up to rate buffer amount.","commit_id":"8777d9939ee86ca114ffe511c3c202e8d8391a1a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":3479,"context_line":""},{"line_number":3480,"context_line":"        # Convert rate_buffer to milliseconds and compare"},{"line_number":3481,"context_line":"        if now - self.running_time \u003e self.rate_buffer_ms:"},{"line_number":3482,"context_line":"            self.running_time \u003d now"},{"line_number":3483,"context_line":"        elif self.running_time \u003e now:"},{"line_number":3484,"context_line":"            if block:"},{"line_number":3485,"context_line":"                # Convert diff to a floating point number of seconds and sleep"}],"source_content_type":"text/x-python","patch_set":1,"id":"812e6cf1_92522fc4","line":3482,"range":{"start_line":3482,"start_character":12,"end_line":3482,"end_character":35},"in_reply_to":"9398cbe3_b9361c4f","updated":"2022-05-04 10:18:12.000000000","message":"it\u0027s addressed in the next patch - kept it separate so that this patch is pure refactoring","commit_id":"8777d9939ee86ca114ffe511c3c202e8d8391a1a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fe6b40597dafd75d7240bfcca906f1bef021b7a4","unresolved":true,"context_lines":[{"line_number":3479,"context_line":""},{"line_number":3480,"context_line":"        # Convert rate_buffer to milliseconds and compare"},{"line_number":3481,"context_line":"        if now - self.running_time \u003e self.rate_buffer_ms:"},{"line_number":3482,"context_line":"            self.running_time \u003d now"},{"line_number":3483,"context_line":"        elif self.running_time \u003e now:"},{"line_number":3484,"context_line":"            if block:"},{"line_number":3485,"context_line":"                # Convert diff to a floating point number of seconds and sleep"}],"source_content_type":"text/x-python","patch_set":1,"id":"9398cbe3_b9361c4f","line":3482,"range":{"start_line":3482,"start_character":12,"end_line":3482,"end_character":35},"in_reply_to":"b22a79af_8e233bd7","updated":"2022-04-28 18:40:15.000000000","message":"i didn\u0027t really understand this branch was setting a \"floor\" on running_time until I looked at the next patch\n\nI agree it\u0027s strange the way existing rate limiter was implemented and the follow on patch makes more sense to me.\n\nAre we leaving this here for \"backwards compatiblity\"??? cause it seemed like a lot of tests had to change anyway and i\u0027m not sure the existing behavior was anything more than bug...","commit_id":"8777d9939ee86ca114ffe511c3c202e8d8391a1a"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fe8a9654c9be251917ee03021727eb24e73030c3","unresolved":true,"context_lines":[{"line_number":3479,"context_line":""},{"line_number":3480,"context_line":"        # Convert rate_buffer to milliseconds and compare"},{"line_number":3481,"context_line":"        if now - self.running_time \u003e self.rate_buffer_ms:"},{"line_number":3482,"context_line":"            self.running_time \u003d now"},{"line_number":3483,"context_line":"        elif self.running_time \u003e now:"},{"line_number":3484,"context_line":"            if block:"},{"line_number":3485,"context_line":"                # Convert diff to a floating point number of seconds and sleep"}],"source_content_type":"text/x-python","patch_set":1,"id":"0139ff58_dda9a080","line":3482,"range":{"start_line":3482,"start_character":12,"end_line":3482,"end_character":35},"in_reply_to":"b2c649a2_71229779","updated":"2022-04-01 03:44:17.000000000","message":"I thought the point was that if the rate counter got too far behind, it\u0027d nuke it as it didn\u0027t have enough time to catch up.","commit_id":"8777d9939ee86ca114ffe511c3c202e8d8391a1a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1a510b9d4bff1990331002707366ce4c4fccbd11","unresolved":true,"context_lines":[{"line_number":3480,"context_line":"        # Convert rate_buffer to milliseconds and compare"},{"line_number":3481,"context_line":"        if now - self.running_time \u003e self.rate_buffer_ms:"},{"line_number":3482,"context_line":"            self.running_time \u003d now"},{"line_number":3483,"context_line":"        elif self.running_time \u003e now:"},{"line_number":3484,"context_line":"            if block:"},{"line_number":3485,"context_line":"                # Convert diff to a floating point number of seconds and sleep"},{"line_number":3486,"context_line":"                self._sleep((self.running_time - now) / self.clock_accuracy)"}],"source_content_type":"text/x-python","patch_set":1,"id":"9b96856b_c7e9221e","line":3483,"range":{"start_line":3483,"start_character":8,"end_line":3483,"end_character":37},"updated":"2022-03-23 18:37:51.000000000","message":"this changes w.r.t. master which had\n\n  running_time - now \u003e time_per_request\n\nso running time is the start of the next interval rather than end of next interval","commit_id":"8777d9939ee86ca114ffe511c3c202e8d8391a1a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f2f4ea76f7c4188b6f8faaed50a0d589bb4035e4","unresolved":true,"context_lines":[{"line_number":3480,"context_line":"        # Convert rate_buffer to milliseconds and compare"},{"line_number":3481,"context_line":"        if now - self.running_time \u003e self.rate_buffer_ms:"},{"line_number":3482,"context_line":"            self.running_time \u003d now"},{"line_number":3483,"context_line":"        elif self.running_time \u003e now:"},{"line_number":3484,"context_line":"            if block:"},{"line_number":3485,"context_line":"                # Convert diff to a floating point number of seconds and sleep"},{"line_number":3486,"context_line":"                self._sleep((self.running_time - now) / self.clock_accuracy)"}],"source_content_type":"text/x-python","patch_set":1,"id":"c3ed067f_89818368","line":3483,"range":{"start_line":3483,"start_character":8,"end_line":3483,"end_character":37},"in_reply_to":"9b96856b_c7e9221e","updated":"2022-03-24 11:26:53.000000000","message":"the implementation on master leads to \u0027bunching\u0027 behaviour as demonstrated by the test in test_slo:\n\n  * assume the max_rate is 1 per sec, running_time is initially 0\n  * a request made at say t\u003d99 is granted immediately and \n    running_time is set to 100\n  * a request at any time in the second preceding running_time, \n    including t\u003d99, would be granted without sleeping\n  * running time is incremented by 1 second to 101\n  * a next request at t\u003c100 would then sleep until 101\n  * running time is incremented by 1 second to 102\n  * a next request at 101 would be granted without sleeping\n  * running time is incremented by 1 second to 103\n  * a next request at 101.99 would sleep until 103\n\ne.g.\n\n  * requests made at    99, 99.01,  99.99, 101, 101.99 \n  * requests granted at 99, 99.01, 101,    101, 103\n\nThe change here means that for the same requests:\n\n  * requests made at    99,  99.01, 100, 101, 102 \n  * requests granted at 99, 100,    101, 102, 103","commit_id":"8777d9939ee86ca114ffe511c3c202e8d8391a1a"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fe8a9654c9be251917ee03021727eb24e73030c3","unresolved":true,"context_lines":[{"line_number":3468,"context_line":"        self.rate_buffer_ms \u003d rate_buffer * self.clock_accuracy"},{"line_number":3469,"context_line":"        self.running_time \u003d running_time"},{"line_number":3470,"context_line":"        self.time_per_incr \u003d (self.clock_accuracy / self.max_rate"},{"line_number":3471,"context_line":"                              if self.max_rate else 0)"},{"line_number":3472,"context_line":""},{"line_number":3473,"context_line":"    def _sleep(self, seconds):"},{"line_number":3474,"context_line":"        raise NotImplementedError"}],"source_content_type":"text/x-python","patch_set":3,"id":"bc71a6c0_f5be291c","line":3471,"range":{"start_line":3471,"start_character":52,"end_line":3471,"end_character":53},"updated":"2022-04-01 03:44:17.000000000","message":"isn\u0027t this going to give us a ZeroDivisionError... \u003cedit:\u003e oh order of operations, it\u0027s not:\n\n  self.clock_accuracy / (self.max_rate if self.max_rate else 0)\n\nIts more like:\n\n  (self.clock_accuracy / self.max_rate) if self.max_rate else 0\n  \nNoting I\u0027m adding the brackets only to emphasis.\n\nObvious now, but threw me for a bit :)","commit_id":"6505b050563e2aebf235dcfdfe384ee75d22378d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b640462b9284b36a655163074bff03a973e86d59","unresolved":false,"context_lines":[{"line_number":3468,"context_line":"        self.rate_buffer_ms \u003d rate_buffer * self.clock_accuracy"},{"line_number":3469,"context_line":"        self.running_time \u003d running_time"},{"line_number":3470,"context_line":"        self.time_per_incr \u003d (self.clock_accuracy / self.max_rate"},{"line_number":3471,"context_line":"                              if self.max_rate else 0)"},{"line_number":3472,"context_line":""},{"line_number":3473,"context_line":"    def _sleep(self, seconds):"},{"line_number":3474,"context_line":"        raise NotImplementedError"}],"source_content_type":"text/x-python","patch_set":3,"id":"175e0e99_f571cfa6","line":3471,"range":{"start_line":3471,"start_character":52,"end_line":3471,"end_character":53},"in_reply_to":"bc71a6c0_f5be291c","updated":"2022-04-04 09:11:45.000000000","message":"Ack","commit_id":"6505b050563e2aebf235dcfdfe384ee75d22378d"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fe8a9654c9be251917ee03021727eb24e73030c3","unresolved":true,"context_lines":[{"line_number":3509,"context_line":"                self._sleep((self.running_time - now) / self.clock_accuracy)"},{"line_number":3510,"context_line":"            else:"},{"line_number":3511,"context_line":"                grant \u003d False"},{"line_number":3512,"context_line":"        # Return the absolute time for the next interval in milliseconds; note"},{"line_number":3513,"context_line":"        # that time could have passed well beyond that point, but the next call"},{"line_number":3514,"context_line":"        # will catch that and skip the sleep."},{"line_number":3515,"context_line":"        if grant:"}],"source_content_type":"text/x-python","patch_set":3,"id":"d353f7bc_6f16e291","line":3512,"range":{"start_line":3512,"start_character":10,"end_line":3512,"end_character":72},"updated":"2022-04-01 03:44:17.000000000","message":"Umm no we\u0027re not","commit_id":"6505b050563e2aebf235dcfdfe384ee75d22378d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b640462b9284b36a655163074bff03a973e86d59","unresolved":false,"context_lines":[{"line_number":3509,"context_line":"                self._sleep((self.running_time - now) / self.clock_accuracy)"},{"line_number":3510,"context_line":"            else:"},{"line_number":3511,"context_line":"                grant \u003d False"},{"line_number":3512,"context_line":"        # Return the absolute time for the next interval in milliseconds; note"},{"line_number":3513,"context_line":"        # that time could have passed well beyond that point, but the next call"},{"line_number":3514,"context_line":"        # will catch that and skip the sleep."},{"line_number":3515,"context_line":"        if grant:"}],"source_content_type":"text/x-python","patch_set":3,"id":"88005dbc_f8fb813a","line":3512,"range":{"start_line":3512,"start_character":10,"end_line":3512,"end_character":72},"in_reply_to":"d353f7bc_6f16e291","updated":"2022-04-04 09:11:45.000000000","message":"Done","commit_id":"6505b050563e2aebf235dcfdfe384ee75d22378d"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fe8a9654c9be251917ee03021727eb24e73030c3","unresolved":true,"context_lines":[{"line_number":3520,"context_line":"        # used to sort RateLimiters by readiness"},{"line_number":3521,"context_line":"        if isinstance(other, RateLimiter):"},{"line_number":3522,"context_line":"            return self.running_time \u003c other.running_time"},{"line_number":3523,"context_line":"        return self.running_time \u003c other"},{"line_number":3524,"context_line":""},{"line_number":3525,"context_line":""},{"line_number":3526,"context_line":"class RateLimiter(AbstractRateLimiter):"}],"source_content_type":"text/x-python","patch_set":3,"id":"8b71bafb_4884c814","line":3523,"updated":"2022-04-01 03:44:17.000000000","message":"Oh this is cool","commit_id":"6505b050563e2aebf235dcfdfe384ee75d22378d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":3520,"context_line":"        # used to sort RateLimiters by readiness"},{"line_number":3521,"context_line":"        if isinstance(other, RateLimiter):"},{"line_number":3522,"context_line":"            return self.running_time \u003c other.running_time"},{"line_number":3523,"context_line":"        return self.running_time \u003c other"},{"line_number":3524,"context_line":""},{"line_number":3525,"context_line":""},{"line_number":3526,"context_line":"class RateLimiter(AbstractRateLimiter):"}],"source_content_type":"text/x-python","patch_set":3,"id":"bf754cde_bef4b709","line":3523,"in_reply_to":"8b71bafb_4884c814","updated":"2022-05-04 10:18:12.000000000","message":"Ack","commit_id":"6505b050563e2aebf235dcfdfe384ee75d22378d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fe6b40597dafd75d7240bfcca906f1bef021b7a4","unresolved":true,"context_lines":[{"line_number":3462,"context_line":"            allowed to catch up (at a faster than listed rate). A larger number"},{"line_number":3463,"context_line":"            will result in larger spikes in rate but better average accuracy."},{"line_number":3464,"context_line":"        :param running_time: The running time in milliseconds of the next"},{"line_number":3465,"context_line":"            allowable request. Best to start at zero."},{"line_number":3466,"context_line":"        \"\"\""},{"line_number":3467,"context_line":"        self.max_rate \u003d max_rate"},{"line_number":3468,"context_line":"        self.rate_buffer_ms \u003d rate_buffer * self.clock_accuracy"}],"source_content_type":"text/x-python","patch_set":4,"id":"be060b14_430c426a","line":3465,"updated":"2022-04-28 18:40:15.000000000","message":"s/of the next allowable/until the next allowed/g ???\n\nwhy start at zero instead of \"now\"","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":3462,"context_line":"            allowed to catch up (at a faster than listed rate). A larger number"},{"line_number":3463,"context_line":"            will result in larger spikes in rate but better average accuracy."},{"line_number":3464,"context_line":"        :param running_time: The running time in milliseconds of the next"},{"line_number":3465,"context_line":"            allowable request. Best to start at zero."},{"line_number":3466,"context_line":"        \"\"\""},{"line_number":3467,"context_line":"        self.max_rate \u003d max_rate"},{"line_number":3468,"context_line":"        self.rate_buffer_ms \u003d rate_buffer * self.clock_accuracy"}],"source_content_type":"text/x-python","patch_set":4,"id":"23e447dd_ef05799d","line":3465,"in_reply_to":"be060b14_430c426a","updated":"2022-05-04 10:18:12.000000000","message":"good question and I had the same thought when looking at the original ratelimit_sleep function that this copied from. I don\u0027t know why that was thought to be the best recommendation. I think it is only significant if set in the future.\n\nI\u0027ll re-write.","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fe6b40597dafd75d7240bfcca906f1bef021b7a4","unresolved":true,"context_lines":[{"line_number":3493,"context_line":"            return True"},{"line_number":3494,"context_line":""},{"line_number":3495,"context_line":"        if now is None:"},{"line_number":3496,"context_line":"            now \u003d time.time()"},{"line_number":3497,"context_line":"        # Convert seconds to milliseconds"},{"line_number":3498,"context_line":"        now \u003d now * self.clock_accuracy"},{"line_number":3499,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"a86260db_9ca0f4c3","line":3496,"updated":"2022-04-28 18:40:15.000000000","message":"nit: more consistent with surrounding style as:\n\n  now \u003d now or time.time()","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":3493,"context_line":"            return True"},{"line_number":3494,"context_line":""},{"line_number":3495,"context_line":"        if now is None:"},{"line_number":3496,"context_line":"            now \u003d time.time()"},{"line_number":3497,"context_line":"        # Convert seconds to milliseconds"},{"line_number":3498,"context_line":"        now \u003d now * self.clock_accuracy"},{"line_number":3499,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"df45a2da_f0fada90","line":3496,"in_reply_to":"a86260db_9ca0f4c3","updated":"2022-05-04 10:18:12.000000000","message":"Done","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":3504,"context_line":"        if now - self.running_time \u003e self.rate_buffer_ms:"},{"line_number":3505,"context_line":"            self.running_time \u003d now"},{"line_number":3506,"context_line":""},{"line_number":3507,"context_line":"        if now \u003e\u003d self.running_time:"},{"line_number":3508,"context_line":"            self.running_time +\u003d time_per_request"},{"line_number":3509,"context_line":"            allowed \u003d True"},{"line_number":3510,"context_line":"        elif block:"}],"source_content_type":"text/x-python","patch_set":4,"id":"dcf330e5_52db54bf","line":3507,"updated":"2022-05-04 10:18:12.000000000","message":"there\u0027s a subtle change here w.r.t. master ratelimit_sleep:\n\ncopying from my comment on patchset 1:\n\nthe implementation on master leads to \u0027bunching\u0027 behaviour as demonstrated by the test in test_slo:\n\n  * assume the max_rate is 1 per sec, running_time is initially 0\n  * a request made at say t\u003d99 is granted immediately and \n    running_time is set to 100\n  * a request at any time in the second preceding running_time, \n    including t\u003d99, would be granted without sleeping\n  * running time is incremented by 1 second to 101\n  * a next request at t\u003c100 would then sleep until 101\n  * running time is incremented by 1 second to 102\n  * a next request at 101 would be granted without sleeping\n  * running time is incremented by 1 second to 103\n  * a next request at 101.99 would sleep until 103\ne.g.\n\n  * requests made at    99, 99.01,  99.99, 101, 101.99 \n  * requests granted at 99, 99.01, 101,    101, 103\nThe change here means that for the same requests:\n\n  * requests made at    99,  99.01, 100, 101, 102 \n  * requests granted at 99, 100,    101, 102, 103","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":3525,"context_line":""},{"line_number":3526,"context_line":"    def __lt__(self, other):"},{"line_number":3527,"context_line":"        # used to sort RateLimiters by readiness"},{"line_number":3528,"context_line":"        if isinstance(other, RateLimiter):"},{"line_number":3529,"context_line":"            return self.running_time \u003c other.running_time"},{"line_number":3530,"context_line":"        return self.running_time \u003c other"},{"line_number":3531,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"0f0327d6_0066e9e9","line":3528,"range":{"start_line":3528,"start_character":29,"end_line":3528,"end_character":40},"updated":"2022-05-04 10:18:12.000000000","message":"should be AbstractRateLimiter - but method will be moved back to obj updater and fixed there","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fe6b40597dafd75d7240bfcca906f1bef021b7a4","unresolved":true,"context_lines":[{"line_number":3530,"context_line":"        return self.running_time \u003c other"},{"line_number":3531,"context_line":""},{"line_number":3532,"context_line":""},{"line_number":3533,"context_line":"class RateLimiter(AbstractRateLimiter):"},{"line_number":3534,"context_line":"    def __init__(self, max_rate, rate_buffer\u003d5, running_time\u003d0):"},{"line_number":3535,"context_line":"        super(RateLimiter, self).__init__(max_rate, rate_buffer, running_time)"},{"line_number":3536,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"8d374ff2_46f46868","line":3533,"updated":"2022-04-28 18:40:15.000000000","message":"could even be called EventletRateLimiter","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":3530,"context_line":"        return self.running_time \u003c other"},{"line_number":3531,"context_line":""},{"line_number":3532,"context_line":""},{"line_number":3533,"context_line":"class RateLimiter(AbstractRateLimiter):"},{"line_number":3534,"context_line":"    def __init__(self, max_rate, rate_buffer\u003d5, running_time\u003d0):"},{"line_number":3535,"context_line":"        super(RateLimiter, self).__init__(max_rate, rate_buffer, running_time)"},{"line_number":3536,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"788846f2_ce8add5a","line":3533,"in_reply_to":"8d374ff2_46f46868","updated":"2022-05-04 10:18:12.000000000","message":"Done","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fe6b40597dafd75d7240bfcca906f1bef021b7a4","unresolved":true,"context_lines":[{"line_number":3565,"context_line":"    warnings.warn("},{"line_number":3566,"context_line":"        \u0027ratelimit_sleep() is deprecated; use the ``RateLimiter`` class \u0027"},{"line_number":3567,"context_line":"        \u0027instead.\u0027, DeprecationWarning"},{"line_number":3568,"context_line":"    )"},{"line_number":3569,"context_line":"    rate_limit \u003d RateLimiter(max_rate, rate_buffer\u003drate_buffer,"},{"line_number":3570,"context_line":"                             running_time\u003drunning_time)"},{"line_number":3571,"context_line":"    rate_limit.wait(incr_by\u003dincr_by)"}],"source_content_type":"text/x-python","patch_set":4,"id":"64744b0b_19acc978","line":3568,"updated":"2022-04-28 18:40:15.000000000","message":"We leave this in place for out-of-tree consumers; it appears you updated all in-tree callers.","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":3565,"context_line":"    warnings.warn("},{"line_number":3566,"context_line":"        \u0027ratelimit_sleep() is deprecated; use the ``RateLimiter`` class \u0027"},{"line_number":3567,"context_line":"        \u0027instead.\u0027, DeprecationWarning"},{"line_number":3568,"context_line":"    )"},{"line_number":3569,"context_line":"    rate_limit \u003d RateLimiter(max_rate, rate_buffer\u003drate_buffer,"},{"line_number":3570,"context_line":"                             running_time\u003drunning_time)"},{"line_number":3571,"context_line":"    rate_limit.wait(incr_by\u003dincr_by)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3432c8a3_76f88ec1","line":3568,"in_reply_to":"64744b0b_19acc978","updated":"2022-05-04 10:18:12.000000000","message":"Ack","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"}],"swift/obj/auditor.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fe6b40597dafd75d7240bfcca906f1bef021b7a4","unresolved":true,"context_lines":[{"line_number":266,"context_line":"                    for chunk in reader:"},{"line_number":267,"context_line":"                        chunk_len \u003d len(chunk)"},{"line_number":268,"context_line":"                        self.bytes_rate_limiter.is_allowed("},{"line_number":269,"context_line":"                            incr_by\u003dchunk_len, block\u003dTrue)"},{"line_number":270,"context_line":"                        self.bytes_processed +\u003d chunk_len"},{"line_number":271,"context_line":"                        self.total_bytes_processed +\u003d chunk_len"},{"line_number":272,"context_line":"            for watcher in self.watchers:"}],"source_content_type":"text/x-python","patch_set":4,"id":"a396437d_ee03a197","line":269,"updated":"2022-04-28 18:40:15.000000000","message":"not obvious why we\u0027re not using wait","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":266,"context_line":"                    for chunk in reader:"},{"line_number":267,"context_line":"                        chunk_len \u003d len(chunk)"},{"line_number":268,"context_line":"                        self.bytes_rate_limiter.is_allowed("},{"line_number":269,"context_line":"                            incr_by\u003dchunk_len, block\u003dTrue)"},{"line_number":270,"context_line":"                        self.bytes_processed +\u003d chunk_len"},{"line_number":271,"context_line":"                        self.total_bytes_processed +\u003d chunk_len"},{"line_number":272,"context_line":"            for watcher in self.watchers:"}],"source_content_type":"text/x-python","patch_set":4,"id":"0745f129_a65a11bf","line":269,"in_reply_to":"a396437d_ee03a197","updated":"2022-05-04 10:18:12.000000000","message":"Done","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"}],"swift/obj/updater.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fe6b40597dafd75d7240bfcca906f1bef021b7a4","unresolved":true,"context_lines":[{"line_number":66,"context_line":"        if isinstance(other, RateLimiterBucket):"},{"line_number":67,"context_line":"            return self.wait_until \u003c other.wait_until"},{"line_number":68,"context_line":"        return self.wait_until \u003c other"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"class BucketizedUpdateSkippingLimiter(object):"},{"line_number":72,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":4,"id":"2155fcee_cc0f67f2","side":"PARENT","line":69,"updated":"2022-04-28 18:40:15.000000000","message":"if we\u0027re going to subclass anyway; maybe we can leave the \"sortability\" of Ratelimiters to the implementation here - in the context where it\u0027s used","commit_id":"954032d5d245411e676a5722b7e581c97a0aaaf7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":66,"context_line":"        if isinstance(other, RateLimiterBucket):"},{"line_number":67,"context_line":"            return self.wait_until \u003c other.wait_until"},{"line_number":68,"context_line":"        return self.wait_until \u003c other"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"class BucketizedUpdateSkippingLimiter(object):"},{"line_number":72,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":4,"id":"d1047c94_1ca5cbe6","side":"PARENT","line":69,"in_reply_to":"2155fcee_cc0f67f2","updated":"2022-05-04 10:18:12.000000000","message":"I agree, will move the comparator back to this subclass - we can move it up later if required in other use cases","commit_id":"954032d5d245411e676a5722b7e581c97a0aaaf7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fe6b40597dafd75d7240bfcca906f1bef021b7a4","unresolved":true,"context_lines":[{"line_number":142,"context_line":"        for update_ctx in self.iterator:"},{"line_number":143,"context_line":"            bucket \u003d self.buckets[self._bucket_key(update_ctx[\u0027update\u0027])]"},{"line_number":144,"context_line":"            now \u003d self._get_time()"},{"line_number":145,"context_line":"            if bucket.is_allowed(now\u003dnow):"},{"line_number":146,"context_line":"                # no need to ratelimit, just return next update"},{"line_number":147,"context_line":"                return update_ctx"},{"line_number":148,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"4ea0b307_d833caab","line":145,"updated":"2022-04-28 18:40:15.000000000","message":"so is_allowed is block\u003dFalse by default","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":142,"context_line":"        for update_ctx in self.iterator:"},{"line_number":143,"context_line":"            bucket \u003d self.buckets[self._bucket_key(update_ctx[\u0027update\u0027])]"},{"line_number":144,"context_line":"            now \u003d self._get_time()"},{"line_number":145,"context_line":"            if bucket.is_allowed(now\u003dnow):"},{"line_number":146,"context_line":"                # no need to ratelimit, just return next update"},{"line_number":147,"context_line":"                return update_ctx"},{"line_number":148,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"40ca7574_aa511266","line":145,"in_reply_to":"4ea0b307_d833caab","updated":"2022-05-04 10:18:12.000000000","message":"Ack","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fe6b40597dafd75d7240bfcca906f1bef021b7a4","unresolved":true,"context_lines":[{"line_number":162,"context_line":"                # to the queue of deferred buckets"},{"line_number":163,"context_line":"                # note: buckets may have multiple entries in deferred_buckets,"},{"line_number":164,"context_line":"                # one for each deferred update in that particular bucket"},{"line_number":165,"context_line":"                bucket.deque.append(update_ctx)"},{"line_number":166,"context_line":"                self.deferred_buckets.append(bucket)"},{"line_number":167,"context_line":"            else:"},{"line_number":168,"context_line":"                self.stats.skips +\u003d 1"}],"source_content_type":"text/x-python","patch_set":4,"id":"6942fe23_16acbdb3","line":165,"updated":"2022-04-28 18:40:15.000000000","message":"oic, we just reach stright into that bucket/ratelimiter and grab it\u0027s deque","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":162,"context_line":"                # to the queue of deferred buckets"},{"line_number":163,"context_line":"                # note: buckets may have multiple entries in deferred_buckets,"},{"line_number":164,"context_line":"                # one for each deferred update in that particular bucket"},{"line_number":165,"context_line":"                bucket.deque.append(update_ctx)"},{"line_number":166,"context_line":"                self.deferred_buckets.append(bucket)"},{"line_number":167,"context_line":"            else:"},{"line_number":168,"context_line":"                self.stats.skips +\u003d 1"}],"source_content_type":"text/x-python","patch_set":4,"id":"0ac90cf0_7db5b546","line":165,"in_reply_to":"6942fe23_16acbdb3","updated":"2022-05-04 10:18:12.000000000","message":"Ack","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"120c285fd93d56d6601e473658068558a36d2375","unresolved":true,"context_lines":[{"line_number":52,"context_line":"    \"\"\""},{"line_number":53,"context_line":"    def __init__(self, max_updates_per_second):"},{"line_number":54,"context_line":"        super(RateLimiterBucket, self).__init__(max_updates_per_second,"},{"line_number":55,"context_line":"                                                rate_buffer\u003d0)"},{"line_number":56,"context_line":"        self.deque \u003d deque()"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    def __len__(self):"}],"source_content_type":"text/x-python","patch_set":5,"id":"63a26af3_50f4d39f","line":55,"updated":"2022-05-16 19:25:57.000000000","message":"it looks like there\u0027s some minor test churn if we use the default rate_buffer here\n\n... I wonder what is the ideal rate_buffer for this use-case","commit_id":"5227cb702b744bbe9aaecfff002604be45f64a8c"}],"test/unit/common/middleware/test_slo.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fe6b40597dafd75d7240bfcca906f1bef021b7a4","unresolved":true,"context_lines":[{"line_number":2458,"context_line":"            status, headers, body \u003d self.call_slo(req)"},{"line_number":2459,"context_line":""},{"line_number":2460,"context_line":"        self.assertEqual(status, \u0027200 OK\u0027)  # sanity check"},{"line_number":2461,"context_line":"        self.assertEqual(sleeps, [1.0] * 6)"},{"line_number":2462,"context_line":""},{"line_number":2463,"context_line":"    def test_get_manifest_with_submanifest(self):"},{"line_number":2464,"context_line":"        req \u003d Request.blank("}],"source_content_type":"text/x-python","patch_set":4,"id":"e1a7d27f_79b50bba","line":2461,"updated":"2022-04-28 18:40:15.000000000","message":"i mean... this assertions are obviously different\n\ndo we have any reason to believe the old expecations were wrong?","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":2458,"context_line":"            status, headers, body \u003d self.call_slo(req)"},{"line_number":2459,"context_line":""},{"line_number":2460,"context_line":"        self.assertEqual(status, \u0027200 OK\u0027)  # sanity check"},{"line_number":2461,"context_line":"        self.assertEqual(sleeps, [1.0] * 6)"},{"line_number":2462,"context_line":""},{"line_number":2463,"context_line":"    def test_get_manifest_with_submanifest(self):"},{"line_number":2464,"context_line":"        req \u003d Request.blank("}],"source_content_type":"text/x-python","patch_set":4,"id":"58c96a7f_35cb3283","line":2461,"in_reply_to":"e1a7d27f_79b50bba","updated":"2022-05-04 10:18:12.000000000","message":"ah, I left a comment on patchset 1 about this but it has been lost in time...I re-commented in utils.\n\nThe implementation on master would bunch allowed requests into pairs and sleep between pairs, and these slo tests are the only place it was seen and *asserted as correct*. So on this line - why were there only 3 sleeps when 7 requests were being ratelimited? and why was each sleep 2 seconds for a default rate_limit_segments_per_sec of 1? A: because on master the ratelimiting allows 2 requests through before then sleeping for 2 seconds!\n\nAdmittedly, the change I have made contradicts my claim that this patch is pure refactoring :/  I will update the commit message, but I can break out the fix into a follow-on if we feel that would be better.","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"}],"test/unit/common/test_utils.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fe8a9654c9be251917ee03021727eb24e73030c3","unresolved":true,"context_lines":[{"line_number":5953,"context_line":"        grant_times \u003d self._do_test(1, 1, 3, 3)"},{"line_number":5954,"context_line":"        self.assertEqual([3, 3, 3, 4, 5], grant_times)"},{"line_number":5955,"context_line":""},{"line_number":5956,"context_line":"        grant_times \u003d self._do_test(1, 0, 4, 3)"},{"line_number":5957,"context_line":"        self.assertEqual([4, 5, 6, 7, 8], grant_times)"},{"line_number":5958,"context_line":""},{"line_number":5959,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"4741cba2_4bd82408","line":5956,"range":{"start_line":5956,"start_character":39,"end_line":5956,"end_character":47},"updated":"2022-04-01 03:44:17.000000000","message":"OK so when difference between the running time and the start time is better then the rate buffer then the rate buffer is reset. And we can also see that as the rate_time builds up in the first few do_tests.","commit_id":"6505b050563e2aebf235dcfdfe384ee75d22378d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b640462b9284b36a655163074bff03a973e86d59","unresolved":false,"context_lines":[{"line_number":5953,"context_line":"        grant_times \u003d self._do_test(1, 1, 3, 3)"},{"line_number":5954,"context_line":"        self.assertEqual([3, 3, 3, 4, 5], grant_times)"},{"line_number":5955,"context_line":""},{"line_number":5956,"context_line":"        grant_times \u003d self._do_test(1, 0, 4, 3)"},{"line_number":5957,"context_line":"        self.assertEqual([4, 5, 6, 7, 8], grant_times)"},{"line_number":5958,"context_line":""},{"line_number":5959,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"bcf11ceb_dc31e69a","line":5956,"range":{"start_line":5956,"start_character":39,"end_line":5956,"end_character":47},"in_reply_to":"4741cba2_4bd82408","updated":"2022-04-04 09:11:45.000000000","message":"Ack","commit_id":"6505b050563e2aebf235dcfdfe384ee75d22378d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fe6b40597dafd75d7240bfcca906f1bef021b7a4","unresolved":true,"context_lines":[{"line_number":5906,"context_line":"            return current_time[0]"},{"line_number":5907,"context_line":""},{"line_number":5908,"context_line":"        def mock_sleep(duration):"},{"line_number":5909,"context_line":"            current_time[0] +\u003d duration"},{"line_number":5910,"context_line":""},{"line_number":5911,"context_line":"        with patch(\u0027time.time\u0027, mock_time):"},{"line_number":5912,"context_line":"            with patch(\u0027eventlet.sleep\u0027, mock_sleep):"}],"source_content_type":"text/x-python","patch_set":4,"id":"9e4df7c0_2c9019ff","line":5909,"updated":"2022-04-28 18:40:15.000000000","message":"nonlocal will be so great","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":5906,"context_line":"            return current_time[0]"},{"line_number":5907,"context_line":""},{"line_number":5908,"context_line":"        def mock_sleep(duration):"},{"line_number":5909,"context_line":"            current_time[0] +\u003d duration"},{"line_number":5910,"context_line":""},{"line_number":5911,"context_line":"        with patch(\u0027time.time\u0027, mock_time):"},{"line_number":5912,"context_line":"            with patch(\u0027eventlet.sleep\u0027, mock_sleep):"}],"source_content_type":"text/x-python","patch_set":4,"id":"50fa93f1_440cd0c5","line":5909,"in_reply_to":"9e4df7c0_2c9019ff","updated":"2022-05-04 10:18:12.000000000","message":"+1","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"}],"test/unit/obj/test_updater.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fe6b40597dafd75d7240bfcca906f1bef021b7a4","unresolved":true,"context_lines":[{"line_number":2157,"context_line":"        b1.last_time \u003d next(time_iter)"},{"line_number":2158,"context_line":"        buckets.put(b1)"},{"line_number":2159,"context_line":"        buckets.put(b2)"},{"line_number":2160,"context_line":"        self.assertEqual([b2, b1], [buckets.get_nowait() for _ in range(2)])"},{"line_number":2161,"context_line":""},{"line_number":2162,"context_line":""},{"line_number":2163,"context_line":"class TestSweepStats(unittest.TestCase):"}],"source_content_type":"text/x-python","patch_set":4,"id":"71e9d3fb_109bbf72","side":"PARENT","line":2160,"updated":"2022-04-28 18:40:15.000000000","message":"i guess these tests moved over to utils","commit_id":"954032d5d245411e676a5722b7e581c97a0aaaf7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":2157,"context_line":"        b1.last_time \u003d next(time_iter)"},{"line_number":2158,"context_line":"        buckets.put(b1)"},{"line_number":2159,"context_line":"        buckets.put(b2)"},{"line_number":2160,"context_line":"        self.assertEqual([b2, b1], [buckets.get_nowait() for _ in range(2)])"},{"line_number":2161,"context_line":""},{"line_number":2162,"context_line":""},{"line_number":2163,"context_line":"class TestSweepStats(unittest.TestCase):"}],"source_content_type":"text/x-python","patch_set":4,"id":"043c7ca1_cf34dbf5","side":"PARENT","line":2160,"in_reply_to":"71e9d3fb_109bbf72","updated":"2022-05-04 10:18:12.000000000","message":"but now test_bucket_ordering is moving back :)","commit_id":"954032d5d245411e676a5722b7e581c97a0aaaf7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fe6b40597dafd75d7240bfcca906f1bef021b7a4","unresolved":true,"context_lines":[{"line_number":1906,"context_line":"        it \u003d object_updater.BucketizedUpdateSkippingLimiter("},{"line_number":1907,"context_line":"            [3, 1], self.logger, self.stats, 1000, 10)"},{"line_number":1908,"context_line":"        self.assertEqual(1000, it.num_buckets)"},{"line_number":1909,"context_line":"        self.assertEqual(10, it.buckets[0].max_rate)"},{"line_number":1910,"context_line":"        self.assertEqual([3, 1], [x for x in it.iterator])"},{"line_number":1911,"context_line":""},{"line_number":1912,"context_line":"        # rate of 0 implies unlimited"}],"source_content_type":"text/x-python","patch_set":4,"id":"cb806d46_603dbf6d","line":1909,"updated":"2022-04-28 18:40:15.000000000","message":"maybe more obvoius as:\n\n  diff --git a/test/unit/obj/test_updater.py b/test/unit/obj/test_updater.py\n  index ced80ebb6..9ecf5068a 100644\n  --- a/test/unit/obj/test_updater.py\n  +++ b/test/unit/obj/test_updater.py\n  @@ -1906,21 +1906,21 @@ class TestBucketizedUpdateSkippingLimiter(unittest.TestCase):\n           it \u003d object_updater.BucketizedUpdateSkippingLimiter(\n               [3, 1], self.logger, self.stats, 1000, 10)\n           self.assertEqual(1000, it.num_buckets)\n  -        self.assertEqual(10, it.buckets[0].max_rate)\n  +        self.assertEqual([10] * 1000, [b.max_rate for b in it.buckets])\n           self.assertEqual([3, 1], [x for x in it.iterator])\n   \n           # rate of 0 implies unlimited\n           it \u003d object_updater.BucketizedUpdateSkippingLimiter(\n               iter([3, 1]), self.logger, self.stats, 9, 0)\n           self.assertEqual(9, it.num_buckets)\n  -        self.assertEqual(0, it.buckets[0].max_rate)\n  +        self.assertEqual([0] * 9, [b.max_rate for b in it.buckets])\n           self.assertEqual([3, 1], [x for x in it.iterator])\n   \n           # num_buckets is collared at 1\n           it \u003d object_updater.BucketizedUpdateSkippingLimiter(\n               iter([3, 1]), self.logger, self.stats, 0, 1)\n           self.assertEqual(1, it.num_buckets)\n  -        self.assertEqual(1, it.buckets[0].max_rate)\n  +        self.assertEqual([1] * 1, [b.max_rate for b in it.buckets])\n           self.assertEqual([3, 1], [x for x in it.iterator])\n   \n       def test_iteration_unlimited(self):","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"017125a93e6e0e64a985108eac37fabbcd7e1f7f","unresolved":false,"context_lines":[{"line_number":1906,"context_line":"        it \u003d object_updater.BucketizedUpdateSkippingLimiter("},{"line_number":1907,"context_line":"            [3, 1], self.logger, self.stats, 1000, 10)"},{"line_number":1908,"context_line":"        self.assertEqual(1000, it.num_buckets)"},{"line_number":1909,"context_line":"        self.assertEqual(10, it.buckets[0].max_rate)"},{"line_number":1910,"context_line":"        self.assertEqual([3, 1], [x for x in it.iterator])"},{"line_number":1911,"context_line":""},{"line_number":1912,"context_line":"        # rate of 0 implies unlimited"}],"source_content_type":"text/x-python","patch_set":4,"id":"f2f31870_fc674d84","line":1909,"in_reply_to":"cb806d46_603dbf6d","updated":"2022-05-04 10:18:12.000000000","message":"Done","commit_id":"fea3690da6296d30b2999ccdc90dbefb0ce3eb2d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"120c285fd93d56d6601e473658068558a36d2375","unresolved":true,"context_lines":[{"line_number":1862,"context_line":"            [[ctx[\u0027update\u0027][\u0027obj\u0027] for ctx in q] for q in captured_queues])"},{"line_number":1863,"context_line":"        actual_sleeps \u003d [call[0][0] for call in mock_sleep.call_args_list]"},{"line_number":1864,"context_line":"        self.assertEqual(2, len(actual_sleeps))"},{"line_number":1865,"context_line":"        self.assertAlmostEqual(0.1, actual_sleeps[0], 3)"},{"line_number":1866,"context_line":"        self.assertAlmostEqual(0.1, actual_sleeps[1], 3)"},{"line_number":1867,"context_line":"        info_lines \u003d self.logger.get_lines_for_level(\u0027info\u0027)"},{"line_number":1868,"context_line":"        self.assertTrue(info_lines)"}],"source_content_type":"text/x-python","patch_set":5,"id":"b7c56f43_15807cea","line":1865,"updated":"2022-05-16 19:25:57.000000000","message":"E       AssertionError: 0.1 !\u003d 0.089 within 3 places (0.01100000000000001 difference)\n\n^ this pops if I use the default rate_buffer","commit_id":"5227cb702b744bbe9aaecfff002604be45f64a8c"}]}
