2 पॉइंट द्वारा GN⁺ 2023-06-29 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • TypeID UUIDv7 का एक विस्तारित type-safe identifier है, जो Stripe API के prefix इस्तेमाल करने के तरीके से प्रेरित globally unique identifier format है
  • canonical string लोअरकेस स्ट्रिंग होती है और यह तीन हिस्सों से बनी होती है: अधिकतम 63 अक्षरों का लोअरकेस snake_case ASCII type prefix, _ separator, और modified base32 में encoded 26-अक्षरों का UUIDv7 suffix
  • type prefix की मदद से user ID को गलती से वहाँ इस्तेमाल करने से रोका जा सकता है जहाँ post ID चाहिए, और debugging के समय तुरंत समझा जा सकता है कि identifier किस entity type को दर्शाता है
  • TypeID, UUID का superset है, और type information हटाकर decode करने पर एक वैध UUIDv7 मिलता है
  • यह K-sortable है, इसलिए database primary key के रूप में इस्तेमाल किया जा सकता है, और पूरी तरह random global ID वाले UUIDv4 की तुलना में database locality खराब होने की समस्या को कम करने के लिए बनाया गया है
  • base32 encoding में URL safety, case-insensitivity, ambiguous characters से बचाव, double-click selection की सुविधा, और UUID की पारंपरिक hex encoding की तुलना में कम लंबाई जैसी विशेषताएँ हैं
  • आधिकारिक implementation Go, SQL, TypeScript में उपलब्ध हैं, और नवीनतम spec version v0.3.0 है
  • command-line tool से TypeID generate करना, मौजूदा TypeID का UUID decode करना, और UUID को TypeID में encode करना संभव है
    • typeid new prefix से नया TypeID generate करें
    • typeid decode prefix_01h2xcejqtf2nbrexx3vqjhp41 से type और uuid output करें
    • typeid encode prefix 0188bac7-4afa-78aa-bc3b-bd1eef28d881 से TypeID generate करें
  • Jetify के TypeID Converter में TypeID string को UUID में बदला जा सकता है या prefix:UUID format से TypeID में convert किया जा सकता है

