)]}'
{".zuul.yaml":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"151b3132c480c107dad4e788640ae09f1257ff90","unresolved":true,"context_lines":[{"line_number":336,"context_line":"      - tools/playbooks/common/install_dependencies.yaml"},{"line_number":337,"context_line":"      - tools/playbooks/saio_single_node_setup/setup_saio.yaml"},{"line_number":338,"context_line":"      - tools/playbooks/saio_single_node_setup/make_rings.yaml"},{"line_number":339,"context_line":"      - tools/playbooks/saio_single_node_setup/add_s3api.yaml"},{"line_number":340,"context_line":"    run: tools/playbooks/probetests/run.yaml"},{"line_number":341,"context_line":"    post-run: tools/playbooks/probetests/post.yaml"},{"line_number":342,"context_line":""}],"source_content_type":"text/x-yaml","patch_set":15,"id":"625ed7b7_855a67c7","line":339,"updated":"2022-06-08 00:58:56.000000000","message":"Look at you, learning how to Zuul!","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":336,"context_line":"      - tools/playbooks/common/install_dependencies.yaml"},{"line_number":337,"context_line":"      - tools/playbooks/saio_single_node_setup/setup_saio.yaml"},{"line_number":338,"context_line":"      - tools/playbooks/saio_single_node_setup/make_rings.yaml"},{"line_number":339,"context_line":"      - tools/playbooks/saio_single_node_setup/add_s3api.yaml"},{"line_number":340,"context_line":"    run: tools/playbooks/probetests/run.yaml"},{"line_number":341,"context_line":"    post-run: tools/playbooks/probetests/post.yaml"},{"line_number":342,"context_line":""}],"source_content_type":"text/x-yaml","patch_set":15,"id":"309b1fe0_dbe31555","line":339,"in_reply_to":"625ed7b7_855a67c7","updated":"2024-04-01 14:05:21.000000000","message":"Acknowledged","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"}],"/COMMIT_MSG":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b96c188205c90e07552c474006a924584a5171ee","unresolved":true,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Expire the entire s3api MPU"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"It\u0027s not possible to reference s3api MPU segments from s3api - they may"},{"line_number":10,"context_line":"as well be in the reserved namespace.  Since X-Delete-At expiration will"},{"line_number":11,"context_line":"only be set on the manifest; we should at least *try* to avoid creating"},{"line_number":12,"context_line":"orphaned segments on purpose."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"The use of SLO for s3api MPUs is an implementation detail.  Because SLO"},{"line_number":15,"context_line":"segments are NOT in a reserved namespace it would not be appropriate to"},{"line_number":16,"context_line":"clean up SLOs automatically in this manner."},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"This is just a best effort cleanup, s3api MPUs already have a related"},{"line_number":19,"context_line":"bug to address orphaned segments."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"Related-Bug: #1813202"},{"line_number":22,"context_line":"Change-Id: Ib5cec0e552cd51592653e9e100729fcf91f99415"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":10,"id":"29c6857a_f5828548","line":19,"range":{"start_line":9,"start_character":0,"end_line":19,"end_character":33},"updated":"2022-01-13 13:00:18.000000000","message":"I found the commit message a little confusing.\n\nhow about something like:\n\n  Delete s3api MPU segments when expiring the manifest\n\n  s3api MPU segments will be automatically deleted by the \n  expirer when it expires an s3api manifest.\n\n  This is just a best effort cleanup of the segments. In some \n  circumstances (e.g. when manifest objects are not consistent)\n  this may fail to delete all segments. However, s3api MPUs \n  already have a related bug to address orphaned segments.\n\n  The automatic deletion is only applied to s3api segments, \n  not to SLO segments in general, because:\n\n  (a) s3api segments cannot be referenced via the S3 API, and are \n      therefore orphaned as soon as the manifest is deleted; SLO \n      segments in general are not necessarily orphaned when a \n      manifest is deleted.\n\n (b) the names of s3api MPU segments can be easily inferred from \n     the manifest DELETE response headers without inspecting the \n     manifest body.","commit_id":"60cb24a6beaeb592b47fcbbd5bfab4b97a119d48"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Expire the entire s3api MPU"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"It\u0027s not possible to reference s3api MPU segments from s3api - they may"},{"line_number":10,"context_line":"as well be in the reserved namespace.  Since X-Delete-At expiration will"},{"line_number":11,"context_line":"only be set on the manifest; we should at least *try* to avoid creating"},{"line_number":12,"context_line":"orphaned segments on purpose."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"The use of SLO for s3api MPUs is an implementation detail.  Because SLO"},{"line_number":15,"context_line":"segments are NOT in a reserved namespace it would not be appropriate to"},{"line_number":16,"context_line":"clean up SLOs automatically in this manner."},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"This is just a best effort cleanup, s3api MPUs already have a related"},{"line_number":19,"context_line":"bug to address orphaned segments."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"Related-Bug: #1813202"},{"line_number":22,"context_line":"Change-Id: Ib5cec0e552cd51592653e9e100729fcf91f99415"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":10,"id":"ba4be928_d948aeee","line":19,"range":{"start_line":9,"start_character":0,"end_line":19,"end_character":33},"in_reply_to":"29c6857a_f5828548","updated":"2024-04-01 14:05:21.000000000","message":"Done","commit_id":"60cb24a6beaeb592b47fcbbd5bfab4b97a119d48"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"c07149c2000581a0a9bebd9fcc74ba3f94cd2c57","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"a7a51df0_8267c9b6","updated":"2021-12-22 06:32:26.000000000","message":"Its a pretty good approach, don\u0027t like all the s3-isms bleeding out into the proxy controller and object server etc though. I\u0027m move onto the next. And might come back to this one after I\u0027ve looked at the others.","commit_id":"edff82be41225a2002ed177c2d1348e1d5873f72"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"db34c487c171aaecaa4cdba105e3985458ddcc8f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"a775102d_24ec9ff4","updated":"2021-12-21 22:56:28.000000000","message":"thanks!  i\u0027m going to rebase and stuff","commit_id":"edff82be41225a2002ed177c2d1348e1d5873f72"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c9f4264667243283be27a67274a2458bfe24f355","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"9c5479e1_f62c3069","updated":"2022-01-10 16:43:26.000000000","message":"I could respin a a WAG at some swift.backend_responses datastructure in the request environ\n\nmaybe just a list of buffered http response objects - hopefully won\u0027t mess with GC too much - alternatively just (status_int, headers) tuples\n\nI\u0027m suspicious it ends up duplicating some info with stuff OpenTracing already wants to track - I want to discuss with Matt","commit_id":"210807787136a603e7ed06b5bd87efedff60afe3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"990fc81e9b23c543dd9bedd5cc8bcead16058b4e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"6511ee7b_f653f2da","updated":"2022-01-10 11:22:58.000000000","message":"I\u0027m not sure if headers is the best way to pass out the aggregate of backend responses vs some new data structure in the request.\n\nHow hard do we need to try to deal with inconsistent backend responses, given that some kind of fallback cleanup will be needed?","commit_id":"210807787136a603e7ed06b5bd87efedff60afe3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"638d351a698e4014097119f3367fa29c0a063e3e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"b67a76f6_84ffeb20","updated":"2022-01-11 20:45:35.000000000","message":"now with a squashed probe test and no changes to the proxy!","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4d91fc0634159dd6f7280e8c041bfef8ad1732ae","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"673d8864_2c9dded2","updated":"2022-01-12 15:20:12.000000000","message":"this seems reasonably simple! \n\n-1 because I am nervous about the lack of check on the manifest delete response status code","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"bd1b4324_e21979f7","updated":"2022-01-13 06:12:25.000000000","message":"wow, thanks guys!","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b96c188205c90e07552c474006a924584a5171ee","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":10,"id":"35c1bdc5_ddc2223b","updated":"2022-01-13 13:00:18.000000000","message":"looking good!","commit_id":"60cb24a6beaeb592b47fcbbd5bfab4b97a119d48"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"b46fc8a8bb91ecfdac6c294d1b76490e4b783671","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"1d903e60_8024a6e9","updated":"2022-05-09 20:07:05.000000000","message":"we\u0027ve been running this in prod for some time","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"07b6a6636d05f55f539bfb35fdeb75f695c3f85e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":18,"id":"93acc9e8_e071bba2","updated":"2023-01-03 19:21:07.000000000","message":"wat?\n\ntox.tox_env.python.api.NoInterpreter: could not find python interpreter matching any of the specs py36","commit_id":"52460eed7518ae432c44d3547fea9196b0dc026b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"7ba6195836d46fe556883238fab3f46640df2f96","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":19,"id":"2bca8084_36b44bc2","updated":"2023-03-28 00:41:07.000000000","message":"Just reminding myself why we\u0027re not merging this - it leaks +segments almost as bad as an s3api mpu overwrite.  Two ways:\n\n1) during the DELETE it\u0027s looking for resp s3api metadata, if there\u0027s any inconsistency I think it like throws out extra tombstones; but if it misses a stale replica (and still matches the .data x-delete-at)... well I guess those segments were probably orphaneded anyway.\n2) during the \"for num-segment in etag\" loop the expirer can just get restarted, it\u0027s the only one that knows it just deleted an mpu and no one is going back for them.\n\nWe need ALOs bad.","commit_id":"d1a1821d2b32110377e6b8f3ba884f63510d27af"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"896c195c7f3ec647e24cecc74a0116241cda5598","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":20,"id":"bca86fba_3ff1c6db","updated":"2023-07-25 01:41:37.000000000","message":"Just a rebase","commit_id":"001470f4e4ca141163298ee671faf4945a4a13a2"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d813622596130874558a16025daa22a1234aba01","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":32,"id":"a238c9f5_2ea9202c","updated":"2024-03-20 19:09:29.000000000","message":"Tracebacks from carrying this in prod:\n```\nException while deleting object .expiring_objects 1710806308 1710879219.33361-.../YWE3OTZkZTMtNjY3OC00OWVjLWJiZDQtMWQ2OWMzNDdkYzcw/4 list index out of range: \nTraceback (most recent call last):\n  File \".../swift/obj/expirer.py\", line 481, in delete_object\n    is_async_delete)\n  File \".../swift/obj/expirer.py\", line 573, in delete_actual_object\n    num_segments \u003d int(resp.headers[segments_key].rsplit(\u0027-\u0027, 1)[1])\nIndexError: list index out of range\n```","commit_id":"d7f8e8b98c3ac6d77a7ba91e24b5a46add9c7268"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":33,"id":"bbf9bf66_c1cd3d4b","updated":"2024-04-01 14:05:21.000000000","message":"There was some concerns in earlier versions about the leaking of s3api context into object server and proxy server; we resolved that by making the handling of of the needed s3 metadata generic for ALL sysmeta.\n\nWe still leak some s3api mpu specific handling into the expirer; i\u0027m not sure what our long term plan for this patch should be.\n\nI addressed some comments and extended the testing.","commit_id":"9e713648524dd099ee9cfc94ed3a3b4c8e1e5f3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5b86a4a7e9c5868b150beaf97b6b443927bed67d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":34,"id":"89c216ca_7bb338ed","updated":"2024-04-04 18:34:07.000000000","message":"Also meant to say that I think we could probably break out some of the test changes and merge to master","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8e0d4617ca9854d94ca05570003aed1e8adfcaad","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":34,"id":"a0f1c539_ee8b6daa","updated":"2024-04-04 19:07:05.000000000","message":"could probably do with more polish - I think pulling out some of the test infra for merge to master is a good idea!","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"70b8c0d3f18ddd36bbb3ee048c3dbd81f9ff97cb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":34,"id":"fcd52e17_07819878","updated":"2024-04-04 18:18:09.000000000","message":"posting comments I have so far - the change patchset 32-\u003e34 looks sane, nice fix! I need to look more at the tests.","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"84e94ce2d1a6192a6edae06a41a54dc9a22b585d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":34,"id":"99a308b5_edf0b1d7","updated":"2024-04-08 16:36:59.000000000","message":"recheck\n\nfunc test failure unrelated","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8e0d4617ca9854d94ca05570003aed1e8adfcaad","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":34,"id":"ca932a13_27dd4e61","in_reply_to":"89c216ca_7bb338ed","updated":"2024-04-04 19:07:05.000000000","message":"good idea!","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6ae1792e323539e246b733015cf913fa12e9b355","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":39,"id":"f3c0cc2c_cc423c70","updated":"2024-06-04 20:42:36.000000000","message":"I ported the new tests to use a real `InternalClient(app\u003dFakeSwift())` and moved the drive by FakeInternalClient stuff out to a follow-up:\n\n921337: wip: is there such a thing as *good* FakeInternalClient | https://review.opendev.org/c/openstack/swift/+/921337\n\n... but I think I\u0027d actually be ok as a rule of thumb to start moving in the direction of NOT having FakeInternalClient classes when a InternalClient(app\u003dFakeSwift()) would do better?  If folks are real excited about that direction I could even try to pull out some more test_expirer refactors as a pre-req.","commit_id":"4b729c66577f9e4d7b6679715e17cdd166b6b33b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"a53c7500f0363202f82320eb0b11426657f18900","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":82,"id":"83eda7c4_37d10813","updated":"2025-05-20 19:15:17.000000000","message":"recheck\n\nLooks like some transient mirror error.","commit_id":"8a6628acfb13af9ac717620f4357a234882a81c3"},{"author":{"_account_id":35790,"name":"Shreeya Deshpande","email":"shreeyad@nvidia.com","username":"shreeyad"},"change_message_id":"e0d5a3b61e8842afc53b4894312cbf6ba60291a7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":89,"id":"73a93a42_95a9543c","updated":"2026-03-03 16:21:03.000000000","message":"recheck","commit_id":"329daeb18680e142af1c1f5c1e898d0c7d515f6d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fcfb06ba2e3f773598058f769de08abc5b9253c8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":92,"id":"789948ab_5c06d170","updated":"2026-03-25 10:00:41.000000000","message":"recheck\n\nunrelated error with heat","commit_id":"a9482f7a05f289c5df828db65435e213945ec898"}],"swift/common/internal_client.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ffdecaa4fc2e516ae10bd5210bc7bd7c780b13c2","unresolved":true,"context_lines":[{"line_number":239,"context_line":"        # Drain the response body to prevent unexpected disconnect"},{"line_number":240,"context_line":"        # in proxy-server"},{"line_number":241,"context_line":"        drain_and_close(resp)"},{"line_number":242,"context_line":"        return resp.headers"},{"line_number":243,"context_line":""},{"line_number":244,"context_line":"    def _get_metadata("},{"line_number":245,"context_line":"            self, path, metadata_prefix\u003d\u0027\u0027, acceptable_statuses\u003d(2,),"}],"source_content_type":"text/x-python","patch_set":1,"id":"faf9b49e_6fb1a9f9","line":242,"updated":"2021-07-13 18:05:36.000000000","message":"this seems reasonable to me; there\u0027s obviously not going to be a body to respond - but headers could definately be useful!","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"db34c487c171aaecaa4cdba105e3985458ddcc8f","unresolved":false,"context_lines":[{"line_number":239,"context_line":"        # Drain the response body to prevent unexpected disconnect"},{"line_number":240,"context_line":"        # in proxy-server"},{"line_number":241,"context_line":"        drain_and_close(resp)"},{"line_number":242,"context_line":"        return resp.headers"},{"line_number":243,"context_line":""},{"line_number":244,"context_line":"    def _get_metadata("},{"line_number":245,"context_line":"            self, path, metadata_prefix\u003d\u0027\u0027, acceptable_statuses\u003d(2,),"}],"source_content_type":"text/x-python","patch_set":1,"id":"9c609628_e9989b64","line":242,"in_reply_to":"75023a5b_c74b12e9","updated":"2021-12-21 22:56:28.000000000","message":"Done","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"98f453900bdf43044753978046da00e34aab5af8","unresolved":true,"context_lines":[{"line_number":239,"context_line":"        # Drain the response body to prevent unexpected disconnect"},{"line_number":240,"context_line":"        # in proxy-server"},{"line_number":241,"context_line":"        drain_and_close(resp)"},{"line_number":242,"context_line":"        return resp.headers"},{"line_number":243,"context_line":""},{"line_number":244,"context_line":"    def _get_metadata("},{"line_number":245,"context_line":"            self, path, metadata_prefix\u003d\u0027\u0027, acceptable_statuses\u003d(2,),"}],"source_content_type":"text/x-python","patch_set":1,"id":"75023a5b_c74b12e9","line":242,"in_reply_to":"faf9b49e_6fb1a9f9","updated":"2021-07-15 00:12:09.000000000","message":"I wonder if we should maybe rename the method name to make it in some way more clear that this is for use with requests where we expect an empty (or at least, uninteresting) body.","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"98f453900bdf43044753978046da00e34aab5af8","unresolved":true,"context_lines":[{"line_number":659,"context_line":"                                    to get a response with an acceptable status"},{"line_number":660,"context_line":"        :raises Exception: Exception is raised when code fails in an"},{"line_number":661,"context_line":"                           unexpected way."},{"line_number":662,"context_line":"        \"\"\""},{"line_number":663,"context_line":""},{"line_number":664,"context_line":"        path \u003d self.make_path(account, container, obj)"},{"line_number":665,"context_line":"        return self.handle_request(\u0027DELETE\u0027, path, (headers or {}),"}],"source_content_type":"text/x-python","patch_set":1,"id":"e05849f1_30f97e91","line":662,"updated":"2021-07-15 00:12:09.000000000","message":"Oughta add a :returns:","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"db34c487c171aaecaa4cdba105e3985458ddcc8f","unresolved":false,"context_lines":[{"line_number":659,"context_line":"                                    to get a response with an acceptable status"},{"line_number":660,"context_line":"        :raises Exception: Exception is raised when code fails in an"},{"line_number":661,"context_line":"                           unexpected way."},{"line_number":662,"context_line":"        \"\"\""},{"line_number":663,"context_line":""},{"line_number":664,"context_line":"        path \u003d self.make_path(account, container, obj)"},{"line_number":665,"context_line":"        return self.handle_request(\u0027DELETE\u0027, path, (headers or {}),"}],"source_content_type":"text/x-python","patch_set":1,"id":"7ce8bda7_c2557dc1","line":662,"in_reply_to":"e05849f1_30f97e91","updated":"2021-12-21 22:56:28.000000000","message":"Done","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ffdecaa4fc2e516ae10bd5210bc7bd7c780b13c2","unresolved":true,"context_lines":[{"line_number":663,"context_line":""},{"line_number":664,"context_line":"        path \u003d self.make_path(account, container, obj)"},{"line_number":665,"context_line":"        return self.handle_request(\u0027DELETE\u0027, path, (headers or {}),"},{"line_number":666,"context_line":"                                   acceptable_statuses)"},{"line_number":667,"context_line":""},{"line_number":668,"context_line":"    def get_object_metadata("},{"line_number":669,"context_line":"            self, account, container, obj, metadata_prefix\u003d\u0027\u0027,"}],"source_content_type":"text/x-python","patch_set":1,"id":"27ddf3d8_100fab31","line":666,"updated":"2021-07-13 18:05:36.000000000","message":"there\u0027s some other call sites for handle_request that should also pass through the return headers","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":663,"context_line":""},{"line_number":664,"context_line":"        path \u003d self.make_path(account, container, obj)"},{"line_number":665,"context_line":"        return self.handle_request(\u0027DELETE\u0027, path, (headers or {}),"},{"line_number":666,"context_line":"                                   acceptable_statuses)"},{"line_number":667,"context_line":""},{"line_number":668,"context_line":"    def get_object_metadata("},{"line_number":669,"context_line":"            self, account, container, obj, metadata_prefix\u003d\u0027\u0027,"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f8572cf_d4de8605","line":666,"in_reply_to":"27ddf3d8_100fab31","updated":"2024-04-01 14:05:21.000000000","message":"Acknowledged","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f0e5cb531eb8cb29d551aa987dcb37d51511150a","unresolved":true,"context_lines":[{"line_number":243,"context_line":"        # Drain the response body to prevent unexpected disconnect"},{"line_number":244,"context_line":"        # in proxy-server"},{"line_number":245,"context_line":"        drain_and_close(resp)"},{"line_number":246,"context_line":"        return resp.headers"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"    def _get_metadata("},{"line_number":249,"context_line":"            self, path, metadata_prefix\u003d\u0027\u0027, acceptable_statuses\u003d(2,),"}],"source_content_type":"text/x-python","patch_set":5,"id":"e141a7be_d63f2703","line":246,"updated":"2021-12-22 11:16:08.000000000","message":"+1 in general, let\u0027s have these \u0027helper\u0027 methods return something useful!","commit_id":"edff82be41225a2002ed177c2d1348e1d5873f72"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":243,"context_line":"        # Drain the response body to prevent unexpected disconnect"},{"line_number":244,"context_line":"        # in proxy-server"},{"line_number":245,"context_line":"        drain_and_close(resp)"},{"line_number":246,"context_line":"        return resp.headers"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"    def _get_metadata("},{"line_number":249,"context_line":"            self, path, metadata_prefix\u003d\u0027\u0027, acceptable_statuses\u003d(2,),"}],"source_content_type":"text/x-python","patch_set":5,"id":"849ef4be_5d033464","line":246,"in_reply_to":"e141a7be_d63f2703","updated":"2024-04-01 14:05:21.000000000","message":"Acknowledged","commit_id":"edff82be41225a2002ed177c2d1348e1d5873f72"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4d91fc0634159dd6f7280e8c041bfef8ad1732ae","unresolved":true,"context_lines":[{"line_number":248,"context_line":"        # Drain the response body to prevent unexpected disconnect"},{"line_number":249,"context_line":"        # in proxy-server"},{"line_number":250,"context_line":"        drain_and_close(resp)"},{"line_number":251,"context_line":"        return resp.headers"},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"    def _get_metadata("},{"line_number":254,"context_line":"            self, path, metadata_prefix\u003d\u0027\u0027, acceptable_statuses\u003d(2,),"}],"source_content_type":"text/x-python","patch_set":9,"id":"a9d70dbd_02d6086a","line":251,"updated":"2022-01-12 15:20:12.000000000","message":"it might prove more generally useful to return resp (in fact, we may need to - see comment in expirer.py about checking the response status before deleting segments)","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[{"line_number":248,"context_line":"        # Drain the response body to prevent unexpected disconnect"},{"line_number":249,"context_line":"        # in proxy-server"},{"line_number":250,"context_line":"        drain_and_close(resp)"},{"line_number":251,"context_line":"        return resp.headers"},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"    def _get_metadata("},{"line_number":254,"context_line":"            self, path, metadata_prefix\u003d\u0027\u0027, acceptable_statuses\u003d(2,),"}],"source_content_type":"text/x-python","patch_set":9,"id":"b061ec5f_7811a031","line":251,"in_reply_to":"a9d70dbd_02d6086a","updated":"2022-01-13 06:12:25.000000000","message":"Done","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"e6628b0bbea2d2dab74204b8404d123534ebbfe6","unresolved":true,"context_lines":[{"line_number":664,"context_line":"                                    defaults to (2, HTTP_NOT_FOUND)."},{"line_number":665,"context_line":"        :param headers: extra headers to send with request"},{"line_number":666,"context_line":""},{"line_number":667,"context_line":"        :returns: Returns dict of object metadata."},{"line_number":668,"context_line":""},{"line_number":669,"context_line":"        :raises UnexpectedResponse: Exception raised when requests fail"},{"line_number":670,"context_line":"                                    to get a response with an acceptable status"}],"source_content_type":"text/x-python","patch_set":9,"id":"37d4308d_2542e91a","line":667,"updated":"2022-01-11 23:06:41.000000000","message":"NIT: In reality it\u0027s just returning the response headers.. so yeah I guess it\u0027s the object metadata :) If the object didn\u0027t exist there will be less headers returned. If someone is expecting a certain metadata response it maynot be there. But it\u0027s a dict and they should use .get() in anycase so meh.\n\nIt\u0027s just the make_request mentions headers and here is object metadata, they are basically the same but thought it should be consistant.","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[{"line_number":664,"context_line":"                                    defaults to (2, HTTP_NOT_FOUND)."},{"line_number":665,"context_line":"        :param headers: extra headers to send with request"},{"line_number":666,"context_line":""},{"line_number":667,"context_line":"        :returns: Returns dict of object metadata."},{"line_number":668,"context_line":""},{"line_number":669,"context_line":"        :raises UnexpectedResponse: Exception raised when requests fail"},{"line_number":670,"context_line":"                                    to get a response with an acceptable status"}],"source_content_type":"text/x-python","patch_set":9,"id":"d3e54dd0_eceb25d7","line":667,"in_reply_to":"37d4308d_2542e91a","updated":"2022-01-13 06:12:25.000000000","message":"Done","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4d91fc0634159dd6f7280e8c041bfef8ad1732ae","unresolved":true,"context_lines":[{"line_number":674,"context_line":""},{"line_number":675,"context_line":"        path \u003d self.make_path(account, container, obj)"},{"line_number":676,"context_line":"        return self.handle_request(\u0027DELETE\u0027, path, (headers or {}),"},{"line_number":677,"context_line":"                                   acceptable_statuses)"},{"line_number":678,"context_line":""},{"line_number":679,"context_line":"    def get_object_metadata("},{"line_number":680,"context_line":"            self, account, container, obj, metadata_prefix\u003d\u0027\u0027,"}],"source_content_type":"text/x-python","patch_set":9,"id":"5f321809_ac49f2a0","line":677,"updated":"2022-01-12 15:20:12.000000000","message":"I see diffs in test_internal_client.py but no test in that module fails if I revert this change (tests *do* fail in test_expirer.py but I expected coverage in test_internal_client.py)","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[{"line_number":674,"context_line":""},{"line_number":675,"context_line":"        path \u003d self.make_path(account, container, obj)"},{"line_number":676,"context_line":"        return self.handle_request(\u0027DELETE\u0027, path, (headers or {}),"},{"line_number":677,"context_line":"                                   acceptable_statuses)"},{"line_number":678,"context_line":""},{"line_number":679,"context_line":"    def get_object_metadata("},{"line_number":680,"context_line":"            self, account, container, obj, metadata_prefix\u003d\u0027\u0027,"}],"source_content_type":"text/x-python","patch_set":9,"id":"50c16807_7994fcec","line":677,"in_reply_to":"5f321809_ac49f2a0","updated":"2022-01-13 06:12:25.000000000","message":"Done","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"}],"swift/obj/expirer.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"98f453900bdf43044753978046da00e34aab5af8","unresolved":true,"context_lines":[{"line_number":501,"context_line":"        s3api_mpu_key \u003d \u0027x-backend-s3api-upload-segments\u0027"},{"line_number":502,"context_line":"        if s3api_mpu_key in metadata:"},{"line_number":503,"context_line":"            headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":504,"context_line":"            upload_id, num_segments \u003d metadata[s3api_mpu_key].split(\u0027/\u0027)"},{"line_number":505,"context_line":"            c \u003d \u0027%s+segments\u0027 % c"},{"line_number":506,"context_line":"            for segment_number in range(int(num_segments)):"},{"line_number":507,"context_line":"                segment_name \u003d \u0027%s/%s/%s\u0027 % (o, upload_id, segment_number + 1)"}],"source_content_type":"text/x-python","patch_set":1,"id":"f87b6926_61cb7f0a","line":504,"updated":"2021-07-15 00:12:09.000000000","message":"Throws a ValueError if there was more than one item in the set, which could happen if, for example, we have:\n\n* an overwrite that missed some primaries,\n* a POST that hits both stale and fresh data and sets expiry for \"soon\",\n* an expirer that\u0027s processing more quickly than replication/reconstruction could square the overwrite.","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"db34c487c171aaecaa4cdba105e3985458ddcc8f","unresolved":false,"context_lines":[{"line_number":501,"context_line":"        s3api_mpu_key \u003d \u0027x-backend-s3api-upload-segments\u0027"},{"line_number":502,"context_line":"        if s3api_mpu_key in metadata:"},{"line_number":503,"context_line":"            headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":504,"context_line":"            upload_id, num_segments \u003d metadata[s3api_mpu_key].split(\u0027/\u0027)"},{"line_number":505,"context_line":"            c \u003d \u0027%s+segments\u0027 % c"},{"line_number":506,"context_line":"            for segment_number in range(int(num_segments)):"},{"line_number":507,"context_line":"                segment_name \u003d \u0027%s/%s/%s\u0027 % (o, upload_id, segment_number + 1)"}],"source_content_type":"text/x-python","patch_set":1,"id":"0b2f2e13_cc3c2b96","line":504,"in_reply_to":"f87b6926_61cb7f0a","updated":"2021-12-21 22:56:28.000000000","message":"Done","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ffdecaa4fc2e516ae10bd5210bc7bd7c780b13c2","unresolved":true,"context_lines":[{"line_number":512,"context_line":"                except UnexpectedResponse as err:"},{"line_number":513,"context_line":"                    self.logger.exception("},{"line_number":514,"context_line":"                        \u0027%s unable to delete a segment: %s/%s/%s\u0027 % ("},{"line_number":515,"context_line":"                            err, a, c, segment_name))"}],"source_content_type":"text/x-python","patch_set":1,"id":"e0a6a740_d4c7a04b","line":515,"updated":"2021-07-13 18:05:36.000000000","message":"this is the most sketch part (I think) - after we delete the manifest (and consume the s3meta) if we die/fail while expiring the segments there\u0027s no one else that would know to pickup our slack.\n\nIn a future where the expirer is handling ALOs (still best effort) we could count on a row tracking consistency daemon to \"handle\" new ALO tombstones by ensuring segments in their reserved namespace are replaced with tombstones.","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"db34c487c171aaecaa4cdba105e3985458ddcc8f","unresolved":false,"context_lines":[{"line_number":512,"context_line":"                except UnexpectedResponse as err:"},{"line_number":513,"context_line":"                    self.logger.exception("},{"line_number":514,"context_line":"                        \u0027%s unable to delete a segment: %s/%s/%s\u0027 % ("},{"line_number":515,"context_line":"                            err, a, c, segment_name))"}],"source_content_type":"text/x-python","patch_set":1,"id":"60b97d46_81850554","line":515,"in_reply_to":"5edd1ae4_f9c90336","updated":"2021-12-21 22:56:28.000000000","message":"Done","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"98f453900bdf43044753978046da00e34aab5af8","unresolved":true,"context_lines":[{"line_number":512,"context_line":"                except UnexpectedResponse as err:"},{"line_number":513,"context_line":"                    self.logger.exception("},{"line_number":514,"context_line":"                        \u0027%s unable to delete a segment: %s/%s/%s\u0027 % ("},{"line_number":515,"context_line":"                            err, a, c, segment_name))"}],"source_content_type":"text/x-python","patch_set":1,"id":"5edd1ae4_f9c90336","line":515,"in_reply_to":"e0a6a740_d4c7a04b","updated":"2021-07-15 00:12:09.000000000","message":"Might be interesting if the *object-server* were responsible for writing down asyncs to clean up the segments -- do it down in diskfile and we could make it not matter whether this happened because of an expirer delete, client delete, overwrite...\n\nGetting the number of segments from meta is a handy trick; means we don\u0027t need to worry about EC/encryption. 🤔","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f0e5cb531eb8cb29d551aa987dcb37d51511150a","unresolved":true,"context_lines":[{"line_number":486,"context_line":"        \"\"\""},{"line_number":487,"context_line":"        Deletes the end-user object indicated by the actual object name given"},{"line_number":488,"context_line":"        \u0027\u003caccount\u003e/\u003ccontainer\u003e/\u003cobject\u003e\u0027 if and only if the X-Delete-At value"},{"line_number":489,"context_line":"        of the object is exactly the timestamp given."},{"line_number":490,"context_line":""},{"line_number":491,"context_line":"        :param actual_obj: The name of the end-user object to delete:"},{"line_number":492,"context_line":"                           \u0027\u003caccount\u003e/\u003ccontainer\u003e/\u003cobject\u003e\u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"c620284f_9fd81c81","line":489,"updated":"2021-12-22 11:16:08.000000000","message":"docstring needs updating w.r.t. async deletes","commit_id":"edff82be41225a2002ed177c2d1348e1d5873f72"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":486,"context_line":"        \"\"\""},{"line_number":487,"context_line":"        Deletes the end-user object indicated by the actual object name given"},{"line_number":488,"context_line":"        \u0027\u003caccount\u003e/\u003ccontainer\u003e/\u003cobject\u003e\u0027 if and only if the X-Delete-At value"},{"line_number":489,"context_line":"        of the object is exactly the timestamp given."},{"line_number":490,"context_line":""},{"line_number":491,"context_line":"        :param actual_obj: The name of the end-user object to delete:"},{"line_number":492,"context_line":"                           \u0027\u003caccount\u003e/\u003ccontainer\u003e/\u003cobject\u003e\u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"1263e7d3_86bb560f","line":489,"in_reply_to":"c620284f_9fd81c81","updated":"2024-04-01 14:05:21.000000000","message":"unrelated and somewhat already addressed by the is_async_delete kwarg but I updated the text anyway.","commit_id":"edff82be41225a2002ed177c2d1348e1d5873f72"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c9f4264667243283be27a67274a2458bfe24f355","unresolved":true,"context_lines":[{"line_number":522,"context_line":"                return"},{"line_number":523,"context_line":"            # cleanup s3api mpu segments"},{"line_number":524,"context_line":"            headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":525,"context_line":"            num_segments \u003d max("},{"line_number":526,"context_line":"                int(v.rsplit(\u0027-\u0027, 1)[1]) for v in"},{"line_number":527,"context_line":"                metadata[\u0027X-Object-Sysmeta-S3Api-Etag\u0027].split(\u0027,\u0027))"},{"line_number":528,"context_line":"            for i, upload_id in enumerate(metadata[s3api_mpu_key].split(\u0027,\u0027)):"}],"source_content_type":"text/x-python","patch_set":8,"id":"82550800_8a166587","line":525,"updated":"2022-01-10 16:43:26.000000000","message":"I also didn\u0027t like how the \"max num_segments\" can\u0027t say which upload_id it goes with","commit_id":"210807787136a603e7ed06b5bd87efedff60afe3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":522,"context_line":"                return"},{"line_number":523,"context_line":"            # cleanup s3api mpu segments"},{"line_number":524,"context_line":"            headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":525,"context_line":"            num_segments \u003d max("},{"line_number":526,"context_line":"                int(v.rsplit(\u0027-\u0027, 1)[1]) for v in"},{"line_number":527,"context_line":"                metadata[\u0027X-Object-Sysmeta-S3Api-Etag\u0027].split(\u0027,\u0027))"},{"line_number":528,"context_line":"            for i, upload_id in enumerate(metadata[s3api_mpu_key].split(\u0027,\u0027)):"}],"source_content_type":"text/x-python","patch_set":8,"id":"0d35607e_e4c44469","line":525,"in_reply_to":"82550800_8a166587","updated":"2024-04-01 14:05:21.000000000","message":"Acknowledged","commit_id":"210807787136a603e7ed06b5bd87efedff60afe3"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"e6628b0bbea2d2dab74204b8404d123534ebbfe6","unresolved":true,"context_lines":[{"line_number":476,"context_line":"            try:"},{"line_number":477,"context_line":"                self.swift.delete_object("},{"line_number":478,"context_line":"                    a, c, segment_name, headers\u003dheaders,"},{"line_number":479,"context_line":"                    acceptable_statuses\u003dacceptable_statuses)"},{"line_number":480,"context_line":"            except UnexpectedResponse as err:"},{"line_number":481,"context_line":"                self.logger.exception("},{"line_number":482,"context_line":"                    \u0027%s unable to delete a segment: %s/%s/%s\u0027 % ("}],"source_content_type":"text/x-python","patch_set":9,"id":"e4ad4e52_b37327ee","line":479,"updated":"2022-01-11 23:06:41.000000000","message":"If there are 1000s of segments do we want to do this serially? Might hold up the expirer for a while.\n\nMight want to think about concurrency pool or enqueueing the items onto the expirer queue (like async delete).","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[{"line_number":476,"context_line":"            try:"},{"line_number":477,"context_line":"                self.swift.delete_object("},{"line_number":478,"context_line":"                    a, c, segment_name, headers\u003dheaders,"},{"line_number":479,"context_line":"                    acceptable_statuses\u003dacceptable_statuses)"},{"line_number":480,"context_line":"            except UnexpectedResponse as err:"},{"line_number":481,"context_line":"                self.logger.exception("},{"line_number":482,"context_line":"                    \u0027%s unable to delete a segment: %s/%s/%s\u0027 % ("}],"source_content_type":"text/x-python","patch_set":9,"id":"b53c0145_2111745a","line":479,"in_reply_to":"e4ad4e52_b37327ee","updated":"2022-01-13 06:12:25.000000000","message":"doing the delete\u0027s in a pool might be quite nice, maybe crib something like what we do in bulk middleware","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4d91fc0634159dd6f7280e8c041bfef8ad1732ae","unresolved":true,"context_lines":[{"line_number":480,"context_line":"            except UnexpectedResponse as err:"},{"line_number":481,"context_line":"                self.logger.exception("},{"line_number":482,"context_line":"                    \u0027%s unable to delete a segment: %s/%s/%s\u0027 % ("},{"line_number":483,"context_line":"                        err, a, c, segment_name))"},{"line_number":484,"context_line":""},{"line_number":485,"context_line":"    def delete_actual_object(self, actual_obj, timestamp, is_async_delete):"},{"line_number":486,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":9,"id":"dfa70d1f_cc5c504a","line":483,"updated":"2022-01-12 15:20:12.000000000","message":"we should probably increment the \u0027objects\u0027 or \u0027errors\u0027 stats as appropriate for each segment (or have new stats to differentiate segment deletes)","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[{"line_number":480,"context_line":"            except UnexpectedResponse as err:"},{"line_number":481,"context_line":"                self.logger.exception("},{"line_number":482,"context_line":"                    \u0027%s unable to delete a segment: %s/%s/%s\u0027 % ("},{"line_number":483,"context_line":"                        err, a, c, segment_name))"},{"line_number":484,"context_line":""},{"line_number":485,"context_line":"    def delete_actual_object(self, actual_obj, timestamp, is_async_delete):"},{"line_number":486,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":9,"id":"569f859d_94f7b6e0","line":483,"in_reply_to":"dfa70d1f_cc5c504a","updated":"2022-01-13 06:12:25.000000000","message":"Done","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4d91fc0634159dd6f7280e8c041bfef8ad1732ae","unresolved":true,"context_lines":[{"line_number":510,"context_line":"        a, c, o \u003d split_path(\u0027/\u0027 + actual_obj, 3, 3, True)"},{"line_number":511,"context_line":"        metadata \u003d self.swift.delete_object("},{"line_number":512,"context_line":"            a, c, o,"},{"line_number":513,"context_line":"            headers\u003dheaders, acceptable_statuses\u003dacceptable_statuses)"},{"line_number":514,"context_line":"        upload_id_key \u003d \u0027X-Object-Sysmeta-S3Api-Upload-Id\u0027"},{"line_number":515,"context_line":"        segments_key \u003d \u0027X-Object-Sysmeta-S3Api-Etag\u0027"},{"line_number":516,"context_line":"        if upload_id_key not in metadata:"}],"source_content_type":"text/x-python","patch_set":9,"id":"955570b4_11851fb9","line":513,"updated":"2022-01-12 15:20:12.000000000","message":"it\u0027s not immediately obvious from the object server that we would never get headers back with a HTTP_CONFLICT status, in which case I don\u0027t think we would want to go ahead and delete the segments.\n\nThe way it is written here may be safe, but I think it would be worth making it very obviously safe by checking the response status (and/or definitely only adding the metadata headers to 204 responses, but that is less explicit)","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[{"line_number":510,"context_line":"        a, c, o \u003d split_path(\u0027/\u0027 + actual_obj, 3, 3, True)"},{"line_number":511,"context_line":"        metadata \u003d self.swift.delete_object("},{"line_number":512,"context_line":"            a, c, o,"},{"line_number":513,"context_line":"            headers\u003dheaders, acceptable_statuses\u003dacceptable_statuses)"},{"line_number":514,"context_line":"        upload_id_key \u003d \u0027X-Object-Sysmeta-S3Api-Upload-Id\u0027"},{"line_number":515,"context_line":"        segments_key \u003d \u0027X-Object-Sysmeta-S3Api-Etag\u0027"},{"line_number":516,"context_line":"        if upload_id_key not in metadata:"}],"source_content_type":"text/x-python","patch_set":9,"id":"7b46bf3f_bfd669ee","line":513,"in_reply_to":"955570b4_11851fb9","updated":"2022-01-13 06:12:25.000000000","message":"Done","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"e6628b0bbea2d2dab74204b8404d123534ebbfe6","unresolved":true,"context_lines":[{"line_number":511,"context_line":"        metadata \u003d self.swift.delete_object("},{"line_number":512,"context_line":"            a, c, o,"},{"line_number":513,"context_line":"            headers\u003dheaders, acceptable_statuses\u003dacceptable_statuses)"},{"line_number":514,"context_line":"        upload_id_key \u003d \u0027X-Object-Sysmeta-S3Api-Upload-Id\u0027"},{"line_number":515,"context_line":"        segments_key \u003d \u0027X-Object-Sysmeta-S3Api-Etag\u0027"},{"line_number":516,"context_line":"        if upload_id_key not in metadata:"},{"line_number":517,"context_line":"            return"},{"line_number":518,"context_line":"        # cleanup s3api mpu segments"}],"source_content_type":"text/x-python","patch_set":9,"id":"fa9f8343_21b6747e","line":515,"range":{"start_line":514,"start_character":8,"end_line":515,"end_character":52},"updated":"2022-01-11 23:06:41.000000000","message":"Could use:\n\n  from swift.common.middleware.s3api.utils import sysmeta_header\n  ...\n  upload_id_key \u003d sysmeta_header(\u0027object\u0027, \u0027upload-id\u0027)\n  segments_key \u003d sysmeta_header(\u0027object\u0027, \u0027etag\u0027)\n\nSo it remains consistant if we ever change anything in s3api.","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[{"line_number":511,"context_line":"        metadata \u003d self.swift.delete_object("},{"line_number":512,"context_line":"            a, c, o,"},{"line_number":513,"context_line":"            headers\u003dheaders, acceptable_statuses\u003dacceptable_statuses)"},{"line_number":514,"context_line":"        upload_id_key \u003d \u0027X-Object-Sysmeta-S3Api-Upload-Id\u0027"},{"line_number":515,"context_line":"        segments_key \u003d \u0027X-Object-Sysmeta-S3Api-Etag\u0027"},{"line_number":516,"context_line":"        if upload_id_key not in metadata:"},{"line_number":517,"context_line":"            return"},{"line_number":518,"context_line":"        # cleanup s3api mpu segments"}],"source_content_type":"text/x-python","patch_set":9,"id":"484f121c_fb41f811","line":515,"range":{"start_line":514,"start_character":8,"end_line":515,"end_character":52},"in_reply_to":"fa9f8343_21b6747e","updated":"2022-01-13 06:12:25.000000000","message":"Done","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"e6628b0bbea2d2dab74204b8404d123534ebbfe6","unresolved":true,"context_lines":[{"line_number":517,"context_line":"            return"},{"line_number":518,"context_line":"        # cleanup s3api mpu segments"},{"line_number":519,"context_line":"        headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":520,"context_line":"        num_segments \u003d int(metadata[segments_key].rsplit(\u0027-\u0027, 1)[1])"},{"line_number":521,"context_line":"        self._delete_mpu_segments(a, c, o, metadata[upload_id_key],"},{"line_number":522,"context_line":"                                  num_segments, headers, acceptable_statuses)"}],"source_content_type":"text/x-python","patch_set":9,"id":"9811a23e_ef5fd4e8","line":520,"updated":"2022-01-11 23:06:41.000000000","message":"Nice! Cleaver way of getting the number of segments. Love it.","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[{"line_number":517,"context_line":"            return"},{"line_number":518,"context_line":"        # cleanup s3api mpu segments"},{"line_number":519,"context_line":"        headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":520,"context_line":"        num_segments \u003d int(metadata[segments_key].rsplit(\u0027-\u0027, 1)[1])"},{"line_number":521,"context_line":"        self._delete_mpu_segments(a, c, o, metadata[upload_id_key],"},{"line_number":522,"context_line":"                                  num_segments, headers, acceptable_statuses)"}],"source_content_type":"text/x-python","patch_set":9,"id":"9e5bf01a_c9019318","line":520,"in_reply_to":"9811a23e_ef5fd4e8","updated":"2022-01-13 06:12:25.000000000","message":"Ack","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4d91fc0634159dd6f7280e8c041bfef8ad1732ae","unresolved":true,"context_lines":[{"line_number":519,"context_line":"        headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":520,"context_line":"        num_segments \u003d int(metadata[segments_key].rsplit(\u0027-\u0027, 1)[1])"},{"line_number":521,"context_line":"        self._delete_mpu_segments(a, c, o, metadata[upload_id_key],"},{"line_number":522,"context_line":"                                  num_segments, headers, acceptable_statuses)"}],"source_content_type":"text/x-python","patch_set":9,"id":"9b325215_8da1cc1b","line":522,"updated":"2022-01-12 15:20:12.000000000","message":"IIUC the time spent in this method will add to the timing stat of the original delete which could make stats a little weird.","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[{"line_number":519,"context_line":"        headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":520,"context_line":"        num_segments \u003d int(metadata[segments_key].rsplit(\u0027-\u0027, 1)[1])"},{"line_number":521,"context_line":"        self._delete_mpu_segments(a, c, o, metadata[upload_id_key],"},{"line_number":522,"context_line":"                                  num_segments, headers, acceptable_statuses)"}],"source_content_type":"text/x-python","patch_set":9,"id":"fb9f9af9_d45293b9","line":522,"in_reply_to":"9b325215_8da1cc1b","updated":"2022-01-13 06:12:25.000000000","message":"I thought about this and tried moving things around but didn\u0027t like the churn\n\ni think the timing stat also wraps the queue cleanup - so ... it\u0027s more like the timing of processing the queue entry (which we\u0027re extending to include a bunch of segment deletes ... so we should expect it to get bigger after upgrade)\n\ni\u0027m inclined to leave it be - but I\u0027d be happy to review/squash working code!","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b96c188205c90e07552c474006a924584a5171ee","unresolved":false,"context_lines":[{"line_number":519,"context_line":"        headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":520,"context_line":"        num_segments \u003d int(metadata[segments_key].rsplit(\u0027-\u0027, 1)[1])"},{"line_number":521,"context_line":"        self._delete_mpu_segments(a, c, o, metadata[upload_id_key],"},{"line_number":522,"context_line":"                                  num_segments, headers, acceptable_statuses)"}],"source_content_type":"text/x-python","patch_set":9,"id":"688cb1ac_dafbc540","line":522,"in_reply_to":"fb9f9af9_d45293b9","updated":"2022-01-13 13:00:18.000000000","message":"ack","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"151b3132c480c107dad4e788640ae09f1257ff90","unresolved":true,"context_lines":[{"line_number":485,"context_line":"                    \u0027%s unable to delete a segment: %s/%s/%s\u0027 % ("},{"line_number":486,"context_line":"                        err, a, c, segment_name))"},{"line_number":487,"context_line":"            else:"},{"line_number":488,"context_line":"                self.logger.increment(\u0027segments\u0027)"},{"line_number":489,"context_line":""},{"line_number":490,"context_line":"    def delete_actual_object(self, actual_obj, timestamp, is_async_delete):"},{"line_number":491,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":10,"id":"5dd31bc9_dc301beb","line":488,"updated":"2022-06-08 00:58:56.000000000","message":"Do we have any tests for the new stat?","commit_id":"60cb24a6beaeb592b47fcbbd5bfab4b97a119d48"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b96c188205c90e07552c474006a924584a5171ee","unresolved":true,"context_lines":[{"line_number":485,"context_line":"                    \u0027%s unable to delete a segment: %s/%s/%s\u0027 % ("},{"line_number":486,"context_line":"                        err, a, c, segment_name))"},{"line_number":487,"context_line":"            else:"},{"line_number":488,"context_line":"                self.logger.increment(\u0027segments\u0027)"},{"line_number":489,"context_line":""},{"line_number":490,"context_line":"    def delete_actual_object(self, actual_obj, timestamp, is_async_delete):"},{"line_number":491,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":10,"id":"b3763769_7db4c65f","line":488,"updated":"2022-01-13 13:00:18.000000000","message":"ok, we get a new metric -\u003e more insight","commit_id":"60cb24a6beaeb592b47fcbbd5bfab4b97a119d48"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":485,"context_line":"                    \u0027%s unable to delete a segment: %s/%s/%s\u0027 % ("},{"line_number":486,"context_line":"                        err, a, c, segment_name))"},{"line_number":487,"context_line":"            else:"},{"line_number":488,"context_line":"                self.logger.increment(\u0027segments\u0027)"},{"line_number":489,"context_line":""},{"line_number":490,"context_line":"    def delete_actual_object(self, actual_obj, timestamp, is_async_delete):"},{"line_number":491,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":10,"id":"92e143d0_e149e07a","line":488,"in_reply_to":"5dd31bc9_dc301beb","updated":"2024-04-01 14:05:21.000000000","message":"it was covered by swift/test/unit/obj/test_expirer.py::TestObjectExpirer::test_failed_delete_continues_on ... i updated the assertions.","commit_id":"60cb24a6beaeb592b47fcbbd5bfab4b97a119d48"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":485,"context_line":"                    \u0027%s unable to delete a segment: %s/%s/%s\u0027 % ("},{"line_number":486,"context_line":"                        err, a, c, segment_name))"},{"line_number":487,"context_line":"            else:"},{"line_number":488,"context_line":"                self.logger.increment(\u0027segments\u0027)"},{"line_number":489,"context_line":""},{"line_number":490,"context_line":"    def delete_actual_object(self, actual_obj, timestamp, is_async_delete):"},{"line_number":491,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":10,"id":"3c6769d3_96818215","line":488,"in_reply_to":"b3763769_7db4c65f","updated":"2024-04-01 14:05:21.000000000","message":"Acknowledged","commit_id":"60cb24a6beaeb592b47fcbbd5bfab4b97a119d48"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b96c188205c90e07552c474006a924584a5171ee","unresolved":true,"context_lines":[{"line_number":518,"context_line":"            headers\u003dheaders, acceptable_statuses\u003dacceptable_statuses)"},{"line_number":519,"context_line":"        upload_id_key \u003d sysmeta_header(\u0027object\u0027, \u0027upload-id\u0027)"},{"line_number":520,"context_line":"        if not (is_success(resp.status_int) and upload_id_key in resp.headers):"},{"line_number":521,"context_line":"            return"},{"line_number":522,"context_line":"        segments_key \u003d sysmeta_header(\u0027object\u0027, \u0027etag\u0027)"},{"line_number":523,"context_line":"        # cleanup s3api mpu segments"},{"line_number":524,"context_line":"        headers.pop(\u0027X-If-Delete-At\u0027, None)"}],"source_content_type":"text/x-python","patch_set":10,"id":"e7822a1e_0728f8b1","line":521,"updated":"2022-01-13 13:00:18.000000000","message":"nit: is the early return worth it vs indenting the remainder of the method? IDK, it\u0027s just a style thing and I\u0027m probably inconsistent myself ;)","commit_id":"60cb24a6beaeb592b47fcbbd5bfab4b97a119d48"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":518,"context_line":"            headers\u003dheaders, acceptable_statuses\u003dacceptable_statuses)"},{"line_number":519,"context_line":"        upload_id_key \u003d sysmeta_header(\u0027object\u0027, \u0027upload-id\u0027)"},{"line_number":520,"context_line":"        if not (is_success(resp.status_int) and upload_id_key in resp.headers):"},{"line_number":521,"context_line":"            return"},{"line_number":522,"context_line":"        segments_key \u003d sysmeta_header(\u0027object\u0027, \u0027etag\u0027)"},{"line_number":523,"context_line":"        # cleanup s3api mpu segments"},{"line_number":524,"context_line":"        headers.pop(\u0027X-If-Delete-At\u0027, None)"}],"source_content_type":"text/x-python","patch_set":10,"id":"f2be103d_760aa886","line":521,"in_reply_to":"e7822a1e_0728f8b1","updated":"2024-04-01 14:05:21.000000000","message":"since there\u0027s no body under this if; if we indented the next few lines of the happy path it\u0027d end up looking like a \"guard don\u0027t return early\" and you have to carry the error condition in your head all the way to the bottom so I think I\u0027d prefer this consistently.","commit_id":"60cb24a6beaeb592b47fcbbd5bfab4b97a119d48"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e2d531cf56a1730d26caf5db6e29840716c62cd9","unresolved":true,"context_lines":[{"line_number":481,"context_line":"            try:"},{"line_number":482,"context_line":"                self.swift.delete_object("},{"line_number":483,"context_line":"                    a, c, segment_name, headers\u003dheaders,"},{"line_number":484,"context_line":"                    acceptable_statuses\u003dacceptable_statuses)"},{"line_number":485,"context_line":"            except UnexpectedResponse as err:"},{"line_number":486,"context_line":"                self.logger.increment(\u0027errors\u0027)"},{"line_number":487,"context_line":"                self.logger.exception("}],"source_content_type":"text/x-python","patch_set":14,"id":"9c19fbea_c0794d4a","line":484,"range":{"start_line":484,"start_character":40,"end_line":484,"end_character":59},"updated":"2022-02-11 17:32:22.000000000","message":"We should make sure this always allows 404s.","commit_id":"baf8d307496c8105e9017ba559905cf2934badbb"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"151b3132c480c107dad4e788640ae09f1257ff90","unresolved":false,"context_lines":[{"line_number":481,"context_line":"            try:"},{"line_number":482,"context_line":"                self.swift.delete_object("},{"line_number":483,"context_line":"                    a, c, segment_name, headers\u003dheaders,"},{"line_number":484,"context_line":"                    acceptable_statuses\u003dacceptable_statuses)"},{"line_number":485,"context_line":"            except UnexpectedResponse as err:"},{"line_number":486,"context_line":"                self.logger.increment(\u0027errors\u0027)"},{"line_number":487,"context_line":"                self.logger.exception("}],"source_content_type":"text/x-python","patch_set":14,"id":"f7b20233_fef720e4","line":484,"range":{"start_line":484,"start_character":40,"end_line":484,"end_character":59},"in_reply_to":"9c19fbea_c0794d4a","updated":"2022-06-08 00:58:56.000000000","message":"With PS15, this no longer comes through from the caller.","commit_id":"baf8d307496c8105e9017ba559905cf2934badbb"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"151b3132c480c107dad4e788640ae09f1257ff90","unresolved":true,"context_lines":[{"line_number":27,"context_line":"from swift.common.daemon import Daemon"},{"line_number":28,"context_line":"from swift.common.http import is_success"},{"line_number":29,"context_line":"from swift.common.internal_client import InternalClient, UnexpectedResponse"},{"line_number":30,"context_line":"from swift.common.middleware.s3api.utils import sysmeta_header"},{"line_number":31,"context_line":"from swift.common.utils import get_logger, dump_recon_cache, split_path, \\"},{"line_number":32,"context_line":"    Timestamp, config_true_value, normalize_delete_at_timestamp, \\"},{"line_number":33,"context_line":"    RateLimitedIterator, md5"}],"source_content_type":"text/x-python","patch_set":15,"id":"2a97fb77_ddd87c74","line":30,"updated":"2022-06-08 00:58:56.000000000","message":"Might be worth us doing a\n\n ... as s3_sysmeta_header\n\n*shrug*","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":27,"context_line":"from swift.common.daemon import Daemon"},{"line_number":28,"context_line":"from swift.common.http import is_success"},{"line_number":29,"context_line":"from swift.common.internal_client import InternalClient, UnexpectedResponse"},{"line_number":30,"context_line":"from swift.common.middleware.s3api.utils import sysmeta_header"},{"line_number":31,"context_line":"from swift.common.utils import get_logger, dump_recon_cache, split_path, \\"},{"line_number":32,"context_line":"    Timestamp, config_true_value, normalize_delete_at_timestamp, \\"},{"line_number":33,"context_line":"    RateLimitedIterator, md5"}],"source_content_type":"text/x-python","patch_set":15,"id":"fc6f87c1_f9eda60f","line":30,"in_reply_to":"2a97fb77_ddd87c74","updated":"2024-04-01 14:05:21.000000000","message":"Done","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"151b3132c480c107dad4e788640ae09f1257ff90","unresolved":true,"context_lines":[{"line_number":484,"context_line":"                    a, c, segment_name, headers\u003dheaders,"},{"line_number":485,"context_line":"                    acceptable_statuses\u003dacceptable_statuses)"},{"line_number":486,"context_line":"            except UnexpectedResponse as err:"},{"line_number":487,"context_line":"                self.logger.increment(\u0027errors\u0027)"},{"line_number":488,"context_line":"                self.logger.exception("},{"line_number":489,"context_line":"                    \u0027%s unable to delete a segment: %s/%s/%s\u0027 % ("},{"line_number":490,"context_line":"                        err, a, c, segment_name))"}],"source_content_type":"text/x-python","patch_set":15,"id":"c7a73066_bd0592ac","line":487,"updated":"2022-06-08 00:58:56.000000000","message":"This block has no coverage.","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":484,"context_line":"                    a, c, segment_name, headers\u003dheaders,"},{"line_number":485,"context_line":"                    acceptable_statuses\u003dacceptable_statuses)"},{"line_number":486,"context_line":"            except UnexpectedResponse as err:"},{"line_number":487,"context_line":"                self.logger.increment(\u0027errors\u0027)"},{"line_number":488,"context_line":"                self.logger.exception("},{"line_number":489,"context_line":"                    \u0027%s unable to delete a segment: %s/%s/%s\u0027 % ("},{"line_number":490,"context_line":"                        err, a, c, segment_name))"}],"source_content_type":"text/x-python","patch_set":15,"id":"8815462c_24d716eb","line":487,"in_reply_to":"c7a73066_bd0592ac","updated":"2024-04-01 14:05:21.000000000","message":"it\u0027s was covered by \"test_delete_object\" - i added an assertion.","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"151b3132c480c107dad4e788640ae09f1257ff90","unresolved":true,"context_lines":[{"line_number":514,"context_line":"        else:"},{"line_number":515,"context_line":"            headers \u003d {\u0027X-Timestamp\u0027: timestamp.normal,"},{"line_number":516,"context_line":"                       \u0027X-If-Delete-At\u0027: timestamp.normal,"},{"line_number":517,"context_line":"                       \u0027X-Backend-Clean-Expiring-Object-Queue\u0027: \u0027no\u0027}"},{"line_number":518,"context_line":"            acceptable_statuses \u003d (2, HTTP_CONFLICT)"},{"line_number":519,"context_line":"        a, c, o \u003d split_path(\u0027/\u0027 + actual_obj, 3, 3, True)"},{"line_number":520,"context_line":"        resp \u003d self.swift.delete_object("}],"source_content_type":"text/x-python","patch_set":15,"id":"b0d33744_d5badd71","line":517,"updated":"2022-06-08 00:58:56.000000000","message":"We sure we want to carry this header to the segments? What if they had some other expiration time?","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":514,"context_line":"        else:"},{"line_number":515,"context_line":"            headers \u003d {\u0027X-Timestamp\u0027: timestamp.normal,"},{"line_number":516,"context_line":"                       \u0027X-If-Delete-At\u0027: timestamp.normal,"},{"line_number":517,"context_line":"                       \u0027X-Backend-Clean-Expiring-Object-Queue\u0027: \u0027no\u0027}"},{"line_number":518,"context_line":"            acceptable_statuses \u003d (2, HTTP_CONFLICT)"},{"line_number":519,"context_line":"        a, c, o \u003d split_path(\u0027/\u0027 + actual_obj, 3, 3, True)"},{"line_number":520,"context_line":"        resp \u003d self.swift.delete_object("}],"source_content_type":"text/x-python","patch_set":15,"id":"b796160e_6a4ad373","line":517,"in_reply_to":"b0d33744_d5badd71","updated":"2024-04-01 14:05:21.000000000","message":"do you mean specifically the x-if-delete-at?  I think we should NOT send x-if-delete-at to the segments; the DELETE would fail 412:\n\nhttps://github.com/NVIDIA/swift/blob/master/swift/obj/server.py#L1260-L1263\n\nIn this change we send the segment delete\u0027s using internal-client w/o any conditional headers.\n\nIf you mean `clean-expiring-object-queue: no` I don\u0027t think I really understand how that works; but it sort of reads like the expirer should always set it to false for it\u0027s conditional deletes.","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"151b3132c480c107dad4e788640ae09f1257ff90","unresolved":true,"context_lines":[{"line_number":521,"context_line":"            a, c, o,"},{"line_number":522,"context_line":"            headers\u003dheaders, acceptable_statuses\u003dacceptable_statuses)"},{"line_number":523,"context_line":"        upload_id_key \u003d sysmeta_header(\u0027object\u0027, \u0027upload-id\u0027)"},{"line_number":524,"context_line":"        if not (is_success(resp.status_int) and upload_id_key in resp.headers):"},{"line_number":525,"context_line":"            return"},{"line_number":526,"context_line":"        segments_key \u003d sysmeta_header(\u0027object\u0027, \u0027etag\u0027)"},{"line_number":527,"context_line":"        # cleanup s3api mpu segments"}],"source_content_type":"text/x-python","patch_set":15,"id":"497e800f_6e629d4e","line":524,"range":{"start_line":524,"start_character":48,"end_line":524,"end_character":77},"updated":"2022-06-08 00:58:56.000000000","message":"Note that this is our one chance to try to deal with segments -- if we fall over after this point, we\u0027re still going to have some orphaned data.\n\nStill a good optimization, though; better than we\u0027re currently doing with overwrites: https://bugs.launchpad.net/swift/+bug/1813202\n\nJust another reason to look for an auditing solution like https://review.opendev.org/c/openstack/swift/+/783476","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":521,"context_line":"            a, c, o,"},{"line_number":522,"context_line":"            headers\u003dheaders, acceptable_statuses\u003dacceptable_statuses)"},{"line_number":523,"context_line":"        upload_id_key \u003d sysmeta_header(\u0027object\u0027, \u0027upload-id\u0027)"},{"line_number":524,"context_line":"        if not (is_success(resp.status_int) and upload_id_key in resp.headers):"},{"line_number":525,"context_line":"            return"},{"line_number":526,"context_line":"        segments_key \u003d sysmeta_header(\u0027object\u0027, \u0027etag\u0027)"},{"line_number":527,"context_line":"        # cleanup s3api mpu segments"}],"source_content_type":"text/x-python","patch_set":15,"id":"2d64a87b_e7ce8f88","line":524,"range":{"start_line":524,"start_character":48,"end_line":524,"end_character":77},"in_reply_to":"497e800f_6e629d4e","updated":"2024-04-01 14:05:21.000000000","message":"Acknowledged","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"151b3132c480c107dad4e788640ae09f1257ff90","unresolved":true,"context_lines":[{"line_number":523,"context_line":"        upload_id_key \u003d sysmeta_header(\u0027object\u0027, \u0027upload-id\u0027)"},{"line_number":524,"context_line":"        if not (is_success(resp.status_int) and upload_id_key in resp.headers):"},{"line_number":525,"context_line":"            return"},{"line_number":526,"context_line":"        segments_key \u003d sysmeta_header(\u0027object\u0027, \u0027etag\u0027)"},{"line_number":527,"context_line":"        # cleanup s3api mpu segments"},{"line_number":528,"context_line":"        headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":529,"context_line":"        num_segments \u003d int(resp.headers[segments_key].rsplit(\u0027-\u0027, 1)[1])"}],"source_content_type":"text/x-python","patch_set":15,"id":"8b989c38_dc3233d5","line":526,"updated":"2022-06-08 00:58:56.000000000","message":"Right, and anybody that has the upload-id sysmeta will have the etag sysmeta, since that came later. Meanwhile, we can\u0027t help anything that was uploaded before we started writing down upload-ids, which also means we can\u0027t help anything written while carrying https://review.opendev.org/c/x/swift3/+/302475/6/swift3/controllers/multi_upload.py#621 -- so no need to look for swift3 sysmeta.","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":523,"context_line":"        upload_id_key \u003d sysmeta_header(\u0027object\u0027, \u0027upload-id\u0027)"},{"line_number":524,"context_line":"        if not (is_success(resp.status_int) and upload_id_key in resp.headers):"},{"line_number":525,"context_line":"            return"},{"line_number":526,"context_line":"        segments_key \u003d sysmeta_header(\u0027object\u0027, \u0027etag\u0027)"},{"line_number":527,"context_line":"        # cleanup s3api mpu segments"},{"line_number":528,"context_line":"        headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":529,"context_line":"        num_segments \u003d int(resp.headers[segments_key].rsplit(\u0027-\u0027, 1)[1])"}],"source_content_type":"text/x-python","patch_set":15,"id":"4e02abd3_64c72c3b","line":526,"in_reply_to":"8b989c38_dc3233d5","updated":"2024-04-01 14:05:21.000000000","message":"Acknowledged","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"151b3132c480c107dad4e788640ae09f1257ff90","unresolved":true,"context_lines":[{"line_number":525,"context_line":"            return"},{"line_number":526,"context_line":"        segments_key \u003d sysmeta_header(\u0027object\u0027, \u0027etag\u0027)"},{"line_number":527,"context_line":"        # cleanup s3api mpu segments"},{"line_number":528,"context_line":"        headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":529,"context_line":"        num_segments \u003d int(resp.headers[segments_key].rsplit(\u0027-\u0027, 1)[1])"},{"line_number":530,"context_line":"        self._delete_mpu_segments(a, c, o, resp.headers[upload_id_key],"},{"line_number":531,"context_line":"                                  num_segments, headers)"}],"source_content_type":"text/x-python","patch_set":15,"id":"e6d7089f_56132800","line":528,"updated":"2022-06-08 00:58:56.000000000","message":"So that\u0027s cool -- we\u0027ll also clean up segments for MPUs that get async-deleted.\n\nI think we only ever test with is_async_delete\u003dFalse, though.","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":525,"context_line":"            return"},{"line_number":526,"context_line":"        segments_key \u003d sysmeta_header(\u0027object\u0027, \u0027etag\u0027)"},{"line_number":527,"context_line":"        # cleanup s3api mpu segments"},{"line_number":528,"context_line":"        headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":529,"context_line":"        num_segments \u003d int(resp.headers[segments_key].rsplit(\u0027-\u0027, 1)[1])"},{"line_number":530,"context_line":"        self._delete_mpu_segments(a, c, o, resp.headers[upload_id_key],"},{"line_number":531,"context_line":"                                  num_segments, headers)"}],"source_content_type":"text/x-python","patch_set":15,"id":"39d99f99_1a9a0742","line":528,"in_reply_to":"e6d7089f_56132800","updated":"2024-04-01 14:05:21.000000000","message":"I think is_async_delete\u003dTrue won\u0027t make any material difference; it\u0027s covered by `test_delete_actual_object_bulk`, but I threw an explicit test for s3api mpu up there","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d813622596130874558a16025daa22a1234aba01","unresolved":true,"context_lines":[{"line_number":513,"context_line":"        segments_key \u003d sysmeta_header(\u0027object\u0027, \u0027etag\u0027)"},{"line_number":514,"context_line":"        # cleanup s3api mpu segments"},{"line_number":515,"context_line":"        headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":516,"context_line":"        num_segments \u003d int(resp.headers[segments_key].rsplit(\u0027-\u0027, 1)[1])"},{"line_number":517,"context_line":"        self._delete_mpu_segments(a, c, o, resp.headers[upload_id_key],"},{"line_number":518,"context_line":"                                  num_segments, headers)"}],"source_content_type":"text/x-python","patch_set":32,"id":"c8e3de75_1e2a7366","line":516,"range":{"start_line":516,"start_character":27,"end_line":516,"end_character":54},"updated":"2024-03-20 19:09:29.000000000","message":"This can come back empty, on account of https://github.com/openstack/swift/blob/master/swift/common/middleware/s3api/controllers/multi_upload.py#L239-L245\n\nThe situation might improve if we ever circle back on https://review.opendev.org/c/openstack/swift/+/894800, but we\u0027ll still want to be prepared to see `\u0027\u0027` here.","commit_id":"d7f8e8b98c3ac6d77a7ba91e24b5a46add9c7268"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":513,"context_line":"        segments_key \u003d sysmeta_header(\u0027object\u0027, \u0027etag\u0027)"},{"line_number":514,"context_line":"        # cleanup s3api mpu segments"},{"line_number":515,"context_line":"        headers.pop(\u0027X-If-Delete-At\u0027, None)"},{"line_number":516,"context_line":"        num_segments \u003d int(resp.headers[segments_key].rsplit(\u0027-\u0027, 1)[1])"},{"line_number":517,"context_line":"        self._delete_mpu_segments(a, c, o, resp.headers[upload_id_key],"},{"line_number":518,"context_line":"                                  num_segments, headers)"}],"source_content_type":"text/x-python","patch_set":32,"id":"7f3e9c0c_edc7f1dc","line":516,"range":{"start_line":516,"start_character":27,"end_line":516,"end_character":54},"in_reply_to":"c8e3de75_1e2a7366","updated":"2024-04-01 14:05:21.000000000","message":"well spotted!  #fixed","commit_id":"d7f8e8b98c3ac6d77a7ba91e24b5a46add9c7268"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"70b8c0d3f18ddd36bbb3ee048c3dbd81f9ff97cb","unresolved":true,"context_lines":[{"line_number":28,"context_line":"from swift.common.http import is_success"},{"line_number":29,"context_line":"from swift.common.internal_client import InternalClient, UnexpectedResponse"},{"line_number":30,"context_line":"from swift.common.middleware.s3api.utils import sysmeta_header as \\"},{"line_number":31,"context_line":"    s3_sysmeta_header"},{"line_number":32,"context_line":"from swift.common.utils import get_logger, dump_recon_cache, split_path, \\"},{"line_number":33,"context_line":"    Timestamp, config_true_value, normalize_delete_at_timestamp, \\"},{"line_number":34,"context_line":"    RateLimitedIterator, md5"}],"source_content_type":"text/x-python","patch_set":34,"id":"4e8e2077_3943b5bc","line":31,"updated":"2024-04-04 18:18:09.000000000","message":"+1 yeah that\u0027s unfortunate naming","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8e0d4617ca9854d94ca05570003aed1e8adfcaad","unresolved":false,"context_lines":[{"line_number":28,"context_line":"from swift.common.http import is_success"},{"line_number":29,"context_line":"from swift.common.internal_client import InternalClient, UnexpectedResponse"},{"line_number":30,"context_line":"from swift.common.middleware.s3api.utils import sysmeta_header as \\"},{"line_number":31,"context_line":"    s3_sysmeta_header"},{"line_number":32,"context_line":"from swift.common.utils import get_logger, dump_recon_cache, split_path, \\"},{"line_number":33,"context_line":"    Timestamp, config_true_value, normalize_delete_at_timestamp, \\"},{"line_number":34,"context_line":"    RateLimitedIterator, md5"}],"source_content_type":"text/x-python","patch_set":34,"id":"c35277e0_8f5864c2","line":31,"in_reply_to":"4e8e2077_3943b5bc","updated":"2024-04-04 19:07:05.000000000","message":"Acknowledged","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"70b8c0d3f18ddd36bbb3ee048c3dbd81f9ff97cb","unresolved":true,"context_lines":[{"line_number":484,"context_line":""},{"line_number":485,"context_line":"        For \"normal\" expiration the DELETE request may be rejected if the"},{"line_number":486,"context_line":"        X-Delete-At value of the object is exactly the timestamp given; this"},{"line_number":487,"context_line":"        behavior does not effect is_async_delete\u003dTrue."},{"line_number":488,"context_line":""},{"line_number":489,"context_line":"        :param actual_obj: The name of the end-user object to delete:"},{"line_number":490,"context_line":"                           \u0027\u003caccount\u003e/\u003ccontainer\u003e/\u003cobject\u003e\u0027"}],"source_content_type":"text/x-python","patch_set":34,"id":"d9b48992_a8e2d112","line":487,"range":{"start_line":487,"start_character":26,"end_line":487,"end_character":32},"updated":"2024-04-04 18:18:09.000000000","message":"s/effect/affect/","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6ae1792e323539e246b733015cf913fa12e9b355","unresolved":false,"context_lines":[{"line_number":484,"context_line":""},{"line_number":485,"context_line":"        For \"normal\" expiration the DELETE request may be rejected if the"},{"line_number":486,"context_line":"        X-Delete-At value of the object is exactly the timestamp given; this"},{"line_number":487,"context_line":"        behavior does not effect is_async_delete\u003dTrue."},{"line_number":488,"context_line":""},{"line_number":489,"context_line":"        :param actual_obj: The name of the end-user object to delete:"},{"line_number":490,"context_line":"                           \u0027\u003caccount\u003e/\u003ccontainer\u003e/\u003cobject\u003e\u0027"}],"source_content_type":"text/x-python","patch_set":34,"id":"2eeec66c_448028f0","line":487,"range":{"start_line":487,"start_character":26,"end_line":487,"end_character":32},"in_reply_to":"5a263975_daadd1b9","updated":"2024-06-04 20:42:36.000000000","message":"Done","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8e0d4617ca9854d94ca05570003aed1e8adfcaad","unresolved":true,"context_lines":[{"line_number":484,"context_line":""},{"line_number":485,"context_line":"        For \"normal\" expiration the DELETE request may be rejected if the"},{"line_number":486,"context_line":"        X-Delete-At value of the object is exactly the timestamp given; this"},{"line_number":487,"context_line":"        behavior does not effect is_async_delete\u003dTrue."},{"line_number":488,"context_line":""},{"line_number":489,"context_line":"        :param actual_obj: The name of the end-user object to delete:"},{"line_number":490,"context_line":"                           \u0027\u003caccount\u003e/\u003ccontainer\u003e/\u003cobject\u003e\u0027"}],"source_content_type":"text/x-python","patch_set":34,"id":"5a263975_daadd1b9","line":487,"range":{"start_line":487,"start_character":26,"end_line":487,"end_character":32},"in_reply_to":"d9b48992_a8e2d112","updated":"2024-04-04 19:07:05.000000000","message":"#willfix","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"70b8c0d3f18ddd36bbb3ee048c3dbd81f9ff97cb","unresolved":true,"context_lines":[{"line_number":513,"context_line":"        segments_key \u003d s3_sysmeta_header(\u0027object\u0027, \u0027etag\u0027)"},{"line_number":514,"context_line":"        if not (is_success(resp.status_int) and all("},{"line_number":515,"context_line":"                resp.headers.get(key) for key in ("},{"line_number":516,"context_line":"                    upload_id_key, segments_key))):"},{"line_number":517,"context_line":"            # upload_id/segments headers may have been set to the empty string"},{"line_number":518,"context_line":"            # during a COPY that creates a non-mpu object"},{"line_number":519,"context_line":"            return"}],"source_content_type":"text/x-python","patch_set":34,"id":"4706debb_9c75db70","line":516,"updated":"2024-04-04 18:18:09.000000000","message":"+1 validate upload_id and segments_key have values before going on to use them","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8e0d4617ca9854d94ca05570003aed1e8adfcaad","unresolved":false,"context_lines":[{"line_number":513,"context_line":"        segments_key \u003d s3_sysmeta_header(\u0027object\u0027, \u0027etag\u0027)"},{"line_number":514,"context_line":"        if not (is_success(resp.status_int) and all("},{"line_number":515,"context_line":"                resp.headers.get(key) for key in ("},{"line_number":516,"context_line":"                    upload_id_key, segments_key))):"},{"line_number":517,"context_line":"            # upload_id/segments headers may have been set to the empty string"},{"line_number":518,"context_line":"            # during a COPY that creates a non-mpu object"},{"line_number":519,"context_line":"            return"}],"source_content_type":"text/x-python","patch_set":34,"id":"7ea96883_cc4b400d","line":516,"in_reply_to":"4706debb_9c75db70","updated":"2024-04-04 19:07:05.000000000","message":"Acknowledged","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"70b8c0d3f18ddd36bbb3ee048c3dbd81f9ff97cb","unresolved":true,"context_lines":[{"line_number":514,"context_line":"        if not (is_success(resp.status_int) and all("},{"line_number":515,"context_line":"                resp.headers.get(key) for key in ("},{"line_number":516,"context_line":"                    upload_id_key, segments_key))):"},{"line_number":517,"context_line":"            # upload_id/segments headers may have been set to the empty string"},{"line_number":518,"context_line":"            # during a COPY that creates a non-mpu object"},{"line_number":519,"context_line":"            return"},{"line_number":520,"context_line":"        # cleanup s3api mpu segments"}],"source_content_type":"text/x-python","patch_set":34,"id":"7425695a_438976f5","line":517,"range":{"start_line":517,"start_character":14,"end_line":517,"end_character":23},"updated":"2024-04-04 18:18:09.000000000","message":"re. the comment: IIUC the upload_id specifically *isn\u0027t* set to empty string or we\u0027d already be returning here - it\u0027s the etag+parts_count that\u0027s set to \u0027\u0027 despite there being a valid upload_id","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8e0d4617ca9854d94ca05570003aed1e8adfcaad","unresolved":true,"context_lines":[{"line_number":514,"context_line":"        if not (is_success(resp.status_int) and all("},{"line_number":515,"context_line":"                resp.headers.get(key) for key in ("},{"line_number":516,"context_line":"                    upload_id_key, segments_key))):"},{"line_number":517,"context_line":"            # upload_id/segments headers may have been set to the empty string"},{"line_number":518,"context_line":"            # during a COPY that creates a non-mpu object"},{"line_number":519,"context_line":"            return"},{"line_number":520,"context_line":"        # cleanup s3api mpu segments"}],"source_content_type":"text/x-python","patch_set":34,"id":"9e72a9f5_5dd1d0cf","line":517,"range":{"start_line":517,"start_character":14,"end_line":517,"end_character":23},"in_reply_to":"7425695a_438976f5","updated":"2024-04-04 19:07:05.000000000","message":"good point!  must be true.\n\nAnd you\u0027re right:\n\nhttps://github.com/openstack/swift/blob/master/swift/common/middleware/s3api/controllers/multi_upload.py#L239-L245\n\n... only the `sysmeta(\u0027object\u0027, \u0027etag\u0027)` is getting blanked (i.e. `x-object-sysmeta-s3api-etag`)\n\n#willfix","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6ae1792e323539e246b733015cf913fa12e9b355","unresolved":false,"context_lines":[{"line_number":514,"context_line":"        if not (is_success(resp.status_int) and all("},{"line_number":515,"context_line":"                resp.headers.get(key) for key in ("},{"line_number":516,"context_line":"                    upload_id_key, segments_key))):"},{"line_number":517,"context_line":"            # upload_id/segments headers may have been set to the empty string"},{"line_number":518,"context_line":"            # during a COPY that creates a non-mpu object"},{"line_number":519,"context_line":"            return"},{"line_number":520,"context_line":"        # cleanup s3api mpu segments"}],"source_content_type":"text/x-python","patch_set":34,"id":"5874a7f4_132ddcc4","line":517,"range":{"start_line":517,"start_character":14,"end_line":517,"end_character":23},"in_reply_to":"9e72a9f5_5dd1d0cf","updated":"2024-06-04 20:42:36.000000000","message":"Done","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"}],"swift/obj/server.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ffdecaa4fc2e516ae10bd5210bc7bd7c780b13c2","unresolved":true,"context_lines":[{"line_number":1252,"context_line":"            # if we can not verify the x-if-delete-at time"},{"line_number":1253,"context_line":"            if not orig_timestamp:"},{"line_number":1254,"context_line":"                # no object found at all"},{"line_number":1255,"context_line":"                return HTTPNotFound()"},{"line_number":1256,"context_line":"            if orig_timestamp \u003e\u003d req_timestamp:"},{"line_number":1257,"context_line":"                # Found a newer object -- return 409 as work item is stale"},{"line_number":1258,"context_line":"                return HTTPConflict()"}],"source_content_type":"text/x-python","patch_set":1,"id":"ccbdea34_dd7279c3","line":1255,"updated":"2021-07-13 18:05:36.000000000","message":"it was a key insight to me that an expirer DELETE can\u0027t accidently write tombstones if there isn\u0027t an object with matching x-delete-at in it\u0027s metdata (and if there IS, and we DO write a tombstone, we know that we got that s3api MPU metadata in the response)","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"db34c487c171aaecaa4cdba105e3985458ddcc8f","unresolved":false,"context_lines":[{"line_number":1252,"context_line":"            # if we can not verify the x-if-delete-at time"},{"line_number":1253,"context_line":"            if not orig_timestamp:"},{"line_number":1254,"context_line":"                # no object found at all"},{"line_number":1255,"context_line":"                return HTTPNotFound()"},{"line_number":1256,"context_line":"            if orig_timestamp \u003e\u003d req_timestamp:"},{"line_number":1257,"context_line":"                # Found a newer object -- return 409 as work item is stale"},{"line_number":1258,"context_line":"                return HTTPConflict()"}],"source_content_type":"text/x-python","patch_set":1,"id":"f6a3bb93_c744699b","line":1255,"in_reply_to":"52ce561b_63792640","updated":"2021-12-21 22:56:28.000000000","message":"Done","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"98f453900bdf43044753978046da00e34aab5af8","unresolved":true,"context_lines":[{"line_number":1252,"context_line":"            # if we can not verify the x-if-delete-at time"},{"line_number":1253,"context_line":"            if not orig_timestamp:"},{"line_number":1254,"context_line":"                # no object found at all"},{"line_number":1255,"context_line":"                return HTTPNotFound()"},{"line_number":1256,"context_line":"            if orig_timestamp \u003e\u003d req_timestamp:"},{"line_number":1257,"context_line":"                # Found a newer object -- return 409 as work item is stale"},{"line_number":1258,"context_line":"                return HTTPConflict()"}],"source_content_type":"text/x-python","patch_set":1,"id":"52ce561b_63792640","line":1255,"in_reply_to":"ccbdea34_dd7279c3","updated":"2021-07-15 00:12:09.000000000","message":"Well, modulo the scheduled-delete functionality I added in https://github.com/openstack/swift/commit/83d01619 ;-)","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ffdecaa4fc2e516ae10bd5210bc7bd7c780b13c2","unresolved":true,"context_lines":[{"line_number":1282,"context_line":"                     \u0027X-Object-Sysmeta-S3api-Etag\u0027: orig_metadata.get("},{"line_number":1283,"context_line":"                         \u0027X-Object-Sysmeta-S3Api-Etag\u0027),"},{"line_number":1284,"context_line":"                     \u0027X-Object-Sysmeta-S3api-Upload-Id\u0027: orig_metadata.get("},{"line_number":1285,"context_line":"                         \u0027X-Object-Sysmeta-S3Api-Upload-Id\u0027),"},{"line_number":1286,"context_line":"                     \u0027X-Backend-Content-Type\u0027: orig_metadata.get("},{"line_number":1287,"context_line":"                         \u0027Content-Type\u0027, \u0027\u0027)})"},{"line_number":1288,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"b2c766e5_dcf4f25a","line":1285,"updated":"2021-07-13 18:05:36.000000000","message":"there\u0027s probably a LOT of orig_metadata that could be reasonable to include in the response - possibly *all* of the sysmtea!?","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":1282,"context_line":"                     \u0027X-Object-Sysmeta-S3api-Etag\u0027: orig_metadata.get("},{"line_number":1283,"context_line":"                         \u0027X-Object-Sysmeta-S3Api-Etag\u0027),"},{"line_number":1284,"context_line":"                     \u0027X-Object-Sysmeta-S3api-Upload-Id\u0027: orig_metadata.get("},{"line_number":1285,"context_line":"                         \u0027X-Object-Sysmeta-S3Api-Upload-Id\u0027),"},{"line_number":1286,"context_line":"                     \u0027X-Backend-Content-Type\u0027: orig_metadata.get("},{"line_number":1287,"context_line":"                         \u0027Content-Type\u0027, \u0027\u0027)})"},{"line_number":1288,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"8ff142d6_4b6af7bb","line":1285,"in_reply_to":"b2c766e5_dcf4f25a","updated":"2024-04-01 14:05:21.000000000","message":"it looks like we decided we did want to include all sysmeta.","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f0e5cb531eb8cb29d551aa987dcb37d51511150a","unresolved":true,"context_lines":[{"line_number":1281,"context_line":"                     \u0027X-Object-Sysmeta-S3api-Etag\u0027: orig_metadata.get("},{"line_number":1282,"context_line":"                         \u0027X-Object-Sysmeta-S3Api-Etag\u0027),"},{"line_number":1283,"context_line":"                     \u0027X-Object-Sysmeta-S3api-Upload-Id\u0027: orig_metadata.get("},{"line_number":1284,"context_line":"                         \u0027X-Object-Sysmeta-S3Api-Upload-Id\u0027),"},{"line_number":1285,"context_line":"                     \u0027X-Backend-Content-Type\u0027: orig_metadata.get("},{"line_number":1286,"context_line":"                         \u0027Content-Type\u0027, \u0027\u0027)})"},{"line_number":1287,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"5f5d9f4a_cf03351e","line":1284,"updated":"2021-12-22 11:16:08.000000000","message":"maybe we could just return all metadata with the DELETE to avoid the bleeding of s3Api to the backend?","commit_id":"edff82be41225a2002ed177c2d1348e1d5873f72"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":1281,"context_line":"                     \u0027X-Object-Sysmeta-S3api-Etag\u0027: orig_metadata.get("},{"line_number":1282,"context_line":"                         \u0027X-Object-Sysmeta-S3Api-Etag\u0027),"},{"line_number":1283,"context_line":"                     \u0027X-Object-Sysmeta-S3api-Upload-Id\u0027: orig_metadata.get("},{"line_number":1284,"context_line":"                         \u0027X-Object-Sysmeta-S3Api-Upload-Id\u0027),"},{"line_number":1285,"context_line":"                     \u0027X-Backend-Content-Type\u0027: orig_metadata.get("},{"line_number":1286,"context_line":"                         \u0027Content-Type\u0027, \u0027\u0027)})"},{"line_number":1287,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"a89821d8_49f19802","line":1284,"in_reply_to":"5f5d9f4a_cf03351e","updated":"2024-04-01 14:05:21.000000000","message":"I think we did that.","commit_id":"edff82be41225a2002ed177c2d1348e1d5873f72"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c9f4264667243283be27a67274a2458bfe24f355","unresolved":true,"context_lines":[{"line_number":1283,"context_line":"        for key, value in orig_metadata.items():"},{"line_number":1284,"context_line":"            if (is_sys_or_user_meta(\u0027object\u0027, key) or"},{"line_number":1285,"context_line":"                    is_object_transient_sysmeta(key)):"},{"line_number":1286,"context_line":"                response.headers[key] \u003d value"},{"line_number":1287,"context_line":"        return response"},{"line_number":1288,"context_line":""},{"line_number":1289,"context_line":"    @public"}],"source_content_type":"text/x-python","patch_set":8,"id":"8fad181c_0c74f0f8","line":1286,"updated":"2022-01-10 16:43:26.000000000","message":"previously DELETE responses didn\u0027t HAVE any sysmeta keys for the proxy to look at - so the \"change in format of the values\" didn\u0027t have any existing consumers to surprise.","commit_id":"210807787136a603e7ed06b5bd87efedff60afe3"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"151b3132c480c107dad4e788640ae09f1257ff90","unresolved":true,"context_lines":[{"line_number":1283,"context_line":"        for key, value in orig_metadata.items():"},{"line_number":1284,"context_line":"            if (is_sys_or_user_meta(\u0027object\u0027, key) or"},{"line_number":1285,"context_line":"                    is_object_transient_sysmeta(key)):"},{"line_number":1286,"context_line":"                response.headers[key] \u003d value"},{"line_number":1287,"context_line":"        return response"},{"line_number":1288,"context_line":""},{"line_number":1289,"context_line":"    @public"}],"source_content_type":"text/x-python","patch_set":8,"id":"cc291a0e_9ccda4ed","line":1286,"in_reply_to":"8fad181c_0c74f0f8","updated":"2022-06-08 00:58:56.000000000","message":"I\u0027m confused -- what \"change in format of the values\"?\n\nOr is this comment pretty stale? But this file doesn\u0027t seem to have changed since PS 8...","commit_id":"210807787136a603e7ed06b5bd87efedff60afe3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":1283,"context_line":"        for key, value in orig_metadata.items():"},{"line_number":1284,"context_line":"            if (is_sys_or_user_meta(\u0027object\u0027, key) or"},{"line_number":1285,"context_line":"                    is_object_transient_sysmeta(key)):"},{"line_number":1286,"context_line":"                response.headers[key] \u003d value"},{"line_number":1287,"context_line":"        return response"},{"line_number":1288,"context_line":""},{"line_number":1289,"context_line":"    @public"}],"source_content_type":"text/x-python","patch_set":8,"id":"8885168f_f4fa48d3","line":1286,"in_reply_to":"cc291a0e_9ccda4ed","updated":"2024-04-01 14:05:21.000000000","message":"not sure, maybe I just ment that including these headers shouldn\u0027t be a problem - and it hasn\u0027t been!","commit_id":"210807787136a603e7ed06b5bd87efedff60afe3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[{"line_number":1234,"context_line":"            if orig_timestamp \u003c req_timestamp:"},{"line_number":1235,"context_line":"                response_class \u003d HTTPNoContent"},{"line_number":1236,"context_line":"            else:"},{"line_number":1237,"context_line":"                response_class \u003d HTTPConflict"},{"line_number":1238,"context_line":"        response_timestamp \u003d max(orig_timestamp, req_timestamp)"},{"line_number":1239,"context_line":"        orig_delete_at \u003d Timestamp(orig_metadata.get(\u0027X-Delete-At\u0027) or 0)"},{"line_number":1240,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":9,"id":"edbb647e_e2d5c25c","line":1237,"updated":"2022-01-13 06:12:25.000000000","message":"probably","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4d91fc0634159dd6f7280e8c041bfef8ad1732ae","unresolved":true,"context_lines":[{"line_number":1275,"context_line":"                \u0027DELETE\u0027, account, container, obj, request,"},{"line_number":1276,"context_line":"                HeaderKeyDict({\u0027x-timestamp\u0027: req_timestamp.internal}),"},{"line_number":1277,"context_line":"                device, policy)"},{"line_number":1278,"context_line":"        response \u003d response_class("},{"line_number":1279,"context_line":"            request\u003drequest,"},{"line_number":1280,"context_line":"            headers\u003d{\u0027X-Backend-Timestamp\u0027: response_timestamp.internal,"},{"line_number":1281,"context_line":"                     \u0027X-Backend-Content-Type\u0027: orig_metadata.get("}],"source_content_type":"text/x-python","patch_set":9,"id":"b4796803_3e26a458","line":1278,"range":{"start_line":1278,"start_character":19,"end_line":1278,"end_character":33},"updated":"2022-01-12 15:20:12.000000000","message":"I think this could be HTTPConflict ??","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[{"line_number":1275,"context_line":"                \u0027DELETE\u0027, account, container, obj, request,"},{"line_number":1276,"context_line":"                HeaderKeyDict({\u0027x-timestamp\u0027: req_timestamp.internal}),"},{"line_number":1277,"context_line":"                device, policy)"},{"line_number":1278,"context_line":"        response \u003d response_class("},{"line_number":1279,"context_line":"            request\u003drequest,"},{"line_number":1280,"context_line":"            headers\u003d{\u0027X-Backend-Timestamp\u0027: response_timestamp.internal,"},{"line_number":1281,"context_line":"                     \u0027X-Backend-Content-Type\u0027: orig_metadata.get("}],"source_content_type":"text/x-python","patch_set":9,"id":"9941c0a6_764e9026","line":1278,"range":{"start_line":1278,"start_character":19,"end_line":1278,"end_character":33},"in_reply_to":"b4796803_3e26a458","updated":"2022-01-13 06:12:25.000000000","message":"Ack","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6ae1792e323539e246b733015cf913fa12e9b355","unresolved":false,"context_lines":[{"line_number":1297,"context_line":"            if (is_sys_or_user_meta(\u0027object\u0027, key) or"},{"line_number":1298,"context_line":"                    is_object_transient_sysmeta(key)):"},{"line_number":1299,"context_line":"                response.headers[key] \u003d value"},{"line_number":1300,"context_line":"        return response"},{"line_number":1301,"context_line":""},{"line_number":1302,"context_line":"    @public"},{"line_number":1303,"context_line":"    @replication"}],"source_content_type":"text/x-python","patch_set":39,"id":"dd18e88d_f9641de4","line":1300,"updated":"2024-06-04 20:42:36.000000000","message":"is this new behavior just untetsed?!","commit_id":"4b729c66577f9e4d7b6679715e17cdd166b6b33b"}],"swift/proxy/controllers/base.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ffdecaa4fc2e516ae10bd5210bc7bd7c780b13c2","unresolved":true,"context_lines":[{"line_number":107,"context_line":"    if not s3api_meta:"},{"line_number":108,"context_line":"        return"},{"line_number":109,"context_line":"    key \u003d \u0027X-Backend-S3Api-Upload-Segments\u0027"},{"line_number":110,"context_line":"    upload_segments \u003d \u0027,\u0027.join(s3api_meta)"},{"line_number":111,"context_line":"    if hasattr(resp_headers, \u0027append\u0027):"},{"line_number":112,"context_line":"        resp_headers.append((key, upload_segments))"},{"line_number":113,"context_line":"    else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"d6aa11ff_097cff6b","line":110,"updated":"2021-07-13 18:05:36.000000000","message":"this is a little wonky - we\u0027re taking the metadata from ALL the backend DELETE responses and consolidating them into a single header (which will most often have only one value because s3api_meta is a set)","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"db34c487c171aaecaa4cdba105e3985458ddcc8f","unresolved":false,"context_lines":[{"line_number":107,"context_line":"    if not s3api_meta:"},{"line_number":108,"context_line":"        return"},{"line_number":109,"context_line":"    key \u003d \u0027X-Backend-S3Api-Upload-Segments\u0027"},{"line_number":110,"context_line":"    upload_segments \u003d \u0027,\u0027.join(s3api_meta)"},{"line_number":111,"context_line":"    if hasattr(resp_headers, \u0027append\u0027):"},{"line_number":112,"context_line":"        resp_headers.append((key, upload_segments))"},{"line_number":113,"context_line":"    else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"5b984517_afc80c15","line":110,"in_reply_to":"3f10b1e4_2d09927a","updated":"2021-12-21 22:56:28.000000000","message":"Done","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"98f453900bdf43044753978046da00e34aab5af8","unresolved":true,"context_lines":[{"line_number":107,"context_line":"    if not s3api_meta:"},{"line_number":108,"context_line":"        return"},{"line_number":109,"context_line":"    key \u003d \u0027X-Backend-S3Api-Upload-Segments\u0027"},{"line_number":110,"context_line":"    upload_segments \u003d \u0027,\u0027.join(s3api_meta)"},{"line_number":111,"context_line":"    if hasattr(resp_headers, \u0027append\u0027):"},{"line_number":112,"context_line":"        resp_headers.append((key, upload_segments))"},{"line_number":113,"context_line":"    else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f10b1e4_2d09927a","line":110,"in_reply_to":"d6aa11ff_097cff6b","updated":"2021-07-15 00:12:09.000000000","message":"OIC -- we need to do this aggregation in the proxy, where we\u0027ve got all the backend responses in hand.\n\nDo we do anything similar for versioning and the X-Backend-Content-Type header?\n\nWhat happens if there\u0027s more than one item in the set?","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ffdecaa4fc2e516ae10bd5210bc7bd7c780b13c2","unresolved":true,"context_lines":[{"line_number":2077,"context_line":"                resp.body \u003d bodies[status_index]"},{"line_number":2078,"context_line":"                if headers:"},{"line_number":2079,"context_line":"                    resp_headers \u003d headers[status_index]"},{"line_number":2080,"context_line":"                    add_s3api_metadata(resp_headers, headers)"},{"line_number":2081,"context_line":"                    update_headers(resp, resp_headers)"},{"line_number":2082,"context_line":"                if etag:"},{"line_number":2083,"context_line":"                    resp.headers[\u0027etag\u0027] \u003d normalize_etag(etag)"}],"source_content_type":"text/x-python","patch_set":1,"id":"be9c2f21_3f330cc2","line":2080,"updated":"2021-07-13 18:05:36.000000000","message":"we could ONLY do this on DELETE?  I think this method is also used for POST.\n\nit kinda sucks that s3api context bleeds down into the proxy... again, we could do something similar for ALL sysmeta?","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":2077,"context_line":"                resp.body \u003d bodies[status_index]"},{"line_number":2078,"context_line":"                if headers:"},{"line_number":2079,"context_line":"                    resp_headers \u003d headers[status_index]"},{"line_number":2080,"context_line":"                    add_s3api_metadata(resp_headers, headers)"},{"line_number":2081,"context_line":"                    update_headers(resp, resp_headers)"},{"line_number":2082,"context_line":"                if etag:"},{"line_number":2083,"context_line":"                    resp.headers[\u0027etag\u0027] \u003d normalize_etag(etag)"}],"source_content_type":"text/x-python","patch_set":1,"id":"750cdc3d_82cf0bcf","line":2080,"in_reply_to":"be9c2f21_3f330cc2","updated":"2024-04-01 14:05:21.000000000","message":"Acknowledged","commit_id":"178674f074e20462cca411ea28b0f6a348685c5e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f0e5cb531eb8cb29d551aa987dcb37d51511150a","unresolved":true,"context_lines":[{"line_number":91,"context_line":"            response.headers[name] \u003d value"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"def add_s3api_metadata(resp_headers, all_headers):"},{"line_number":95,"context_line":"    if hasattr(resp_headers, \u0027items\u0027):"},{"line_number":96,"context_line":"        resp_headers \u003d resp_headers.items()"},{"line_number":97,"context_line":"    s3api_meta \u003d []"}],"source_content_type":"text/x-python","patch_set":5,"id":"debe1ccb_422f732a","line":94,"updated":"2021-12-22 11:16:08.000000000","message":"it\u0027s unfortunate to have this s3api implementation detail bleed into base.py - is this handled here because there may be different metadata coming back in each of the DELETE responses, and we want to capture the superset, before we lose the backend responses ?\n\nThe warning in expirer implies this is an unexpected/unusual case? could it be dealt with otherwise (if we have some fallback for clean up of orphaned segments)?","commit_id":"edff82be41225a2002ed177c2d1348e1d5873f72"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":91,"context_line":"            response.headers[name] \u003d value"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"def add_s3api_metadata(resp_headers, all_headers):"},{"line_number":95,"context_line":"    if hasattr(resp_headers, \u0027items\u0027):"},{"line_number":96,"context_line":"        resp_headers \u003d resp_headers.items()"},{"line_number":97,"context_line":"    s3api_meta \u003d []"}],"source_content_type":"text/x-python","patch_set":5,"id":"6b0ffa52_365176e7","line":94,"in_reply_to":"debe1ccb_422f732a","updated":"2024-04-01 14:05:21.000000000","message":"Acknowledged","commit_id":"edff82be41225a2002ed177c2d1348e1d5873f72"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f0e5cb531eb8cb29d551aa987dcb37d51511150a","unresolved":true,"context_lines":[{"line_number":103,"context_line":"        etag \u003d headers.pop(\u0027X-Object-Sysmeta-S3Api-Etag\u0027, None)"},{"line_number":104,"context_line":"        if not etag:"},{"line_number":105,"context_line":"            continue"},{"line_number":106,"context_line":"        upload_segments \u003d \u0027%s/%s\u0027 % (upload_id, etag.rsplit(\u0027-\u0027, 1)[1])"},{"line_number":107,"context_line":"        s3api_meta.append(upload_segments)"},{"line_number":108,"context_line":"    if not s3api_meta:"},{"line_number":109,"context_line":"        return"}],"source_content_type":"text/x-python","patch_set":5,"id":"1bb25f6c_8256ad53","line":106,"range":{"start_line":106,"start_character":48,"end_line":106,"end_character":67},"updated":"2021-12-22 11:16:08.000000000","message":"so does the \u0027Etag\u0027 actually have the number of segments embedded in it?\n\nin expirer this is referred to as \u0027segment_key\u0027 and unpacked to upload_id, num_segments","commit_id":"edff82be41225a2002ed177c2d1348e1d5873f72"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":103,"context_line":"        etag \u003d headers.pop(\u0027X-Object-Sysmeta-S3Api-Etag\u0027, None)"},{"line_number":104,"context_line":"        if not etag:"},{"line_number":105,"context_line":"            continue"},{"line_number":106,"context_line":"        upload_segments \u003d \u0027%s/%s\u0027 % (upload_id, etag.rsplit(\u0027-\u0027, 1)[1])"},{"line_number":107,"context_line":"        s3api_meta.append(upload_segments)"},{"line_number":108,"context_line":"    if not s3api_meta:"},{"line_number":109,"context_line":"        return"}],"source_content_type":"text/x-python","patch_set":5,"id":"c6fce84d_dcc9b06c","line":106,"range":{"start_line":106,"start_character":48,"end_line":106,"end_character":67},"in_reply_to":"1bb25f6c_8256ad53","updated":"2024-04-01 14:05:21.000000000","message":"yes","commit_id":"edff82be41225a2002ed177c2d1348e1d5873f72"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"990fc81e9b23c543dd9bedd5cc8bcead16058b4e","unresolved":true,"context_lines":[{"line_number":102,"context_line":"                    is_object_transient_sysmeta(key)):"},{"line_number":103,"context_line":"                sysmeta[key].add(value)"},{"line_number":104,"context_line":"    for key, values in sysmeta.items():"},{"line_number":105,"context_line":"        resp_headers.append((key, \u0027,\u0027.join(values)))"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"def source_key(resp):"}],"source_content_type":"text/x-python","patch_set":8,"id":"ecd2e861_02db517c","line":105,"updated":"2022-01-10 11:22:58.000000000","message":"I think we\u0027ll need to use a new header key here - in general,  consumers of object sysmeta are not going to tolerate being fed comma separated values. It\u0027s a little scarey that this change did not break a unit test.\n\nBut then the question is how to choose a new key that is guaranteed to be unique?","commit_id":"210807787136a603e7ed06b5bd87efedff60afe3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c45f1c9e919933c428ee3af25b8de29cf129f3b4","unresolved":true,"context_lines":[{"line_number":102,"context_line":"                    is_object_transient_sysmeta(key)):"},{"line_number":103,"context_line":"                sysmeta[key].add(value)"},{"line_number":104,"context_line":"    for key, values in sysmeta.items():"},{"line_number":105,"context_line":"        resp_headers.append((key, \u0027,\u0027.join(values)))"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"def source_key(resp):"}],"source_content_type":"text/x-python","patch_set":8,"id":"c5bf0f36_79507554","line":105,"in_reply_to":"b1a44591_4d87040c","updated":"2022-01-10 18:22:09.000000000","message":"I was concerned that _compute_quorum_response is on the call path for GETs and HEADs too. I notice that swift-tox-func-encryption-py27 passes so maybe I\u0027m wrong, maybe _compute_quorum_response only gets called for non-success GET or HEAD responses.","commit_id":"210807787136a603e7ed06b5bd87efedff60afe3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":102,"context_line":"                    is_object_transient_sysmeta(key)):"},{"line_number":103,"context_line":"                sysmeta[key].add(value)"},{"line_number":104,"context_line":"    for key, values in sysmeta.items():"},{"line_number":105,"context_line":"        resp_headers.append((key, \u0027,\u0027.join(values)))"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"def source_key(resp):"}],"source_content_type":"text/x-python","patch_set":8,"id":"0b57b60e_72334e59","line":105,"in_reply_to":"c5bf0f36_79507554","updated":"2024-04-01 14:05:21.000000000","message":"I guess I backed off this approach; so I\u0027m not really sure where the backend sysmeta resp header plumbing to internal client responses is sitting at right now.","commit_id":"210807787136a603e7ed06b5bd87efedff60afe3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c9f4264667243283be27a67274a2458bfe24f355","unresolved":true,"context_lines":[{"line_number":102,"context_line":"                    is_object_transient_sysmeta(key)):"},{"line_number":103,"context_line":"                sysmeta[key].add(value)"},{"line_number":104,"context_line":"    for key, values in sysmeta.items():"},{"line_number":105,"context_line":"        resp_headers.append((key, \u0027,\u0027.join(values)))"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"def source_key(resp):"}],"source_content_type":"text/x-python","patch_set":8,"id":"b1a44591_4d87040c","line":105,"in_reply_to":"ecd2e861_02db517c","updated":"2022-01-10 16:43:26.000000000","message":"I think that\u0027s a good point - let\u0027s just overload the expected return values of sysmeta keys in the response\n\nRE: no breaking tests\n\nwell, no one would have been looking for the new CSV list of sysmeta values from unsafe requests since we never attempted to return them before","commit_id":"210807787136a603e7ed06b5bd87efedff60afe3"}],"test/probe/test_object_expirer.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4d91fc0634159dd6f7280e8c041bfef8ad1732ae","unresolved":true,"context_lines":[{"line_number":462,"context_line":"        # brain.put_object()"},{"line_number":463,"context_line":"        # brain.stop_primary_half()"},{"line_number":464,"context_line":"        num_parts \u003d 2"},{"line_number":465,"context_line":"        bucket_name, key_name \u003d self._make_s3api_mpu("},{"line_number":466,"context_line":"            s3client, bucket_name, key_name, num_parts)"},{"line_number":467,"context_line":""},{"line_number":468,"context_line":"        # setup expiration (on just the manifest)"}],"source_content_type":"text/x-python","patch_set":9,"id":"c165f188_4ee36dac","line":465,"range":{"start_line":465,"start_character":8,"end_line":465,"end_character":29},"updated":"2022-01-12 15:20:12.000000000","message":"is this reassignment necessary? the returned values seem to equal the input args","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[{"line_number":462,"context_line":"        # brain.put_object()"},{"line_number":463,"context_line":"        # brain.stop_primary_half()"},{"line_number":464,"context_line":"        num_parts \u003d 2"},{"line_number":465,"context_line":"        bucket_name, key_name \u003d self._make_s3api_mpu("},{"line_number":466,"context_line":"            s3client, bucket_name, key_name, num_parts)"},{"line_number":467,"context_line":""},{"line_number":468,"context_line":"        # setup expiration (on just the manifest)"}],"source_content_type":"text/x-python","patch_set":9,"id":"99990bbc_1190307b","line":465,"range":{"start_line":465,"start_character":8,"end_line":465,"end_character":29},"in_reply_to":"c165f188_4ee36dac","updated":"2022-01-13 06:12:25.000000000","message":"no, just a clunky interface that got jumbled in the rebase","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4d91fc0634159dd6f7280e8c041bfef8ad1732ae","unresolved":true,"context_lines":[{"line_number":510,"context_line":"            obj for obj in self.client.iter_objects("},{"line_number":511,"context_line":"                self.account, segment_container_name)"},{"line_number":512,"context_line":"        ]"},{"line_number":513,"context_line":"        self.assertEqual(0, len(found_segments))"},{"line_number":514,"context_line":""},{"line_number":515,"context_line":""},{"line_number":516,"context_line":"if __name__ \u003d\u003d \"__main__\":"}],"source_content_type":"text/x-python","patch_set":9,"id":"6393365d_d83b6a4a","line":513,"updated":"2022-01-12 15:20:12.000000000","message":"nice!","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[{"line_number":510,"context_line":"            obj for obj in self.client.iter_objects("},{"line_number":511,"context_line":"                self.account, segment_container_name)"},{"line_number":512,"context_line":"        ]"},{"line_number":513,"context_line":"        self.assertEqual(0, len(found_segments))"},{"line_number":514,"context_line":""},{"line_number":515,"context_line":""},{"line_number":516,"context_line":"if __name__ \u003d\u003d \"__main__\":"}],"source_content_type":"text/x-python","patch_set":9,"id":"2fb63892_1a8c14b9","line":513,"in_reply_to":"6393365d_d83b6a4a","updated":"2022-01-13 06:12:25.000000000","message":"Ack","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"}],"test/unit/common/test_internal_client.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4d91fc0634159dd6f7280e8c041bfef8ad1732ae","unresolved":true,"context_lines":[{"line_number":97,"context_line":"        pass"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"class StubResponse(object):"},{"line_number":101,"context_line":"    def __init__(self, status_int, body\u003dNone, headers\u003dNone, app_iter\u003dNone):"},{"line_number":102,"context_line":"        self.status_int \u003d status_int"},{"line_number":103,"context_line":"        self.body \u003d body or \u0027\u0027"}],"source_content_type":"text/x-python","patch_set":9,"id":"72828d5b_19f376fd","line":100,"updated":"2022-01-12 15:20:12.000000000","message":"nit: we have a StubResponse in test/unit/__init__.py, but that is faking an  HTTPResponse. Might be worth naming this StubSwobResponse to avoid confusion (renaming the other to StubHTTPResponse would have more churn I suspect)","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"82174345e79114195880bd5c2d33eeb12fc638c3","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        pass"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"class StubResponse(object):"},{"line_number":101,"context_line":"    def __init__(self, status_int, body\u003dNone, headers\u003dNone, app_iter\u003dNone):"},{"line_number":102,"context_line":"        self.status_int \u003d status_int"},{"line_number":103,"context_line":"        self.body \u003d body or \u0027\u0027"}],"source_content_type":"text/x-python","patch_set":9,"id":"50c51b4e_b06d1417","line":100,"in_reply_to":"72828d5b_19f376fd","updated":"2022-01-13 06:12:25.000000000","message":"Done","commit_id":"d333a1d67e8bf2214b28ac7788647b0ba5747aba"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b96c188205c90e07552c474006a924584a5171ee","unresolved":true,"context_lines":[{"line_number":1337,"context_line":"            \u0027Content-Length\u0027: \u00270\u0027,"},{"line_number":1338,"context_line":"            \u0027Bar\u0027: \u0027baz\u0027,"},{"line_number":1339,"context_line":"            \u0027Content-Type\u0027: \u0027text/html; charset\u003dUTF-8\u0027,"},{"line_number":1340,"context_line":"        }, resp.headers)"},{"line_number":1341,"context_line":""},{"line_number":1342,"context_line":"    def test_get_object_metadata(self):"},{"line_number":1343,"context_line":"        account, container, obj \u003d path_parts()"}],"source_content_type":"text/x-python","patch_set":10,"id":"0c9e33f0_66d50262","line":1340,"updated":"2022-01-13 13:00:18.000000000","message":"+1","commit_id":"60cb24a6beaeb592b47fcbbd5bfab4b97a119d48"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":1337,"context_line":"            \u0027Content-Length\u0027: \u00270\u0027,"},{"line_number":1338,"context_line":"            \u0027Bar\u0027: \u0027baz\u0027,"},{"line_number":1339,"context_line":"            \u0027Content-Type\u0027: \u0027text/html; charset\u003dUTF-8\u0027,"},{"line_number":1340,"context_line":"        }, resp.headers)"},{"line_number":1341,"context_line":""},{"line_number":1342,"context_line":"    def test_get_object_metadata(self):"},{"line_number":1343,"context_line":"        account, container, obj \u003d path_parts()"}],"source_content_type":"text/x-python","patch_set":10,"id":"f1c35c0a_bfd86fa9","line":1340,"in_reply_to":"0c9e33f0_66d50262","updated":"2024-04-01 14:05:21.000000000","message":"Acknowledged","commit_id":"60cb24a6beaeb592b47fcbbd5bfab4b97a119d48"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"151b3132c480c107dad4e788640ae09f1257ff90","unresolved":true,"context_lines":[{"line_number":98,"context_line":"class StubSwobResponse(object):"},{"line_number":99,"context_line":"    def __init__(self, status_int, body\u003dNone, headers\u003dNone, app_iter\u003dNone):"},{"line_number":100,"context_line":"        self.status_int \u003d status_int"},{"line_number":101,"context_line":"        self.body \u003d body or \u0027\u0027"},{"line_number":102,"context_line":"        self.headers \u003d headers or {}"},{"line_number":103,"context_line":"        self.app_iter \u003d app_iter"},{"line_number":104,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"30d4011c_d60095fc","line":101,"updated":"2022-06-08 00:58:56.000000000","message":"nit: Better as\n\n body \u003d body or b\u0027\u0027\n\nWe shouldn\u0027t ever have unicode bodies, only bytes.","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":98,"context_line":"class StubSwobResponse(object):"},{"line_number":99,"context_line":"    def __init__(self, status_int, body\u003dNone, headers\u003dNone, app_iter\u003dNone):"},{"line_number":100,"context_line":"        self.status_int \u003d status_int"},{"line_number":101,"context_line":"        self.body \u003d body or \u0027\u0027"},{"line_number":102,"context_line":"        self.headers \u003d headers or {}"},{"line_number":103,"context_line":"        self.app_iter \u003d app_iter"},{"line_number":104,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"7dadc52a_2068fdfc","line":101,"in_reply_to":"30d4011c_d60095fc","updated":"2024-04-01 14:05:21.000000000","message":"Done","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"}],"test/unit/obj/test_expirer.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"151b3132c480c107dad4e788640ae09f1257ff90","unresolved":true,"context_lines":[{"line_number":1068,"context_line":"                \u0027X-Object-Sysmeta-S3Api-Etag\u0027: \u0027bar-3\u0027,"},{"line_number":1069,"context_line":"            }),"},{"line_number":1070,"context_line":"            # delete segment response"},{"line_number":1071,"context_line":"            swob.Response(status\u003d404),"},{"line_number":1072,"context_line":"            swob.Response(status\u003d204),"},{"line_number":1073,"context_line":"            swob.Response(status\u003d404),"},{"line_number":1074,"context_line":"        ]"}],"source_content_type":"text/x-python","patch_set":15,"id":"797917f3_aa6a574f","line":1071,"updated":"2022-06-08 00:58:56.000000000","message":"We probably want to throw in some 503s, too, to demonstrate that we keep chugging along even in the face of server errors.","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c10bf1aa97d761a17ad46af381321a03075a55eb","unresolved":false,"context_lines":[{"line_number":1068,"context_line":"                \u0027X-Object-Sysmeta-S3Api-Etag\u0027: \u0027bar-3\u0027,"},{"line_number":1069,"context_line":"            }),"},{"line_number":1070,"context_line":"            # delete segment response"},{"line_number":1071,"context_line":"            swob.Response(status\u003d404),"},{"line_number":1072,"context_line":"            swob.Response(status\u003d204),"},{"line_number":1073,"context_line":"            swob.Response(status\u003d404),"},{"line_number":1074,"context_line":"        ]"}],"source_content_type":"text/x-python","patch_set":15,"id":"e801cfcc_4b18b346","line":1071,"in_reply_to":"797917f3_aa6a574f","updated":"2024-04-01 14:05:21.000000000","message":"Done","commit_id":"28553920d653d08fe0b06af0bda7808ec8b5a2a4"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"70b8c0d3f18ddd36bbb3ee048c3dbd81f9ff97cb","unresolved":true,"context_lines":[{"line_number":936,"context_line":"        self.assertEqual(str(log_kwargs[\u0027exc_info\u0027][1]),"},{"line_number":937,"context_line":"                         \u0027exception 1\u0027)"},{"line_number":938,"context_line":""},{"line_number":939,"context_line":"    def test_delete_actual_object(self):"},{"line_number":940,"context_line":"        x \u003d expirer.ObjectExpirer("},{"line_number":941,"context_line":"            {}, swift\u003dunit.FakeInternalClient([swob.Response(status\u003d204)]))"},{"line_number":942,"context_line":"        ts \u003d Timestamp(\u00271234\u0027)"}],"source_content_type":"text/x-python","patch_set":34,"id":"09670493_ba487800","line":939,"updated":"2024-04-04 18:18:09.000000000","message":"If we wanted to move away from FakeInternalClient, this test, for example, could be written:\n\n```\ndiff --git a/test/unit/obj/test_expirer.py b/test/unit/obj/test_expirer.py\nindex 5ed97f23f..da08c6e0f 100644\n--- a/test/unit/obj/test_expirer.py\n+++ b/test/unit/obj/test_expirer.py\n@@ -15,6 +15,9 @@\n\n from time import time\n from unittest import main, TestCase\n+\n+from swift.common.internal_client import InternalClient\n+from swift.common.swob import HTTPNoContent\n from test.debug_logger import debug_logger\n from test.unit import FakeRing, mocked_http_conn, make_timestamp_iter\n from tempfile import mkdtemp\n@@ -30,6 +33,7 @@ from six.moves import urllib\n from swift.common import internal_client, utils, swob\n from swift.common.utils import Timestamp\n from swift.obj import expirer\n+from test.unit.common.middleware.helpers import FakeSwift\n\n\n def not_random():\n@@ -937,19 +941,18 @@ class TestObjectExpirer(TestCase):\n                          \u0027exception 1\u0027)\n\n     def test_delete_actual_object(self):\n+        fake_swift \u003d FakeSwift()\n+        fake_swift.register(\u0027DELETE\u0027, \u0027/v1/path/to/object\u0027, HTTPNoContent, {})\n         x \u003d expirer.ObjectExpirer(\n-            {}, swift\u003dunit.FakeInternalClient([swob.Response(status\u003d204)]))\n+            {}, swift\u003dInternalClient(None, \u0027test-ic\u0027, 1, app\u003dfake_swift))\n         ts \u003d Timestamp(\u00271234\u0027)\n-        with x.swift:\n-            x.delete_actual_object(\u0027path/to/object\u0027, ts, False)\n-        self.assertEqual(1, len(x.swift.calls))\n-        request \u003d x.swift.calls[0]\n-        self.assertEqual(ts, request.headers[\u0027X-If-Delete-At\u0027])\n-        self.assertEqual(request.headers[\u0027X-Timestamp\u0027],\n-                         request.headers[\u0027X-If-Delete-At\u0027])\n+        x.delete_actual_object(\u0027path/to/object\u0027, ts, False)\n+        self.assertEqual([(\u0027DELETE\u0027, \u0027/v1/path/to/object\u0027)], fake_swift.calls)\n+        self.assertEqual(ts, fake_swift.headers[0][\u0027X-If-Delete-At\u0027])\n+        self.assertEqual(ts, fake_swift.headers[0][\u0027X-Timestamp\u0027])\n         self.assertEqual(\n             \u0027no\u0027,\n-            request.headers[\u0027X-Backend-Clean-Expiring-Object-Queue\u0027])\n+            fake_swift.headers[0][\u0027X-Backend-Clean-Expiring-Object-Queue\u0027])\n\n     def test_delete_actual_object_bulk(self):\n         got_env \u003d [None]\n```","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8e0d4617ca9854d94ca05570003aed1e8adfcaad","unresolved":true,"context_lines":[{"line_number":936,"context_line":"        self.assertEqual(str(log_kwargs[\u0027exc_info\u0027][1]),"},{"line_number":937,"context_line":"                         \u0027exception 1\u0027)"},{"line_number":938,"context_line":""},{"line_number":939,"context_line":"    def test_delete_actual_object(self):"},{"line_number":940,"context_line":"        x \u003d expirer.ObjectExpirer("},{"line_number":941,"context_line":"            {}, swift\u003dunit.FakeInternalClient([swob.Response(status\u003d204)]))"},{"line_number":942,"context_line":"        ts \u003d Timestamp(\u00271234\u0027)"}],"source_content_type":"text/x-python","patch_set":34,"id":"f977f706_5785ecfe","line":939,"in_reply_to":"09670493_ba487800","updated":"2024-04-04 19:07:05.000000000","message":"I\u0027m down with that #willfix","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6ae1792e323539e246b733015cf913fa12e9b355","unresolved":false,"context_lines":[{"line_number":936,"context_line":"        self.assertEqual(str(log_kwargs[\u0027exc_info\u0027][1]),"},{"line_number":937,"context_line":"                         \u0027exception 1\u0027)"},{"line_number":938,"context_line":""},{"line_number":939,"context_line":"    def test_delete_actual_object(self):"},{"line_number":940,"context_line":"        x \u003d expirer.ObjectExpirer("},{"line_number":941,"context_line":"            {}, swift\u003dunit.FakeInternalClient([swob.Response(status\u003d204)]))"},{"line_number":942,"context_line":"        ts \u003d Timestamp(\u00271234\u0027)"}],"source_content_type":"text/x-python","patch_set":34,"id":"490a94f3_685577b4","line":939,"in_reply_to":"f977f706_5785ecfe","updated":"2024-06-04 20:42:36.000000000","message":"that diff didn\u0027t apply cleanly anymore for me so I ended up re-writing it; I sort of forgot why I was changing this test exactly; but I guess I should use the new pattern in `test_delete_actual_object_bulk_s3api_mpu`","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"70b8c0d3f18ddd36bbb3ee048c3dbd81f9ff97cb","unresolved":true,"context_lines":[{"line_number":938,"context_line":""},{"line_number":939,"context_line":"    def test_delete_actual_object(self):"},{"line_number":940,"context_line":"        x \u003d expirer.ObjectExpirer("},{"line_number":941,"context_line":"            {}, swift\u003dunit.FakeInternalClient([swob.Response(status\u003d204)]))"},{"line_number":942,"context_line":"        ts \u003d Timestamp(\u00271234\u0027)"},{"line_number":943,"context_line":"        with x.swift:"},{"line_number":944,"context_line":"            x.delete_actual_object(\u0027path/to/object\u0027, ts, False)"}],"source_content_type":"text/x-python","patch_set":34,"id":"a7d497ef_0dd39f83","line":941,"updated":"2024-04-04 18:18:09.000000000","message":"so in this module we use unit.FakeInternalClient and FakeInternalClient and there\u0027s also make_fake_ic() which returns something different again ?!?","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8e0d4617ca9854d94ca05570003aed1e8adfcaad","unresolved":true,"context_lines":[{"line_number":938,"context_line":""},{"line_number":939,"context_line":"    def test_delete_actual_object(self):"},{"line_number":940,"context_line":"        x \u003d expirer.ObjectExpirer("},{"line_number":941,"context_line":"            {}, swift\u003dunit.FakeInternalClient([swob.Response(status\u003d204)]))"},{"line_number":942,"context_line":"        ts \u003d Timestamp(\u00271234\u0027)"},{"line_number":943,"context_line":"        with x.swift:"},{"line_number":944,"context_line":"            x.delete_actual_object(\u0027path/to/object\u0027, ts, False)"}],"source_content_type":"text/x-python","patch_set":34,"id":"f92bae7c_44799401","line":941,"in_reply_to":"a7d497ef_0dd39f83","updated":"2024-04-04 19:07:05.000000000","message":"heh, and so the solution is to introduce yet another competing standard - maybe I\u0027ll get inspired and try and clean them up if I pull out the pre-factor next iteration.","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6ae1792e323539e246b733015cf913fa12e9b355","unresolved":true,"context_lines":[{"line_number":938,"context_line":""},{"line_number":939,"context_line":"    def test_delete_actual_object(self):"},{"line_number":940,"context_line":"        x \u003d expirer.ObjectExpirer("},{"line_number":941,"context_line":"            {}, swift\u003dunit.FakeInternalClient([swob.Response(status\u003d204)]))"},{"line_number":942,"context_line":"        ts \u003d Timestamp(\u00271234\u0027)"},{"line_number":943,"context_line":"        with x.swift:"},{"line_number":944,"context_line":"            x.delete_actual_object(\u0027path/to/object\u0027, ts, False)"}],"source_content_type":"text/x-python","patch_set":34,"id":"0ed655ab_f7b97fe0","line":941,"in_reply_to":"f92bae7c_44799401","updated":"2024-06-04 20:42:36.000000000","message":"yuk, i\u0027m not feeling particularlly inspired... but I have a ton of patches going on the expier right now in different directions so maybe they\u0027d benifit from additional test cleanup prefactoring.","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"70b8c0d3f18ddd36bbb3ee048c3dbd81f9ff97cb","unresolved":true,"context_lines":[{"line_number":942,"context_line":"        ts \u003d Timestamp(\u00271234\u0027)"},{"line_number":943,"context_line":"        with x.swift:"},{"line_number":944,"context_line":"            x.delete_actual_object(\u0027path/to/object\u0027, ts, False)"},{"line_number":945,"context_line":"        self.assertEqual(1, len(x.swift.calls))"},{"line_number":946,"context_line":"        request \u003d x.swift.calls[0]"},{"line_number":947,"context_line":"        self.assertEqual(ts, request.headers[\u0027X-If-Delete-At\u0027])"},{"line_number":948,"context_line":"        self.assertEqual(request.headers[\u0027X-Timestamp\u0027],"}],"source_content_type":"text/x-python","patch_set":34,"id":"1320201a_c22b1758","line":945,"updated":"2024-04-04 18:18:09.000000000","message":"Isn\u0027t using the fake IC as a context manager taking care of this assertion? i.e. the exit() checks that all responses were consumed.\n\nBut I also just noticed the exit() would raise an Exception (not an AssertionError) 😭 so maybe the with ``x.swift`` pattern isn\u0027t so great!\n\nyuk:\n\n```\ndiff --git a/test/unit/obj/test_expirer.py b/test/unit/obj/test_expirer.py\nindex 5ed97f23f..866a10023 100644\n--- a/test/unit/obj/test_expirer.py\n+++ b/test/unit/obj/test_expirer.py\n@@ -938,7 +938,8 @@ class TestObjectExpirer(TestCase):\n\n     def test_delete_actual_object(self):\n         x \u003d expirer.ObjectExpirer(\n-            {}, swift\u003dunit.FakeInternalClient([swob.Response(status\u003d204)]))\n+            {}, swift\u003dunit.FakeInternalClient([swob.Response(status\u003d204),\n+                                               swob.Response(status\u003d204)]))\n         ts \u003d Timestamp(\u00271234\u0027)\n         with x.swift:\n             x.delete_actual_object(\u0027path/to/object\u0027, ts, False)\n             ```\n\ngives me:\n\n```\ntest_expirer.py::TestObjectExpirer::test_delete_actual_object FAILED     [100%]\ntest/unit/obj/test_expirer.py:938 (TestObjectExpirer.test_delete_actual_object)\nself \u003d \u003ctest.unit.obj.test_expirer.TestObjectExpirer testMethod\u003dtest_delete_actual_object\u003e\n\n    def test_delete_actual_object(self):\n        x \u003d expirer.ObjectExpirer(\n            {}, swift\u003dunit.FakeInternalClient([swob.Response(status\u003d204), swob.Response(status\u003d204)]))\n        ts \u003d Timestamp(\u00271234\u0027)\n        with x.swift:\n\u003e           x.delete_actual_object(\u0027path/to/object\u0027, ts, False)\n\ntest_expirer.py:944: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself \u003d \u003ctest.unit.FakeInternalClient object at 0x104db7c40\u003e\nargs \u003d (None, None, None)\nunused_responses \u003d [\u003cswift.common.swob.Response object at 0x104db7e80\u003e]\n\n    def __exit__(self, *args):\n        unused_responses \u003d [r for r in self.resp_iter]\n        if unused_responses:\n\u003e           raise Exception(\u0027Unused responses: %r\u0027 % unused_responses)\nE           Exception: Unused responses: [\u003cswift.common.swob.Response object at 0x104db7e80\u003e]\n\n../__init__.py:1086: Exception\n\n```","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8e0d4617ca9854d94ca05570003aed1e8adfcaad","unresolved":true,"context_lines":[{"line_number":942,"context_line":"        ts \u003d Timestamp(\u00271234\u0027)"},{"line_number":943,"context_line":"        with x.swift:"},{"line_number":944,"context_line":"            x.delete_actual_object(\u0027path/to/object\u0027, ts, False)"},{"line_number":945,"context_line":"        self.assertEqual(1, len(x.swift.calls))"},{"line_number":946,"context_line":"        request \u003d x.swift.calls[0]"},{"line_number":947,"context_line":"        self.assertEqual(ts, request.headers[\u0027X-If-Delete-At\u0027])"},{"line_number":948,"context_line":"        self.assertEqual(request.headers[\u0027X-Timestamp\u0027],"}],"source_content_type":"text/x-python","patch_set":34,"id":"4abb3509_ea6ffde5","line":945,"in_reply_to":"1320201a_c22b1758","updated":"2024-04-04 19:07:05.000000000","message":"yeah this thing is weird; maybe I can to make it more consistent and used more consistently.","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6ae1792e323539e246b733015cf913fa12e9b355","unresolved":false,"context_lines":[{"line_number":942,"context_line":"        ts \u003d Timestamp(\u00271234\u0027)"},{"line_number":943,"context_line":"        with x.swift:"},{"line_number":944,"context_line":"            x.delete_actual_object(\u0027path/to/object\u0027, ts, False)"},{"line_number":945,"context_line":"        self.assertEqual(1, len(x.swift.calls))"},{"line_number":946,"context_line":"        request \u003d x.swift.calls[0]"},{"line_number":947,"context_line":"        self.assertEqual(ts, request.headers[\u0027X-If-Delete-At\u0027])"},{"line_number":948,"context_line":"        self.assertEqual(request.headers[\u0027X-Timestamp\u0027],"}],"source_content_type":"text/x-python","patch_set":34,"id":"89b999ba_5d3319d9","line":945,"in_reply_to":"4abb3509_ea6ffde5","updated":"2024-06-04 20:42:36.000000000","message":"Acknowledged","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8e0d4617ca9854d94ca05570003aed1e8adfcaad","unresolved":true,"context_lines":[{"line_number":1180,"context_line":"        stub_responses \u003d ["},{"line_number":1181,"context_line":"            # delete manifest response"},{"line_number":1182,"context_line":"            swob.Response(status\u003d204, headers\u003d{"},{"line_number":1183,"context_line":"                \u0027X-Object-Sysmeta-S3Api-Upload-Id\u0027: \u0027\u0027,"},{"line_number":1184,"context_line":"                \u0027X-Object-Sysmeta-S3Api-Etag\u0027: \u0027\u0027,"},{"line_number":1185,"context_line":"            }),"},{"line_number":1186,"context_line":"        ]"}],"source_content_type":"text/x-python","patch_set":34,"id":"c26287f3_882e2c7c","line":1183,"updated":"2024-04-04 19:07:05.000000000","message":"so this isn\u0027t very realistic; I should remove this header and only have the s3api-etag","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6ae1792e323539e246b733015cf913fa12e9b355","unresolved":false,"context_lines":[{"line_number":1180,"context_line":"        stub_responses \u003d ["},{"line_number":1181,"context_line":"            # delete manifest response"},{"line_number":1182,"context_line":"            swob.Response(status\u003d204, headers\u003d{"},{"line_number":1183,"context_line":"                \u0027X-Object-Sysmeta-S3Api-Upload-Id\u0027: \u0027\u0027,"},{"line_number":1184,"context_line":"                \u0027X-Object-Sysmeta-S3Api-Etag\u0027: \u0027\u0027,"},{"line_number":1185,"context_line":"            }),"},{"line_number":1186,"context_line":"        ]"}],"source_content_type":"text/x-python","patch_set":34,"id":"018249b1_c58586d7","line":1183,"in_reply_to":"c26287f3_882e2c7c","updated":"2024-06-04 20:42:36.000000000","message":"Done","commit_id":"92be61cb7f653e51998524a59fa385f59d9f9168"}]}
