)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c07e6aa7a65e9edd79be9ceb875090fd920e64d5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"2e6512d7_cac29a8e","updated":"2026-02-25 20:30:20.000000000","message":"ok, I can see the vision:\n\n```\n\u003e\u003e\u003e \u0027%x\u0027 % (int(\u002785c77777c8404a58bc584\u0027, base\u003d16) \u0026 0xfffffffff)\n\u00274a58bc584\u0027\n```\n\nI think we *are* running into that \"the first digit of jitter is always 4 b/c a truncated uuid4 is sort of a weird thing for trans_id to use\" problem...\n\nbut if we do this *and* a \"better\" trans_id maybe we\u0027re onto something?  It sort of feels like w/i a req.environ we might only want to ever create *1* new timestamp using the jitter sourced from txid (or risk creating two new Timestamps with the same jitter!)\n\nFWIW I think it\u0027d be slightly easier to grep about if we maybe changed trans-id so that it used the whole `298972a34a` part from the `1772050373.18046_298972a34a000000` timestamp - like swap out the \"txid always have a 4\" for \"txid always have a 2\" - but that kind of flips the responsibility back to \"create a timestamp to use as txid\" instead of \"use txid as source of jitter\"\n\nI\u0027m becoming somewhat leery of allowing Timestamp.now to override jitter directly, but maybe it\u0027s ok with:\n\n\n```\nself._timestamp \u003d make_timestamp_now(..., jitter\u003dself.environ.pop(\u0027swift.catch_error_prepared_use_only_once\u0027, None))\n```\n\n... but then maybe you burn the fixed jitter on a container_info HEAD request and you don\u0027t get the PUT txid in the datafile timestamp *anyway* - I guess I\u0027d have to try it out and see.","commit_id":"ab910bd44411b65dd40f9d2710f460680e6c7d28"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"65293d1b91a361f94429b3ccfa9f57ee1d9e6338","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"ead786b4_440855ee","updated":"2026-02-27 11:10:01.000000000","message":"Clay, Matt - thanks for taking a look. This was intended as a quick prototype to illustrate unification of the trans id and timestamp. But it\u0027s taught me that grafting the two together isn\u0027t the best way, and I think from your comments that you\u0027ve identified/stumbled on the same deficiencies.\n\nI think a better way would be to have a single source of identity in the request environ from which a transaction id and an x-timestamp can be derived. And that single thing should encapsulate whatever random element (or node id or w/e) the two share.\n\nMaybe the transaction-id and x-timestamp can be the same thing?? Maybe not if they have different formatting requirements[*]. But they should at least be different serialisations of the same thing.\n\n```\nThing.time \u003d 1234567890.12345\nThing.jitter \u003d 1234567890abcdef\n\nThing.internal \u003d \u0027%10.5f_2%09x000000\u0027 % (Thing.time, Thing.jitter \u0026 0xfffffffff000000)\nThing.trans_id \u003d \u0027tx%016x-%6x\u0027 % (Thing.jitter, Thing.time)\n```\n\n\n[*] ...and currently they DO have different format requirements not least because not all x-timestamps have the same format (with and without jitter/hex-part).","commit_id":"2ce5dd0efc5f0c163371d2352b961141bda1712e"}],"swift/common/utils/__init__.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c07e6aa7a65e9edd79be9ceb875090fd920e64d5","unresolved":true,"context_lines":[{"line_number":471,"context_line":""},{"line_number":472,"context_line":"def get_trans_id_random_int(trans_id):"},{"line_number":473,"context_line":"    if trans_id and trans_id.startswith(\u0027tx\u0027):"},{"line_number":474,"context_line":"        return int(trans_id.split(\u0027-\u0027)[0][2:], base\u003d16)"},{"line_number":475,"context_line":"    return None"},{"line_number":476,"context_line":""},{"line_number":477,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"94732fe8_7482d18e","line":474,"updated":"2026-02-25 20:30:20.000000000","message":"```\n\u003e\u003e\u003e trans_id \u003d \u0027tx85c77777c8404a58bc584-00699f4c3a-s8k-dc-rack-role-02\u0027\n\u003e\u003e\u003e trans_id.split(\u0027-\u0027)[0][2:]\n\u002785c77777c8404a58bc584\u0027\n```\n\nso this is *more* \"jitter\" than we need?  And maybe some of it (like the 4) isn\u0027t entirely random?","commit_id":"ab910bd44411b65dd40f9d2710f460680e6c7d28"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"65293d1b91a361f94429b3ccfa9f57ee1d9e6338","unresolved":true,"context_lines":[{"line_number":471,"context_line":""},{"line_number":472,"context_line":"def get_trans_id_random_int(trans_id):"},{"line_number":473,"context_line":"    if trans_id and trans_id.startswith(\u0027tx\u0027):"},{"line_number":474,"context_line":"        return int(trans_id.split(\u0027-\u0027)[0][2:], base\u003d16)"},{"line_number":475,"context_line":"    return None"},{"line_number":476,"context_line":""},{"line_number":477,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"af6a3dd3_d4ecb915","line":474,"in_reply_to":"94732fe8_7482d18e","updated":"2026-02-27 11:10:01.000000000","message":"right. But this is just a helper function that doesn\u0027t know what you want to _do) with the random int and therefore how much of it you want. It does \"know\" (by virtue of being 15 lines away from generate_trans_id) that it\u0027s not pure random. \nThis is one reason why this pattern isn\u0027t great and a *single* *encapsulation* of unique identity would be better.","commit_id":"ab910bd44411b65dd40f9d2710f460680e6c7d28"}],"swift/common/utils/timestamp.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"8ef35a5424f0cc5347aa5206f009fe049d015420","unresolved":true,"context_lines":[{"line_number":328,"context_line":"    \"\"\""},{"line_number":329,"context_line":""},{"line_number":330,"context_line":"    def __init__(self, timestamp, offset\u003d0, delta\u003d0, check_bounds\u003dTrue,"},{"line_number":331,"context_line":"                 jitter\u003dNone):"},{"line_number":332,"context_line":"        \"\"\""},{"line_number":333,"context_line":"        Create a new Timestamp."},{"line_number":334,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"a6aa812d_7167f0cb","line":331,"range":{"start_line":331,"start_character":17,"end_line":331,"end_character":23},"updated":"2026-02-26 05:19:39.000000000","message":"This is esposing jitter as a param now, so we happy with the name jitter? or is this just until we come up with something else.","commit_id":"ab910bd44411b65dd40f9d2710f460680e6c7d28"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"65293d1b91a361f94429b3ccfa9f57ee1d9e6338","unresolved":true,"context_lines":[{"line_number":328,"context_line":"    \"\"\""},{"line_number":329,"context_line":""},{"line_number":330,"context_line":"    def __init__(self, timestamp, offset\u003d0, delta\u003d0, check_bounds\u003dTrue,"},{"line_number":331,"context_line":"                 jitter\u003dNone):"},{"line_number":332,"context_line":"        \"\"\""},{"line_number":333,"context_line":"        Create a new Timestamp."},{"line_number":334,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"5b26b40f_fea4624c","line":331,"range":{"start_line":331,"start_character":17,"end_line":331,"end_character":23},"in_reply_to":"a6aa812d_7167f0cb","updated":"2026-02-27 11:10:01.000000000","message":"this was a quick hack. I blow hot and cold on whether jitter is suitable as a general name for anything that isn\u0027t the float time, or whether it is only suitable when that things is random.","commit_id":"ab910bd44411b65dd40f9d2710f460680e6c7d28"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c07e6aa7a65e9edd79be9ceb875090fd920e64d5","unresolved":true,"context_lines":[{"line_number":397,"context_line":"            jitter \u003d random.randint(0x000000000, 0xfffffffff)"},{"line_number":398,"context_line":"        else:"},{"line_number":399,"context_line":"            # select least significant 9 digits"},{"line_number":400,"context_line":"            jitter \u003d jitter \u0026 0xfffffffff"},{"line_number":401,"context_line":"        # jitter is shifted to the left of the 6 offset digits"},{"line_number":402,"context_line":"        return (0x2000000000 + jitter) \u003c\u003c (4 * NUM_OFFSET_DIGITS)"},{"line_number":403,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"2a2426b1_d7a4f777","line":400,"updated":"2026-02-25 20:30:20.000000000","message":"I like that we don\u0027t overflow jitter - i\u0027m not sure \"disregard invalid input using a mask\" is the ideal interface.","commit_id":"ab910bd44411b65dd40f9d2710f460680e6c7d28"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"65293d1b91a361f94429b3ccfa9f57ee1d9e6338","unresolved":true,"context_lines":[{"line_number":397,"context_line":"            jitter \u003d random.randint(0x000000000, 0xfffffffff)"},{"line_number":398,"context_line":"        else:"},{"line_number":399,"context_line":"            # select least significant 9 digits"},{"line_number":400,"context_line":"            jitter \u003d jitter \u0026 0xfffffffff"},{"line_number":401,"context_line":"        # jitter is shifted to the left of the 6 offset digits"},{"line_number":402,"context_line":"        return (0x2000000000 + jitter) \u003c\u003c (4 * NUM_OFFSET_DIGITS)"},{"line_number":403,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"4020eb75_50ed6e54","line":400,"in_reply_to":"2a2426b1_d7a4f777","updated":"2026-02-27 11:10:01.000000000","message":"I think it would be fine. It\u0027s not that dissimilar to throwing away precision of the float time that is passed in. We just want a source of randomness. I don\u0027t think exposing the internal structure of *this* version of a Timestamp hex part would be great i.e. having to construct a Timestamp with exactly 9 hex digits of jitter might not stand the test of time.\n\nBut, that said, it\u0027s another example of why the pattern as a whole is wrong: we shouldn\u0027t be grafting bits of transaction ids into Timestamp and as a result bleeding their internal structures. We should have a single encapsulation of unique identity from which we derive a transaction id and an x-timestamp.","commit_id":"ab910bd44411b65dd40f9d2710f460680e6c7d28"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c07e6aa7a65e9edd79be9ceb875090fd920e64d5","unresolved":true,"context_lines":[{"line_number":693,"context_line":"    if not resource_type:"},{"line_number":694,"context_line":"        return NormalTimestamp.now()"},{"line_number":695,"context_line":"    elif resource_type.lower() \u003d\u003d \u0027object\u0027 and request_method \u003d\u003d \u0027PUT\u0027:"},{"line_number":696,"context_line":"        return Timestamp.now(jitter\u003djitter)"},{"line_number":697,"context_line":"    else:"},{"line_number":698,"context_line":"        return NormalTimestamp.now()"},{"line_number":699,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"d10bb6a0_9f0c9774","line":696,"updated":"2026-02-25 20:30:20.000000000","message":"you can sort of tell on the surface that `Timestamp.now(jitter\u003d\u003cfixed_value\u003e)` it sort of at odds with the whole idea of `Timestamp.now() !\u003d Timestamp.now()` *never no matter what*\n\n\"no matter what\" being ~\u003d there\u0027s no optional kwarg that can break the constraint","commit_id":"ab910bd44411b65dd40f9d2710f460680e6c7d28"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"65293d1b91a361f94429b3ccfa9f57ee1d9e6338","unresolved":true,"context_lines":[{"line_number":693,"context_line":"    if not resource_type:"},{"line_number":694,"context_line":"        return NormalTimestamp.now()"},{"line_number":695,"context_line":"    elif resource_type.lower() \u003d\u003d \u0027object\u0027 and request_method \u003d\u003d \u0027PUT\u0027:"},{"line_number":696,"context_line":"        return Timestamp.now(jitter\u003djitter)"},{"line_number":697,"context_line":"    else:"},{"line_number":698,"context_line":"        return NormalTimestamp.now()"},{"line_number":699,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"03fb89c4_c93464a7","line":696,"in_reply_to":"d10bb6a0_9f0c9774","updated":"2026-02-27 11:10:01.000000000","message":"right! because this pattern delegates the guarantee of uniqueness to some other thing. It\u0027s the opposete of good encapsulation 😭","commit_id":"ab910bd44411b65dd40f9d2710f460680e6c7d28"}],"test/unit/__init__.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c07e6aa7a65e9edd79be9ceb875090fd920e64d5","unresolved":true,"context_lines":[{"line_number":1155,"context_line":"    if now is None:"},{"line_number":1156,"context_line":"        now \u003d klass.now()"},{"line_number":1157,"context_line":"    with mocklib.patch.object("},{"line_number":1158,"context_line":"            klass, \u0027now\u0027, classmethod(lambda *args, **kwargs: now)):"},{"line_number":1159,"context_line":"        yield now"},{"line_number":1160,"context_line":""},{"line_number":1161,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"f6786773_ceefc432","line":1158,"updated":"2026-02-25 20:30:20.000000000","message":"might be worth squashing into parent - but also hopefully was easy to debug/spot/add when needed.","commit_id":"ab910bd44411b65dd40f9d2710f460680e6c7d28"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"65293d1b91a361f94429b3ccfa9f57ee1d9e6338","unresolved":false,"context_lines":[{"line_number":1155,"context_line":"    if now is None:"},{"line_number":1156,"context_line":"        now \u003d klass.now()"},{"line_number":1157,"context_line":"    with mocklib.patch.object("},{"line_number":1158,"context_line":"            klass, \u0027now\u0027, classmethod(lambda *args, **kwargs: now)):"},{"line_number":1159,"context_line":"        yield now"},{"line_number":1160,"context_line":""},{"line_number":1161,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"236ea85b_88e8e58e","line":1158,"in_reply_to":"f6786773_ceefc432","updated":"2026-02-27 11:10:01.000000000","message":"Acknowledged","commit_id":"ab910bd44411b65dd40f9d2710f460680e6c7d28"}],"test/unit/common/test_swob.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c07e6aa7a65e9edd79be9ceb875090fd920e64d5","unresolved":true,"context_lines":[{"line_number":721,"context_line":"                                                  \u0027swift.trans_id\u0027: txn_id})"},{"line_number":722,"context_line":"                req.ensure_x_timestamp()"},{"line_number":723,"context_line":"            exp_timestamp \u003d Timestamp(1234567890.12345, jitter\u003d0x4fb89babf)"},{"line_number":724,"context_line":"            self.assertEqual(\u00271234567890.12345_24fb89babf000000\u0027,"},{"line_number":725,"context_line":"                             exp_timestamp.internal)"},{"line_number":726,"context_line":"            self.assertEqual(exp_timestamp.internal,"},{"line_number":727,"context_line":"                             req.headers.get(\u0027X-Timestamp\u0027))"}],"source_content_type":"text/x-python","patch_set":1,"id":"358eac36_934752c6","line":724,"updated":"2026-02-25 20:30:20.000000000","message":"neat!  and so the trick when doing your grep is to look for a trans-id with the 9 digits `4fb89babf`","commit_id":"ab910bd44411b65dd40f9d2710f460680e6c7d28"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"65293d1b91a361f94429b3ccfa9f57ee1d9e6338","unresolved":true,"context_lines":[{"line_number":721,"context_line":"                                                  \u0027swift.trans_id\u0027: txn_id})"},{"line_number":722,"context_line":"                req.ensure_x_timestamp()"},{"line_number":723,"context_line":"            exp_timestamp \u003d Timestamp(1234567890.12345, jitter\u003d0x4fb89babf)"},{"line_number":724,"context_line":"            self.assertEqual(\u00271234567890.12345_24fb89babf000000\u0027,"},{"line_number":725,"context_line":"                             exp_timestamp.internal)"},{"line_number":726,"context_line":"            self.assertEqual(exp_timestamp.internal,"},{"line_number":727,"context_line":"                             req.headers.get(\u0027X-Timestamp\u0027))"}],"source_content_type":"text/x-python","patch_set":1,"id":"f5e74362_e79af0df","line":724,"in_reply_to":"358eac36_934752c6","updated":"2026-02-27 11:10:01.000000000","message":"yes, the outcome is neat. I verified it functionally. But the pattern of this patch sucks IMHO (I\u0027m allowed to say that about my own patch, hehe)","commit_id":"ab910bd44411b65dd40f9d2710f460680e6c7d28"}]}
