)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"c48ca048_15628456","updated":"2022-05-20 13:25:28.000000000","message":"@Clay superb review thank you, I will squash in your follow ups","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"f48d71ca_805e6e4b","updated":"2022-05-19 20:19:50.000000000","message":"I think we want rate_buffer to get reloaded too:\n\nhttps://review.opendev.org/c/openstack/swift/+/842617\n\nbut in principle this change looks great!  There was a couple of tests that I thought were a little dense; one of them I think could maybe get pulled apart:\n\nhttps://review.opendev.org/c/openstack/swift/+/842616","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cc970dbfad04d38c5def239b98e2ad4b54b5b75a","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"9fc77296_109d6a45","updated":"2022-05-20 16:37:02.000000000","message":"this addresses all of my concerns, thanks for squashing in those ideas.","commit_id":"7730d4806c4dc4bb9a5a630f2f84e05229a6d726"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"fd9eb7a6de9aedfb533b360baa8b6ffacc8323cc","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"8aa2a9d6_a5e636a6","updated":"2023-05-23 23:07:30.000000000","message":"`_apply_config` feels a little... wordy? I took a stab at reworking it in https://review.opendev.org/c/openstack/swift/+/883984\n\nI\u0027m torn about how much of a fuss to make of the behavior when configuring `config_reload_interval` but not `backend_ratelimit_conf_path` -- it\u0027s a little weird (to me), but I think we\u0027ve done a decent job steering people toward the external conf now.","commit_id":"08ab90e0d1dabd6c738ee80abf8cb54c86a2f13b"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"06f3e6006231011b929cc3b21b726ed032503fce","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"0c9005d9_873d5061","updated":"2023-05-02 00:43:59.000000000","message":"rebased","commit_id":"08ab90e0d1dabd6c738ee80abf8cb54c86a2f13b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"3364601fdd90d2d7dafab6a938f393d8b5b14262","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":10,"id":"0662ee9c_bcef437c","updated":"2024-05-11 18:08:49.000000000","message":"recheck\n\nFailure collecting logs.","commit_id":"e9abfd76ee5ef94a51b2dbe5a758432cfeeab8e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f89e5f9ae6fe143544a34ff88156e4ad9c4f7a10","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":10,"id":"9d504752_7f25fbac","updated":"2024-05-10 23:06:08.000000000","message":"the automatic config reloading is working well for us in prod and helping!","commit_id":"e9abfd76ee5ef94a51b2dbe5a758432cfeeab8e9"}],"etc/backend-ratelimit.conf-sample":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":7,"context_line":"#"},{"line_number":8,"context_line":"# Set the number of seconds of unused rate-limiting allowance that can"},{"line_number":9,"context_line":"# accumulate and be used to allow a subsequent burst of requests."},{"line_number":10,"context_line":"# requests_per_device_rate_buffer \u003d 1.0"}],"source_content_type":"application/octet-stream","patch_set":4,"id":"08eb9017_8e54e664","line":10,"updated":"2022-05-19 20:19:50.000000000","message":"does it tho?","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":false,"context_lines":[{"line_number":7,"context_line":"#"},{"line_number":8,"context_line":"# Set the number of seconds of unused rate-limiting allowance that can"},{"line_number":9,"context_line":"# accumulate and be used to allow a subsequent burst of requests."},{"line_number":10,"context_line":"# requests_per_device_rate_buffer \u003d 1.0"}],"source_content_type":"application/octet-stream","patch_set":4,"id":"a467d54f_674268a6","line":10,"in_reply_to":"08eb9017_8e54e664","updated":"2022-05-20 13:25:28.000000000","message":"Done","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"}],"swift/common/middleware/backend_ratelimit.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":42,"context_line":"    \"\"\""},{"line_number":43,"context_line":"    def __init__(self, app, filter_conf, logger\u003dNone):"},{"line_number":44,"context_line":"        self.app \u003d app"},{"line_number":45,"context_line":"        self.filter_conf \u003d filter_conf"},{"line_number":46,"context_line":"        self.current_conf \u003d {}"},{"line_number":47,"context_line":"        self.logger \u003d logger or get_logger(self.filter_conf,"},{"line_number":48,"context_line":"                                           log_route\u003d\u0027backend_ratelimit\u0027)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3b1f35bc_d7571f11","line":45,"updated":"2022-05-19 20:19:50.000000000","message":"good call on the rename; keeps thing sane","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":false,"context_lines":[{"line_number":42,"context_line":"    \"\"\""},{"line_number":43,"context_line":"    def __init__(self, app, filter_conf, logger\u003dNone):"},{"line_number":44,"context_line":"        self.app \u003d app"},{"line_number":45,"context_line":"        self.filter_conf \u003d filter_conf"},{"line_number":46,"context_line":"        self.current_conf \u003d {}"},{"line_number":47,"context_line":"        self.logger \u003d logger or get_logger(self.filter_conf,"},{"line_number":48,"context_line":"                                           log_route\u003d\u0027backend_ratelimit\u0027)"}],"source_content_type":"text/x-python","patch_set":4,"id":"7e5933bf_cac6132f","line":45,"in_reply_to":"3b1f35bc_d7571f11","updated":"2022-05-20 13:25:28.000000000","message":"Ack","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":72,"context_line":""},{"line_number":73,"context_line":"    def _refresh_ratelimiters(self):"},{"line_number":74,"context_line":"        for dev, rl in self.rate_limiters.items():"},{"line_number":75,"context_line":"            rl.set_max_rate(self.requests_per_device_per_second)"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def _apply_config(self, conf):"},{"line_number":78,"context_line":"        self.current_conf \u003d conf"}],"source_content_type":"text/x-python","patch_set":4,"id":"97b2d28a_707e9542","line":75,"updated":"2022-05-19 20:19:50.000000000","message":"don\u0027t the ratelimiters need the new rate_buffer value?","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":false,"context_lines":[{"line_number":72,"context_line":""},{"line_number":73,"context_line":"    def _refresh_ratelimiters(self):"},{"line_number":74,"context_line":"        for dev, rl in self.rate_limiters.items():"},{"line_number":75,"context_line":"            rl.set_max_rate(self.requests_per_device_per_second)"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def _apply_config(self, conf):"},{"line_number":78,"context_line":"        self.current_conf \u003d conf"}],"source_content_type":"text/x-python","patch_set":4,"id":"a7e18f4e_34723f24","line":75,"in_reply_to":"97b2d28a_707e9542","updated":"2022-05-20 13:25:28.000000000","message":"eeek! thanks","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":93,"context_line":"            new_conf.update("},{"line_number":94,"context_line":"                readconf(self.conf_path, BACKEND_RATELIMIT_CONFIG_SECTION))"},{"line_number":95,"context_line":"            if new_conf \u003d\u003d self.current_conf:"},{"line_number":96,"context_line":"                self.logger.debug(\u0027Loaded conf file: config unchanged\u0027)"},{"line_number":97,"context_line":"            else:"},{"line_number":98,"context_line":"                self._apply_config(new_conf)"},{"line_number":99,"context_line":"                self.logger.debug(\u0027Loaded conf file: config changed\u0027)"}],"source_content_type":"text/x-python","patch_set":4,"id":"b0e08bdc_b161ee46","line":96,"updated":"2022-05-19 20:19:50.000000000","message":"i don\u0027t trust this equality check or log message\n\nit seems like the literal config could change in such a way that says \"config changed\" but there\u0027s no effective difference applied (e.g. when you put config_reload_interval in your backend_ratelimit_conf_path)","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":false,"context_lines":[{"line_number":93,"context_line":"            new_conf.update("},{"line_number":94,"context_line":"                readconf(self.conf_path, BACKEND_RATELIMIT_CONFIG_SECTION))"},{"line_number":95,"context_line":"            if new_conf \u003d\u003d self.current_conf:"},{"line_number":96,"context_line":"                self.logger.debug(\u0027Loaded conf file: config unchanged\u0027)"},{"line_number":97,"context_line":"            else:"},{"line_number":98,"context_line":"                self._apply_config(new_conf)"},{"line_number":99,"context_line":"                self.logger.debug(\u0027Loaded conf file: config changed\u0027)"}],"source_content_type":"text/x-python","patch_set":4,"id":"53e01a42_a0a2beac","line":96,"in_reply_to":"b0e08bdc_b161ee46","updated":"2022-05-20 13:25:28.000000000","message":"good point, will fix\n\nI also think it might be useful to log at info level when the config does change","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cc970dbfad04d38c5def239b98e2ad4b54b5b75a","unresolved":true,"context_lines":[{"line_number":78,"context_line":"        # also be overridden by options in a separate config file..."},{"line_number":79,"context_line":"        self._last_config_reload_attempt \u003d time.time()"},{"line_number":80,"context_line":"        self._apply_config(self.filter_conf)"},{"line_number":81,"context_line":"        self._load_config_file(warn_if_missing\u003dconf_path_set)"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"    def _refresh_ratelimiters(self):"},{"line_number":84,"context_line":"        for dev, rl in self.rate_limiters.items():"}],"source_content_type":"text/x-python","patch_set":5,"id":"b97bfc24_e20f8c00","line":81,"updated":"2022-05-20 16:37:02.000000000","message":"here the warning is conditional","commit_id":"7730d4806c4dc4bb9a5a630f2f84e05229a6d726"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f78b83311d77c127dbcd3433ead94a549c148c44","unresolved":false,"context_lines":[{"line_number":78,"context_line":"        # also be overridden by options in a separate config file..."},{"line_number":79,"context_line":"        self._last_config_reload_attempt \u003d time.time()"},{"line_number":80,"context_line":"        self._apply_config(self.filter_conf)"},{"line_number":81,"context_line":"        self._load_config_file(warn_if_missing\u003dconf_path_set)"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"    def _refresh_ratelimiters(self):"},{"line_number":84,"context_line":"        for dev, rl in self.rate_limiters.items():"}],"source_content_type":"text/x-python","patch_set":5,"id":"58527022_893fba75","line":81,"in_reply_to":"b97bfc24_e20f8c00","updated":"2024-03-14 10:15:37.000000000","message":"yes, the idea is that there\u0027s only a warning if you set the value but the file isn\u0027t found, and there\u0027s only at warning start-up","commit_id":"7730d4806c4dc4bb9a5a630f2f84e05229a6d726"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cc970dbfad04d38c5def239b98e2ad4b54b5b75a","unresolved":true,"context_lines":[{"line_number":134,"context_line":"            if (now - self._last_config_reload_attempt"},{"line_number":135,"context_line":"                    \u003e\u003d self.config_reload_interval):"},{"line_number":136,"context_line":"                try:"},{"line_number":137,"context_line":"                    self._load_config_file()"},{"line_number":138,"context_line":"                except Exception:  # noqa"},{"line_number":139,"context_line":"                    self.logger.exception(\u0027Error reloading config file\u0027)"},{"line_number":140,"context_line":"                finally:"}],"source_content_type":"text/x-python","patch_set":5,"id":"a88c6948_434856d5","line":137,"updated":"2022-05-20 16:37:02.000000000","message":"but we don\u0027t warn if the config \"goes away\"","commit_id":"7730d4806c4dc4bb9a5a630f2f84e05229a6d726"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f78b83311d77c127dbcd3433ead94a549c148c44","unresolved":false,"context_lines":[{"line_number":134,"context_line":"            if (now - self._last_config_reload_attempt"},{"line_number":135,"context_line":"                    \u003e\u003d self.config_reload_interval):"},{"line_number":136,"context_line":"                try:"},{"line_number":137,"context_line":"                    self._load_config_file()"},{"line_number":138,"context_line":"                except Exception:  # noqa"},{"line_number":139,"context_line":"                    self.logger.exception(\u0027Error reloading config file\u0027)"},{"line_number":140,"context_line":"                finally:"}],"source_content_type":"text/x-python","patch_set":5,"id":"52d861e0_7050cbb0","line":137,"in_reply_to":"a88c6948_434856d5","updated":"2024-03-14 10:15:37.000000000","message":"fixing this to warn when config file first goes away, then log at info when  it first comes back","commit_id":"7730d4806c4dc4bb9a5a630f2f84e05229a6d726"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"fd9eb7a6de9aedfb533b360baa8b6ffacc8323cc","unresolved":true,"context_lines":[{"line_number":71,"context_line":"            self.conf_path \u003d default_conf_path"},{"line_number":72,"context_line":"            conf_path_set \u003d False"},{"line_number":73,"context_line":"        self.config_reload_interval \u003d non_negative_float("},{"line_number":74,"context_line":"            filter_conf.get(\u0027config_reload_interval\u0027,"},{"line_number":75,"context_line":"                            DEFAULT_CONFIG_RELOAD_INTERVAL))"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"        # other conf options are read from filter section at startup but may"}],"source_content_type":"text/x-python","patch_set":7,"id":"d637e3b6_c79cbbc4","line":74,"range":{"start_line":74,"start_character":29,"end_line":74,"end_character":51},"updated":"2023-05-23 23:07:30.000000000","message":"What happens when `config_reload_interval` is configured, but `backend_ratelimit_conf_path` is _not_? As an operator used to the old config-in-filter-section mode, I\u0027d kinda expect that the filter section would be re-read, but it looks like we go quietly looking at the default path instead -- maybe we could at least have an explicit note about how any filter-section configs *won\u0027t* be reloaded?","commit_id":"08ab90e0d1dabd6c738ee80abf8cb54c86a2f13b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f78b83311d77c127dbcd3433ead94a549c148c44","unresolved":false,"context_lines":[{"line_number":71,"context_line":"            self.conf_path \u003d default_conf_path"},{"line_number":72,"context_line":"            conf_path_set \u003d False"},{"line_number":73,"context_line":"        self.config_reload_interval \u003d non_negative_float("},{"line_number":74,"context_line":"            filter_conf.get(\u0027config_reload_interval\u0027,"},{"line_number":75,"context_line":"                            DEFAULT_CONFIG_RELOAD_INTERVAL))"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"        # other conf options are read from filter section at startup but may"}],"source_content_type":"text/x-python","patch_set":7,"id":"ed2995fc_b9681329","line":74,"range":{"start_line":74,"start_character":29,"end_line":74,"end_character":51},"in_reply_to":"d637e3b6_c79cbbc4","updated":"2024-03-14 10:15:37.000000000","message":"Added a note - the filter conf is never reloaded","commit_id":"08ab90e0d1dabd6c738ee80abf8cb54c86a2f13b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"fd9eb7a6de9aedfb533b360baa8b6ffacc8323cc","unresolved":false,"context_lines":[{"line_number":83,"context_line":"    def _refresh_ratelimiters(self):"},{"line_number":84,"context_line":"        for dev, rl in self.rate_limiters.items():"},{"line_number":85,"context_line":"            rl.set_max_rate(self.requests_per_device_per_second)"},{"line_number":86,"context_line":"            rl.set_rate_buffer(self.requests_per_device_rate_buffer)"},{"line_number":87,"context_line":""},{"line_number":88,"context_line":"    def _apply_config(self, conf):"},{"line_number":89,"context_line":"        self.current_conf \u003d conf"}],"source_content_type":"text/x-python","patch_set":7,"id":"26be2f6a_0de927aa","line":86,"updated":"2023-05-23 23:07:30.000000000","message":"So this updates the already-instantiated limiters -- what if there\u0027s a device that hasn\u0027t gotten any requests yet? I guess it works out because the lambda delays the evaluation of `self.requests_per_device_per_second` and `self.requests_per_device_rate_buffer`.","commit_id":"08ab90e0d1dabd6c738ee80abf8cb54c86a2f13b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"fd9eb7a6de9aedfb533b360baa8b6ffacc8323cc","unresolved":true,"context_lines":[{"line_number":100,"context_line":"        if new_value !\u003d self.requests_per_device_rate_buffer:"},{"line_number":101,"context_line":"            self.requests_per_device_rate_buffer \u003d new_value"},{"line_number":102,"context_line":"            modified \u003d True"},{"line_number":103,"context_line":"        self._refresh_ratelimiters()"},{"line_number":104,"context_line":"        return modified"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    def _load_config_file(self, warn_if_missing\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":7,"id":"8dd4839d_67e7015d","line":103,"updated":"2023-05-23 23:07:30.000000000","message":"It feels weird that we do this even when `modified` (which we\u0027ve meticulously tracked) is False.","commit_id":"08ab90e0d1dabd6c738ee80abf8cb54c86a2f13b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f78b83311d77c127dbcd3433ead94a549c148c44","unresolved":false,"context_lines":[{"line_number":100,"context_line":"        if new_value !\u003d self.requests_per_device_rate_buffer:"},{"line_number":101,"context_line":"            self.requests_per_device_rate_buffer \u003d new_value"},{"line_number":102,"context_line":"            modified \u003d True"},{"line_number":103,"context_line":"        self._refresh_ratelimiters()"},{"line_number":104,"context_line":"        return modified"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    def _load_config_file(self, warn_if_missing\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":7,"id":"502569aa_ce879816","line":103,"in_reply_to":"8dd4839d_67e7015d","updated":"2024-03-14 10:15:37.000000000","message":"Done","commit_id":"08ab90e0d1dabd6c738ee80abf8cb54c86a2f13b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"fd9eb7a6de9aedfb533b360baa8b6ffacc8323cc","unresolved":true,"context_lines":[{"line_number":101,"context_line":"            self.requests_per_device_rate_buffer \u003d new_value"},{"line_number":102,"context_line":"            modified \u003d True"},{"line_number":103,"context_line":"        self._refresh_ratelimiters()"},{"line_number":104,"context_line":"        return modified"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    def _load_config_file(self, warn_if_missing\u003dFalse):"},{"line_number":107,"context_line":"        # If conf file can be read then apply its options to the filter conf"}],"source_content_type":"text/x-python","patch_set":7,"id":"e43f6789_c8cc5129","line":104,"updated":"2023-05-23 23:07:30.000000000","message":"So we return either... `True` or `[]`? Little odd...","commit_id":"08ab90e0d1dabd6c738ee80abf8cb54c86a2f13b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f78b83311d77c127dbcd3433ead94a549c148c44","unresolved":false,"context_lines":[{"line_number":101,"context_line":"            self.requests_per_device_rate_buffer \u003d new_value"},{"line_number":102,"context_line":"            modified \u003d True"},{"line_number":103,"context_line":"        self._refresh_ratelimiters()"},{"line_number":104,"context_line":"        return modified"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    def _load_config_file(self, warn_if_missing\u003dFalse):"},{"line_number":107,"context_line":"        # If conf file can be read then apply its options to the filter conf"}],"source_content_type":"text/x-python","patch_set":7,"id":"5374188a_fd4978b6","line":104,"in_reply_to":"e43f6789_c8cc5129","updated":"2024-03-14 10:15:37.000000000","message":"Done","commit_id":"08ab90e0d1dabd6c738ee80abf8cb54c86a2f13b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"fd9eb7a6de9aedfb533b360baa8b6ffacc8323cc","unresolved":true,"context_lines":[{"line_number":110,"context_line":"        # filter conf value or default value. If the conf file cannot be read"},{"line_number":111,"context_line":"        # or is invalid, then the current config is left unchanged."},{"line_number":112,"context_line":"        try:"},{"line_number":113,"context_line":"            new_conf \u003d dict(self.filter_conf)  # filter_conf not current_conf"},{"line_number":114,"context_line":"            new_conf.update("},{"line_number":115,"context_line":"                readconf(self.conf_path, BACKEND_RATELIMIT_CONFIG_SECTION))"},{"line_number":116,"context_line":"            modified \u003d self._apply_config(new_conf)"}],"source_content_type":"text/x-python","patch_set":7,"id":"a0b3880e_db7f895a","line":113,"updated":"2023-05-23 23:07:30.000000000","message":"Hmm... so the filter config is *not* reloaded; if you want to do _that_, you need to reload the whole service...","commit_id":"08ab90e0d1dabd6c738ee80abf8cb54c86a2f13b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f78b83311d77c127dbcd3433ead94a549c148c44","unresolved":false,"context_lines":[{"line_number":110,"context_line":"        # filter conf value or default value. If the conf file cannot be read"},{"line_number":111,"context_line":"        # or is invalid, then the current config is left unchanged."},{"line_number":112,"context_line":"        try:"},{"line_number":113,"context_line":"            new_conf \u003d dict(self.filter_conf)  # filter_conf not current_conf"},{"line_number":114,"context_line":"            new_conf.update("},{"line_number":115,"context_line":"                readconf(self.conf_path, BACKEND_RATELIMIT_CONFIG_SECTION))"},{"line_number":116,"context_line":"            modified \u003d self._apply_config(new_conf)"}],"source_content_type":"text/x-python","patch_set":7,"id":"099464ca_a1c33851","line":113,"in_reply_to":"a0b3880e_db7f895a","updated":"2024-03-14 10:15:37.000000000","message":"Acknowledged","commit_id":"08ab90e0d1dabd6c738ee80abf8cb54c86a2f13b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"fd9eb7a6de9aedfb533b360baa8b6ffacc8323cc","unresolved":true,"context_lines":[{"line_number":112,"context_line":"        try:"},{"line_number":113,"context_line":"            new_conf \u003d dict(self.filter_conf)  # filter_conf not current_conf"},{"line_number":114,"context_line":"            new_conf.update("},{"line_number":115,"context_line":"                readconf(self.conf_path, BACKEND_RATELIMIT_CONFIG_SECTION))"},{"line_number":116,"context_line":"            modified \u003d self._apply_config(new_conf)"},{"line_number":117,"context_line":"            if modified:"},{"line_number":118,"context_line":"                self.logger.info(\u0027Loaded config file %s, config changed\u0027,"}],"source_content_type":"text/x-python","patch_set":7,"id":"ff7b9ef6_5f1f5f6b","line":115,"range":{"start_line":115,"start_character":16,"end_line":115,"end_character":39},"updated":"2023-05-23 23:07:30.000000000","message":"I\u0027m a little surprised we don\u0027t track mtime and early-exit if it hasn\u0027t changed. We really want to read the whole config off disk every 60s?","commit_id":"08ab90e0d1dabd6c738ee80abf8cb54c86a2f13b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f89e5f9ae6fe143544a34ff88156e4ad9c4f7a10","unresolved":false,"context_lines":[{"line_number":112,"context_line":"        try:"},{"line_number":113,"context_line":"            new_conf \u003d dict(self.filter_conf)  # filter_conf not current_conf"},{"line_number":114,"context_line":"            new_conf.update("},{"line_number":115,"context_line":"                readconf(self.conf_path, BACKEND_RATELIMIT_CONFIG_SECTION))"},{"line_number":116,"context_line":"            modified \u003d self._apply_config(new_conf)"},{"line_number":117,"context_line":"            if modified:"},{"line_number":118,"context_line":"                self.logger.info(\u0027Loaded config file %s, config changed\u0027,"}],"source_content_type":"text/x-python","patch_set":7,"id":"964c2d64_e44e8587","line":115,"range":{"start_line":115,"start_character":16,"end_line":115,"end_character":39},"in_reply_to":"ff7b9ef6_5f1f5f6b","updated":"2024-05-10 23:06:08.000000000","message":"I\u0027m not really surprised, this file is small and reloading config is already a new/complex enough as it is.  adding mtime tracking would strictly be an improvement, better as a follow up after merging \"the simplist thing that will work\"","commit_id":"08ab90e0d1dabd6c738ee80abf8cb54c86a2f13b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f78b83311d77c127dbcd3433ead94a549c148c44","unresolved":true,"context_lines":[{"line_number":135,"context_line":"        except ValueError as err:"},{"line_number":136,"context_line":"            # ...but if it exists it should be valid"},{"line_number":137,"context_line":"            self.logger.warning(\u0027Invalid config file %s, config unchanged: %s\u0027,"},{"line_number":138,"context_line":"                                self.conf_path, err)"},{"line_number":139,"context_line":""},{"line_number":140,"context_line":"    def _maybe_reload_config(self):"},{"line_number":141,"context_line":"        if self.config_reload_interval:"}],"source_content_type":"text/x-python","patch_set":10,"id":"84f53a33_91eced9b","line":138,"updated":"2024-03-14 10:15:37.000000000","message":"hmmm, I wonder why I treated this case differently than the file being unreadable?","commit_id":"e9abfd76ee5ef94a51b2dbe5a758432cfeeab8e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f89e5f9ae6fe143544a34ff88156e4ad9c4f7a10","unresolved":false,"context_lines":[{"line_number":135,"context_line":"        except ValueError as err:"},{"line_number":136,"context_line":"            # ...but if it exists it should be valid"},{"line_number":137,"context_line":"            self.logger.warning(\u0027Invalid config file %s, config unchanged: %s\u0027,"},{"line_number":138,"context_line":"                                self.conf_path, err)"},{"line_number":139,"context_line":""},{"line_number":140,"context_line":"    def _maybe_reload_config(self):"},{"line_number":141,"context_line":"        if self.config_reload_interval:"}],"source_content_type":"text/x-python","patch_set":10,"id":"b824b767_8b15c3e7","line":138,"in_reply_to":"15baff25_c0b08a1e","updated":"2024-05-10 23:06:08.000000000","message":"makes sense to me!","commit_id":"e9abfd76ee5ef94a51b2dbe5a758432cfeeab8e9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fedcd9d064936a925e67b70488e190019c8c1e50","unresolved":true,"context_lines":[{"line_number":135,"context_line":"        except ValueError as err:"},{"line_number":136,"context_line":"            # ...but if it exists it should be valid"},{"line_number":137,"context_line":"            self.logger.warning(\u0027Invalid config file %s, config unchanged: %s\u0027,"},{"line_number":138,"context_line":"                                self.conf_path, err)"},{"line_number":139,"context_line":""},{"line_number":140,"context_line":"    def _maybe_reload_config(self):"},{"line_number":141,"context_line":"        if self.config_reload_interval:"}],"source_content_type":"text/x-python","patch_set":10,"id":"15baff25_c0b08a1e","line":138,"in_reply_to":"84f53a33_91eced9b","updated":"2024-04-04 15:14:29.000000000","message":"A: I think I considered this more \"concerning\": the SRE has a conf file, but it\u0027s content is not valid and that\u0027s not obvious to SRE - SRE expects the conf file to be applied but it is not - so warn about it repeatedly. \n\nIn contrast SRE can observe the *absence* of a deleted conf file and wouldn\u0027t expect any conf to be applied so warn just once.","commit_id":"e9abfd76ee5ef94a51b2dbe5a758432cfeeab8e9"}],"swift/common/utils.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":3518,"context_line":"    def set_max_rate(self, max_rate):"},{"line_number":3519,"context_line":"        self.max_rate \u003d max_rate"},{"line_number":3520,"context_line":"        self.time_per_incr \u003d (self.clock_accuracy / self.max_rate"},{"line_number":3521,"context_line":"                              if self.max_rate else 0)"},{"line_number":3522,"context_line":""},{"line_number":3523,"context_line":"    def _sleep(self, seconds):"},{"line_number":3524,"context_line":"        # subclasses should override to implement a sleep"}],"source_content_type":"text/x-python","patch_set":4,"id":"b6a9aa5b_d9c28661","line":3521,"updated":"2022-05-19 20:19:50.000000000","message":"alternatively maybe make time_per_incr a property you can just twiddle rl.max_rate directly; this is probably a little more performant/OOP","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":false,"context_lines":[{"line_number":3518,"context_line":"    def set_max_rate(self, max_rate):"},{"line_number":3519,"context_line":"        self.max_rate \u003d max_rate"},{"line_number":3520,"context_line":"        self.time_per_incr \u003d (self.clock_accuracy / self.max_rate"},{"line_number":3521,"context_line":"                              if self.max_rate else 0)"},{"line_number":3522,"context_line":""},{"line_number":3523,"context_line":"    def _sleep(self, seconds):"},{"line_number":3524,"context_line":"        # subclasses should override to implement a sleep"}],"source_content_type":"text/x-python","patch_set":4,"id":"d045955a_565fb62c","line":3521,"in_reply_to":"b6a9aa5b_d9c28661","updated":"2022-05-20 13:25:28.000000000","message":"Ack","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"}],"test/unit/common/middleware/test_backend_ratelimit.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":133,"context_line":"            self.assertEqual([], rl.logger.get_lines_for_level(\u0027warning\u0027))"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        do_test(\u0027\u0027)"},{"line_number":136,"context_line":"        do_test(os.path.join(self.tempdir, \u0027backend_rl.conf\u0027))"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"    def test_init_config_file_no_section(self):"},{"line_number":139,"context_line":"        # warn and ignore conf file without section"}],"source_content_type":"text/x-python","patch_set":4,"id":"2558a4ca_e3541fb4","line":136,"updated":"2022-05-19 20:19:50.000000000","message":"not even a *warning*???","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":true,"context_lines":[{"line_number":133,"context_line":"            self.assertEqual([], rl.logger.get_lines_for_level(\u0027warning\u0027))"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        do_test(\u0027\u0027)"},{"line_number":136,"context_line":"        do_test(os.path.join(self.tempdir, \u0027backend_rl.conf\u0027))"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"    def test_init_config_file_no_section(self):"},{"line_number":139,"context_line":"        # warn and ignore conf file without section"}],"source_content_type":"text/x-python","patch_set":4,"id":"80565f05_b53d70bd","line":136,"in_reply_to":"2558a4ca_e3541fb4","updated":"2022-05-20 13:25:28.000000000","message":"I was unsure which way to jump - I don\u0027t want lots of warnings for a normal situation (conf file not expected). On reflection, we could warn if the conf path is explicitly configured but not found...during startup? or always?","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f78b83311d77c127dbcd3433ead94a549c148c44","unresolved":false,"context_lines":[{"line_number":133,"context_line":"            self.assertEqual([], rl.logger.get_lines_for_level(\u0027warning\u0027))"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        do_test(\u0027\u0027)"},{"line_number":136,"context_line":"        do_test(os.path.join(self.tempdir, \u0027backend_rl.conf\u0027))"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"    def test_init_config_file_no_section(self):"},{"line_number":139,"context_line":"        # warn and ignore conf file without section"}],"source_content_type":"text/x-python","patch_set":4,"id":"057925a1_b8622580","line":136,"in_reply_to":"80565f05_b53d70bd","updated":"2024-03-14 10:15:37.000000000","message":"Done","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":147,"context_line":"        with mock.patch(\u0027swift.common.middleware.backend_ratelimit.get_logger\u0027,"},{"line_number":148,"context_line":"                        return_value\u003ddebug_logger()):"},{"line_number":149,"context_line":"            rl \u003d factory(self.swift)"},{"line_number":150,"context_line":"        self.assertEqual(1.3, rl.requests_per_device_per_second)"},{"line_number":151,"context_line":"        lines \u003d rl.logger.get_lines_for_level(\u0027warning\u0027)"},{"line_number":152,"context_line":"        self.assertEqual(1, len(lines), lines)"},{"line_number":153,"context_line":"        self.assertIn(\u0027Invalid config file\u0027, lines[0])"}],"source_content_type":"text/x-python","patch_set":4,"id":"e193e637_6147c527","line":150,"updated":"2022-05-19 20:19:50.000000000","message":"so we don\u0027t reload the value form the DEFAULT section","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fedcd9d064936a925e67b70488e190019c8c1e50","unresolved":false,"context_lines":[{"line_number":147,"context_line":"        with mock.patch(\u0027swift.common.middleware.backend_ratelimit.get_logger\u0027,"},{"line_number":148,"context_line":"                        return_value\u003ddebug_logger()):"},{"line_number":149,"context_line":"            rl \u003d factory(self.swift)"},{"line_number":150,"context_line":"        self.assertEqual(1.3, rl.requests_per_device_per_second)"},{"line_number":151,"context_line":"        lines \u003d rl.logger.get_lines_for_level(\u0027warning\u0027)"},{"line_number":152,"context_line":"        self.assertEqual(1, len(lines), lines)"},{"line_number":153,"context_line":"        self.assertIn(\u0027Invalid config file\u0027, lines[0])"}],"source_content_type":"text/x-python","patch_set":4,"id":"b53d8dd9_1aef56d9","line":150,"in_reply_to":"3545ee71_af2e4417","updated":"2024-04-04 15:14:29.000000000","message":"Done","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":true,"context_lines":[{"line_number":147,"context_line":"        with mock.patch(\u0027swift.common.middleware.backend_ratelimit.get_logger\u0027,"},{"line_number":148,"context_line":"                        return_value\u003ddebug_logger()):"},{"line_number":149,"context_line":"            rl \u003d factory(self.swift)"},{"line_number":150,"context_line":"        self.assertEqual(1.3, rl.requests_per_device_per_second)"},{"line_number":151,"context_line":"        lines \u003d rl.logger.get_lines_for_level(\u0027warning\u0027)"},{"line_number":152,"context_line":"        self.assertEqual(1, len(lines), lines)"},{"line_number":153,"context_line":"        self.assertIn(\u0027Invalid config file\u0027, lines[0])"}],"source_content_type":"text/x-python","patch_set":4,"id":"3545ee71_af2e4417","line":150,"in_reply_to":"e193e637_6147c527","updated":"2022-05-20 13:25:28.000000000","message":"not currently","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":150,"context_line":"        self.assertEqual(1.3, rl.requests_per_device_per_second)"},{"line_number":151,"context_line":"        lines \u003d rl.logger.get_lines_for_level(\u0027warning\u0027)"},{"line_number":152,"context_line":"        self.assertEqual(1, len(lines), lines)"},{"line_number":153,"context_line":"        self.assertIn(\u0027Invalid config file\u0027, lines[0])"},{"line_number":154,"context_line":"        self.assertEqual([], rl.logger.get_lines_for_level(\u0027error\u0027))"},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"    def _do_test_init_config_file_overrides_filter_conf(self, actual_path,"}],"source_content_type":"text/x-python","patch_set":4,"id":"c01e6e0d_c02798e5","line":153,"updated":"2022-05-19 20:19:50.000000000","message":"but we do warn","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":false,"context_lines":[{"line_number":150,"context_line":"        self.assertEqual(1.3, rl.requests_per_device_per_second)"},{"line_number":151,"context_line":"        lines \u003d rl.logger.get_lines_for_level(\u0027warning\u0027)"},{"line_number":152,"context_line":"        self.assertEqual(1, len(lines), lines)"},{"line_number":153,"context_line":"        self.assertIn(\u0027Invalid config file\u0027, lines[0])"},{"line_number":154,"context_line":"        self.assertEqual([], rl.logger.get_lines_for_level(\u0027error\u0027))"},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"    def _do_test_init_config_file_overrides_filter_conf(self, actual_path,"}],"source_content_type":"text/x-python","patch_set":4,"id":"beb236ac_e4fbd7f0","line":153,"in_reply_to":"c01e6e0d_c02798e5","updated":"2022-05-20 13:25:28.000000000","message":"Ack","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":184,"context_line":"        factory \u003d backend_ratelimit.filter_factory(conf)"},{"line_number":185,"context_line":"        rl \u003d factory(self.swift)"},{"line_number":186,"context_line":"        self.assertEqual(12.3, rl.requests_per_device_per_second)"},{"line_number":187,"context_line":"        self.assertEqual(2.4, rl.requests_per_device_rate_buffer)"},{"line_number":188,"context_line":"        # options related to conf file loading are not loaded from conf file..."},{"line_number":189,"context_line":"        self.assertEqual(conf_path, rl.conf_path)"},{"line_number":190,"context_line":"        self.assertEqual(15, rl.config_reload_interval)"}],"source_content_type":"text/x-python","patch_set":4,"id":"96622f33_a11114dd","line":187,"updated":"2022-05-19 20:19:50.000000000","message":"so we *are* reading this config... but the requests_per_device_rate_buffer option isn\u0027t set","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":false,"context_lines":[{"line_number":184,"context_line":"        factory \u003d backend_ratelimit.filter_factory(conf)"},{"line_number":185,"context_line":"        rl \u003d factory(self.swift)"},{"line_number":186,"context_line":"        self.assertEqual(12.3, rl.requests_per_device_per_second)"},{"line_number":187,"context_line":"        self.assertEqual(2.4, rl.requests_per_device_rate_buffer)"},{"line_number":188,"context_line":"        # options related to conf file loading are not loaded from conf file..."},{"line_number":189,"context_line":"        self.assertEqual(conf_path, rl.conf_path)"},{"line_number":190,"context_line":"        self.assertEqual(15, rl.config_reload_interval)"}],"source_content_type":"text/x-python","patch_set":4,"id":"96b03b1d_81acc87b","line":187,"in_reply_to":"96622f33_a11114dd","updated":"2022-05-20 13:25:28.000000000","message":"Done","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":210,"context_line":"        # explicitly configure conf path"},{"line_number":211,"context_line":"        actual_path \u003d os.path.join(self.tempdir, \u0027backend_rl.conf\u0027)"},{"line_number":212,"context_line":"        self._do_test_init_config_file_overrides_filter_conf(actual_path,"},{"line_number":213,"context_line":"                                                             actual_path)"},{"line_number":214,"context_line":""},{"line_number":215,"context_line":"    def _do_test_config_file_reload(self, config_reload_interval,"},{"line_number":216,"context_line":"                                    exp_reload_time):"}],"source_content_type":"text/x-python","patch_set":4,"id":"2a21d2e5_31602546","line":213,"updated":"2022-05-19 20:19:50.000000000","message":"i found these two tests really hard to reason about; maybe a doc string on _do_test_init_config_file_overrides_filter_conf would have helped.  I think it\u0027s too DRY and not enough DAMP.","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":true,"context_lines":[{"line_number":210,"context_line":"        # explicitly configure conf path"},{"line_number":211,"context_line":"        actual_path \u003d os.path.join(self.tempdir, \u0027backend_rl.conf\u0027)"},{"line_number":212,"context_line":"        self._do_test_init_config_file_overrides_filter_conf(actual_path,"},{"line_number":213,"context_line":"                                                             actual_path)"},{"line_number":214,"context_line":""},{"line_number":215,"context_line":"    def _do_test_config_file_reload(self, config_reload_interval,"},{"line_number":216,"context_line":"                                    exp_reload_time):"}],"source_content_type":"text/x-python","patch_set":4,"id":"5a006b22_6fbff2d1","line":213,"in_reply_to":"2a21d2e5_31602546","updated":"2022-05-20 13:25:28.000000000","message":"thanks for your follow up patch","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fedcd9d064936a925e67b70488e190019c8c1e50","unresolved":false,"context_lines":[{"line_number":210,"context_line":"        # explicitly configure conf path"},{"line_number":211,"context_line":"        actual_path \u003d os.path.join(self.tempdir, \u0027backend_rl.conf\u0027)"},{"line_number":212,"context_line":"        self._do_test_init_config_file_overrides_filter_conf(actual_path,"},{"line_number":213,"context_line":"                                                             actual_path)"},{"line_number":214,"context_line":""},{"line_number":215,"context_line":"    def _do_test_config_file_reload(self, config_reload_interval,"},{"line_number":216,"context_line":"                                    exp_reload_time):"}],"source_content_type":"text/x-python","patch_set":4,"id":"eef8d54a_59080a64","line":213,"in_reply_to":"5a006b22_6fbff2d1","updated":"2024-04-04 15:14:29.000000000","message":"Done","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":222,"context_line":"        if config_reload_interval is not None:"},{"line_number":223,"context_line":"            filter_conf[\u0027config_reload_interval\u0027] \u003d config_reload_interval"},{"line_number":224,"context_line":"        else:"},{"line_number":225,"context_line":"            config_reload_interval \u003d 60"},{"line_number":226,"context_line":"        # create the actual file"},{"line_number":227,"context_line":"        conf_path \u003d os.path.join(self.tempdir, \u0027backend-ratelimit.conf\u0027)"},{"line_number":228,"context_line":"        with open(conf_path, \u0027w\u0027) as fd:"}],"source_content_type":"text/x-python","patch_set":4,"id":"b7c47239_38b04821","line":225,"updated":"2022-05-19 20:19:50.000000000","message":"there\u0027s really only two ways to call this function:\n\n(None, 60)\n(x, x)\n\n... anything else would fail\n\nI\u0027m not sure I\u0027d argue (None, 60) is similar enough to (60, 60) that we don\u0027t WANT it - this _do_test was relatively easy to read.  But it seems like we might recognize the tradeoff against readability with the extra variables/helper abstraction","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f78b83311d77c127dbcd3433ead94a549c148c44","unresolved":false,"context_lines":[{"line_number":222,"context_line":"        if config_reload_interval is not None:"},{"line_number":223,"context_line":"            filter_conf[\u0027config_reload_interval\u0027] \u003d config_reload_interval"},{"line_number":224,"context_line":"        else:"},{"line_number":225,"context_line":"            config_reload_interval \u003d 60"},{"line_number":226,"context_line":"        # create the actual file"},{"line_number":227,"context_line":"        conf_path \u003d os.path.join(self.tempdir, \u0027backend-ratelimit.conf\u0027)"},{"line_number":228,"context_line":"        with open(conf_path, \u0027w\u0027) as fd:"}],"source_content_type":"text/x-python","patch_set":4,"id":"25d86f7f_89e1f794","line":225,"in_reply_to":"23209c26_73900cc9","updated":"2024-03-14 10:15:37.000000000","message":"Done","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":true,"context_lines":[{"line_number":222,"context_line":"        if config_reload_interval is not None:"},{"line_number":223,"context_line":"            filter_conf[\u0027config_reload_interval\u0027] \u003d config_reload_interval"},{"line_number":224,"context_line":"        else:"},{"line_number":225,"context_line":"            config_reload_interval \u003d 60"},{"line_number":226,"context_line":"        # create the actual file"},{"line_number":227,"context_line":"        conf_path \u003d os.path.join(self.tempdir, \u0027backend-ratelimit.conf\u0027)"},{"line_number":228,"context_line":"        with open(conf_path, \u0027w\u0027) as fd:"}],"source_content_type":"text/x-python","patch_set":4,"id":"23209c26_73900cc9","line":225,"in_reply_to":"b7c47239_38b04821","updated":"2022-05-20 13:25:28.000000000","message":"moved the filter_conf assignment to the caller to make it a little more explicit","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":277,"context_line":"        # verify the per dev ratelimiters were updated"},{"line_number":278,"context_line":"        per_dev_rl_rates \u003d [per_dev_rl.max_rate"},{"line_number":279,"context_line":"                            for per_dev_rl in list(rl.rate_limiters.values())]"},{"line_number":280,"context_line":"        self.assertEqual([29.3, 29.3], per_dev_rl_rates)"},{"line_number":281,"context_line":""},{"line_number":282,"context_line":"        # modify the config file again"},{"line_number":283,"context_line":"        # remove requests_per_device_per_second option"}],"source_content_type":"text/x-python","patch_set":4,"id":"bf134537_80e0b4ae","line":280,"updated":"2022-05-19 20:19:50.000000000","message":"maybe check per ratelimiter rate buffer values too","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":false,"context_lines":[{"line_number":277,"context_line":"        # verify the per dev ratelimiters were updated"},{"line_number":278,"context_line":"        per_dev_rl_rates \u003d [per_dev_rl.max_rate"},{"line_number":279,"context_line":"                            for per_dev_rl in list(rl.rate_limiters.values())]"},{"line_number":280,"context_line":"        self.assertEqual([29.3, 29.3], per_dev_rl_rates)"},{"line_number":281,"context_line":""},{"line_number":282,"context_line":"        # modify the config file again"},{"line_number":283,"context_line":"        # remove requests_per_device_per_second option"}],"source_content_type":"text/x-python","patch_set":4,"id":"0e8584e5_8c2594d3","line":280,"in_reply_to":"bf134537_80e0b4ae","updated":"2022-05-20 13:25:28.000000000","message":"Done","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":284,"context_line":"        with open(conf_path, \u0027w\u0027) as fd:"},{"line_number":285,"context_line":"            fd.write(\u0027[backend_ratelimit]\\n\u0027"},{"line_number":286,"context_line":"                     \u0027backend_ratelimit_conf_path \u003d /etc/swift/rl.conf\\n\u0027"},{"line_number":287,"context_line":"                     \u0027config_reload_interval \u003d 999999\\n\u0027)"},{"line_number":288,"context_line":""},{"line_number":289,"context_line":"        # send some requests, not yet time for config file to be reloaded"},{"line_number":290,"context_line":"        with mock.patch(\u0027swift.common.middleware.backend_ratelimit.time.time\u0027,"}],"source_content_type":"text/x-python","patch_set":4,"id":"87c50776_cef25bef","line":287,"updated":"2022-05-19 20:19:50.000000000","message":"so this is basically an empty config","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":false,"context_lines":[{"line_number":284,"context_line":"        with open(conf_path, \u0027w\u0027) as fd:"},{"line_number":285,"context_line":"            fd.write(\u0027[backend_ratelimit]\\n\u0027"},{"line_number":286,"context_line":"                     \u0027backend_ratelimit_conf_path \u003d /etc/swift/rl.conf\\n\u0027"},{"line_number":287,"context_line":"                     \u0027config_reload_interval \u003d 999999\\n\u0027)"},{"line_number":288,"context_line":""},{"line_number":289,"context_line":"        # send some requests, not yet time for config file to be reloaded"},{"line_number":290,"context_line":"        with mock.patch(\u0027swift.common.middleware.backend_ratelimit.time.time\u0027,"}],"source_content_type":"text/x-python","patch_set":4,"id":"0c8819a9_bf9b8d8e","line":287,"in_reply_to":"87c50776_cef25bef","updated":"2022-05-20 13:25:28.000000000","message":"Ack","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":288,"context_line":""},{"line_number":289,"context_line":"        # send some requests, not yet time for config file to be reloaded"},{"line_number":290,"context_line":"        with mock.patch(\u0027swift.common.middleware.backend_ratelimit.time.time\u0027,"},{"line_number":291,"context_line":"                        return_value\u003dnow + 2 * exp_reload_time - 1):"},{"line_number":292,"context_line":"            resp1 \u003d req1.get_response(rl)"},{"line_number":293,"context_line":"            resp2 \u003d req2.get_response(rl)"},{"line_number":294,"context_line":"        self.assertEqual(200, resp1.status_int)"}],"source_content_type":"text/x-python","patch_set":4,"id":"2167ee29_137ea1a7","line":291,"updated":"2022-05-19 20:19:50.000000000","message":"ok, well NOW i\u0027m curious what happens if time goes backwards","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f89e5f9ae6fe143544a34ff88156e4ad9c4f7a10","unresolved":false,"context_lines":[{"line_number":288,"context_line":""},{"line_number":289,"context_line":"        # send some requests, not yet time for config file to be reloaded"},{"line_number":290,"context_line":"        with mock.patch(\u0027swift.common.middleware.backend_ratelimit.time.time\u0027,"},{"line_number":291,"context_line":"                        return_value\u003dnow + 2 * exp_reload_time - 1):"},{"line_number":292,"context_line":"            resp1 \u003d req1.get_response(rl)"},{"line_number":293,"context_line":"            resp2 \u003d req2.get_response(rl)"},{"line_number":294,"context_line":"        self.assertEqual(200, resp1.status_int)"}],"source_content_type":"text/x-python","patch_set":4,"id":"f6ea28c3_a7e9a4af","line":291,"in_reply_to":"2167ee29_137ea1a7","updated":"2024-05-10 23:06:08.000000000","message":"Acknowledged","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":312,"context_line":"        self.assertEqual(200, resp2.status_int)"},{"line_number":313,"context_line":"        # requests_per_device_per_second option reverts to filter conf"},{"line_number":314,"context_line":"        self.assertEqual(1.3, rl.requests_per_device_per_second)"},{"line_number":315,"context_line":"        self.assertEqual(2.4, rl.requests_per_device_rate_buffer)"},{"line_number":316,"context_line":"        self.assertEqual(conf_path, rl.conf_path)"},{"line_number":317,"context_line":"        self.assertEqual(config_reload_interval, rl.config_reload_interval)"},{"line_number":318,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"03e3bb5c_8ead5aed","line":315,"updated":"2022-05-19 20:19:50.000000000","message":"so we must be hanging on to these values somewhere...","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":true,"context_lines":[{"line_number":312,"context_line":"        self.assertEqual(200, resp2.status_int)"},{"line_number":313,"context_line":"        # requests_per_device_per_second option reverts to filter conf"},{"line_number":314,"context_line":"        self.assertEqual(1.3, rl.requests_per_device_per_second)"},{"line_number":315,"context_line":"        self.assertEqual(2.4, rl.requests_per_device_rate_buffer)"},{"line_number":316,"context_line":"        self.assertEqual(conf_path, rl.conf_path)"},{"line_number":317,"context_line":"        self.assertEqual(config_reload_interval, rl.config_reload_interval)"},{"line_number":318,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"b34bca43_3a2c9203","line":315,"in_reply_to":"03e3bb5c_8ead5aed","updated":"2022-05-20 13:25:28.000000000","message":"self.filter_conf is *always* the starting point that is updated by any loaded conf - previously loaded config file value is forgotten unless included in config file on next reload.\n\nThis means that the current config can be known from the current state of the *-server.conf file and backend-ratelimit.conf file (with the caveat that if the config file cannot be opened then the current running config is unchanged - see later comment)","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":322,"context_line":"        self.assertEqual([1.3, 1.3], sorted(per_dev_rl_rates))"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"    def test_config_file_reload(self):"},{"line_number":325,"context_line":"        self._do_test_config_file_reload(None, 60)"},{"line_number":326,"context_line":"        self._do_test_config_file_reload(30, 30)"},{"line_number":327,"context_line":""},{"line_number":328,"context_line":"    def test_config_file_reload_error(self):"}],"source_content_type":"text/x-python","patch_set":4,"id":"e266020e_ca830823","line":325,"updated":"2022-05-19 20:19:50.000000000","message":"I think once you test how the config_reload_interval works; \u0027verifying\u0027 that the default value works as if it had been explicitly set to 60 provides little value","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":false,"context_lines":[{"line_number":322,"context_line":"        self.assertEqual([1.3, 1.3], sorted(per_dev_rl_rates))"},{"line_number":323,"context_line":""},{"line_number":324,"context_line":"    def test_config_file_reload(self):"},{"line_number":325,"context_line":"        self._do_test_config_file_reload(None, 60)"},{"line_number":326,"context_line":"        self._do_test_config_file_reload(30, 30)"},{"line_number":327,"context_line":""},{"line_number":328,"context_line":"    def test_config_file_reload_error(self):"}],"source_content_type":"text/x-python","patch_set":4,"id":"24c114a2_bd042b5f","line":325,"in_reply_to":"e266020e_ca830823","updated":"2022-05-20 13:25:28.000000000","message":"Ack","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":360,"context_line":"                        return_value\u003dnow + 10000):"},{"line_number":361,"context_line":"            with mock.patch("},{"line_number":362,"context_line":"                    \u0027swift.common.middleware.backend_ratelimit.readconf\u0027,"},{"line_number":363,"context_line":"                    side_effect\u003dValueError(\u0027BOOM\u0027)"},{"line_number":364,"context_line":"            ) as mock_readconf:"},{"line_number":365,"context_line":"                resp1 \u003d req1.get_response(rl)"},{"line_number":366,"context_line":"        self.assertEqual(200, resp1.status_int)"}],"source_content_type":"text/x-python","patch_set":4,"id":"e51dfde2_fb1e858d","line":363,"updated":"2022-05-19 20:19:50.000000000","message":"or maybe just delete the file or make it un-parseable?","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":false,"context_lines":[{"line_number":360,"context_line":"                        return_value\u003dnow + 10000):"},{"line_number":361,"context_line":"            with mock.patch("},{"line_number":362,"context_line":"                    \u0027swift.common.middleware.backend_ratelimit.readconf\u0027,"},{"line_number":363,"context_line":"                    side_effect\u003dValueError(\u0027BOOM\u0027)"},{"line_number":364,"context_line":"            ) as mock_readconf:"},{"line_number":365,"context_line":"                resp1 \u003d req1.get_response(rl)"},{"line_number":366,"context_line":"        self.assertEqual(200, resp1.status_int)"}],"source_content_type":"text/x-python","patch_set":4,"id":"a06b5a72_30f1b14f","line":363,"in_reply_to":"e51dfde2_fb1e858d","updated":"2022-05-20 13:25:28.000000000","message":"Ack","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":379,"context_line":"            resp1 \u003d req1.get_response(rl)"},{"line_number":380,"context_line":"        self.assertEqual(200, resp1.status_int)"},{"line_number":381,"context_line":"        # previous conf file value has been retained"},{"line_number":382,"context_line":"        self.assertEqual(12.3, rl.requests_per_device_per_second)"},{"line_number":383,"context_line":"        self.assertEqual(2.4, rl.requests_per_device_rate_buffer)"},{"line_number":384,"context_line":"        self.assertEqual([], rl.logger.get_lines_for_level(\u0027warning\u0027))"},{"line_number":385,"context_line":"        self.assertEqual([], rl.logger.get_lines_for_level(\u0027error\u0027))"}],"source_content_type":"text/x-python","patch_set":4,"id":"afe52c0f_3919d4b3","line":382,"updated":"2022-05-19 20:19:50.000000000","message":"ok, so we use the load loaded value - we don\u0027t go back to the value in the app-section/original-conf","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fedcd9d064936a925e67b70488e190019c8c1e50","unresolved":false,"context_lines":[{"line_number":379,"context_line":"            resp1 \u003d req1.get_response(rl)"},{"line_number":380,"context_line":"        self.assertEqual(200, resp1.status_int)"},{"line_number":381,"context_line":"        # previous conf file value has been retained"},{"line_number":382,"context_line":"        self.assertEqual(12.3, rl.requests_per_device_per_second)"},{"line_number":383,"context_line":"        self.assertEqual(2.4, rl.requests_per_device_rate_buffer)"},{"line_number":384,"context_line":"        self.assertEqual([], rl.logger.get_lines_for_level(\u0027warning\u0027))"},{"line_number":385,"context_line":"        self.assertEqual([], rl.logger.get_lines_for_level(\u0027error\u0027))"}],"source_content_type":"text/x-python","patch_set":4,"id":"66e24e30_2a351b0b","line":382,"in_reply_to":"5313c0e3_d2e040b0","updated":"2024-04-04 15:14:29.000000000","message":"Done","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":true,"context_lines":[{"line_number":379,"context_line":"            resp1 \u003d req1.get_response(rl)"},{"line_number":380,"context_line":"        self.assertEqual(200, resp1.status_int)"},{"line_number":381,"context_line":"        # previous conf file value has been retained"},{"line_number":382,"context_line":"        self.assertEqual(12.3, rl.requests_per_device_per_second)"},{"line_number":383,"context_line":"        self.assertEqual(2.4, rl.requests_per_device_rate_buffer)"},{"line_number":384,"context_line":"        self.assertEqual([], rl.logger.get_lines_for_level(\u0027warning\u0027))"},{"line_number":385,"context_line":"        self.assertEqual([], rl.logger.get_lines_for_level(\u0027error\u0027))"}],"source_content_type":"text/x-python","patch_set":4,"id":"5313c0e3_d2e040b0","line":382,"in_reply_to":"afe52c0f_3919d4b3","updated":"2022-05-20 13:25:28.000000000","message":"yes. If the file cannot be loaded, nothing changes, unlike loading an empty [backend_ratelimit] section , when config is reset to filter_conf.\n\nIn verbal conversation I felt there was consensus that being unable to open a config file should NOT cause running config to reset. On the other hand, if a valid conf file is present then its contents should be reflected in the running state, including absence of options meaning \u0027use default\u0027.","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cc970dbfad04d38c5def239b98e2ad4b54b5b75a","unresolved":true,"context_lines":[{"line_number":339,"context_line":"                       \u0027requests_per_device_per_second\u0027: \"1.3\","},{"line_number":340,"context_line":"                       \u0027requests_per_device_rate_buffer\u0027: \"2.4\"}"},{"line_number":341,"context_line":"        rl \u003d self._do_test_config_file_reload(filter_conf, 30)"},{"line_number":342,"context_line":"        self.assertEqual(30, rl.config_reload_interval)"},{"line_number":343,"context_line":""},{"line_number":344,"context_line":"    def test_config_file_reload_set_and_missing(self):"},{"line_number":345,"context_line":"        now \u003d time.time()"}],"source_content_type":"text/x-python","patch_set":5,"id":"9841d3f2_0c843c1f","line":342,"updated":"2022-05-20 16:37:02.000000000","message":"yeah this is bit better!","commit_id":"7730d4806c4dc4bb9a5a630f2f84e05229a6d726"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fedcd9d064936a925e67b70488e190019c8c1e50","unresolved":false,"context_lines":[{"line_number":339,"context_line":"                       \u0027requests_per_device_per_second\u0027: \"1.3\","},{"line_number":340,"context_line":"                       \u0027requests_per_device_rate_buffer\u0027: \"2.4\"}"},{"line_number":341,"context_line":"        rl \u003d self._do_test_config_file_reload(filter_conf, 30)"},{"line_number":342,"context_line":"        self.assertEqual(30, rl.config_reload_interval)"},{"line_number":343,"context_line":""},{"line_number":344,"context_line":"    def test_config_file_reload_set_and_missing(self):"},{"line_number":345,"context_line":"        now \u003d time.time()"}],"source_content_type":"text/x-python","patch_set":5,"id":"d889498e_8c5798aa","line":342,"in_reply_to":"9841d3f2_0c843c1f","updated":"2024-04-04 15:14:29.000000000","message":"Acknowledged","commit_id":"7730d4806c4dc4bb9a5a630f2f84e05229a6d726"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cc970dbfad04d38c5def239b98e2ad4b54b5b75a","unresolved":true,"context_lines":[{"line_number":388,"context_line":"                       \u0027requests_per_device_rate_buffer\u0027: \"2.4\"}"},{"line_number":389,"context_line":"        factory \u003d backend_ratelimit.filter_factory(filter_conf)"},{"line_number":390,"context_line":""},{"line_number":391,"context_line":"        # expect warning during init"},{"line_number":392,"context_line":"        with mock.patch(\u0027swift.common.middleware.backend_ratelimit.time.time\u0027,"},{"line_number":393,"context_line":"                        return_value\u003dnow):"},{"line_number":394,"context_line":"            with mock.patch("}],"source_content_type":"text/x-python","patch_set":5,"id":"55a8ee99_0a383455","line":391,"updated":"2022-05-20 16:37:02.000000000","message":"no warning during init","commit_id":"7730d4806c4dc4bb9a5a630f2f84e05229a6d726"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f32df1cf7983fedf61f8f1432ff779118bd27efb","unresolved":true,"context_lines":[{"line_number":388,"context_line":"                       \u0027requests_per_device_rate_buffer\u0027: \"2.4\"}"},{"line_number":389,"context_line":"        factory \u003d backend_ratelimit.filter_factory(filter_conf)"},{"line_number":390,"context_line":""},{"line_number":391,"context_line":"        # expect warning during init"},{"line_number":392,"context_line":"        with mock.patch(\u0027swift.common.middleware.backend_ratelimit.time.time\u0027,"},{"line_number":393,"context_line":"                        return_value\u003dnow):"},{"line_number":394,"context_line":"            with mock.patch("}],"source_content_type":"text/x-python","patch_set":5,"id":"5a628aea_1940a0c3","line":391,"in_reply_to":"55a8ee99_0a383455","updated":"2022-05-20 17:42:25.000000000","message":"that\u0027s what happens when I cut and paste tests to be DAMP :\u0027(","commit_id":"7730d4806c4dc4bb9a5a630f2f84e05229a6d726"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f78b83311d77c127dbcd3433ead94a549c148c44","unresolved":false,"context_lines":[{"line_number":388,"context_line":"                       \u0027requests_per_device_rate_buffer\u0027: \"2.4\"}"},{"line_number":389,"context_line":"        factory \u003d backend_ratelimit.filter_factory(filter_conf)"},{"line_number":390,"context_line":""},{"line_number":391,"context_line":"        # expect warning during init"},{"line_number":392,"context_line":"        with mock.patch(\u0027swift.common.middleware.backend_ratelimit.time.time\u0027,"},{"line_number":393,"context_line":"                        return_value\u003dnow):"},{"line_number":394,"context_line":"            with mock.patch("}],"source_content_type":"text/x-python","patch_set":5,"id":"5e279a23_0d072165","line":391,"in_reply_to":"5a628aea_1940a0c3","updated":"2024-03-14 10:15:37.000000000","message":"Done","commit_id":"7730d4806c4dc4bb9a5a630f2f84e05229a6d726"}],"test/unit/common/test_utils.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":5882,"context_line":"        self.assertEqual(10000, rl.time_per_incr)"},{"line_number":5883,"context_line":"        rl.set_max_rate(2)"},{"line_number":5884,"context_line":"        self.assertEqual(2, rl.max_rate)"},{"line_number":5885,"context_line":"        self.assertEqual(500, rl.time_per_incr)"},{"line_number":5886,"context_line":""},{"line_number":5887,"context_line":"    def test_non_blocking(self):"},{"line_number":5888,"context_line":"        rate_limiter \u003d utils.EventletRateLimiter(0.1, rate_buffer\u003d0)"}],"source_content_type":"text/x-python","patch_set":4,"id":"8b57e9aa_04dc05f8","line":5885,"updated":"2022-05-19 20:19:50.000000000","message":"nice.","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fedcd9d064936a925e67b70488e190019c8c1e50","unresolved":false,"context_lines":[{"line_number":5882,"context_line":"        self.assertEqual(10000, rl.time_per_incr)"},{"line_number":5883,"context_line":"        rl.set_max_rate(2)"},{"line_number":5884,"context_line":"        self.assertEqual(2, rl.max_rate)"},{"line_number":5885,"context_line":"        self.assertEqual(500, rl.time_per_incr)"},{"line_number":5886,"context_line":""},{"line_number":5887,"context_line":"    def test_non_blocking(self):"},{"line_number":5888,"context_line":"        rate_limiter \u003d utils.EventletRateLimiter(0.1, rate_buffer\u003d0)"}],"source_content_type":"text/x-python","patch_set":4,"id":"29746234_b8461419","line":5885,"in_reply_to":"8b57e9aa_04dc05f8","updated":"2024-04-04 15:14:29.000000000","message":"Acknowledged","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"49069d90ddc634baf568ac6df21a14a022c384bc","unresolved":true,"context_lines":[{"line_number":5945,"context_line":"                self.assertTrue(rate_limiter.is_allowed())"},{"line_number":5946,"context_line":"                self.assertFalse(rate_limiter.is_allowed())"},{"line_number":5947,"context_line":""},{"line_number":5948,"context_line":"        mock_sleep.assert_not_called()"},{"line_number":5949,"context_line":""},{"line_number":5950,"context_line":"    def _do_test(self, max_rate, running_time, start_time, rate_buffer,"},{"line_number":5951,"context_line":"                 burst_after_idle\u003dFalse, incr_by\u003d1.0):"}],"source_content_type":"text/x-python","patch_set":4,"id":"4d1fd5f9_0b70f21b","line":5948,"updated":"2022-05-19 20:19:50.000000000","message":"this is just asserting that block is False by default","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"97abc5dfaca045c8ab43d09eb7895b6d40817af5","unresolved":false,"context_lines":[{"line_number":5945,"context_line":"                self.assertTrue(rate_limiter.is_allowed())"},{"line_number":5946,"context_line":"                self.assertFalse(rate_limiter.is_allowed())"},{"line_number":5947,"context_line":""},{"line_number":5948,"context_line":"        mock_sleep.assert_not_called()"},{"line_number":5949,"context_line":""},{"line_number":5950,"context_line":"    def _do_test(self, max_rate, running_time, start_time, rate_buffer,"},{"line_number":5951,"context_line":"                 burst_after_idle\u003dFalse, incr_by\u003d1.0):"}],"source_content_type":"text/x-python","patch_set":4,"id":"abba7275_64e7995d","line":5948,"in_reply_to":"4d1fd5f9_0b70f21b","updated":"2022-05-20 13:25:28.000000000","message":"Ack","commit_id":"897e8d1741960aa3c924d72b7e84a7357d22c1d3"}]}
