[{"data":1,"prerenderedAt":554},["ShallowReactive",2],{"navigation":3,"\u002Fconcepts\u002Fkeys":151,"\u002Fconcepts\u002Fkeys-surround":549},[4,29,56,79,94,121,128,144],{"title":5,"path":6,"stem":7,"children":8,"icon":27,"defaultOpen":28},"Getting Started","\u002Fgetting-started","1.getting-started\u002F1.index",[9,12,17,22],{"title":10,"path":6,"stem":7,"icon":11},"Introduction","i-lucide-book-open",{"title":13,"path":14,"stem":15,"icon":16},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":18,"path":19,"stem":20,"icon":21},"Redis setup","\u002Fgetting-started\u002Fredis-setup","1.getting-started\u002F3.redis-setup","i-lucide-database",{"title":23,"path":24,"stem":25,"icon":26},"Quickstart","\u002Fgetting-started\u002Fquickstart","1.getting-started\u002F4.quickstart","i-lucide-zap","i-lucide-rocket",true,{"title":30,"icon":31,"path":32,"stem":33,"children":34,"page":55},"Concepts","i-lucide-lightbulb","\u002Fconcepts","2.concepts",[35,40,45,50],{"title":36,"path":37,"stem":38,"icon":39},"Keys","\u002Fconcepts\u002Fkeys","2.concepts\u002F1.keys","i-lucide-key-round",{"title":41,"path":42,"stem":43,"icon":44},"Strict vs lax","\u002Fconcepts\u002Fstrict-vs-lax","2.concepts\u002F2.strict-vs-lax","i-lucide-scale",{"title":46,"path":47,"stem":48,"icon":49},"Comparators","\u002Fconcepts\u002Fcomparators","2.concepts\u002F3.comparators","i-lucide-git-compare",{"title":51,"path":52,"stem":53,"icon":54},"Errors","\u002Fconcepts\u002Ferrors","2.concepts\u002F4.errors","i-lucide-triangle-alert",false,{"title":57,"path":58,"stem":59,"children":60,"icon":63},"Counters","\u002Fcounters","3.counters\u002F1.index",[61,64,69,74],{"title":62,"path":58,"stem":59,"icon":63},"Overview","i-lucide-hash",{"title":65,"path":66,"stem":67,"icon":68},"StrictCounter","\u002Fcounters\u002Fstrict-counter","3.counters\u002F2.strict-counter","i-lucide-target",{"title":70,"path":71,"stem":72,"icon":73},"LaxCounter","\u002Fcounters\u002Flax-counter","3.counters\u002F3.lax-counter","i-lucide-wind",{"title":75,"path":76,"stem":77,"icon":78},"Conditional & batch operations","\u002Fcounters\u002Fconditional-and-batch","3.counters\u002F4.conditional-and-batch","i-lucide-layers",{"title":80,"path":81,"stem":82,"children":83,"icon":85},"Instance-aware counters","\u002Finstance-aware-counters","4.instance-aware-counters\u002F1.index",[84,86,90],{"title":62,"path":81,"stem":82,"icon":85},"i-lucide-network",{"title":87,"path":88,"stem":89,"icon":68},"StrictInstanceAwareCounter","\u002Finstance-aware-counters\u002Fstrict","4.instance-aware-counters\u002F2.strict",{"title":91,"path":92,"stem":93,"icon":73},"LaxInstanceAwareCounter","\u002Finstance-aware-counters\u002Flax","4.instance-aware-counters\u002F3.lax",{"title":95,"path":96,"stem":97,"children":98,"icon":100},"Locks","\u002Flocks","5.locks\u002F1.index",[99,101,106,111,116],{"title":62,"path":96,"stem":97,"icon":100},"i-lucide-lock",{"title":102,"path":103,"stem":104,"icon":105},"Mutex","\u002Flocks\u002Fmutex","5.locks\u002F2.mutex","i-lucide-lock-keyhole",{"title":107,"path":108,"stem":109,"icon":110},"RwLock","\u002Flocks\u002Frwlock","5.locks\u002F3.rwlock","i-lucide-book-lock",{"title":112,"path":113,"stem":114,"icon":115},"Lock options","\u002Flocks\u002Foptions","5.locks\u002F4.options","i-lucide-sliders-horizontal",{"title":117,"path":118,"stem":119,"icon":120},"Guard state & errors","\u002Flocks\u002Fguard-state","5.locks\u002F5.guard-state","i-lucide-shield-alert",{"title":122,"path":123,"stem":124,"children":125,"icon":127},"Rate limiting","\u002Frate-limiting","6.rate-limiting\u002F1.index",[126],{"title":122,"path":123,"stem":124,"icon":127},"i-lucide-gauge",{"title":129,"icon":130,"path":131,"stem":132,"children":133,"page":55},"Reference","i-lucide-book-marked","\u002Freference","7.reference",[134,139],{"title":135,"path":136,"stem":137,"icon":138},"Feature flags","\u002Freference\u002Ffeature-flags","7.reference\u002F1.feature-flags","i-lucide-flag",{"title":140,"path":141,"stem":142,"icon":143},"API reference","\u002Freference\u002Fapi","7.reference\u002F2.api","i-lucide-file-code",{"title":145,"path":146,"stem":147,"children":148,"icon":150},"Changelog","\u002Fchangelog","8.changelog\u002F1.index",[149],{"title":145,"path":146,"stem":147,"icon":150},"i-lucide-scroll",{"id":152,"title":36,"badge":153,"body":154,"date":153,"description":543,"extension":544,"links":153,"meta":545,"navigation":546,"path":37,"seo":547,"stem":38,"__hash__":548},"docs\u002F2.concepts\u002F1.keys.md",null,{"type":155,"value":156,"toc":537},"minimark",[157,170,175,178,204,208,219,359,362,410,425,429,443,521,525,533],[158,159,160,161,165,166,169],"p",{},"Everything distkit stores in Redis is addressed by a ",[162,163,164],"code",{},"DistkitRedisKey",". It is a thin wrapper around a ",[162,167,168],{},"String"," that enforces a few rules up front, so an invalid key fails when you build it rather than deep inside a Lua script.",[171,172,174],"h2",{"id":173},"the-rules","The rules",[158,176,177],{},"A key must be:",[179,180,181,189,195],"ul",{},[182,183,184,188],"li",{},[185,186,187],"strong",{},"non-empty",",",[182,190,191,194],{},[185,192,193],{},"at most 255 bytes",", and",[182,196,197,203],{},[185,198,199,200],{},"free of ",[162,201,202],{},":"," - the colon is reserved, because distkit uses it internally to namespace keys.",[171,205,207],{"id":206},"constructing-one","Constructing one",[158,209,210,211,214,215,218],{},"The fallible constructors return a ",[162,212,213],{},"Result"," (really a ",[162,216,217],{},"DistkitError::InvalidRedisKey"," on failure):",[220,221,226],"pre",{"className":222,"code":223,"language":224,"meta":225,"style":225},"language-rust shiki shiki-themes material-theme-lighter github-light github-dark","use distkit::DistkitRedisKey;\n\n\u002F\u002F TryFrom is the usual path.\nlet key = DistkitRedisKey::try_from(\"user_123\".to_string())?;\n\n\u002F\u002F Equivalent explicit constructor.\nlet key = DistkitRedisKey::new(\"user_123\".to_string())?;\n","rust","",[162,227,228,251,257,264,314,319,325],{"__ignoreMap":225},[229,230,233,237,241,245,247],"span",{"class":231,"line":232},"line",1,[229,234,236],{"class":235},"sw1J6","use",[229,238,240],{"class":239},"sbgvK"," distkit",[229,242,244],{"class":243},"smGrS","::",[229,246,164],{"class":239},[229,248,250],{"class":249},"sP7_E",";\n",[229,252,254],{"class":231,"line":253},2,[229,255,256],{"emptyLinePlaceholder":28},"\n",[229,258,260],{"class":231,"line":259},3,[229,261,263],{"class":262},"sutJx","\u002F\u002F TryFrom is the usual path.\n",[229,265,267,271,275,278,281,283,287,290,294,298,300,303,306,309,312],{"class":231,"line":266},4,[229,268,270],{"class":269},"sbsja","let",[229,272,274],{"class":273},"su5hD"," key ",[229,276,277],{"class":243},"=",[229,279,280],{"class":239}," DistkitRedisKey",[229,282,244],{"class":243},[229,284,286],{"class":285},"sGLFI","try_from",[229,288,289],{"class":249},"(",[229,291,293],{"class":292},"sjJ54","\"",[229,295,297],{"class":296},"s_sjI","user_123",[229,299,293],{"class":292},[229,301,302],{"class":243},".",[229,304,305],{"class":285},"to_string",[229,307,308],{"class":249},"())",[229,310,311],{"class":243},"?",[229,313,250],{"class":249},[229,315,317],{"class":231,"line":316},5,[229,318,256],{"emptyLinePlaceholder":28},[229,320,322],{"class":231,"line":321},6,[229,323,324],{"class":262},"\u002F\u002F Equivalent explicit constructor.\n",[229,326,328,330,332,334,336,338,341,343,345,347,349,351,353,355,357],{"class":231,"line":327},7,[229,329,270],{"class":269},[229,331,274],{"class":273},[229,333,277],{"class":243},[229,335,280],{"class":239},[229,337,244],{"class":243},[229,339,340],{"class":285},"new",[229,342,289],{"class":249},[229,344,293],{"class":292},[229,346,297],{"class":296},[229,348,293],{"class":292},[229,350,302],{"class":243},[229,352,305],{"class":285},[229,354,308],{"class":249},[229,356,311],{"class":243},[229,358,250],{"class":249},[158,360,361],{},"If your input might contain colons, sanitize instead of failing:",[220,363,365],{"className":222,"code":364,"language":224,"meta":225,"style":225},"\u002F\u002F Strips colons, then validates the rest.\nlet key = DistkitRedisKey::try_sanitize(\"tenant:42\".to_string())?; \u002F\u002F -> \"tenant42\"\n",[162,366,367,372],{"__ignoreMap":225},[229,368,369],{"class":231,"line":232},[229,370,371],{"class":262},"\u002F\u002F Strips colons, then validates the rest.\n",[229,373,374,376,378,380,382,384,387,389,391,394,396,398,400,402,404,407],{"class":231,"line":253},[229,375,270],{"class":269},[229,377,274],{"class":273},[229,379,277],{"class":243},[229,381,280],{"class":239},[229,383,244],{"class":243},[229,385,386],{"class":285},"try_sanitize",[229,388,289],{"class":249},[229,390,293],{"class":292},[229,392,393],{"class":296},"tenant:42",[229,395,293],{"class":292},[229,397,302],{"class":243},[229,399,305],{"class":285},[229,401,308],{"class":249},[229,403,311],{"class":243},[229,405,406],{"class":249},";",[229,408,409],{"class":262}," \u002F\u002F -> \"tenant42\"\n",[158,411,412,413,416,417,420,421,424],{},"There are ",[162,414,415],{},"*_or_panic"," variants (",[162,418,419],{},"new_or_panic",", ",[162,422,423],{},"sanitize_or_panic",") for cases where the key is a known-good constant and a bad value is genuinely a bug. Avoid them on anything derived from user input.",[171,426,428],{"id":427},"prefixes-vs-keys","Prefixes vs keys",[158,430,431,432,435,436,439,440,442],{},"Counters take a ",[185,433,434],{},"prefix"," key (the namespace for that counter) and then individual ",[185,437,438],{},"item"," keys. Both are ",[162,441,164],{},"s:",[220,444,446],{"className":222,"code":445,"language":224,"meta":225,"style":225},"let prefix = DistkitRedisKey::try_from(\"my_app\".to_string())?;       \u002F\u002F namespace\nlet key = DistkitRedisKey::try_from(\"page_views\".to_string())?;      \u002F\u002F item within it\n",[162,447,448,485],{"__ignoreMap":225},[229,449,450,452,455,457,459,461,463,465,467,470,472,474,476,478,480,482],{"class":231,"line":232},[229,451,270],{"class":269},[229,453,454],{"class":273}," prefix ",[229,456,277],{"class":243},[229,458,280],{"class":239},[229,460,244],{"class":243},[229,462,286],{"class":285},[229,464,289],{"class":249},[229,466,293],{"class":292},[229,468,469],{"class":296},"my_app",[229,471,293],{"class":292},[229,473,302],{"class":243},[229,475,305],{"class":285},[229,477,308],{"class":249},[229,479,311],{"class":243},[229,481,406],{"class":249},[229,483,484],{"class":262},"       \u002F\u002F namespace\n",[229,486,487,489,491,493,495,497,499,501,503,506,508,510,512,514,516,518],{"class":231,"line":253},[229,488,270],{"class":269},[229,490,274],{"class":273},[229,492,277],{"class":243},[229,494,280],{"class":239},[229,496,244],{"class":243},[229,498,286],{"class":285},[229,500,289],{"class":249},[229,502,293],{"class":292},[229,504,505],{"class":296},"page_views",[229,507,293],{"class":292},[229,509,302],{"class":243},[229,511,305],{"class":285},[229,513,308],{"class":249},[229,515,311],{"class":243},[229,517,406],{"class":249},[229,519,520],{"class":262},"      \u002F\u002F item within it\n",[171,522,524],{"id":523},"practical-advice","Practical advice",[179,526,527,530],{},[182,528,529],{},"Keep keys stable over their lifetime - a counter is only meaningful if the same subject maps to the same key.",[182,531,532],{},"Keep them descriptive but bounded; you have 255 bytes, not a paragraph.",[534,535,536],"style",{},"html pre.shiki code .sw1J6, html code.shiki .sw1J6{--shiki-light:#F76D47;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":225,"searchDepth":232,"depth":253,"links":538},[539,540,541,542],{"id":173,"depth":253,"text":174},{"id":206,"depth":253,"text":207},{"id":427,"depth":253,"text":428},{"id":523,"depth":253,"text":524},"DistkitRedisKey wraps and validates every key distkit writes to Redis.","md",{},{"icon":39},{"title":36,"description":543},"hzpmlrXhUBVjds3qLi53oUdTMa9AYO-FIplFCGBMs9k",[550,552],{"title":23,"path":24,"stem":25,"description":551,"icon":26,"children":-1},"A distributed counter running end to end in a few lines.",{"title":41,"path":42,"stem":43,"description":553,"icon":44,"children":-1},"The consistency trade-off that runs through distkit's counters.",1781569582557]