)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"37ff953267b220f9fb20da2f524b3f2ddb41e6a5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"1e9866ea_c9ca5bb7","updated":"2025-04-30 22:35:41.000000000","message":"Oh, I had an old comment lurking...","commit_id":"775a09a7a9d09e5423ee7145ed924fbb1de0e58d"},{"author":{"_account_id":4146,"name":"Clark Boylan","email":"cboylan@sapwetik.org","username":"cboylan"},"change_message_id":"84f6f7bb4476152d7bba9416d1a8dbf9adeb41a4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"a5048ce9_db7090c7","updated":"2024-12-06 16:23:49.000000000","message":"recheck","commit_id":"775a09a7a9d09e5423ee7145ed924fbb1de0e58d"}],"tools/swift_delete_container.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cc13c79885c42734b24264021d275970d1819340","unresolved":true,"context_lines":[{"line_number":49,"context_line":"    data \u003d json.loads(ret)"},{"line_number":50,"context_line":"    ret \u003d []"},{"line_number":51,"context_line":"    for obj in data:"},{"line_number":52,"context_line":"        # TODO do we actually need to do anything different for subdirs here?"},{"line_number":53,"context_line":"        if \u0027subdir\u0027 in obj:"},{"line_number":54,"context_line":"            objpath \u003d obj[\u0027subdir\u0027]"},{"line_number":55,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"12c8330e_558e52a2","line":52,"updated":"2024-11-15 19:29:48.000000000","message":"I think the better question may be: do you actually want `delimiter` in your query string? If you have objects in a container like\n```\nfoo/bar\nfoo/baz/1\nfoo/baz/2\n```\na request like `?prefix\u003dfoo\u0026delimiter\u003d/` will give you\n```\nfoo/bar\nfoo/baz/\n```\nIf you then try to delete those, `DELETE foo/bar` should 204, but I\u0027d expect `DELETE foo/baz/` to 404 -- there isn\u0027t an object named `foo/baz/`. But if you just do `?prefix\u003dfoo`, you\u0027ll get back\n```\nfoo/bar\nfoo/baz/1\nfoo/baz/2\n```\nall of which should correspond to actual data you want deleted.","commit_id":"79e0b5d4a2532970dcb19282d7086b4fe6a39c4d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cc13c79885c42734b24264021d275970d1819340","unresolved":true,"context_lines":[{"line_number":75,"context_line":""},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"# TODO this seems like it may just loop forever if somethings don\u0027t delete"},{"line_number":78,"context_line":"# but logging would show us?"},{"line_number":79,"context_line":"while objects :\u003d list_objects(\u0027/\u0027):"},{"line_number":80,"context_line":"    for obj in objects:"},{"line_number":81,"context_line":"        delete_object(obj)"}],"source_content_type":"text/x-python","patch_set":1,"id":"02ef4a67_1f74af59","line":78,"updated":"2024-11-15 19:29:48.000000000","message":"You might want to look at the `marker` option for container listings. It\u0027s a common pattern in swift to do something like\n```\nobjects \u003d [{\u0027name\u0027: \u0027\u0027}]  # get us into the loop with a reasonable starting marker\nwhile objects:\n    marker \u003d objects[-1][\u0027name\u0027]\n    url \u003d get_url(\u0027\u0027) + \u0027?prefix\u003d%s\u0026marker\u003d%s\u0026format\u003djson\u0027 % (path, marker)\n    objects \u003d json.loads(retry_function(\n        lambda: conn.session.get(url).content.decode(\u0027utf8\u0027)))\n    # do something with `objects`\n```","commit_id":"79e0b5d4a2532970dcb19282d7086b4fe6a39c4d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cc13c79885c42734b24264021d275970d1819340","unresolved":true,"context_lines":[{"line_number":78,"context_line":"# but logging would show us?"},{"line_number":79,"context_line":"while objects :\u003d list_objects(\u0027/\u0027):"},{"line_number":80,"context_line":"    for obj in objects:"},{"line_number":81,"context_line":"        delete_object(obj)"},{"line_number":82,"context_line":"conn.object_store.delete_container(container_name)"}],"source_content_type":"text/x-python","patch_set":1,"id":"7c04bcd2_e047a822","line":81,"updated":"2024-11-15 19:29:48.000000000","message":"FWIW, this would be a fantastic thing to submit to a threadpool.","commit_id":"79e0b5d4a2532970dcb19282d7086b4fe6a39c4d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"37ff953267b220f9fb20da2f524b3f2ddb41e6a5","unresolved":true,"context_lines":[{"line_number":66,"context_line":"    conn.session.post(url, data\u003dto_delete.join(\u0027\\n\u0027), headers\u003dheaders)"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"# Swift docs indicate deletions should happen immediately. In theory this"},{"line_number":70,"context_line":"# means that we don\u0027t need proper pagination and can just delete then list"},{"line_number":71,"context_line":"# the next set of objects to delete. If objects fail to delete we may loop"},{"line_number":72,"context_line":"# forever but logging should make that apparent."}],"source_content_type":"text/x-python","patch_set":2,"id":"5208e81d_4f4f9b6f","line":69,"range":{"start_line":69,"start_character":22,"end_line":69,"end_character":57},"updated":"2025-04-30 22:35:41.000000000","message":"What do we mean by \"deletion\"?\n\nSubsequent GETs/HEADs for the object should 404 -- but the listing is only eventually-consistent. When deleting many objects, the container layer gets overloaded; the object-server will then process the delete and write down locally that it needs to retry the container update \"later\" which can range from minutes to days depending on the cluster\u0027s config and health.\n\nI know from experience that you\u0027ll want to paginate here.","commit_id":"775a09a7a9d09e5423ee7145ed924fbb1de0e58d"},{"author":{"_account_id":4146,"name":"Clark Boylan","email":"cboylan@sapwetik.org","username":"cboylan"},"change_message_id":"53aa2927959d007c92eb74afc480ab7ddcb01ab4","unresolved":true,"context_lines":[{"line_number":66,"context_line":"    conn.session.post(url, data\u003dto_delete.join(\u0027\\n\u0027), headers\u003dheaders)"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"# Swift docs indicate deletions should happen immediately. In theory this"},{"line_number":70,"context_line":"# means that we don\u0027t need proper pagination and can just delete then list"},{"line_number":71,"context_line":"# the next set of objects to delete. If objects fail to delete we may loop"},{"line_number":72,"context_line":"# forever but logging should make that apparent."}],"source_content_type":"text/x-python","patch_set":2,"id":"f13905d2_1dabfbcc","line":69,"range":{"start_line":69,"start_character":22,"end_line":69,"end_character":57},"in_reply_to":"5208e81d_4f4f9b6f","updated":"2025-05-01 16:29:03.000000000","message":"Ok that is good info. I think the idea I had was to just grab X objects, delete them, then the next grab for X objects wouldn\u0027t include those already deleted. But sounds like it can/will so we should do proper pagination instead.","commit_id":"775a09a7a9d09e5423ee7145ed924fbb1de0e58d"}]}