1 टिप्पणियां

 
GN⁺ 2023-06-29
Hacker News की टिप्पणियाँ
  • कुछ सुझाव हैं: prefix string को देर होने से पहले फिक्स करके डॉक्युमेंट करना बेहतर होगा
    Go implementation को देखकर लगता है कि lowercase ASCII ठीक है, लेकिन article-comment जैसे composite type के लिए यह अस्पष्ट है
    जटिल प्रोजेक्ट या ORM में delimiter से बचना मुश्किल होता है, इसलिए single delimiter की अनुमति देने पर विचार किया जा सकता है
    Go implementation में tests नहीं हैं, जबकि यह unit test करने में आसान code है, इसलिए इन्हें ज़रूर जोड़ना चाहिए
    Go में Google के UUID implementation की तरह proper parsing function और internal byte array का उपयोग करना सही होगा, और string को rendering और prefix तक सीमित रखना बेहतर है
    अभी parsing बहुत उदार है और अगर suffix खाली हो तो लगता है कि यह generation mode में चला जाता है, और SplitN के बाद indexing करने पर underscore न हो तो panic हो सकता है
    डिज़ाइन में खामी ढूँढ़ने की कोशिश की, लेकिन आखिरकार लगता है कि इसने trade-off के sweet spot को अच्छी तरह पकड़ा है

    • सबसे जटिल हिस्सों में से एक, base32 encoding, के लिए tests हैं: https://github.com/jetpack-io/typeid-go/blob/main/base32/bas...
      फिर भी बात सही है, और जैसे-जैसे अलग-अलग भाषाओं की implementations बढ़ेंगी, यह जाँचना होगा कि वे एक-दूसरे के साथ compatible हैं या नहीं, इसलिए और सख्त test suite जोड़ने की योजना है
      prefix के बारे में, क्या चिंता इस बात की है कि spec में allowed character set परिभाषित नहीं है?
    • README में दूसरी implementations मांगी गई हैं, इसलिए test suite third-party code के लिए भी उपयोगी होगा
    • बाद में काफ़ी thorough tests implement किए गए: https://github.com/jetpack-io/typeid-go/blob/main/typeid_tes...
      और spec में prefix भी स्पष्ट कर दिया गया है
    • मैं इसके लिए tests लिखकर देखूँगा
    • लगता है prefix को fixed माना गया, जो गलतफ़हमी है
      prefix उपयोग के domain के अनुसार तय होता है
  • हम यह तरीका कई सालों से इस्तेमाल कर रहे हैं, लेकिन दो फ़र्क हैं
    पहला, हमें नहीं लगता कि लोग वास्तव में values हाथ से टाइप करते हैं, इसलिए l और 1 के बीच भ्रम को लेकर ज़्यादा चिंता नहीं करते
    इसके बजाय, शब्दों—खासकर गाली-गलौज—के संयोग से बन जाने की संभावना कम करने के लिए eiou vowels हटाकर base32 का उपयोग करते हैं
    दूसरा, salted base32 characters के दो अक्षर checksum के रूप में जोड़ते हैं
    इससे value गलती से या दुर्भावनापूर्ण तरीके से invalid हो तो data store तक query किए बिना ही पता चल जाता है, समझ नहीं आता कि दूसरी implementations यह क्यों नहीं करतीं

    • कुछ साल पहले auto-generated password के रूप में analrita आ गया था, जिस पर शिकायत मिली थी
      excluded characters में a जोड़ने पर भी विचार किया जा सकता है
    • checksum जोड़ने से सहमत हूँ, लेकिन “गलती से या दुर्भावनापूर्ण तरीके से” वाली बात पर सवाल है
      अगर मानते हैं कि इंसान इसे हाथ से टाइप नहीं करते, तो गलती से गलत value जाने का रास्ता क्या है, यह स्पष्ट नहीं है
      copy/paste errors हो सकते हैं, या कोई page इसे uppercase में render कर दे, लेकिन base32 हो तो case normalize किया जा सकता है
      और यह भी समझना है कि 2-byte, cryptographically insecure checksum दुर्भावनापूर्ण मामले में कैसे मदद करेगा
    • checksum का विचार दिलचस्प है
      सोच रहे हैं कि क्या इसे TypeID spec में शामिल करना उचित होगा
    • कुछ महीने पहले encoding method के हिस्से के रूप में दूसरा तरीका implement किया था
      इससे database lookups कितने कम हुए, यह नहीं पता, लेकिन decoding के दौरान कम अस्पष्ट errors मिलना अच्छा लगा
  • मुख्य लेख से अलग एक “Crockford's alphabet” लिंक भी है: https://www.crockford.com/base32.html
    यह base32 स्कीम alphanumeric वर्णों में से 1 से भ्रमित होने वाले I, L, 0 से भ्रमित होने वाले O, और U को हटाती है
    पेज में U को हटाने की वजह “accidental obscenity” बताई गई है, लेकिन इसका मतलब आखिर क्या है, समझ नहीं आता

    • यह Crockford ने मज़ाकिया अंदाज़ में लिखा था
      अगर बिना भ्रम वाले alphanumeric से एक ठीक-ठाक base32 alphabet बनाना हो, तो O, I, L को हटाना ही काफ़ी है
      तब भी 33 अक्षर बचते हैं, इसलिए एक और हटाना पड़ता है, और क्या हटाना है इससे खास फ़र्क नहीं पड़ता, तो आख़िरी हटाए गए अक्षर के लिए बस एक मनमाना कारण जोड़ दिया गया
      अगर ID यूज़र को दिखाई जाती हो तो यह वजह पूरी तरह बेमानी भी नहीं है, लेकिन जाहिर है कि इससे कोई परफेक्ट रोकथाम नहीं होती
    • I और O को पहले ही हटाकर, U को भी हटा दें तो काफ़ी सारे खुरदरे लगने वाले तीन-अक्षरी या चार-अक्षरी संयोजन हट जाते हैं
      बेशक A होने की वजह से कुछ संयोजन अब भी संभव हैं, लेकिन संभावना बहुत कम हो जाती है
    • सच्चे Latin purist के लिए U एक इतना भद्दा अक्षर है कि अश्लीलता के करीब पड़ता है, क्योंकि Cicero के ज़माने में इसका अस्तित्व ही नहीं था
    • ऐसे और भी उदाहरण हैं: base58, Satoshi/Bitcoin वाला तरीका https://en.wikipedia.org/wiki/Binary-to-text_encoding#Base58, “base62”, Keybase का saltpack https://github.com/keybase/saltpack, मशहूर “Adobe 85” https://en.wikipedia.org/wiki/Ascii85, basE91 https://base91.sourceforge.net
      हमारी कंपनी में QR code के लिए कई नई “radix” भी परिभाषित की गई थीं, और निजी तौर पर मुझे यह computer science का कम इस्तेमाल किया गया क्षेत्र लगता है
    • Crockford से लगभग 4 साल पहले मैंने एक सहकर्मी के साथ लगभग यही character set सोचा था
      हम URL slug की समस्या हल कर रहे थे, और स्ट्रिंग काफ़ी लंबी होने वाली थी, इसलिए हमें लगा कि प्रति byte 5 bit से हाथ से लिखने की असुविधा कम होगी
      आखिर में कुछ और अक्षर हटाने की गुंजाइश थी, और सबके दफ़्तर से जाने के बाद हम दोनों बैठकर गालियों की अपमानजनकता के हिसाब से रैंकिंग बनाकर हटाने वाले अक्षर चुन रहे थे
      बाद में मैंने समझाया कि slur उससे बड़ा मुद्दा है, इसलिए u की जगह n हटाने पर ध्यान दिया गया
      tggr तो बस प्यारा लगता है, लेकिन n**r की वजह से कई HR टीमों के साथ असहज बातचीत करनी पड़ सकती थी
      अंतिम character set अब थोड़ा धुंधला याद है, लेकिन हम आम तौर पर [a-z][0-9] संभाल रहे थे और URL में इस्तेमाल न किए जा सकने वाले या ज़ोर से पढ़ने में कठिन कई चिन्ह थे
      याद के मुताबिक हमने 0, l, 1 तीनों हटा दिए थे, और शायद यह मानकर चल रहे थे कि हाथ से लिखना या तो पूरा uppercase में होगा या पूरा lowercase में
      0o समस्या नहीं था, और 1L भी नहीं
  • Crockford encoding मुझे खास पसंद नहीं है
    वास्तव में, इस तरह encoded वैल्यूज़ को technical support या analysis में संभालते समय मुझे लगा कि यह साफ़ गलती थी
    यह alphabet ऐसे लक्ष्य के लिए डिज़ाइन किया गया था जो व्यवहार में कम ही आता है, जैसे फ़ोन पर identifier पढ़कर सुनाना, और यह ambiguity लाता है
    encoded string से logs को grep करना या cross-reference करना हो तो यह तबाही है, और hyphen की अनुमति देना copy/paste तथा line-break errors का बड़ा कारण बनता है
    object identifier को सीधे टाइप करने की ज़रूरत कम ही पड़ती है, लेकिन application, chat और forum के बीच copy/paste करना, उसे email से भेजना, और log files में खोजना आम बात है
    इन परिस्थितियों में pronounceability का कोई मतलब नहीं, case-insensitive होना उल्टा बाधा है, और ज़रूरत consistency तथा paste और line-break resilience की है
    base58 इन ज़रूरतों के लिए ज़्यादा उपयुक्त bijective encoding है, और लंबाई में भी छोटी है
    Stripe से प्रेरित होकर मैं कई सालों से user_1BzGURpnHGn6oNru84B3Ri जैसे type prefix लगे base58-encoded UUID को object identifier के रूप में इस्तेमाल कर रहा हूँ
    हालाँकि यह भी ध्यान में रखना चाहिए कि Douglas Crockford की base32 encoding 20 साल पहले, एक काफ़ी अलग उपयोग-परिवेश के लिए डिज़ाइन की गई थी

    • मैंने base58 और base64url पर भी विचार किया था, और छोटी encoding मुझे पसंद भी थी
      लेकिन मैं case sensitivity को आधार मानकर नहीं चलना चाहता था, इसलिए आख़िरकार base32 की ओर झुक गया
      उदाहरण के लिए, हो सकता है आप ID को filename के रूप में इस्तेमाल करना चाहें, और आपका environment case-insensitive file system से बंधा हो
      TypeID हमेशा Crockford alphabet को lowercase में इस्तेमाल करता है; यह Crockford encoding के पूरे नियमों का उपयोग नहीं करता
      TypeID में hyphen की अनुमति नहीं है, और न ही ambiguous अक्षरों को बदलकर एक ही ID को कई तरीकों से encode करने की अनुमति है
    • मैं इस बात से सहमत हूँ कि फ़ोन पर identifier पढ़कर सुनाना कम ही होता है
      लेकिन कभी-कभी screenshot या screen share में दिख रहे identifier, या किसी दूसरे device पर मौजूद identifier जिसे आसानी से लिया नहीं जा सकता, उसे हाथ से दर्ज करना पड़ता है
    • base58 या KSUID में इस्तेमाल होने वाला base62 काफ़ी फायदे देता है
      Crockford base32 काम तो करता है, लेकिन मुझे बहुत पसंद नहीं है
      निजी तौर पर मेरी पहली पसंद type prefix लगे KSUID का उपयोग करना है
      इससे base62-encoded 160-bit K-sortable ID मिलती है, और अगर compatibility की वजह से 128-bit ID अनिवार्य न हो तो यह अच्छा विकल्प है
    • Crockford Base32 में hyphen कहाँ है, यह मुझे समझ नहीं आता: https://en.wikipedia.org/wiki/Base32#Crockford's_Base32
      मेरी पसंदीदा base32 encoding z-base-32 है, क्योंकि यह आँखों को ज़्यादा आरामदेह लगती है: https://philzimmermann.com/docs/human-oriented-base-32-encod...
      base58 की सबसे बड़ी समस्या यह है कि यह integers के लिए तो अच्छी बैठती है, लेकिन cryptographic keys जैसे arbitrary binary data के लिए कम उपयुक्त है, और case-sensitive strings देखने में अच्छी नहीं लगतीं
  • साफ़-सुथरा
    “type-safe” prefix पसंद आया
    हमारे ORM में हम इसी तरह DB के integer ID पर entity-वार tag अपने-आप जोड़ने के तरीके को tagged ids कहते थे: https://joist-orm.io/docs/advanced/tagged-ids
    हमने delimiter के तौर पर : इस्तेमाल किया था, लेकिन double-click से copy/paste करने के लिहाज़ से _ न इस्तेमाल करने का थोड़ा अफ़सोस है
    सिद्धांततः Joist से “DB के UUID column” को “domain model के TypeID” में बदलवाना भी काफ़ी आसान होना चाहिए, लेकिन अभी शायद यह सिर्फ user-side configuration से नहीं हो पाएगा
    फिर भी यह अच्छा आइडिया है

    • Reddit भी ऐसा ही है, लेकिन string length के लिए optimized तरीका इस्तेमाल करता है
      element ID t3_15bfi0 जैसे होते हैं, और t3_ type prefix है
      t3 post है, t1 comment है, t5 subreddit है, और बाकी auto-increment primary key की base36 encoding है
    • हमारी कंपनी के typed internal ID system में शुरू में colon delimiter था, लेकिन जल्द ही उसे dot(.) से बदल दिया गया
      colon URL encoding में %-encoding हो जाता था, जिससे ID लंबा हो जाता था, URL बदसूरत और लंबा दिखता था, और यह बहुत परेशान करने वाला था
  • UUIDv7 कई सालों से HN पर लोकप्रिय है, लेकिन सोचता हूँ कि यह कब ठीक से standard बनेगा और libraries, databases, और बाकी ecosystem इसे कब native support देंगे

    • समझ नहीं आता कि आप किस तरह के support की उम्मीद कर रहे हैं
      ज़्यादातर software UUID के अंदर के specific bits की परवाह नहीं करते, इसलिए इसे आज भी इस्तेमाल किया जा सकता है
      अगर कोई software specific bits की परवाह करता है, तो उसे UUIDv4 की तरह mimic किया जा सकता है, और ऐसे bits वैसे भी random generate हो सकते हैं
      अगर generation procedure चाहिए, तो उसे खुद लिख सकते हैं, और यह मुश्किल नहीं है
    • लगता है IETF में standardization के अंतिम चरण में है: https://datatracker.ietf.org/doc/draft-ietf-uuidrev-rfc4122b...
    • यह draft और improvements से गुज़र चुका है, standardization के बहुत क़रीब है, और बहुत-सी libraries पहले से इसे support करती हैं या नए features जोड़ रही हैं
      उदाहरण के लिए, मैं Dart UUID library maintain करता हूँ, और उसकी latest beta major release में v6, v7, और custom v8 शामिल हैं
      implementations की एक सूची भी कहीं है, और मैं उस पेज पर library maintainers की सूची में हूँ, इसलिए हर नया draft आने पर authors से notification मिल जाता है
  • “double-click से copy/paste किया जा सकता है” वाली बात अच्छी लगी
    details मायने रखते हैं

  • मुझे UUID से थोड़ी शिकायत है
    समझ नहीं आता कि UUID versioning जैसी रस्म क्यों निभानी चाहिए, सीधे time + random को जोड़ क्यों नहीं देते
    अगर locality महत्वपूर्ण नहीं है, तो 128-bit random वैसे ही इस्तेमाल किया जा सकता है
    अनुभव से लगता है कि ज़्यादातर लोग सोचते हैं कि UUID को human-readable hex representation में, यहाँ तक कि hyphen सहित, store करना चाहिए
    यह database, network, और memory में बहुत ज़्यादा जगह बर्बाद करता है

    • बहुत-से लोगों ने यही सोचा है
      उदाहरण के लिए ULID https://github.com/ulid/spec छोटा है और समय store करता है, इसलिए lexicographically sort हो जाता है
    • UUID की दुनिया में अक्सर ऐसा बोलने की प्रवृत्ति होती है मानो एक ही use case पूरे क्षेत्र का प्रतिनिधित्व करता हो, और इसलिए एक ही सबसे अच्छा UUID format हो
      हक़ीक़त दूसरे engineering problems जैसी ही है: requirements लिखिए और देखिए कि उन्हें क्या solve करता है
      अलग-अलग formats के फ़ायदे पढ़ना मददगार है, क्योंकि इससे आप दूसरों की मुश्किल से सीखी बातों का लाभ उठा सकते हैं
      sortability और time-based locality जैसी चीज़ें शायद सहज रूप से ध्यान में न आएँ, लेकिन अगर उनकी ज़रूरत है, तो project के 4 साल बाद यह समझने से पहले जान लेना कहीं बेहतर है कि आपने वह data फेंक दिया
      कुछ UUID formats छोटे security issues भी अपने साथ लाते हैं, जैसे UUID v1 में MAC address leak होना, इसलिए उनसे बचना बेहतर है
      अगर मौजूदा समाधान आपके use case के लिए सही है, तो बस वही इस्तेमाल कीजिए
      अगर नहीं, तो ज़्यादा चिंता की ज़रूरत नहीं है
      निजी तौर पर, जहाँ मैं UUID सबसे ज़्यादा इस्तेमाल करता हूँ, वहाँ मैंने बस इतना तय किया है: “कोई unique string भेजो, और मन हो तो अपनी पसंद की UUID library इस्तेमाल करो”
      इस system में लगता है कि हर data source का अपना unique format है, लेकिन यह ठीक है
      scale भी कोई समस्या नहीं है, क्योंकि यह रोज़ कुछ दसियों हज़ार entries के स्तर पर है, और UUID के आधार पर sort करने की ज़रूरत भी नहीं है
      यह असली identifier से ज़्यादा, sender द्वारा हर message के लिए बनाया गया unique token है, जिसका उपयोग कई queues वाले heterogeneous system में downstream duplicate arrivals पकड़ने के लिए होता है
      global uniqueness की भी ज़रूरत नहीं है; सिर्फ छोटे shard के भीतर unique होना काफ़ी है, और सिद्धांततः समय बीतने पर दोहराव हो जाए तो भी फ़र्क नहीं पड़ता
      लेकिन simplicity के लिए हम system को पूरी अवधि में unique बनाए रखते हैं
      जब मैं खुद generate करता हूँ, तो /dev/urandom से data पढ़कर उसे base64 में encode करता हूँ, और ऐसा size चुना है जो == पर ख़त्म न हो
      यह भी किसी असली समस्या की वजह से नहीं, सिर्फ दिखने की वजह से है
    • सिर्फ time और random को जोड़ देने से global uniqueness की guarantee नहीं मिलती
    • निजी तौर पर मुझे UUID standard में सिर्फ साधारण random वाला v4 ही क़ीमती लगता है
      फिर भी यह अब तक समझ नहीं आया कि hyphen की ज़रूरत क्यों है, और बाकी versions मुझे ज़्यादा मायने नहीं रखते
    • hyphen की सबसे बुरी बात यह है कि पूरे हिस्से को double-click से आसानी से copy/paste नहीं किया जा सकता
  • अगर UUIDv7 या UUID की खास ज़रूरत नहीं है, तो https://github.com/segmentio/ksuid कहीं बड़ा key space देता है
    अगर namespace चाहिए, तो string prefix जोड़ सकते हैं, और KSUID collision की संभावना UUID के किसी भी version से बहुत कम है
    sortable timestamp वाले general-purpose ID generators में ksuid सबसे अच्छा लगा, और ज़्यादातर भाषाओं के लिए इसकी libraries उपलब्ध हैं
    UUID v1~v7 काफ़ी wasteful हैं

    • type prefix लगे KSUID बनाने के लिए एक thin JavaScript package प्रकाशित किया है
      अगर आप extra bits संभाल सकते हैं, और ज़्यादातर cases में कर सकते हैं, तो KSUID एक बेहतरीन format है
      [1] https://github.com/sophiabits/resource-id
    • ULID पर जाने की वजह यह थी कि वह हमेशा lowercase होता है, इसलिए उसे case-insensitive तरीके से handle किया जा सकता है
    • मैं कुछ लोकप्रिय ksuid libraries को maintain करता हूँ और वास्तव में उनका इस्तेमाल भी करता हूँ, इसलिए मुझे ksuid पसंद है
      लेकिन ksuid की बड़ी समस्या यह है कि यह 160-bit का है, इसलिए database के native UUID type, जैसे PostgreSQL, में फिट नहीं बैठता और performance cost आती है
      1: https://github.com/svix/rust-ksuid
      2: https://github.com/svix/python-ksuid
  • K-sortable एक शानदार concept है, और loosely ordered keys कई use cases को हल कर देती हैं
    type वाली compact string representation भी पसंद है
    लेकिन चिंता है कि UUID v7 के unintended side effects की वजह से कई security issues पैदा हो सकते हैं
    लोगों को UUID को token की तरह इस्तेमाल नहीं करना चाहिए, और न ही database primary key के रूप में ऐसा करना चाहिए, लेकिन व्यवहार में लोग ऐसा करते हैं
    UUID v4 लगभग cryptographic random होता है, इसलिए लगता है कि अब तक कई security vulnerabilities बस संयोग से टलती रही हैं
    मुझे लगा था कि UUID v7 में actual random data केवल 32-bit तक रह जाता है, और developers को यह अच्छी तरह सिखाना होगा कि UUID guessable हो सकता है
    सुधार: लगता है कि v7 UUID की guessability के बारे में मैंने गलत पढ़ लिया था
    draft में random bits के लिए CSPRNG की सिफारिश है, entropy कम से कम 74-bit है, और इसे “unguessable” बनाने के लिए design किया गया है
    security-related use cases के लिए “UUID v4” इस्तेमाल करने को कहा गया है, लेकिन शायद उसका मतलब timestamp से जुड़े अर्थों के कारण हो सकता है

    • एक दिलचस्प usability issue है
      अगर नाम UUIDv4 और UUIDv7 हों, तो क्या यह लगातार याद रखना कि कौन-सा database के लिए अच्छा है और कौन-सा one-time token के लिए, अंतहीन confusion नहीं पैदा करेगा?
      कोई backward-compatible समाधान भी समझ में नहीं आता
      Elixir में v4 UUID बनाने के लिए UUID.uuid4() function इस्तेमाल होता है
      सिद्धांत रूप में code में इसके usage को scan किया जा सकता है, लेकिन ऐसी चीज़ें कुल मिलाकर error की संभावना बढ़ाती हैं
    • कुछ ऐसे cases दिखते हैं जहाँ यह उपयोगी हो सकता है, लेकिन अतीत में जब भी v1 या v5 जैसे partially sequential UUID देखे, उनका misuse होता रहा
      v3 जैसे hash-based variants के साथ भी यही हुआ
      v4 simple है और उसके misuse की संभावना कम है