agy-superpowers 5.2.1 → 5.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/README.md +47 -150
  2. package/package.json +1 -1
  3. package/template/agent/patches/skills-patches.md +23 -0
  4. package/template/agent/rules/scratch-scripts.md +37 -0
  5. package/template/agent/rules/superpowers.md +6 -50
  6. package/template/agent/skills/brainstorming/SKILL.md +4 -3
  7. package/template/agent/skills/brainstorming/visual-companion.md +2 -3
  8. package/template/agent/skills/finishing-a-development-branch/SKILL.md +11 -16
  9. package/template/agent/skills/subagent-driven-development/SKILL.md +16 -0
  10. package/template/agent/skills/subagent-driven-development/implementer-prompt.md +4 -3
  11. package/template/agent/skills/using-git-worktrees/SKILL.md +3 -2
  12. package/template/agent/skills/using-superpowers/SKILL.md +8 -6
  13. package/template/agent/skills/using-superpowers/references/copilot-tools.md +52 -0
  14. package/template/agent/skills/writing-plans/SKILL.md +5 -3
  15. package/template/agent/skills/writing-skills/SKILL.md +1 -1
  16. package/template/agent/superpowers-version.json +2 -2
  17. package/template/agent/tmp/agent-config-backup.yml +9 -0
  18. package/template/agent/skills/ai-integrated-product/SKILL.md +0 -57
  19. package/template/agent/skills/analytics-setup/SKILL.md +0 -51
  20. package/template/agent/skills/api-design/SKILL.md +0 -193
  21. package/template/agent/skills/app-store-optimizer/SKILL.md +0 -127
  22. package/template/agent/skills/auth-and-identity/SKILL.md +0 -167
  23. package/template/agent/skills/backend-developer/SKILL.md +0 -148
  24. package/template/agent/skills/bootstrapper-finance/SKILL.md +0 -55
  25. package/template/agent/skills/chrome-extension-developer/SKILL.md +0 -53
  26. package/template/agent/skills/community-manager/SKILL.md +0 -115
  27. package/template/agent/skills/content-marketer/SKILL.md +0 -111
  28. package/template/agent/skills/conversion-optimizer/SKILL.md +0 -142
  29. package/template/agent/skills/cto-architect/SKILL.md +0 -133
  30. package/template/agent/skills/customer-success-manager/SKILL.md +0 -126
  31. package/template/agent/skills/data-analyst/SKILL.md +0 -147
  32. package/template/agent/skills/devops-engineer/SKILL.md +0 -117
  33. package/template/agent/skills/email-infrastructure/SKILL.md +0 -164
  34. package/template/agent/skills/game-design/SKILL.md +0 -194
  35. package/template/agent/skills/game-developer/SKILL.md +0 -175
  36. package/template/agent/skills/growth-hacker/SKILL.md +0 -122
  37. package/template/agent/skills/idea-validator/SKILL.md +0 -55
  38. package/template/agent/skills/indie-legal/SKILL.md +0 -53
  39. package/template/agent/skills/influencer-marketer/SKILL.md +0 -141
  40. package/template/agent/skills/landing-page-builder/SKILL.md +0 -59
  41. package/template/agent/skills/launch-strategist/SKILL.md +0 -62
  42. package/template/agent/skills/market-researcher/SKILL.md +0 -53
  43. package/template/agent/skills/micro-saas-builder/SKILL.md +0 -56
  44. package/template/agent/skills/monetization-strategist/SKILL.md +0 -119
  45. package/template/agent/skills/paid-acquisition-specialist/SKILL.md +0 -119
  46. package/template/agent/skills/pricing-psychologist/SKILL.md +0 -58
  47. package/template/agent/skills/real-time-features/SKILL.md +0 -194
  48. package/template/agent/skills/retention-specialist/SKILL.md +0 -123
  49. package/template/agent/skills/rust-developer/SKILL.md +0 -281
  50. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +0 -231
  51. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +0 -124
  52. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +0 -131
  53. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +0 -132
  54. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +0 -95
  55. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +0 -141
  56. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +0 -125
  57. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +0 -127
  58. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +0 -120
  59. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +0 -131
  60. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +0 -156
  61. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +0 -122
  62. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +0 -167
  63. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +0 -134
  64. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +0 -143
  65. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +0 -121
  66. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +0 -143
  67. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +0 -187
  68. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +0 -165
  69. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +0 -177
  70. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +0 -163
  71. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +0 -146
  72. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +0 -142
  73. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +0 -160
  74. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +0 -125
  75. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +0 -162
  76. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +0 -177
  77. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +0 -184
  78. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +0 -168
  79. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +0 -182
  80. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +0 -199
  81. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +0 -175
  82. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +0 -185
  83. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +0 -203
  84. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +0 -171
  85. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +0 -158
  86. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +0 -195
  87. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +0 -171
  88. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +0 -156
  89. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +0 -191
  90. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +0 -198
  91. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +0 -154
  92. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +0 -167
  93. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +0 -169
  94. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +0 -172
  95. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +0 -189
  96. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +0 -113
  97. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +0 -147
  98. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +0 -122
  99. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +0 -161
  100. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +0 -149
  101. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +0 -138
  102. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +0 -169
  103. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +0 -116
  104. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +0 -128
  105. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +0 -136
  106. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +0 -131
  107. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +0 -179
  108. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +0 -144
  109. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +0 -152
  110. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +0 -145
  111. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +0 -133
  112. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +0 -152
  113. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +0 -124
  114. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +0 -115
  115. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +0 -151
  116. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +0 -130
  117. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +0 -155
  118. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +0 -171
  119. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +0 -138
  120. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +0 -107
  121. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +0 -154
  122. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +0 -118
  123. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +0 -157
  124. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +0 -133
  125. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +0 -131
  126. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +0 -136
  127. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +0 -135
  128. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +0 -122
  129. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +0 -172
  130. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +0 -168
  131. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +0 -142
  132. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +0 -168
  133. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +0 -147
  134. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +0 -158
  135. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +0 -139
  136. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +0 -147
  137. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +0 -149
  138. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +0 -174
  139. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +0 -159
  140. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +0 -138
  141. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +0 -142
  142. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +0 -156
  143. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +0 -172
  144. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +0 -164
  145. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +0 -99
  146. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +0 -104
  147. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +0 -94
  148. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +0 -78
  149. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +0 -76
  150. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +0 -123
  151. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +0 -127
  152. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +0 -129
  153. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +0 -131
  154. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +0 -142
  155. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +0 -86
  156. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +0 -154
  157. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +0 -118
  158. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +0 -92
  159. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +0 -65
  160. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +0 -101
  161. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +0 -161
  162. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +0 -187
  163. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +0 -142
  164. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +0 -152
  165. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +0 -141
  166. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +0 -181
  167. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +0 -160
  168. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +0 -171
  169. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +0 -130
  170. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +0 -167
  171. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +0 -144
  172. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +0 -154
  173. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +0 -141
  174. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +0 -95
  175. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +0 -135
  176. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +0 -124
  177. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +0 -135
  178. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +0 -134
  179. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +0 -134
  180. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +0 -105
  181. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +0 -65
  182. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +0 -97
  183. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +0 -122
  184. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +0 -119
  185. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +0 -153
  186. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +0 -136
  187. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +0 -133
  188. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +0 -120
  189. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +0 -137
  190. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +0 -134
  191. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +0 -150
  192. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +0 -123
  193. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +0 -113
  194. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +0 -175
  195. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +0 -149
  196. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +0 -142
  197. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +0 -133
  198. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +0 -148
  199. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +0 -130
  200. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +0 -120
  201. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +0 -155
  202. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +0 -139
  203. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +0 -135
  204. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +0 -162
  205. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +0 -186
  206. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +0 -162
  207. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +0 -160
  208. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +0 -151
  209. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +0 -171
  210. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +0 -142
  211. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +0 -168
  212. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +0 -151
  213. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +0 -144
  214. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +0 -189
  215. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +0 -226
  216. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +0 -161
  217. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +0 -130
  218. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +0 -154
  219. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +0 -127
  220. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +0 -154
  221. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +0 -142
  222. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +0 -146
  223. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +0 -160
  224. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +0 -159
  225. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +0 -144
  226. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +0 -137
  227. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +0 -188
  228. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +0 -143
  229. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +0 -131
  230. package/template/agent/skills/saas-architect/SKILL.md +0 -139
  231. package/template/agent/skills/security-engineer/SKILL.md +0 -133
  232. package/template/agent/skills/seo-specialist/SKILL.md +0 -130
  233. package/template/agent/skills/solo-founder-ops/SKILL.md +0 -56
