[{"data":1,"prerenderedAt":581},["ShallowReactive",2],{"navigation":3,"\u002Fconcepts\u002Ferrors":151,"\u002Fconcepts\u002Ferrors-surround":576},[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":51,"badge":153,"body":154,"date":153,"description":570,"extension":571,"links":153,"meta":572,"navigation":573,"path":52,"seo":574,"stem":53,"__hash__":575},"docs\u002F2.concepts\u002F4.errors.md",null,{"type":155,"value":156,"toc":566},"minimark",[157,170,174,341,344,353,447,451,461,548,562],[158,159,160,161,165,166,169],"p",{},"Library code in distkit never panics. Anything that can go wrong comes back through a single error type, ",[162,163,164],"code",{},"DistkitError",", so ",[162,167,168],{},"?"," works uniformly across counters, locks, and rate limiting.",[171,172,164],"h2",{"id":173},"distkiterror",[175,176,181],"pre",{"className":177,"code":178,"language":179,"meta":180,"style":180},"language-rust shiki shiki-themes material-theme-lighter github-light github-dark","pub enum DistkitError {\n    InvalidRedisKey(String),       \u002F\u002F a key failed validation\n    CounterError(CounterError),    \u002F\u002F counter operation failed   (feature = \"counter\")\n    LockError(LockError),          \u002F\u002F lock operation failed       (feature = \"lock\")\n    RedisError(redis::RedisError), \u002F\u002F transport or Lua script error\n    MutexPoisoned(&'static str),   \u002F\u002F an internal sync primitive was poisoned\n    CustomError(String),           \u002F\u002F catch-all\n    TrypemaError(TrypemaError),    \u002F\u002F rate limiting failed        (feature = \"trypema\")\n}\n","rust","",[162,182,183,204,224,240,256,279,304,319,335],{"__ignoreMap":180},[184,185,188,192,196,200],"span",{"class":186,"line":187},"line",1,[184,189,191],{"class":190},"sw1J6","pub",[184,193,195],{"class":194},"sbsja"," enum",[184,197,199],{"class":198},"sbgvK"," DistkitError",[184,201,203],{"class":202},"sP7_E"," {\n",[184,205,207,211,214,217,220],{"class":186,"line":206},2,[184,208,210],{"class":209},"sGLFI","    InvalidRedisKey",[184,212,213],{"class":202},"(",[184,215,216],{"class":198},"String",[184,218,219],{"class":202},"),",[184,221,223],{"class":222},"sutJx","       \u002F\u002F a key failed validation\n",[184,225,227,230,232,235,237],{"class":186,"line":226},3,[184,228,229],{"class":209},"    CounterError",[184,231,213],{"class":202},[184,233,234],{"class":198},"CounterError",[184,236,219],{"class":202},[184,238,239],{"class":222},"    \u002F\u002F counter operation failed   (feature = \"counter\")\n",[184,241,243,246,248,251,253],{"class":186,"line":242},4,[184,244,245],{"class":209},"    LockError",[184,247,213],{"class":202},[184,249,250],{"class":198},"LockError",[184,252,219],{"class":202},[184,254,255],{"class":222},"          \u002F\u002F lock operation failed       (feature = \"lock\")\n",[184,257,259,262,264,267,271,274,276],{"class":186,"line":258},5,[184,260,261],{"class":209},"    RedisError",[184,263,213],{"class":202},[184,265,266],{"class":198},"redis",[184,268,270],{"class":269},"smGrS","::",[184,272,273],{"class":198},"RedisError",[184,275,219],{"class":202},[184,277,278],{"class":222}," \u002F\u002F transport or Lua script error\n",[184,280,282,285,287,290,293,296,299,301],{"class":186,"line":281},6,[184,283,284],{"class":209},"    MutexPoisoned",[184,286,213],{"class":202},[184,288,289],{"class":269},"&",[184,291,292],{"class":202},"'",[184,294,295],{"class":198},"static",[184,297,298],{"class":198}," str",[184,300,219],{"class":202},[184,302,303],{"class":222},"   \u002F\u002F an internal sync primitive was poisoned\n",[184,305,307,310,312,314,316],{"class":186,"line":306},7,[184,308,309],{"class":209},"    CustomError",[184,311,213],{"class":202},[184,313,216],{"class":198},[184,315,219],{"class":202},[184,317,318],{"class":222},"           \u002F\u002F catch-all\n",[184,320,322,325,327,330,332],{"class":186,"line":321},8,[184,323,324],{"class":209},"    TrypemaError",[184,326,213],{"class":202},[184,328,329],{"class":198},"TrypemaError",[184,331,219],{"class":202},[184,333,334],{"class":222},"    \u002F\u002F rate limiting failed        (feature = \"trypema\")\n",[184,336,338],{"class":186,"line":337},9,[184,339,340],{"class":202},"}\n",[158,342,343],{},"The feature-gated variants only exist when the matching feature is enabled, so you never match on a primitive you didn't compile in.",[158,345,346,349,350,352],{},[162,347,348],{},"From"," is implemented for the inner error types, which is why ",[162,351,168],{}," just works:",[175,354,356],{"className":177,"code":355,"language":179,"meta":180,"style":180},"let key = DistkitRedisKey::try_from(\"user_123\".to_string())?; \u002F\u002F InvalidRedisKey on failure\ncounter.inc(&key, 1).await?;                                  \u002F\u002F RedisError \u002F CounterError on failure\n",[162,357,358,407],{"__ignoreMap":180},[184,359,360,363,367,370,373,375,378,380,384,388,390,393,396,399,401,404],{"class":186,"line":187},[184,361,362],{"class":194},"let",[184,364,366],{"class":365},"su5hD"," key ",[184,368,369],{"class":269},"=",[184,371,372],{"class":198}," DistkitRedisKey",[184,374,270],{"class":269},[184,376,377],{"class":209},"try_from",[184,379,213],{"class":202},[184,381,383],{"class":382},"sjJ54","\"",[184,385,387],{"class":386},"s_sjI","user_123",[184,389,383],{"class":382},[184,391,392],{"class":269},".",[184,394,395],{"class":209},"to_string",[184,397,398],{"class":202},"())",[184,400,168],{"class":269},[184,402,403],{"class":202},";",[184,405,406],{"class":222}," \u002F\u002F InvalidRedisKey on failure\n",[184,408,409,412,414,417,419,421,424,427,431,434,436,440,442,444],{"class":186,"line":206},[184,410,411],{"class":365},"counter",[184,413,392],{"class":269},[184,415,416],{"class":209},"inc",[184,418,213],{"class":202},[184,420,289],{"class":269},[184,422,423],{"class":365},"key",[184,425,426],{"class":202},",",[184,428,430],{"class":429},"srdBf"," 1",[184,432,433],{"class":202},")",[184,435,392],{"class":269},[184,437,439],{"class":438},"sVHd0","await",[184,441,168],{"class":269},[184,443,403],{"class":202},[184,445,446],{"class":222},"                                  \u002F\u002F RedisError \u002F CounterError on failure\n",[171,448,450],{"id":449},"lock-errors","Lock errors",[158,452,453,454,456,457,460],{},"Lock-specific failures are modeled separately as ",[162,455,250],{},", surfaced through ",[162,458,459],{},"DistkitError::LockError",":",[175,462,464],{"className":177,"code":463,"language":179,"meta":180,"style":180},"pub enum LockError {\n    AcquireFail,                  \u002F\u002F a non-blocking acquire would have to wait\n    Timeout { waited: Duration }, \u002F\u002F a bounded acquire ran out of time\n    NotOwner,                     \u002F\u002F tried to release a lock you don't hold\n    InvalidTtl(i64),              \u002F\u002F ttl must be positive\n    InvalidOwner,                 \u002F\u002F owner id must not be empty\n}\n",[162,465,466,477,487,509,519,534,544],{"__ignoreMap":180},[184,467,468,470,472,475],{"class":186,"line":187},[184,469,191],{"class":190},[184,471,195],{"class":194},[184,473,474],{"class":198}," LockError",[184,476,203],{"class":202},[184,478,479,482,484],{"class":186,"line":206},[184,480,481],{"class":198},"    AcquireFail",[184,483,426],{"class":202},[184,485,486],{"class":222},"                  \u002F\u002F a non-blocking acquire would have to wait\n",[184,488,489,492,495,498,500,503,506],{"class":186,"line":226},[184,490,491],{"class":198},"    Timeout",[184,493,494],{"class":202}," {",[184,496,497],{"class":365}," waited",[184,499,460],{"class":269},[184,501,502],{"class":198}," Duration",[184,504,505],{"class":202}," },",[184,507,508],{"class":222}," \u002F\u002F a bounded acquire ran out of time\n",[184,510,511,514,516],{"class":186,"line":242},[184,512,513],{"class":198},"    NotOwner",[184,515,426],{"class":202},[184,517,518],{"class":222},"                     \u002F\u002F tried to release a lock you don't hold\n",[184,520,521,524,526,529,531],{"class":186,"line":258},[184,522,523],{"class":209},"    InvalidTtl",[184,525,213],{"class":202},[184,527,528],{"class":198},"i64",[184,530,219],{"class":202},[184,532,533],{"class":222},"              \u002F\u002F ttl must be positive\n",[184,535,536,539,541],{"class":186,"line":281},[184,537,538],{"class":198},"    InvalidOwner",[184,540,426],{"class":202},[184,542,543],{"class":222},"                 \u002F\u002F owner id must not be empty\n",[184,545,546],{"class":186,"line":306},[184,547,340],{"class":202},[158,549,550,553,554,557,558,561],{},[162,551,552],{},"AcquireFail"," and ",[162,555,556],{},"Timeout"," are the two you handle routinely - they mean \"the lock is busy\", not \"something broke\". See ",[559,560,117],"a",{"href":118}," for how this interacts with lock guards.",[563,564,565],"style",{},"html pre.shiki code .sw1J6, html code.shiki .sw1J6{--shiki-light:#F76D47;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--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 .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--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 .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 .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}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);}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}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 pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}",{"title":180,"searchDepth":187,"depth":206,"links":567},[568,569],{"id":173,"depth":206,"text":164},{"id":449,"depth":206,"text":450},"One DistkitError enum, and a no-panic policy.","md",{},{"icon":54},{"title":51,"description":570},"k8woFzduq8SRlV8fNKk9w1CkYhYxKTRIQNukIoaqO7o",[577,579],{"title":46,"path":47,"stem":48,"description":578,"icon":49,"children":-1},"CounterComparator drives conditional counter writes.",{"title":62,"path":58,"stem":59,"description":580,"icon":63,"children":-1},"Distributed integer counters in strict and lax flavors, both behind one trait.",1781569582557]