)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"d9a6e808bd5986f020b4771fae648969967dcab5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"e6c4cbde_9be90b19","updated":"2021-12-14 23:20:19.000000000","message":"Nice approach, push the deferred queue into the each bucket in the bucket iter. Then we can enqueue the buckets themselves when it comes time to prioritise.\n\nI also like it\u0027s the buckets in the p_queue, the heap method there doesn\u0027t really like dicts. I need to confirm it\u0027ll be able to compare buckets (if the next_time) is the same as another in the queue, it\u0027ll compare (\u003c operator) with other buckets.. but worstcase we can implement that as we now control the bucket class. So that\u0027s a win!\n\nSome todos in there, I\u0027ll have a play with this patch and maybe tackle some of them.","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"a3146d2d503f948b42cd1c960e6560a33ad53b3a","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"01c6429f_7048acab","updated":"2021-12-15 01:57:37.000000000","message":"Something like: https://review.opendev.org/c/openstack/swift/+/821790 ","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"24e5ab907990e76fe201028d9a3e0c0088fbac44","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"b09c2273_363e7476","updated":"2021-12-15 01:11:06.000000000","message":"about to send a follow up patch","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"1b5e31633a4dd454c92b31ff72e528302a298528","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"c3016b2c_da9f5142","updated":"2021-12-21 18:22:26.000000000","message":"recheck","commit_id":"4436a90d8e460004f7aff2d212cd6d4f11dbdc4e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"a493b27dc06f90cc1081a5eb49b3daf449a0c6e4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":10,"id":"be09d8b7_a00a14a3","updated":"2022-01-10 16:32:18.000000000","message":"I think this is good.  The most recent work is just around improving stats handling and I think we could keep going a little.  https://review.opendev.org/c/openstack/swift/+/824030","commit_id":"5798782b528afa8e5665f031df40478f33f43147"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8e05ddeae598ae87f68e78b06e9c94c75b7089b5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"38a9b6d3_d0537fac","updated":"2022-01-10 19:27:37.000000000","message":"sorry, the chrun wasn\u0027t that helpful - test imports were conflicting with https://review.opendev.org/c/openstack/swift/+/819732\n\nI still think this is great!","commit_id":"ec1872a710be1cc9b63cdd8f6970680c46cda787"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c641b080de494e24d51322d486948d5e8c6ba806","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":13,"id":"9cd12b2b_1a839b75","updated":"2022-01-11 10:51:39.000000000","message":"squashed in https://review.opendev.org/c/openstack/swift/+/824030/1","commit_id":"326ed5decd8fc586c348512dd5b46f90310dd517"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"018a83c90d47747ef19ce937bceaf5ba8f5ccc2e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"ff76a2fb_49bd5a62","updated":"2022-01-28 14:59:51.000000000","message":"this is working great!  let\u0027s get it merged","commit_id":"4572c4c5f8cb281ceb465fa3811d5b9f9992c895"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4484719c62bc8bbac50fe32529326a44aa160b70","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":16,"id":"1f738728_9781ad90","updated":"2022-02-04 12:57:14.000000000","message":"Added some docstring","commit_id":"02d80b15be0e8030035fa30343caa08bf89bb50a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0a29630c9cc09f1352653a39aa0e96dd7869d632","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":16,"id":"1a7b9736_d1229506","updated":"2022-02-07 14:15:33.000000000","message":"recheck","commit_id":"02d80b15be0e8030035fa30343caa08bf89bb50a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":17,"id":"8dc16285_cc0db52f","updated":"2022-02-11 09:22:40.000000000","message":"just trying to clear some of the older comments","commit_id":"763fcc1f3f4767bf07657bc81ad66316a93f2f6e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b5f727b0f477fd29b0ad39f5f5a9108b3b609f31","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":17,"id":"718e976d_eb7babbf","updated":"2022-02-10 00:50:16.000000000","message":"recheck","commit_id":"763fcc1f3f4767bf07657bc81ad66316a93f2f6e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4af96d049c9e440e7c67ef0ffe933ec934191c18","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":20,"id":"57971431_98939efc","updated":"2022-02-21 10:57:23.000000000","message":"added a little more test coverage","commit_id":"51da2543ca532204b5b141948dde3a6216c41cf8"}],"swift/obj/updater.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"d9a6e808bd5986f020b4771fae648969967dcab5","unresolved":true,"context_lines":[{"line_number":156,"context_line":"                self.deferred_elements +\u003d 1"},{"line_number":157,"context_line":"                if self.deferred_elements \u003e\u003d self.max_deferred_elements:"},{"line_number":158,"context_line":"                    for bucket in self.buckets:"},{"line_number":159,"context_line":"                        bucket.close()"},{"line_number":160,"context_line":"                # TODO: if we put buckets into a wait_until-sorted queue then"},{"line_number":161,"context_line":"                # we could sleep until the first in queue is ready, because we"},{"line_number":162,"context_line":"                # know that nothing more is going to be sent before then."}],"source_content_type":"text/x-python","patch_set":2,"id":"d784cb4b_8b51df5d","line":159,"updated":"2021-12-14 23:20:19.000000000","message":"If we\u0027re going to implement a \"keep appending and popping off old updates\" statergy, then bucket.close() problaby isn\u0027t required. Rather we want to trigger some global pop/append flag somewhere so the buckets know.\n\nOption1: pop off the oldest in the same bucket the new update is for?\n\nOption2: need to find the oldest bucket (bucket with the oldest opened update) and pop.","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b55efd62cb1252f0bd911a54c59bcdaafdab8721","unresolved":true,"context_lines":[{"line_number":156,"context_line":"                self.deferred_elements +\u003d 1"},{"line_number":157,"context_line":"                if self.deferred_elements \u003e\u003d self.max_deferred_elements:"},{"line_number":158,"context_line":"                    for bucket in self.buckets:"},{"line_number":159,"context_line":"                        bucket.close()"},{"line_number":160,"context_line":"                # TODO: if we put buckets into a wait_until-sorted queue then"},{"line_number":161,"context_line":"                # we could sleep until the first in queue is ready, because we"},{"line_number":162,"context_line":"                # know that nothing more is going to be sent before then."}],"source_content_type":"text/x-python","patch_set":2,"id":"8971bbe1_79779016","line":159,"updated":"2021-12-15 01:03:47.000000000","message":"Locking in these sizes early feels a little weird, but I guess the concern was not wanting to fill a global queue then make a bunch of per-bucket lists, too.","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":156,"context_line":"                self.deferred_elements +\u003d 1"},{"line_number":157,"context_line":"                if self.deferred_elements \u003e\u003d self.max_deferred_elements:"},{"line_number":158,"context_line":"                    for bucket in self.buckets:"},{"line_number":159,"context_line":"                        bucket.close()"},{"line_number":160,"context_line":"                # TODO: if we put buckets into a wait_until-sorted queue then"},{"line_number":161,"context_line":"                # we could sleep until the first in queue is ready, because we"},{"line_number":162,"context_line":"                # know that nothing more is going to be sent before then."}],"source_content_type":"text/x-python","patch_set":2,"id":"92b850d3_9812a026","line":159,"in_reply_to":"797f8316_60fd06c7","updated":"2022-02-11 09:22:40.000000000","message":"Done","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c147bce4e45317c074557fa02dc2476e5d47af60","unresolved":true,"context_lines":[{"line_number":156,"context_line":"                self.deferred_elements +\u003d 1"},{"line_number":157,"context_line":"                if self.deferred_elements \u003e\u003d self.max_deferred_elements:"},{"line_number":158,"context_line":"                    for bucket in self.buckets:"},{"line_number":159,"context_line":"                        bucket.close()"},{"line_number":160,"context_line":"                # TODO: if we put buckets into a wait_until-sorted queue then"},{"line_number":161,"context_line":"                # we could sleep until the first in queue is ready, because we"},{"line_number":162,"context_line":"                # know that nothing more is going to be sent before then."}],"source_content_type":"text/x-python","patch_set":2,"id":"797f8316_60fd06c7","line":159,"in_reply_to":"8971bbe1_79779016","updated":"2021-12-15 10:32:13.000000000","message":"I agree that it would be better to pop-and-drop the *globally* oldest deferral rather than the per-bucket oldest","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":156,"context_line":"                self.deferred_elements +\u003d 1"},{"line_number":157,"context_line":"                if self.deferred_elements \u003e\u003d self.max_deferred_elements:"},{"line_number":158,"context_line":"                    for bucket in self.buckets:"},{"line_number":159,"context_line":"                        bucket.close()"},{"line_number":160,"context_line":"                # TODO: if we put buckets into a wait_until-sorted queue then"},{"line_number":161,"context_line":"                # we could sleep until the first in queue is ready, because we"},{"line_number":162,"context_line":"                # know that nothing more is going to be sent before then."}],"source_content_type":"text/x-python","patch_set":2,"id":"35099c98_6c110690","line":159,"in_reply_to":"9d529c46_ec6c3ea3","updated":"2022-02-11 09:22:40.000000000","message":"Done","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c147bce4e45317c074557fa02dc2476e5d47af60","unresolved":true,"context_lines":[{"line_number":156,"context_line":"                self.deferred_elements +\u003d 1"},{"line_number":157,"context_line":"                if self.deferred_elements \u003e\u003d self.max_deferred_elements:"},{"line_number":158,"context_line":"                    for bucket in self.buckets:"},{"line_number":159,"context_line":"                        bucket.close()"},{"line_number":160,"context_line":"                # TODO: if we put buckets into a wait_until-sorted queue then"},{"line_number":161,"context_line":"                # we could sleep until the first in queue is ready, because we"},{"line_number":162,"context_line":"                # know that nothing more is going to be sent before then."}],"source_content_type":"text/x-python","patch_set":2,"id":"9d529c46_ec6c3ea3","line":159,"in_reply_to":"d784cb4b_8b51df5d","updated":"2021-12-15 10:32:13.000000000","message":"option 1 is the current patch?\n\noption 2 sounds better","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"7da3b943e608288a98cc9c1d25a6469837f74d35","unresolved":true,"context_lines":[{"line_number":163,"context_line":"            # TODO: if shortest bucket queue * bucket_update_delta would take"},{"line_number":164,"context_line":"            # us past the end of the interval then we could choose to stop"},{"line_number":165,"context_line":"            # reading from disk and just drain the buckets for rest of the"},{"line_number":166,"context_line":"            # interval"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"        # queue the buckets with deferred elements in the chronological order"},{"line_number":169,"context_line":"        # in which they are ready to serve an element"}],"source_content_type":"text/x-python","patch_set":2,"id":"c4950a2a_d55deb65","line":166,"updated":"2021-12-15 00:27:33.000000000","message":"Well currently we don\u0027t stop an update sweep once we hit the interval do we? I.e we don\u0027t stop reading the disk until the iterator is exhausted. If we wanted to stop processing when we hit the interval, then we can do that, but I don\u0027t think it\u0027s something we do.","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c147bce4e45317c074557fa02dc2476e5d47af60","unresolved":true,"context_lines":[{"line_number":163,"context_line":"            # TODO: if shortest bucket queue * bucket_update_delta would take"},{"line_number":164,"context_line":"            # us past the end of the interval then we could choose to stop"},{"line_number":165,"context_line":"            # reading from disk and just drain the buckets for rest of the"},{"line_number":166,"context_line":"            # interval"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"        # queue the buckets with deferred elements in the chronological order"},{"line_number":169,"context_line":"        # in which they are ready to serve an element"}],"source_content_type":"text/x-python","patch_set":2,"id":"cf99b96e_c66963fa","line":166,"in_reply_to":"5f56b625_7ba9bd87","updated":"2021-12-15 10:32:13.000000000","message":"true, true","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b55efd62cb1252f0bd911a54c59bcdaafdab8721","unresolved":true,"context_lines":[{"line_number":163,"context_line":"            # TODO: if shortest bucket queue * bucket_update_delta would take"},{"line_number":164,"context_line":"            # us past the end of the interval then we could choose to stop"},{"line_number":165,"context_line":"            # reading from disk and just drain the buckets for rest of the"},{"line_number":166,"context_line":"            # interval"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"        # queue the buckets with deferred elements in the chronological order"},{"line_number":169,"context_line":"        # in which they are ready to serve an element"}],"source_content_type":"text/x-python","patch_set":2,"id":"5f56b625_7ba9bd87","line":166,"in_reply_to":"c4950a2a_d55deb65","updated":"2021-12-15 01:03:47.000000000","message":"Yeah, I\u0027m with Matt -- we\u0027re looking for ways to productively spend the time we\u0027d otherwise spend sleeping because interval is too high -- if interval is low enough that we never get to deferred work, that\u0027s fine, let it get processed on the next sweep.","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":163,"context_line":"            # TODO: if shortest bucket queue * bucket_update_delta would take"},{"line_number":164,"context_line":"            # us past the end of the interval then we could choose to stop"},{"line_number":165,"context_line":"            # reading from disk and just drain the buckets for rest of the"},{"line_number":166,"context_line":"            # interval"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"        # queue the buckets with deferred elements in the chronological order"},{"line_number":169,"context_line":"        # in which they are ready to serve an element"}],"source_content_type":"text/x-python","patch_set":2,"id":"b4e2beb3_55d8d8de","line":166,"in_reply_to":"cf99b96e_c66963fa","updated":"2022-02-11 09:22:40.000000000","message":"Done","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b55efd62cb1252f0bd911a54c59bcdaafdab8721","unresolved":true,"context_lines":[{"line_number":188,"context_line":"                if len(bucket) \u003e 0:"},{"line_number":189,"context_line":"                    # bucket has more deferred elements, re-insert in queue in"},{"line_number":190,"context_line":"                    # correct chronological position"},{"line_number":191,"context_line":"                    p_queue.put(bucket.wait_until(), bucket)"},{"line_number":192,"context_line":"                return item"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"        if undrained_elements:"}],"source_content_type":"text/x-python","patch_set":2,"id":"a8336e0b_732591a8","line":191,"updated":"2021-12-15 01:03:47.000000000","message":"I think it still needs to be a single arg:\n\n p_queue.put((bucket.wait_until(), bucket))","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"d9a6e808bd5986f020b4771fae648969967dcab5","unresolved":true,"context_lines":[{"line_number":188,"context_line":"                if len(bucket) \u003e 0:"},{"line_number":189,"context_line":"                    # bucket has more deferred elements, re-insert in queue in"},{"line_number":190,"context_line":"                    # correct chronological position"},{"line_number":191,"context_line":"                    p_queue.put(bucket.wait_until(), bucket)"},{"line_number":192,"context_line":"                return item"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"        if undrained_elements:"}],"source_content_type":"text/x-python","patch_set":2,"id":"61ebbca2_a7a584d1","line":191,"updated":"2021-12-14 23:20:19.000000000","message":"priority queuing as a whole bucket!! Nice.","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":188,"context_line":"                if len(bucket) \u003e 0:"},{"line_number":189,"context_line":"                    # bucket has more deferred elements, re-insert in queue in"},{"line_number":190,"context_line":"                    # correct chronological position"},{"line_number":191,"context_line":"                    p_queue.put(bucket.wait_until(), bucket)"},{"line_number":192,"context_line":"                return item"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"        if undrained_elements:"}],"source_content_type":"text/x-python","patch_set":2,"id":"56833d8b_26e1f7d7","line":191,"in_reply_to":"61ebbca2_a7a584d1","updated":"2022-02-11 09:22:40.000000000","message":"Ack","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"24e5ab907990e76fe201028d9a3e0c0088fbac44","unresolved":true,"context_lines":[{"line_number":188,"context_line":"                if len(bucket) \u003e 0:"},{"line_number":189,"context_line":"                    # bucket has more deferred elements, re-insert in queue in"},{"line_number":190,"context_line":"                    # correct chronological position"},{"line_number":191,"context_line":"                    p_queue.put(bucket.wait_until(), bucket)"},{"line_number":192,"context_line":"                return item"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"        if undrained_elements:"}],"source_content_type":"text/x-python","patch_set":2,"id":"f3ed77bd_4b96e32c","line":191,"in_reply_to":"a8336e0b_732591a8","updated":"2021-12-15 01:11:06.000000000","message":"I\u0027ve added some bucket.__lt__ which orders by wait_until, which should be enough to just add the bucket now. Sending a follow up in a few minutes.","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":188,"context_line":"                if len(bucket) \u003e 0:"},{"line_number":189,"context_line":"                    # bucket has more deferred elements, re-insert in queue in"},{"line_number":190,"context_line":"                    # correct chronological position"},{"line_number":191,"context_line":"                    p_queue.put(bucket.wait_until(), bucket)"},{"line_number":192,"context_line":"                return item"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"        if undrained_elements:"}],"source_content_type":"text/x-python","patch_set":2,"id":"56a48941_9f0c846b","line":191,"in_reply_to":"e8f2368e_523e9d96","updated":"2022-02-11 09:22:40.000000000","message":"Done","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c147bce4e45317c074557fa02dc2476e5d47af60","unresolved":true,"context_lines":[{"line_number":188,"context_line":"                if len(bucket) \u003e 0:"},{"line_number":189,"context_line":"                    # bucket has more deferred elements, re-insert in queue in"},{"line_number":190,"context_line":"                    # correct chronological position"},{"line_number":191,"context_line":"                    p_queue.put(bucket.wait_until(), bucket)"},{"line_number":192,"context_line":"                return item"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"        if undrained_elements:"}],"source_content_type":"text/x-python","patch_set":2,"id":"e8f2368e_523e9d96","line":191,"in_reply_to":"f3ed77bd_4b96e32c","updated":"2021-12-15 10:32:13.000000000","message":"sorry I was obviously tired when hacking this part and obviously it has not test coverage yet","commit_id":"2c72e9a7190aba9d80e80fd72001dbbf5e463018"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8278b9dc8bbf482d19cf43b5676a53d8d07c3dfd","unresolved":true,"context_lines":[{"line_number":12,"context_line":"# implied."},{"line_number":13,"context_line":"# See the License for the specific language governing permissions and"},{"line_number":14,"context_line":"# limitations under the License."},{"line_number":15,"context_line":"import queue"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"import eventlet"},{"line_number":18,"context_line":"import six.moves.cPickle as pickle"}],"source_content_type":"text/x-python","patch_set":6,"id":"ce3ff433_dadece59","line":15,"updated":"2021-12-15 23:57:02.000000000","message":"from six.moves import queue","commit_id":"6660cc4658484c14c58544ad7e453ed664c69bd6"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":12,"context_line":"# implied."},{"line_number":13,"context_line":"# See the License for the specific language governing permissions and"},{"line_number":14,"context_line":"# limitations under the License."},{"line_number":15,"context_line":"import queue"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"import eventlet"},{"line_number":18,"context_line":"import six.moves.cPickle as pickle"}],"source_content_type":"text/x-python","patch_set":6,"id":"257c8d62_bc4fbd4d","line":15,"in_reply_to":"ce3ff433_dadece59","updated":"2022-02-11 09:22:40.000000000","message":"Done","commit_id":"6660cc4658484c14c58544ad7e453ed664c69bd6"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8278b9dc8bbf482d19cf43b5676a53d8d07c3dfd","unresolved":true,"context_lines":[{"line_number":163,"context_line":"            bucket \u003d self.buckets_ordered_by_readiness.get_nowait()"},{"line_number":164,"context_line":"            if now \u003c self.drain_until:"},{"line_number":165,"context_line":"                # wait for next element to be ready"},{"line_number":166,"context_line":"                eventlet.sleep(max(0, bucket.wait_until - now))"},{"line_number":167,"context_line":"                # drain the most recently deferred element"},{"line_number":168,"context_line":"                item \u003d bucket.deque.pop()"},{"line_number":169,"context_line":"                bucket.last_time \u003d bucket.wait_until"}],"source_content_type":"text/x-python","patch_set":6,"id":"3489711e_df4d6fe5","line":166,"updated":"2021-12-15 23:57:02.000000000","message":"In other places, we use time.sleep() -- isn\u0027t it already monkey-patched?","commit_id":"6660cc4658484c14c58544ad7e453ed664c69bd6"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":163,"context_line":"            bucket \u003d self.buckets_ordered_by_readiness.get_nowait()"},{"line_number":164,"context_line":"            if now \u003c self.drain_until:"},{"line_number":165,"context_line":"                # wait for next element to be ready"},{"line_number":166,"context_line":"                eventlet.sleep(max(0, bucket.wait_until - now))"},{"line_number":167,"context_line":"                # drain the most recently deferred element"},{"line_number":168,"context_line":"                item \u003d bucket.deque.pop()"},{"line_number":169,"context_line":"                bucket.last_time \u003d bucket.wait_until"}],"source_content_type":"text/x-python","patch_set":6,"id":"3106e4d9_dc13f887","line":166,"in_reply_to":"3489711e_df4d6fe5","updated":"2022-02-11 09:22:40.000000000","message":"Ack","commit_id":"6660cc4658484c14c58544ad7e453ed664c69bd6"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"a493b27dc06f90cc1081a5eb49b3daf449a0c6e4","unresolved":true,"context_lines":[{"line_number":407,"context_line":"        def skip_counting_f(update_ctx):"},{"line_number":408,"context_line":"            # in the future we could defer update_ctx"},{"line_number":409,"context_line":"            self.stats.skips +\u003d 1"},{"line_number":410,"context_line":"            self.logger.increment(\"skips\")"},{"line_number":411,"context_line":""},{"line_number":412,"context_line":"        ap_iter \u003d RateLimitedIterator("},{"line_number":413,"context_line":"            self._iter_async_pendings(device),"}],"source_content_type":"text/x-python","patch_set":10,"id":"fa738f4f_7c2ee172","side":"PARENT","line":410,"updated":"2022-01-10 16:32:18.000000000","message":"I think moving the stats into the iterator was a big win - less complex","commit_id":"de888629817a2a326b6e8dc66edb0ce3168818a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":407,"context_line":"        def skip_counting_f(update_ctx):"},{"line_number":408,"context_line":"            # in the future we could defer update_ctx"},{"line_number":409,"context_line":"            self.stats.skips +\u003d 1"},{"line_number":410,"context_line":"            self.logger.increment(\"skips\")"},{"line_number":411,"context_line":""},{"line_number":412,"context_line":"        ap_iter \u003d RateLimitedIterator("},{"line_number":413,"context_line":"            self._iter_async_pendings(device),"}],"source_content_type":"text/x-python","patch_set":10,"id":"438de88b_5644c59f","side":"PARENT","line":410,"in_reply_to":"fa738f4f_7c2ee172","updated":"2022-02-11 09:22:40.000000000","message":"Ack","commit_id":"de888629817a2a326b6e8dc66edb0ce3168818a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"a493b27dc06f90cc1081a5eb49b3daf449a0c6e4","unresolved":true,"context_lines":[{"line_number":81,"context_line":"    :param drain_until: time at which any remaining deferred elements must be"},{"line_number":82,"context_line":"        skipped and the iterator stops. Once the wrapped iterator has been"},{"line_number":83,"context_line":"        exhausted, this iterator will drain deferred elements from its buckets"},{"line_number":84,"context_line":"        until either all buckets have drained or this time is reached."},{"line_number":85,"context_line":"    \"\"\""},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    def __init__(self, update_iterable, logger, num_buckets,"}],"source_content_type":"text/x-python","patch_set":10,"id":"7ba68111_69a9c476","line":84,"updated":"2022-01-10 16:32:18.000000000","message":"I like how this is explicit and passed in\n\n... even tho ops only controls this behavior indrectly through cycle_time, I think it will be sufficient and mostly good enough by default without thinking about what you really want on different node hardware too hard.","commit_id":"5798782b528afa8e5665f031df40478f33f43147"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":81,"context_line":"    :param drain_until: time at which any remaining deferred elements must be"},{"line_number":82,"context_line":"        skipped and the iterator stops. Once the wrapped iterator has been"},{"line_number":83,"context_line":"        exhausted, this iterator will drain deferred elements from its buckets"},{"line_number":84,"context_line":"        until either all buckets have drained or this time is reached."},{"line_number":85,"context_line":"    \"\"\""},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    def __init__(self, update_iterable, logger, num_buckets,"}],"source_content_type":"text/x-python","patch_set":10,"id":"01c128eb_ea0aa423","line":84,"in_reply_to":"7ba68111_69a9c476","updated":"2022-02-11 09:22:40.000000000","message":"Ack","commit_id":"5798782b528afa8e5665f031df40478f33f43147"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"a493b27dc06f90cc1081a5eb49b3daf449a0c6e4","unresolved":true,"context_lines":[{"line_number":548,"context_line":"        self.logger.timing_since(\u0027timing\u0027, start_time)"},{"line_number":549,"context_line":"        self.stats.deferrals \u003d ap_iter.deferrals"},{"line_number":550,"context_line":"        self.stats.drains \u003d ap_iter.drains"},{"line_number":551,"context_line":"        self.stats.skips \u003d ap_iter.skips"},{"line_number":552,"context_line":"        sweep_totals \u003d self.stats.since(start_stats)"},{"line_number":553,"context_line":"        self.logger.info("},{"line_number":554,"context_line":"            (\u0027Object update sweep completed on %(device)s \u0027"}],"source_content_type":"text/x-python","patch_set":10,"id":"7c522ff3_c06f9d6a","line":551,"updated":"2022-01-10 16:32:18.000000000","message":"I\u0027m not sure how DRY out the stats back-propogration though; maybe passing self.stats into bucketizedUpdateSkippingLimiter so it can update them directly.\n\nhttps://review.opendev.org/c/openstack/swift/+/824030 maybe?","commit_id":"5798782b528afa8e5665f031df40478f33f43147"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":548,"context_line":"        self.logger.timing_since(\u0027timing\u0027, start_time)"},{"line_number":549,"context_line":"        self.stats.deferrals \u003d ap_iter.deferrals"},{"line_number":550,"context_line":"        self.stats.drains \u003d ap_iter.drains"},{"line_number":551,"context_line":"        self.stats.skips \u003d ap_iter.skips"},{"line_number":552,"context_line":"        sweep_totals \u003d self.stats.since(start_stats)"},{"line_number":553,"context_line":"        self.logger.info("},{"line_number":554,"context_line":"            (\u0027Object update sweep completed on %(device)s \u0027"}],"source_content_type":"text/x-python","patch_set":10,"id":"5c22248d_6c5da469","line":551,"in_reply_to":"7c522ff3_c06f9d6a","updated":"2022-02-11 09:22:40.000000000","message":"Ack","commit_id":"5798782b528afa8e5665f031df40478f33f43147"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"9757ec2462641bc445e70801468ea00845b288a5","unresolved":true,"context_lines":[{"line_number":183,"context_line":"        if undrained_elements:"},{"line_number":184,"context_line":"            # report final batch of skipped elements"},{"line_number":185,"context_line":"            self.stats.skips +\u003d len(undrained_elements)"},{"line_number":186,"context_line":"            self.logger.update_stats(\"skips\", len(undrained_elements))"},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"        raise StopIteration()"},{"line_number":189,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"e25cb3d9_449784b3","line":186,"updated":"2022-01-26 18:42:14.000000000","message":"I\u0027m starting to think we may want to give this some other name. When trying to make graphs to monitor updater health, I find myself wanting to see how frequently the ratelimiting is kicking in. Previously, I could look at something like\n\n sum(skips) / sum(skips|successes|failures)\n\nNow I need to do something more like\n\n sum(skips|deferrals) / sum(skips|deferrals|successes|failures)\n\nto get a comparable graph, *but* there are these funny spikes when a disk full of asyncs finishes its sweep... and I think I\u0027m double-counting since *these* skips were already deferred.","commit_id":"326ed5decd8fc586c348512dd5b46f90310dd517"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"74d90e13577f6afb259d1f0b9ddfb4d743e9fa66","unresolved":true,"context_lines":[{"line_number":183,"context_line":"        if undrained_elements:"},{"line_number":184,"context_line":"            # report final batch of skipped elements"},{"line_number":185,"context_line":"            self.stats.skips +\u003d len(undrained_elements)"},{"line_number":186,"context_line":"            self.logger.update_stats(\"skips\", len(undrained_elements))"},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"        raise StopIteration()"},{"line_number":189,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"ea60c406_26917229","line":186,"in_reply_to":"757508f6_29d003eb","updated":"2022-01-31 11:24:18.000000000","message":"I think you were actually double-counting *all* the skips. \n\nAssuming that max_deferred_elements \u003e 0 then every update that is rate-limited is counted as a deferral. In addition, every update that was a deferral but is not eventually sent is counted as a skip. There may be a burst of skips at the end of the cycle when there are updates that have not drained, but there can also be trickle of skips as previous deferrals are evicted from the queue.\n\nThe final fate of all updates is one of skip|success|failure.\nA subset of updates also get counted as deferrals, and a subset of those as drains.\n\nSo a measure of what proportion of updates are ratelimited could be:\n\n  ratelimited \u003d deferrals / (skips+successes+failures) [1]\n\nbut this will have distortion w.r.t. real time because skips can burst at the end of cycle.\n\nTo get a better real time view we could use:\n\n  ratelimited \u003d deferrals / (deferrals+successes+failures-drains) [2]\n\nNote: drains are subtracted to avoid double-counting: drains are deferrals that have gone on to also be counted as success|failure. Also note that [2] is equivalent to [1] because skips \u003d\u003d deferrals - drains.\n\nIf we want something simpler we\u0027d need to count the number of updates read from disk, then we could just use:\n\n  ratelimited \u003d deferrals / reads [3]\n\nSeparately, a measure of the proportion of updates *not sent* in the current cycle could be:\n\n  skipped \u003d skips / (skips+successes+failures) [4]\n\nwhich might have bursts at end of cycles.\n\nThere is a glitch however, when max_deferred_elements \u003d\u003d 0. In this case, we would expect:\n\n  ratelimited \u003d\u003d skipped\n\nbut deferrals is never incremented so ratelimited is 0 (as defined by [1] above). This inconsistency could be fixed by incrementing deferrals even when the deferred queue is size 0 i.e. \"deferrals are immediately skips\".","commit_id":"326ed5decd8fc586c348512dd5b46f90310dd517"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":183,"context_line":"        if undrained_elements:"},{"line_number":184,"context_line":"            # report final batch of skipped elements"},{"line_number":185,"context_line":"            self.stats.skips +\u003d len(undrained_elements)"},{"line_number":186,"context_line":"            self.logger.update_stats(\"skips\", len(undrained_elements))"},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"        raise StopIteration()"},{"line_number":189,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"63bd787e_a8c920ea","line":186,"in_reply_to":"cba92c99_c5518f51","updated":"2022-02-11 09:22:40.000000000","message":"Ack","commit_id":"326ed5decd8fc586c348512dd5b46f90310dd517"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"018a83c90d47747ef19ce937bceaf5ba8f5ccc2e","unresolved":true,"context_lines":[{"line_number":183,"context_line":"        if undrained_elements:"},{"line_number":184,"context_line":"            # report final batch of skipped elements"},{"line_number":185,"context_line":"            self.stats.skips +\u003d len(undrained_elements)"},{"line_number":186,"context_line":"            self.logger.update_stats(\"skips\", len(undrained_elements))"},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"        raise StopIteration()"},{"line_number":189,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"757508f6_29d003eb","line":186,"in_reply_to":"e25cb3d9_449784b3","updated":"2022-01-28 14:59:51.000000000","message":"100%","commit_id":"326ed5decd8fc586c348512dd5b46f90310dd517"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c2c3a3f7b78034190ba0e93b8c555f3824de670c","unresolved":true,"context_lines":[{"line_number":183,"context_line":"        if undrained_elements:"},{"line_number":184,"context_line":"            # report final batch of skipped elements"},{"line_number":185,"context_line":"            self.stats.skips +\u003d len(undrained_elements)"},{"line_number":186,"context_line":"            self.logger.update_stats(\"skips\", len(undrained_elements))"},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"        raise StopIteration()"},{"line_number":189,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"cba92c99_c5518f51","line":186,"in_reply_to":"ea60c406_26917229","updated":"2022-02-08 20:15:24.000000000","message":"I still wonder a little if it\u0027s worth separating the \"deferral queue overflowed\" skips (which we expect to be smeared out over time) from the \"no time left to drain\" skips (which will be inherently bursty).\n\nIDK -- I think what I *really* want is some way to amortize the burst over time, but I don\u0027t think there\u0027s a reasonable way to *do* that. So I\u0027m trying to make it easy to just *drop* the bursts, then try to find some rationalization for doing so later...","commit_id":"326ed5decd8fc586c348512dd5b46f90310dd517"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"74d90e13577f6afb259d1f0b9ddfb4d743e9fa66","unresolved":true,"context_lines":[{"line_number":183,"context_line":"        if undrained_elements:"},{"line_number":184,"context_line":"            # report final batch of skipped elements"},{"line_number":185,"context_line":"            self.stats.skips +\u003d len(undrained_elements)"},{"line_number":186,"context_line":"            self.logger.update_stats(\"undrained\", len(undrained_elements))"},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"        raise StopIteration()"},{"line_number":189,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"96a1792a_2a72fc47","line":186,"updated":"2022-01-31 11:24:18.000000000","message":"I\u0027m not sure this helps with Tim\u0027s concern about interpreting the stats","commit_id":"4572c4c5f8cb281ceb465fa3811d5b9f9992c895"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":183,"context_line":"        if undrained_elements:"},{"line_number":184,"context_line":"            # report final batch of skipped elements"},{"line_number":185,"context_line":"            self.stats.skips +\u003d len(undrained_elements)"},{"line_number":186,"context_line":"            self.logger.update_stats(\"undrained\", len(undrained_elements))"},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"        raise StopIteration()"},{"line_number":189,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"b7623eb9_ff2b70ae","line":186,"in_reply_to":"96a1792a_2a72fc47","updated":"2022-02-11 09:22:40.000000000","message":"Done","commit_id":"4572c4c5f8cb281ceb465fa3811d5b9f9992c895"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c2c3a3f7b78034190ba0e93b8c555f3824de670c","unresolved":true,"context_lines":[{"line_number":89,"context_line":"      * The `drains` stat is incremented for each rate-limited update that is"},{"line_number":90,"context_line":"        eventually yielded."},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    Consequently, when this iterator terminates, the the sum of `skips` and"},{"line_number":93,"context_line":"    `drains` is equal to the number of `deferrals`."},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"    :param update_iterable: an async_pending update iterable"}],"source_content_type":"text/x-python","patch_set":16,"id":"d068da17_5ae76f06","line":92,"range":{"start_line":92,"start_character":49,"end_line":92,"end_character":56},"updated":"2022-02-08 20:15:24.000000000","message":"the","commit_id":"02d80b15be0e8030035fa30343caa08bf89bb50a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":89,"context_line":"      * The `drains` stat is incremented for each rate-limited update that is"},{"line_number":90,"context_line":"        eventually yielded."},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    Consequently, when this iterator terminates, the the sum of `skips` and"},{"line_number":93,"context_line":"    `drains` is equal to the number of `deferrals`."},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"    :param update_iterable: an async_pending update iterable"}],"source_content_type":"text/x-python","patch_set":16,"id":"d78eb8ba_c72ebdce","line":92,"range":{"start_line":92,"start_character":49,"end_line":92,"end_character":56},"in_reply_to":"d068da17_5ae76f06","updated":"2022-02-11 09:22:40.000000000","message":"Done","commit_id":"02d80b15be0e8030035fa30343caa08bf89bb50a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c2c3a3f7b78034190ba0e93b8c555f3824de670c","unresolved":true,"context_lines":[{"line_number":153,"context_line":"                return update_ctx"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"            self.stats.deferrals +\u003d 1"},{"line_number":156,"context_line":"            self.logger.increment(\"deferrals\")"},{"line_number":157,"context_line":"            if self.max_deferred_elements \u003e 0:"},{"line_number":158,"context_line":"                if len(self.deferred_buckets) \u003e\u003d self.max_deferred_elements:"},{"line_number":159,"context_line":"                    # create space to defer this update by popping the least"}],"source_content_type":"text/x-python","patch_set":16,"id":"f0634af6_6d6ed86e","line":156,"updated":"2022-02-08 20:15:24.000000000","message":"Deferrals are the new skips! I think I like it.","commit_id":"02d80b15be0e8030035fa30343caa08bf89bb50a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":153,"context_line":"                return update_ctx"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"            self.stats.deferrals +\u003d 1"},{"line_number":156,"context_line":"            self.logger.increment(\"deferrals\")"},{"line_number":157,"context_line":"            if self.max_deferred_elements \u003e 0:"},{"line_number":158,"context_line":"                if len(self.deferred_buckets) \u003e\u003d self.max_deferred_elements:"},{"line_number":159,"context_line":"                    # create space to defer this update by popping the least"}],"source_content_type":"text/x-python","patch_set":16,"id":"61737d6f_cadee143","line":156,"in_reply_to":"f0634af6_6d6ed86e","updated":"2022-02-11 09:22:40.000000000","message":"Ack","commit_id":"02d80b15be0e8030035fa30343caa08bf89bb50a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c2c3a3f7b78034190ba0e93b8c555f3824de670c","unresolved":true,"context_lines":[{"line_number":221,"context_line":""},{"line_number":222,"context_line":"    A measure of the rate at which updates are being rate-limited is:"},{"line_number":223,"context_line":""},{"line_number":224,"context_line":"        deferrals / (deferrals + successes + failures - drains)"},{"line_number":225,"context_line":""},{"line_number":226,"context_line":"    A measure of the rate at which updates are not being sent during a sweep"},{"line_number":227,"context_line":"    is:"}],"source_content_type":"text/x-python","patch_set":16,"id":"10ef53dd_c173209e","line":224,"range":{"start_line":224,"start_character":54,"end_line":224,"end_character":62},"updated":"2022-02-08 20:15:24.000000000","message":"This term bugs me a bit. I\u0027m reasonably convinced that it can\u0027t cause this derived metric to go negative *by the end of a cycle*, since any drains will either succeed or fail. What about the \"instantaneous\" metric though? If we\u0027ve drained some updates, and have the requests still in-flight...\n\nOTOH, maybe it\u0027s moot anyway -- at the point in a cycle where we\u0027re draining, deferrals *must* be zero. at least, for the one node... :-/","commit_id":"02d80b15be0e8030035fa30343caa08bf89bb50a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":221,"context_line":""},{"line_number":222,"context_line":"    A measure of the rate at which updates are being rate-limited is:"},{"line_number":223,"context_line":""},{"line_number":224,"context_line":"        deferrals / (deferrals + successes + failures - drains)"},{"line_number":225,"context_line":""},{"line_number":226,"context_line":"    A measure of the rate at which updates are not being sent during a sweep"},{"line_number":227,"context_line":"    is:"}],"source_content_type":"text/x-python","patch_set":16,"id":"81c287f7_dde83752","line":224,"range":{"start_line":224,"start_character":54,"end_line":224,"end_character":62},"in_reply_to":"10ef53dd_c173209e","updated":"2022-02-11 09:22:40.000000000","message":"Ack","commit_id":"02d80b15be0e8030035fa30343caa08bf89bb50a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c2c3a3f7b78034190ba0e93b8c555f3824de670c","unresolved":true,"context_lines":[{"line_number":224,"context_line":"        deferrals / (deferrals + successes + failures - drains)"},{"line_number":225,"context_line":""},{"line_number":226,"context_line":"    A measure of the rate at which updates are not being sent during a sweep"},{"line_number":227,"context_line":"    is:"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"        skips / (skips + successes + failures)"},{"line_number":230,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":16,"id":"498615e9_b6d1cb4e","line":227,"updated":"2022-02-08 20:15:24.000000000","message":"Might be worth noting that this tends to get back-weighted in a cycle.","commit_id":"02d80b15be0e8030035fa30343caa08bf89bb50a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"17a997929f917f751d7a60748b6cf4a336e114c0","unresolved":true,"context_lines":[{"line_number":56,"context_line":"    def __len__(self):"},{"line_number":57,"context_line":"        return len(self.deque)"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"    def __lt__(self, other):"},{"line_number":60,"context_line":"        # used to sort buckets by readiness"},{"line_number":61,"context_line":"        if isinstance(other, RateLimiterBucket):"},{"line_number":62,"context_line":"            return self.wait_until \u003c other.wait_until"}],"source_content_type":"text/x-python","patch_set":17,"id":"a1344d7d_c9bd23ba","line":59,"updated":"2022-02-11 05:14:14.000000000","message":"I wonder if we should also define __lte__, __gt__, __gte__...","commit_id":"763fcc1f3f4767bf07657bc81ad66316a93f2f6e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"17a997929f917f751d7a60748b6cf4a336e114c0","unresolved":true,"context_lines":[{"line_number":127,"context_line":"        self.deferred_buckets \u003d deque()"},{"line_number":128,"context_line":"        self.drain_until \u003d drain_until"},{"line_number":129,"context_line":"        self.salt \u003d str(uuid.uuid4())"},{"line_number":130,"context_line":"        # an array might be more efficient; but this is pretty cheap"},{"line_number":131,"context_line":"        self.buckets \u003d [RateLimiterBucket(self.bucket_update_delta)"},{"line_number":132,"context_line":"                        for _ in range(self.num_buckets)]"},{"line_number":133,"context_line":"        self.buckets_ordered_by_readiness \u003d None"}],"source_content_type":"text/x-python","patch_set":17,"id":"d3df9757_7e840b8e","line":130,"range":{"start_line":130,"start_character":13,"end_line":130,"end_character":18},"updated":"2022-02-11 05:14:14.000000000","message":"nit: array is off the table, now that we\u0027re not using simple floats.","commit_id":"763fcc1f3f4767bf07657bc81ad66316a93f2f6e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"91e127e9bfeb64079f0a5275fd9b1ea0aee4bb77","unresolved":false,"context_lines":[{"line_number":127,"context_line":"        self.deferred_buckets \u003d deque()"},{"line_number":128,"context_line":"        self.drain_until \u003d drain_until"},{"line_number":129,"context_line":"        self.salt \u003d str(uuid.uuid4())"},{"line_number":130,"context_line":"        # an array might be more efficient; but this is pretty cheap"},{"line_number":131,"context_line":"        self.buckets \u003d [RateLimiterBucket(self.bucket_update_delta)"},{"line_number":132,"context_line":"                        for _ in range(self.num_buckets)]"},{"line_number":133,"context_line":"        self.buckets_ordered_by_readiness \u003d None"}],"source_content_type":"text/x-python","patch_set":17,"id":"5001db02_6079dc3f","line":130,"range":{"start_line":130,"start_character":13,"end_line":130,"end_character":18},"in_reply_to":"d3df9757_7e840b8e","updated":"2022-02-18 23:35:30.000000000","message":"Done","commit_id":"763fcc1f3f4767bf07657bc81ad66316a93f2f6e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"17a997929f917f751d7a60748b6cf4a336e114c0","unresolved":true,"context_lines":[{"line_number":180,"context_line":"            # ready to serve an element"},{"line_number":181,"context_line":"            self.buckets_ordered_by_readiness \u003d queue.PriorityQueue()"},{"line_number":182,"context_line":"            for bucket in self.buckets:"},{"line_number":183,"context_line":"                if len(bucket) \u003e 0:"},{"line_number":184,"context_line":"                    self.buckets_ordered_by_readiness.put(bucket)"},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"        # now drain the buckets..."}],"source_content_type":"text/x-python","patch_set":17,"id":"07d720bd_c03b9b94","line":183,"updated":"2022-02-11 05:14:14.000000000","message":"Might make a good __bool__ ...","commit_id":"763fcc1f3f4767bf07657bc81ad66316a93f2f6e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"91e127e9bfeb64079f0a5275fd9b1ea0aee4bb77","unresolved":false,"context_lines":[{"line_number":180,"context_line":"            # ready to serve an element"},{"line_number":181,"context_line":"            self.buckets_ordered_by_readiness \u003d queue.PriorityQueue()"},{"line_number":182,"context_line":"            for bucket in self.buckets:"},{"line_number":183,"context_line":"                if len(bucket) \u003e 0:"},{"line_number":184,"context_line":"                    self.buckets_ordered_by_readiness.put(bucket)"},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"        # now drain the buckets..."}],"source_content_type":"text/x-python","patch_set":17,"id":"1002703c_95a19015","line":183,"in_reply_to":"07d720bd_c03b9b94","updated":"2022-02-18 23:35:30.000000000","message":"Done","commit_id":"763fcc1f3f4767bf07657bc81ad66316a93f2f6e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"17a997929f917f751d7a60748b6cf4a336e114c0","unresolved":true,"context_lines":[{"line_number":193,"context_line":"                time.sleep(max(0, bucket.wait_until - now))"},{"line_number":194,"context_line":"                # drain the most recently deferred element"},{"line_number":195,"context_line":"                item \u003d bucket.deque.pop()"},{"line_number":196,"context_line":"                bucket.last_time \u003d bucket.wait_until"},{"line_number":197,"context_line":"                if len(bucket) \u003e 0:"},{"line_number":198,"context_line":"                    # bucket has more deferred elements, re-insert in queue in"},{"line_number":199,"context_line":"                    # correct chronological position"}],"source_content_type":"text/x-python","patch_set":17,"id":"457934d0_fc592dd3","line":196,"updated":"2022-02-11 05:14:14.000000000","message":"Not\n\n bucket.last_time \u003d self._get_time()\n\n? bucket.wait_until may be in the past...\n\nnit: Could move this into the if block below; no point updating the last_time if we\u0027re not re-queuing.","commit_id":"763fcc1f3f4767bf07657bc81ad66316a93f2f6e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"91e127e9bfeb64079f0a5275fd9b1ea0aee4bb77","unresolved":false,"context_lines":[{"line_number":193,"context_line":"                time.sleep(max(0, bucket.wait_until - now))"},{"line_number":194,"context_line":"                # drain the most recently deferred element"},{"line_number":195,"context_line":"                item \u003d bucket.deque.pop()"},{"line_number":196,"context_line":"                bucket.last_time \u003d bucket.wait_until"},{"line_number":197,"context_line":"                if len(bucket) \u003e 0:"},{"line_number":198,"context_line":"                    # bucket has more deferred elements, re-insert in queue in"},{"line_number":199,"context_line":"                    # correct chronological position"}],"source_content_type":"text/x-python","patch_set":17,"id":"5355cb64_8d36adc2","line":196,"in_reply_to":"457934d0_fc592dd3","updated":"2022-02-18 23:35:30.000000000","message":"Done","commit_id":"763fcc1f3f4767bf07657bc81ad66316a93f2f6e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"17a997929f917f751d7a60748b6cf4a336e114c0","unresolved":true,"context_lines":[{"line_number":205,"context_line":"                # time to stop iterating: gather all un-drained elements"},{"line_number":206,"context_line":"                undrained_elements.extend(bucket.deque)"},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"        if undrained_elements:"},{"line_number":209,"context_line":"            # report final batch of skipped elements"},{"line_number":210,"context_line":"            self.stats.skips +\u003d len(undrained_elements)"},{"line_number":211,"context_line":"            self.logger.update_stats(\"skips\", len(undrained_elements))"}],"source_content_type":"text/x-python","patch_set":17,"id":"557666c1_9cd6d840","line":208,"updated":"2022-02-11 05:14:14.000000000","message":"Idea for future improvement! Offer some feedback to the (long-lived) updater here, telling it to reduce its target queue size. Conversely, if there are no undrained elements and we hit our max queue size, tell it to increase its target queue size.\n\nExisting config option becomes a hard limit on how large we\u0027re willing to let the queue grow, maybe add a config option for starting size (or just hardcode it to something like 10%).\n\nTwo advantages:\n\n* reduced memory consumption when we\u0027re not in the pathological case\n* reduced skip spikes at the end of the cycle","commit_id":"763fcc1f3f4767bf07657bc81ad66316a93f2f6e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"17a997929f917f751d7a60748b6cf4a336e114c0","unresolved":true,"context_lines":[{"line_number":242,"context_line":""},{"line_number":243,"context_line":"    def copy(self):"},{"line_number":244,"context_line":"        return type(self)(self.errors, self.failures, self.quarantines,"},{"line_number":245,"context_line":"                          self.successes, self.unlinks, self.redirects,"},{"line_number":246,"context_line":"                          self.skips, self.deferrals, self.drains)"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"    def since(self, other):"}],"source_content_type":"text/x-python","patch_set":17,"id":"7d3916cf_b5dfbff7","line":245,"range":{"start_line":245,"start_character":61,"end_line":245,"end_character":70},"updated":"2022-02-11 05:14:14.000000000","message":"Heh, whoops! Good catch.","commit_id":"763fcc1f3f4767bf07657bc81ad66316a93f2f6e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7f3bba9e0d7aaecb43e1d951094f512682dc87d8","unresolved":false,"context_lines":[{"line_number":242,"context_line":""},{"line_number":243,"context_line":"    def copy(self):"},{"line_number":244,"context_line":"        return type(self)(self.errors, self.failures, self.quarantines,"},{"line_number":245,"context_line":"                          self.successes, self.unlinks, self.redirects,"},{"line_number":246,"context_line":"                          self.skips, self.deferrals, self.drains)"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"    def since(self, other):"}],"source_content_type":"text/x-python","patch_set":17,"id":"2c0567f2_24ea94f9","line":245,"range":{"start_line":245,"start_character":61,"end_line":245,"end_character":70},"in_reply_to":"7d3916cf_b5dfbff7","updated":"2022-02-11 09:22:40.000000000","message":"Ack","commit_id":"763fcc1f3f4767bf07657bc81ad66316a93f2f6e"}],"test/unit/obj/test_updater.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"17a997929f917f751d7a60748b6cf4a336e114c0","unresolved":true,"context_lines":[{"line_number":2055,"context_line":""},{"line_number":2056,"context_line":"class TestSweepStats(unittest.TestCase):"},{"line_number":2057,"context_line":"    def test_copy(self):"},{"line_number":2058,"context_line":"        stats \u003d object_updater.SweepStats(1, 2, 3, 4, 5, 6, 7, 8, 9)"},{"line_number":2059,"context_line":"        stats2 \u003d stats.copy()"},{"line_number":2060,"context_line":"        self.assertEqual(vars(stats), vars(stats2))"},{"line_number":2061,"context_line":""}],"source_content_type":"text/x-python","patch_set":17,"id":"66cf8207_d65e1ae4","line":2058,"updated":"2022-02-11 05:14:14.000000000","message":"Even better as\n\n SweepStats(*range(1, len(vars(SweepStats())) + 1))\n\nOtherwise we need to remember to update the test the next time we add a new stat -- of course, it gets more annoying for since() testing...","commit_id":"763fcc1f3f4767bf07657bc81ad66316a93f2f6e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"91e127e9bfeb64079f0a5275fd9b1ea0aee4bb77","unresolved":false,"context_lines":[{"line_number":2055,"context_line":""},{"line_number":2056,"context_line":"class TestSweepStats(unittest.TestCase):"},{"line_number":2057,"context_line":"    def test_copy(self):"},{"line_number":2058,"context_line":"        stats \u003d object_updater.SweepStats(1, 2, 3, 4, 5, 6, 7, 8, 9)"},{"line_number":2059,"context_line":"        stats2 \u003d stats.copy()"},{"line_number":2060,"context_line":"        self.assertEqual(vars(stats), vars(stats2))"},{"line_number":2061,"context_line":""}],"source_content_type":"text/x-python","patch_set":17,"id":"7ef87d49_45afc288","line":2058,"in_reply_to":"66cf8207_d65e1ae4","updated":"2022-02-18 23:35:30.000000000","message":"Done","commit_id":"763fcc1f3f4767bf07657bc81ad66316a93f2f6e"}]}