@@ -1,198 +0,0 @@
1
- # async-select-racing
2
-
3
- > Use `select!` to race futures and handle the first to complete
4
-
5
- ## Why It Matters
6
-
7
- Sometimes you need the first result from multiple futures—timeout vs operation, cancellation vs work, or competing alternatives. `tokio::select!` lets you race futures and handle whichever completes first, while properly cancelling the others.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Can't express "whichever finishes first"
13
- async fn fetch_with_fallback() -> Data {
14
- match fetch_primary().await {
15
- Ok(data) => data,
16
- Err(_) => fetch_fallback().await.unwrap(), // Sequential, not racing
17
- }
18
- }
19
-
20
- // Manual timeout is error-prone
21
- async fn fetch_with_timeout() -> Option<Data> {
22
- let start = Instant::now();
23
- loop {
24
- if start.elapsed() > Duration::from_secs(5) {
25
- return None;
26
- }
27
- // How do we check timeout while awaiting?
28
- }
29
- }
30
- ```
31
-
32
- ## Good
33
-
34
- ```rust
35
- use tokio::select;
36
-
37
- async fn fetch_with_timeout() -> Result<Data, Error> {
38
- select! {
39
- result = fetch_data() => result,
40
- _ = tokio::time::sleep(Duration::from_secs(5)) => {
41
- Err(Error::Timeout)
42
- }
43
- }
44
- }
45
-
46
- async fn fetch_with_fallback() -> Data {
47
- select! {
48
- result = fetch_primary() => {
49
- match result {
50
- Ok(data) => data,
51
- Err(_) => fetch_fallback().await.unwrap()
52
- }
53
- }
54
- _ = tokio::time::sleep(Duration::from_secs(1)) => {
55
- // Primary too slow, use fallback
56
- fetch_fallback().await.unwrap()
57
- }
58
- }
59
- }
60
- ```
61
-
62
- ## select! Syntax
63
-
64
- ```rust
65
- select! {
66
- // Pattern = future => handler
67
- result = async_operation() => {
68
- // Handle result
69
- println!("Got: {:?}", result);
70
- }
71
-
72
- // Can bind with pattern matching
73
- Ok(data) = fallible_operation() => {
74
- process(data);
75
- }
76
-
77
- // Conditional branches with if guards
78
- msg = channel.recv(), if should_receive => {
79
- handle_message(msg);
80
- }
81
-
82
- // else branch for when all futures are disabled
83
- else => {
84
- println!("All branches disabled");
85
- }
86
- }
87
- ```
88
-
89
- ## Cancellation Behavior
90
-
91
- ```rust
92
- async fn select_example() {
93
- select! {
94
- _ = operation_a() => {
95
- println!("A completed first");
96
- // operation_b() is dropped/cancelled
97
- }
98
- _ = operation_b() => {
99
- println!("B completed first");
100
- // operation_a() is dropped/cancelled
101
- }
102
- }
103
- }
104
-
105
- // Futures are cancelled at their next .await point
106
- // For immediate cancellation, futures must be cancel-safe
107
- ```
108
-
109
- ## Biased Selection
110
-
111
- ```rust
112
- // By default, select! randomly picks when multiple are ready
113
- // Use biased mode for deterministic priority
114
- select! {
115
- biased; // Check branches in order
116
-
117
- msg = high_priority.recv() => handle_high(msg),
118
- msg = low_priority.recv() => handle_low(msg),
119
- }
120
-
121
- // Without biased, both channels have equal chance
122
- // when both have messages ready
123
- ```
124
-
125
- ## Loop with select!
126
-
127
- ```rust
128
- async fn event_loop(
129
- mut commands: mpsc::Receiver<Command>,
130
- shutdown: CancellationToken,
131
- ) {
132
- loop {
133
- select! {
134
- _ = shutdown.cancelled() => {
135
- println!("Shutting down");
136
- break;
137
- }
138
- Some(cmd) = commands.recv() => {
139
- process_command(cmd).await;
140
- }
141
- else => {
142
- // commands channel closed
143
- break;
144
- }
145
- }
146
- }
147
- }
148
- ```
149
-
150
- ## Racing Multiple of Same Type
151
-
152
- ```rust
153
- // Race multiple servers for fastest response
154
- async fn fastest_response(servers: &[String]) -> Result<Response> {
155
- let futures = servers.iter()
156
- .map(|s| fetch_from(s))
157
- .collect::<Vec<_>>();
158
-
159
- // select! requires static branches, use select_all for dynamic
160
- let (result, _index, _remaining) =
161
- futures::future::select_all(futures).await;
162
-
163
- result
164
- }
165
- ```
166
-
167
- ## Common Patterns
168
-
169
- ```rust
170
- // Timeout
171
- select! {
172
- result = operation() => result,
173
- _ = sleep(Duration::from_secs(5)) => Err(Timeout),
174
- }
175
-
176
- // Cancellation
177
- select! {
178
- result = operation() => result,
179
- _ = cancel_token.cancelled() => Err(Cancelled),
180
- }
181
-
182
- // Interval with cancellation
183
- let mut interval = tokio::time::interval(Duration::from_secs(1));
184
- loop {
185
- select! {
186
- _ = shutdown.cancelled() => break,
187
- _ = interval.tick() => {
188
- do_periodic_work().await;
189
- }
190
- }
191
- }
192
- ```
193
-
194
- ## See Also
195
-
196
- - [async-cancellation-token](./async-cancellation-token.md) - Cancellation patterns
197
- - [async-join-parallel](./async-join-parallel.md) - All futures, not racing
198
- - [async-bounded-channel](./async-bounded-channel.md) - Channel operations in select
@@ -1,154 +0,0 @@
1
- # async-spawn-blocking
2
-
3
- > Use `spawn_blocking` for CPU-intensive work
4
-
5
- ## Why It Matters
6
-
7
- Async runtimes like Tokio use a small number of threads to handle many tasks. CPU-intensive or blocking operations on these threads starve other tasks. `spawn_blocking` moves such work to a dedicated thread pool.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // BAD: Blocks the async runtime thread
13
- async fn process_image(data: &[u8]) -> ProcessedImage {
14
- // CPU-intensive work on async thread!
15
- let resized = resize_image(data); // Blocks!
16
- let compressed = compress(resized); // Blocks!
17
- compressed
18
- }
19
-
20
- // BAD: Synchronous file I/O in async context
21
- async fn read_large_file(path: &Path) -> Vec<u8> {
22
- std::fs::read(path).unwrap() // Blocks the runtime!
23
- }
24
- ```
25
-
26
- ## Good
27
-
28
- ```rust
29
- use tokio::task;
30
-
31
- // GOOD: Offload CPU work to blocking pool
32
- async fn process_image(data: Vec<u8>) -> ProcessedImage {
33
- task::spawn_blocking(move || {
34
- let resized = resize_image(&data);
35
- compress(resized)
36
- })
37
- .await
38
- .expect("spawn_blocking failed")
39
- }
40
-
41
- // GOOD: Use async file I/O
42
- async fn read_large_file(path: &Path) -> tokio::io::Result<Vec<u8>> {
43
- tokio::fs::read(path).await
44
- }
45
-
46
- // GOOD: Or spawn_blocking for unavoidable sync I/O
47
- async fn read_with_sync_lib(path: PathBuf) -> Vec<u8> {
48
- task::spawn_blocking(move || {
49
- sync_library::read_file(&path)
50
- })
51
- .await
52
- .unwrap()
53
- }
54
- ```
55
-
56
- ## What Counts as Blocking
57
-
58
- ```rust
59
- // CPU-intensive operations
60
- - Cryptographic operations (hashing, encryption)
61
- - Image/video processing
62
- - Compression/decompression
63
- - Complex parsing
64
- - Mathematical computations
65
-
66
- // Blocking I/O
67
- - std::fs operations
68
- - Synchronous database drivers
69
- - Synchronous HTTP clients
70
- - Thread::sleep
71
-
72
- // Example thresholds (rough guidelines):
73
- // < 10µs: OK on async thread
74
- // 10µs - 1ms: Consider spawn_blocking
75
- // > 1ms: Definitely spawn_blocking
76
- ```
77
-
78
- ## Practical Examples
79
-
80
- ```rust
81
- // Password hashing (CPU-intensive)
82
- async fn hash_password(password: String) -> String {
83
- task::spawn_blocking(move || {
84
- bcrypt::hash(password, bcrypt::DEFAULT_COST).unwrap()
85
- })
86
- .await
87
- .unwrap()
88
- }
89
-
90
- // JSON parsing of large documents
91
- async fn parse_large_json(data: String) -> serde_json::Value {
92
- task::spawn_blocking(move || {
93
- serde_json::from_str(&data).unwrap()
94
- })
95
- .await
96
- .unwrap()
97
- }
98
-
99
- // Compression
100
- async fn compress_data(data: Vec<u8>) -> Vec<u8> {
101
- task::spawn_blocking(move || {
102
- let mut encoder = flate2::write::GzEncoder::new(
103
- Vec::new(),
104
- flate2::Compression::default(),
105
- );
106
- encoder.write_all(&data).unwrap();
107
- encoder.finish().unwrap()
108
- })
109
- .await
110
- .unwrap()
111
- }
112
- ```
113
-
114
- ## spawn_blocking vs spawn
115
-
116
- ```rust
117
- // spawn: Runs async code on runtime threads
118
- tokio::spawn(async {
119
- // Async code here
120
- some_async_operation().await;
121
- });
122
-
123
- // spawn_blocking: Runs sync code on blocking thread pool
124
- tokio::task::spawn_blocking(|| {
125
- // Synchronous, possibly CPU-intensive code
126
- heavy_computation();
127
- });
128
-
129
- // spawn_blocking returns JoinHandle that can be awaited
130
- let result = tokio::task::spawn_blocking(|| {
131
- expensive_sync_operation()
132
- }).await?;
133
- ```
134
-
135
- ## Rayon for Parallel CPU Work
136
-
137
- ```rust
138
- // For parallel CPU work, consider Rayon inside spawn_blocking
139
- async fn parallel_process(items: Vec<Item>) -> Vec<Output> {
140
- task::spawn_blocking(move || {
141
- use rayon::prelude::*;
142
- items.par_iter()
143
- .map(|item| cpu_intensive_transform(item))
144
- .collect()
145
- })
146
- .await
147
- .unwrap()
148
- }
149
- ```
150
-
151
- ## See Also
152
-
153
- - [async-tokio-fs](async-tokio-fs.md) - Use tokio::fs for async file I/O
154
- - [async-no-lock-await](async-no-lock-await.md) - Don't hold locks across await
@@ -1,167 +0,0 @@
1
- # async-tokio-fs
2
-
3
- > Use `tokio::fs` instead of `std::fs` in async code
4
-
5
- ## Why It Matters
6
-
7
- `std::fs` operations are blocking—they stop the current thread until the syscall completes. In async code, this blocks the executor thread, preventing it from running other tasks. `tokio::fs` wraps filesystem operations in `spawn_blocking`, keeping the executor responsive.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- async fn process_files(paths: &[PathBuf]) -> Result<Vec<String>> {
13
- let mut contents = Vec::new();
14
-
15
- for path in paths {
16
- // BLOCKS the entire executor thread!
17
- let data = std::fs::read_to_string(path)?;
18
- contents.push(data);
19
- }
20
-
21
- Ok(contents)
22
- }
23
-
24
- // While reading a file, NO other tasks can run on this thread
25
- ```
26
-
27
- ## Good
28
-
29
- ```rust
30
- use tokio::fs;
31
-
32
- async fn process_files(paths: &[PathBuf]) -> Result<Vec<String>> {
33
- let mut contents = Vec::new();
34
-
35
- for path in paths {
36
- // Non-blocking: allows other tasks to run
37
- let data = fs::read_to_string(path).await?;
38
- contents.push(data);
39
- }
40
-
41
- Ok(contents)
42
- }
43
-
44
- // Even better: concurrent reads
45
- async fn process_files_concurrent(paths: &[PathBuf]) -> Result<Vec<String>> {
46
- let futures: Vec<_> = paths.iter()
47
- .map(|path| fs::read_to_string(path))
48
- .collect();
49
-
50
- futures::future::try_join_all(futures).await
51
- }
52
- ```
53
-
54
- ## tokio::fs API
55
-
56
- ```rust
57
- use tokio::fs;
58
-
59
- // Reading
60
- let contents = fs::read_to_string("file.txt").await?;
61
- let bytes = fs::read("file.bin").await?;
62
-
63
- // Writing
64
- fs::write("output.txt", "contents").await?;
65
-
66
- // File operations
67
- let file = fs::File::open("file.txt").await?;
68
- let file = fs::File::create("new.txt").await?;
69
-
70
- // Directory operations
71
- fs::create_dir("new_dir").await?;
72
- fs::create_dir_all("nested/dir/path").await?;
73
- fs::remove_dir("empty_dir").await?;
74
- fs::remove_dir_all("dir_with_contents").await?;
75
-
76
- // Metadata
77
- let metadata = fs::metadata("file.txt").await?;
78
- let canonical = fs::canonicalize("./relative").await?;
79
-
80
- // Rename/remove
81
- fs::rename("old.txt", "new.txt").await?;
82
- fs::remove_file("file.txt").await?;
83
-
84
- // Read directory
85
- let mut entries = fs::read_dir("some_dir").await?;
86
- while let Some(entry) = entries.next_entry().await? {
87
- println!("{}", entry.path().display());
88
- }
89
- ```
90
-
91
- ## Async File I/O
92
-
93
- ```rust
94
- use tokio::fs::File;
95
- use tokio::io::{AsyncReadExt, AsyncWriteExt, AsyncBufReadExt, BufReader};
96
-
97
- // Read with buffer
98
- let mut file = File::open("large.bin").await?;
99
- let mut buffer = vec![0u8; 4096];
100
- let bytes_read = file.read(&mut buffer).await?;
101
-
102
- // Read all
103
- let mut contents = Vec::new();
104
- file.read_to_end(&mut contents).await?;
105
-
106
- // Write
107
- let mut file = File::create("output.bin").await?;
108
- file.write_all(b"data").await?;
109
- file.flush().await?;
110
-
111
- // Buffered line reading
112
- let file = File::open("lines.txt").await?;
113
- let reader = BufReader::new(file);
114
- let mut lines = reader.lines();
115
-
116
- while let Some(line) = lines.next_line().await? {
117
- println!("{}", line);
118
- }
119
- ```
120
-
121
- ## When std::fs is Acceptable
122
-
123
- ```rust
124
- // Startup/initialization (before async runtime)
125
- fn main() {
126
- let config = std::fs::read_to_string("config.toml")
127
- .expect("config file required");
128
-
129
- tokio::runtime::Runtime::new()
130
- .unwrap()
131
- .block_on(run_with_config(config));
132
- }
133
-
134
- // Single-threaded current_thread runtime (less impact)
135
- #[tokio::main(flavor = "current_thread")]
136
- async fn main() {
137
- // Still prefer tokio::fs, but impact is lower
138
- }
139
-
140
- // When file operations are rare and quick
141
- // (e.g., reading small config once per hour)
142
- ```
143
-
144
- ## Performance Considerations
145
-
146
- ```rust
147
- // tokio::fs uses spawn_blocking internally
148
- // For many small files, the overhead adds up
149
-
150
- // Batch operations when possible
151
- let paths: Vec<_> = entries.iter()
152
- .map(|e| e.path())
153
- .collect();
154
-
155
- let contents = futures::future::try_join_all(
156
- paths.iter().map(|p| fs::read_to_string(p))
157
- ).await?;
158
-
159
- // For heavy I/O, consider memory-mapped files
160
- // (requires unsafe or mmap crate)
161
- ```
162
-
163
- ## See Also
164
-
165
- - [async-spawn-blocking](./async-spawn-blocking.md) - How tokio::fs works internally
166
- - [async-tokio-runtime](./async-tokio-runtime.md) - Runtime configuration
167
- - [err-context-chain](./err-context-chain.md) - Adding path context to IO errors
@@ -1,169 +0,0 @@
1
- # async-tokio-runtime
2
-
3
- > Configure Tokio runtime appropriately for your workload
4
-
5
- ## Why It Matters
6
-
7
- Tokio's default multi-threaded runtime isn't always optimal. CPU-bound work needs different configuration than IO-bound work. Incorrect configuration leads to poor performance, blocked workers, or resource exhaustion. Understanding runtime options lets you tune for your specific use case.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Default runtime for everything - not optimal
13
- #[tokio::main]
14
- async fn main() {
15
- // CPU-heavy work on async executor starves IO tasks
16
- for data in datasets {
17
- let result = heavy_computation(data).await;
18
- }
19
- }
20
-
21
- // Single-threaded when multi-threaded is needed
22
- #[tokio::main(flavor = "current_thread")]
23
- async fn main() {
24
- // Can't utilize multiple cores for concurrent tasks
25
- for _ in 0..1000 {
26
- tokio::spawn(async { /* IO work */ });
27
- }
28
- }
29
- ```
30
-
31
- ## Good
32
-
33
- ```rust
34
- // Multi-threaded for concurrent IO (default)
35
- #[tokio::main]
36
- async fn main() {
37
- // Good for many concurrent network connections
38
- let handles: Vec<_> = urls.iter()
39
- .map(|url| tokio::spawn(fetch(url.clone())))
40
- .collect();
41
-
42
- futures::future::join_all(handles).await;
43
- }
44
-
45
- // Current-thread for single-threaded scenarios
46
- #[tokio::main(flavor = "current_thread")]
47
- async fn main() {
48
- // Good for single-connection clients, simpler debugging
49
- let client = Client::new();
50
- client.run().await;
51
- }
52
-
53
- // Custom configuration
54
- #[tokio::main(worker_threads = 4)]
55
- async fn main() {
56
- // Limit to 4 worker threads
57
- }
58
-
59
- // Or manual setup for more control
60
- fn main() {
61
- let runtime = tokio::runtime::Builder::new_multi_thread()
62
- .worker_threads(4)
63
- .enable_all()
64
- .thread_name("my-worker")
65
- .build()
66
- .unwrap();
67
-
68
- runtime.block_on(async_main());
69
- }
70
- ```
71
-
72
- ## Runtime Types
73
-
74
- | Runtime | Use Case | Configuration |
75
- |---------|----------|---------------|
76
- | Multi-thread | IO-bound, many connections | `#[tokio::main]` (default) |
77
- | Current-thread | CLI tools, tests, single connection | `flavor = "current_thread"` |
78
- | Custom | Fine-tuned performance | `Builder::new_*()` |
79
-
80
- ## Worker Thread Tuning
81
-
82
- ```rust
83
- use tokio::runtime::Builder;
84
-
85
- // IO-bound: more threads than cores can help
86
- let io_runtime = Builder::new_multi_thread()
87
- .worker_threads(num_cpus::get() * 2) // IO can benefit from oversubscription
88
- .max_blocking_threads(32) // For spawn_blocking calls
89
- .enable_io()
90
- .enable_time()
91
- .build()?;
92
-
93
- // CPU-bound: match core count
94
- let cpu_runtime = Builder::new_multi_thread()
95
- .worker_threads(num_cpus::get()) // No benefit from more than cores
96
- .build()?;
97
- ```
98
-
99
- ## Multiple Runtimes
100
-
101
- ```rust
102
- // Separate runtimes for different workloads
103
- struct App {
104
- io_runtime: Runtime,
105
- cpu_runtime: Runtime,
106
- }
107
-
108
- impl App {
109
- fn new() -> Self {
110
- Self {
111
- io_runtime: Builder::new_multi_thread()
112
- .worker_threads(8)
113
- .thread_name("io-worker")
114
- .build()
115
- .unwrap(),
116
- cpu_runtime: Builder::new_multi_thread()
117
- .worker_threads(4)
118
- .thread_name("cpu-worker")
119
- .build()
120
- .unwrap(),
121
- }
122
- }
123
-
124
- fn spawn_io<F>(&self, future: F)
125
- where F: Future + Send + 'static, F::Output: Send + 'static
126
- {
127
- self.io_runtime.spawn(future);
128
- }
129
-
130
- fn spawn_cpu<F>(&self, task: F)
131
- where F: FnOnce() + Send + 'static
132
- {
133
- self.cpu_runtime.spawn_blocking(task);
134
- }
135
- }
136
- ```
137
-
138
- ## Runtime in Tests
139
-
140
- ```rust
141
- // Single test runtime
142
- #[tokio::test]
143
- async fn test_single() {
144
- assert!(true);
145
- }
146
-
147
- // Multi-threaded test
148
- #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
149
- async fn test_concurrent() {
150
- let (tx, rx) = tokio::sync::oneshot::channel();
151
- tokio::spawn(async move { tx.send(42).unwrap() });
152
- assert_eq!(rx.await.unwrap(), 42);
153
- }
154
-
155
- // Custom runtime in test
156
- #[test]
157
- fn test_with_custom_runtime() {
158
- let rt = Builder::new_current_thread().build().unwrap();
159
- rt.block_on(async {
160
- // test code
161
- });
162
- }
163
- ```
164
-
165
- ## See Also
166
-
167
- - [async-spawn-blocking](./async-spawn-blocking.md) - Handling blocking code
168
- - [async-no-lock-await](./async-no-lock-await.md) - Avoiding lock issues
169
- - [async-joinset-structured](./async-joinset-structured.md) - Managing spawned tasks