@ngxtm/devkit 3.4.0 → 3.4.1
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.
- package/package.json +2 -1
- package/rules/README.md +141 -0
- package/rules/dart/best-practices/SKILL.md +23 -0
- package/rules/dart/language/SKILL.md +52 -0
- package/rules/dart/tooling/SKILL.md +43 -0
- package/rules/dotnet/aspnet-core/SKILL.md +92 -0
- package/rules/dotnet/aspnet-core/references/REFERENCE.md +335 -0
- package/rules/dotnet/best-practices/SKILL.md +101 -0
- package/rules/dotnet/best-practices/references/REFERENCE.md +256 -0
- package/rules/dotnet/blazor/SKILL.md +146 -0
- package/rules/dotnet/blazor/references/REFERENCE.md +392 -0
- package/rules/dotnet/language/SKILL.md +82 -0
- package/rules/dotnet/language/references/REFERENCE.md +222 -0
- package/rules/dotnet/patterns.rule.md +388 -0
- package/rules/dotnet/razor-pages/SKILL.md +124 -0
- package/rules/dotnet/razor-pages/references/REFERENCE.md +321 -0
- package/rules/dotnet/security/SKILL.md +89 -0
- package/rules/dotnet/security/references/REFERENCE.md +295 -0
- package/rules/dotnet/tooling/SKILL.md +92 -0
- package/rules/dotnet/tooling/references/REFERENCE.md +300 -0
- package/rules/flutter/auto-route-navigation/SKILL.md +43 -0
- package/rules/flutter/auto-route-navigation/references/REFERENCE.md +19 -0
- package/rules/flutter/auto-route-navigation/references/router-config.md +62 -0
- package/rules/flutter/bloc-state-management/SKILL.md +64 -0
- package/rules/flutter/bloc-state-management/references/REFERENCE.md +20 -0
- package/rules/flutter/bloc-state-management/references/auth-bloc-example.md +52 -0
- package/rules/flutter/bloc-state-management/references/equatable-usage.md +56 -0
- package/rules/flutter/bloc-state-management/references/property-based-state.md +68 -0
- package/rules/flutter/bloc.rule.md +76 -0
- package/rules/flutter/cicd/SKILL.md +48 -0
- package/rules/flutter/cicd/references/advanced-workflow.md +66 -0
- package/rules/flutter/cicd/references/fastlane.md +139 -0
- package/rules/flutter/cicd/references/github-actions.md +59 -0
- package/rules/flutter/dependency-injection/SKILL.md +42 -0
- package/rules/flutter/dependency-injection/references/REFERENCE.md +15 -0
- package/rules/flutter/dependency-injection/references/modules.md +37 -0
- package/rules/flutter/error-handling/SKILL.md +32 -0
- package/rules/flutter/error-handling/references/REFERENCE.md +19 -0
- package/rules/flutter/error-handling/references/error-mapping.md +31 -0
- package/rules/flutter/feature-based-clean-architecture/SKILL.md +46 -0
- package/rules/flutter/feature-based-clean-architecture/references/REFERENCE.md +14 -0
- package/rules/flutter/feature-based-clean-architecture/references/folder-structure.md +36 -0
- package/rules/flutter/getx-navigation/SKILL.md +70 -0
- package/rules/flutter/getx-navigation/references/app-pages.md +40 -0
- package/rules/flutter/getx-navigation/references/middleware-example.md +29 -0
- package/rules/flutter/getx-state-management/SKILL.md +76 -0
- package/rules/flutter/getx-state-management/references/binding-example.md +32 -0
- package/rules/flutter/getx-state-management/references/reactive-vs-simple.md +39 -0
- package/rules/flutter/go-router-navigation/SKILL.md +57 -0
- package/rules/flutter/idiomatic-flutter/SKILL.md +20 -0
- package/rules/flutter/layer-based-clean-architecture/SKILL.md +50 -0
- package/rules/flutter/layer-based-clean-architecture/references/REFERENCE.md +60 -0
- package/rules/flutter/layer-based-clean-architecture/references/repository-mapping.md +50 -0
- package/rules/flutter/localization/SKILL.md +50 -0
- package/rules/flutter/localization/references/REFERENCE.md +48 -0
- package/rules/flutter/localization/references/sheet-loader.md +33 -0
- package/rules/flutter/navigator-v1-navigation/SKILL.md +71 -0
- package/rules/flutter/navigator-v1-navigation/references/on-generate-route.md +48 -0
- package/rules/flutter/performance/SKILL.md +24 -0
- package/rules/flutter/retrofit-networking/SKILL.md +51 -0
- package/rules/flutter/retrofit-networking/references/REFERENCE.md +19 -0
- package/rules/flutter/retrofit-networking/references/token-refresh.md +40 -0
- package/rules/flutter/riverpod-state-management/SKILL.md +53 -0
- package/rules/flutter/riverpod-state-management/references/architecture.md +124 -0
- package/rules/flutter/riverpod-state-management/references/best-practices.md +89 -0
- package/rules/flutter/riverpod-state-management/references/testing.md +73 -0
- package/rules/flutter/riverpod.rule.md +78 -0
- package/rules/flutter/security/SKILL.md +33 -0
- package/rules/flutter/security/references/REFERENCE.md +15 -0
- package/rules/flutter/security/references/network-security.md +28 -0
- package/rules/flutter/testing/SKILL.md +44 -0
- package/rules/flutter/testing/references/REFERENCE.md +21 -0
- package/rules/flutter/testing/references/bloc-testing.md +38 -0
- package/rules/flutter/testing/references/integration-testing.md +128 -0
- package/rules/flutter/testing/references/robot-pattern.md +82 -0
- package/rules/flutter/testing/references/unit-testing.md +130 -0
- package/rules/flutter/testing/references/widget-testing.md +120 -0
- package/rules/flutter/widgets/SKILL.md +37 -0
- package/rules/golang/chi-router/SKILL.md +219 -0
- package/rules/golang/chi-router/references/REFERENCE.md +13 -0
- package/rules/golang/chi-router/references/routing-patterns.md +205 -0
- package/rules/golang/cobra-cli/SKILL.md +227 -0
- package/rules/golang/cobra-cli/references/REFERENCE.md +13 -0
- package/rules/golang/cobra-cli/references/command-patterns.md +224 -0
- package/rules/golang/core/SKILL.md +210 -0
- package/rules/golang/core/references/REFERENCE.md +14 -0
- package/rules/golang/core/references/concurrency-patterns.md +114 -0
- package/rules/golang/core/references/error-handling.md +87 -0
- package/rules/golang/echo-framework/SKILL.md +215 -0
- package/rules/golang/echo-framework/references/REFERENCE.md +14 -0
- package/rules/golang/echo-framework/references/middleware-patterns.md +141 -0
- package/rules/golang/echo-framework/references/routing-patterns.md +140 -0
- package/rules/golang/ent-orm/SKILL.md +239 -0
- package/rules/golang/ent-orm/references/REFERENCE.md +13 -0
- package/rules/golang/ent-orm/references/schema-patterns.md +255 -0
- package/rules/golang/fiber-framework/SKILL.md +196 -0
- package/rules/golang/fiber-framework/references/REFERENCE.md +13 -0
- package/rules/golang/fiber-framework/references/routing-patterns.md +191 -0
- package/rules/golang/gin-framework/SKILL.md +205 -0
- package/rules/golang/gin-framework/references/REFERENCE.md +14 -0
- package/rules/golang/gin-framework/references/middleware-patterns.md +119 -0
- package/rules/golang/gorm-orm/SKILL.md +196 -0
- package/rules/golang/gorm-orm/references/REFERENCE.md +14 -0
- package/rules/golang/gorm-orm/references/model-definitions.md +167 -0
- package/rules/golang/gorm-orm/references/query-patterns.md +161 -0
- package/rules/golang/grpc/SKILL.md +231 -0
- package/rules/golang/grpc/references/REFERENCE.md +13 -0
- package/rules/golang/grpc/references/service-patterns.md +276 -0
- package/rules/golang/testify/SKILL.md +239 -0
- package/rules/golang/testify/references/REFERENCE.md +13 -0
- package/rules/golang/testify/references/assert-patterns.md +170 -0
- package/rules/golang/validator/SKILL.md +234 -0
- package/rules/golang/validator/references/REFERENCE.md +13 -0
- package/rules/golang/validator/references/validation-tags.md +211 -0
- package/rules/golang/viper-config/SKILL.md +244 -0
- package/rules/golang/viper-config/references/REFERENCE.md +13 -0
- package/rules/golang/viper-config/references/config-loading.md +181 -0
- package/rules/golang/wire-di/SKILL.md +243 -0
- package/rules/golang/wire-di/references/REFERENCE.md +13 -0
- package/rules/golang/wire-di/references/provider-patterns.md +193 -0
- package/rules/golang/zap-logging/SKILL.md +203 -0
- package/rules/golang/zap-logging/references/REFERENCE.md +13 -0
- package/rules/golang/zap-logging/references/logger-config.md +165 -0
- package/rules/java/build-gradle/SKILL.md +92 -0
- package/rules/java/build-gradle/references/REFERENCE.md +14 -0
- package/rules/java/build-gradle/references/kotlin-dsl.md +118 -0
- package/rules/java/build-gradle/references/task-configuration.md +132 -0
- package/rules/java/build-maven/SKILL.md +86 -0
- package/rules/java/build-maven/references/REFERENCE.md +14 -0
- package/rules/java/build-maven/references/dependency-management.md +111 -0
- package/rules/java/build-maven/references/lifecycle-phases.md +114 -0
- package/rules/java/graalvm-native/SKILL.md +105 -0
- package/rules/java/graalvm-native/references/REFERENCE.md +12 -0
- package/rules/java/java-collections-streams/SKILL.md +148 -0
- package/rules/java/java-collections-streams/references/REFERENCE.md +15 -0
- package/rules/java/java-collections-streams/references/collectors-patterns.md +178 -0
- package/rules/java/java-collections-streams/references/stream-pipelines.md +165 -0
- package/rules/java/java-concurrency/SKILL.md +187 -0
- package/rules/java/java-concurrency/references/REFERENCE.md +17 -0
- package/rules/java/java-concurrency/references/completable-future.md +165 -0
- package/rules/java/java-concurrency/references/executor-patterns.md +176 -0
- package/rules/java/java-concurrency/references/virtual-threads.md +190 -0
- package/rules/java/java-core-language/SKILL.md +121 -0
- package/rules/java/java-core-language/references/REFERENCE.md +15 -0
- package/rules/java/java-core-language/references/jvm-memory-model.md +160 -0
- package/rules/java/java-core-language/references/modern-java-features.md +168 -0
- package/rules/java/java-project-structure/SKILL.md +195 -0
- package/rules/java/java-project-structure/references/REFERENCE.md +15 -0
- package/rules/java/java-project-structure/references/maven-project-layout.md +199 -0
- package/rules/java/java-project-structure/references/module-system.md +159 -0
- package/rules/java/micronaut-core/SKILL.md +99 -0
- package/rules/java/micronaut-core/references/REFERENCE.md +12 -0
- package/rules/java/micronaut-reactive/SKILL.md +68 -0
- package/rules/java/micronaut-reactive/references/REFERENCE.md +12 -0
- package/rules/java/quarkus-core/SKILL.md +85 -0
- package/rules/java/quarkus-core/references/REFERENCE.md +12 -0
- package/rules/java/quarkus-reactive/SKILL.md +67 -0
- package/rules/java/quarkus-reactive/references/REFERENCE.md +12 -0
- package/rules/java/spring-batch/SKILL.md +102 -0
- package/rules/java/spring-batch/references/REFERENCE.md +12 -0
- package/rules/java/spring-boot-architecture/SKILL.md +206 -0
- package/rules/java/spring-boot-architecture/references/REFERENCE.md +15 -0
- package/rules/java/spring-boot-architecture/references/auto-configuration.md +158 -0
- package/rules/java/spring-boot-architecture/references/configuration-properties.md +202 -0
- package/rules/java/spring-boot-web/SKILL.md +217 -0
- package/rules/java/spring-boot-web/references/REFERENCE.md +17 -0
- package/rules/java/spring-cloud/SKILL.md +109 -0
- package/rules/java/spring-cloud/references/REFERENCE.md +13 -0
- package/rules/java/spring-data-jpa/SKILL.md +241 -0
- package/rules/java/spring-data-jpa/references/REFERENCE.md +16 -0
- package/rules/java/spring-security/SKILL.md +161 -0
- package/rules/java/spring-security/references/REFERENCE.md +16 -0
- package/rules/java/spring-security/references/jwt-auth-flow.md +213 -0
- package/rules/java/testing-junit-mockito/SKILL.md +135 -0
- package/rules/java/testing-junit-mockito/references/REFERENCE.md +15 -0
- package/rules/java/testing-junit-mockito/references/junit5-patterns.md +159 -0
- package/rules/java/testing-junit-mockito/references/mockito-patterns.md +148 -0
- package/rules/java/testing-junit-mockito/references/spring-boot-testing.md +152 -0
- package/rules/javascript/best-practices/SKILL.md +64 -0
- package/rules/javascript/best-practices/references/REFERENCE.md +91 -0
- package/rules/javascript/language/SKILL.md +71 -0
- package/rules/javascript/language/references/REFERENCE.md +106 -0
- package/rules/javascript/tooling/SKILL.md +60 -0
- package/rules/javascript/tooling/references/REFERENCE.md +107 -0
- package/rules/metadata.json +54 -0
- package/rules/nestjs/api-standards/SKILL.md +47 -0
- package/rules/nestjs/api-standards/references/pagination-wrapper.md +87 -0
- package/rules/nestjs/architecture/SKILL.md +68 -0
- package/rules/nestjs/architecture/references/dynamic-module.md +53 -0
- package/rules/nestjs/caching/SKILL.md +51 -0
- package/rules/nestjs/caching/references/REFERENCE.md +13 -0
- package/rules/nestjs/caching/references/cache-patterns.md +183 -0
- package/rules/nestjs/configuration/SKILL.md +41 -0
- package/rules/nestjs/configuration/references/REFERENCE.md +13 -0
- package/rules/nestjs/configuration/references/config-patterns.md +184 -0
- package/rules/nestjs/controllers-services/SKILL.md +63 -0
- package/rules/nestjs/controllers-services/references/REFERENCE.md +14 -0
- package/rules/nestjs/controllers-services/references/controller-patterns.md +119 -0
- package/rules/nestjs/controllers-services/references/service-patterns.md +129 -0
- package/rules/nestjs/database/SKILL.md +102 -0
- package/rules/nestjs/database/references/REFERENCE.md +14 -0
- package/rules/nestjs/database/references/typeorm-patterns.md +156 -0
- package/rules/nestjs/deployment/SKILL.md +36 -0
- package/rules/nestjs/deployment/references/REFERENCE.md +13 -0
- package/rules/nestjs/deployment/references/deployment-patterns.md +140 -0
- package/rules/nestjs/documentation/SKILL.md +64 -0
- package/rules/nestjs/documentation/references/REFERENCE.md +13 -0
- package/rules/nestjs/documentation/references/swagger-patterns.md +139 -0
- package/rules/nestjs/error-handling/SKILL.md +55 -0
- package/rules/nestjs/error-handling/references/REFERENCE.md +13 -0
- package/rules/nestjs/error-handling/references/exception-filters.md +152 -0
- package/rules/nestjs/file-uploads/SKILL.md +35 -0
- package/rules/nestjs/file-uploads/references/REFERENCE.md +13 -0
- package/rules/nestjs/file-uploads/references/upload-patterns.md +125 -0
- package/rules/nestjs/observability/SKILL.md +39 -0
- package/rules/nestjs/observability/references/REFERENCE.md +13 -0
- package/rules/nestjs/observability/references/logging-metrics.md +175 -0
- package/rules/nestjs/performance/SKILL.md +60 -0
- package/rules/nestjs/performance/references/REFERENCE.md +13 -0
- package/rules/nestjs/performance/references/performance-patterns.md +107 -0
- package/rules/nestjs/real-time/SKILL.md +45 -0
- package/rules/nestjs/real-time/references/REFERENCE.md +13 -0
- package/rules/nestjs/real-time/references/websocket-patterns.md +121 -0
- package/rules/nestjs/scheduling/SKILL.md +39 -0
- package/rules/nestjs/scheduling/references/REFERENCE.md +13 -0
- package/rules/nestjs/scheduling/references/scheduling-patterns.md +137 -0
- package/rules/nestjs/search/SKILL.md +41 -0
- package/rules/nestjs/search/references/REFERENCE.md +13 -0
- package/rules/nestjs/search/references/search-patterns.md +137 -0
- package/rules/nestjs/security/SKILL.md +87 -0
- package/rules/nestjs/security/references/REFERENCE.md +14 -0
- package/rules/nestjs/security/references/authentication.md +151 -0
- package/rules/nestjs/testing/SKILL.md +40 -0
- package/rules/nestjs/testing/references/REFERENCE.md +14 -0
- package/rules/nestjs/testing/references/unit-testing.md +179 -0
- package/rules/nestjs/transport/SKILL.md +45 -0
- package/rules/nestjs/transport/references/REFERENCE.md +13 -0
- package/rules/nestjs/transport/references/microservices-patterns.md +170 -0
- package/rules/nextjs/app-router/SKILL.md +46 -0
- package/rules/nextjs/app-router/references/REFERENCE.md +14 -0
- package/rules/nextjs/app-router/references/routing-patterns.md +182 -0
- package/rules/nextjs/architecture/SKILL.md +44 -0
- package/rules/nextjs/architecture/references/fsd-structure.md +77 -0
- package/rules/nextjs/authentication/SKILL.md +29 -0
- package/rules/nextjs/authentication/references/auth-implementation.md +73 -0
- package/rules/nextjs/caching/SKILL.md +66 -0
- package/rules/nextjs/caching/references/REFERENCE.md +13 -0
- package/rules/nextjs/caching/references/cache-strategies.md +168 -0
- package/rules/nextjs/data-access-layer/SKILL.md +33 -0
- package/rules/nextjs/data-access-layer/references/patterns.md +66 -0
- package/rules/nextjs/data-fetching/SKILL.md +59 -0
- package/rules/nextjs/data-fetching/references/REFERENCE.md +13 -0
- package/rules/nextjs/data-fetching/references/fetch-patterns.md +160 -0
- package/rules/nextjs/internationalization/SKILL.md +105 -0
- package/rules/nextjs/internationalization/references/REFERENCE.md +13 -0
- package/rules/nextjs/internationalization/references/i18n-patterns.md +180 -0
- package/rules/nextjs/optimization/SKILL.md +64 -0
- package/rules/nextjs/optimization/references/REFERENCE.md +13 -0
- package/rules/nextjs/optimization/references/optimization-patterns.md +190 -0
- package/rules/nextjs/rendering/SKILL.md +91 -0
- package/rules/nextjs/rendering/references/REFERENCE.md +13 -0
- package/rules/nextjs/rendering/references/rendering-modes.md +163 -0
- package/rules/nextjs/server-actions/SKILL.md +46 -0
- package/rules/nextjs/server-actions/references/REFERENCE.md +13 -0
- package/rules/nextjs/server-actions/references/action-patterns.md +188 -0
- package/rules/nextjs/server-components/SKILL.md +52 -0
- package/rules/nextjs/server-components/references/REFERENCE.md +13 -0
- package/rules/nextjs/server-components/references/component-patterns.md +175 -0
- package/rules/nextjs/state-management/SKILL.md +73 -0
- package/rules/nextjs/state-management/references/REFERENCE.md +13 -0
- package/rules/nextjs/state-management/references/state-patterns.md +218 -0
- package/rules/nextjs/styling/SKILL.md +31 -0
- package/rules/nextjs/styling/references/implementation.md +56 -0
- package/rules/react/component-patterns/SKILL.md +66 -0
- package/rules/react/component-patterns/references/REFERENCE.md +126 -0
- package/rules/react/hooks/SKILL.md +60 -0
- package/rules/react/hooks/references/REFERENCE.md +132 -0
- package/rules/react/hooks.rule.md +79 -0
- package/rules/react/performance/SKILL.md +69 -0
- package/rules/react/performance/references/REFERENCE.md +143 -0
- package/rules/react/security/SKILL.md +46 -0
- package/rules/react/security/references/REFERENCE.md +170 -0
- package/rules/react/state-management/SKILL.md +56 -0
- package/rules/react/state-management/references/REFERENCE.md +137 -0
- package/rules/react/testing/SKILL.md +45 -0
- package/rules/react/testing/references/REFERENCE.md +149 -0
- package/rules/react/tooling/SKILL.md +39 -0
- package/rules/react/typescript/SKILL.md +53 -0
- package/rules/rust/actix-web/SKILL.md +160 -0
- package/rules/rust/actix-web/references/REFERENCE.md +13 -0
- package/rules/rust/actix-web/references/handler-patterns.md +198 -0
- package/rules/rust/async-graphql/SKILL.md +228 -0
- package/rules/rust/async-graphql/references/REFERENCE.md +13 -0
- package/rules/rust/async-graphql/references/schema-patterns.md +215 -0
- package/rules/rust/axum/SKILL.md +161 -0
- package/rules/rust/axum/references/REFERENCE.md +14 -0
- package/rules/rust/axum/references/handler-patterns.md +97 -0
- package/rules/rust/bevy/SKILL.md +206 -0
- package/rules/rust/bevy/references/REFERENCE.md +13 -0
- package/rules/rust/bevy/references/ecs-patterns.md +226 -0
- package/rules/rust/clap/SKILL.md +217 -0
- package/rules/rust/clap/references/REFERENCE.md +13 -0
- package/rules/rust/clap/references/derive-patterns.md +205 -0
- package/rules/rust/core/SKILL.md +154 -0
- package/rules/rust/core/references/REFERENCE.md +14 -0
- package/rules/rust/core/references/error-handling.md +92 -0
- package/rules/rust/diesel-orm/SKILL.md +176 -0
- package/rules/rust/diesel-orm/references/REFERENCE.md +13 -0
- package/rules/rust/diesel-orm/references/schema-patterns.md +206 -0
- package/rules/rust/rocket/SKILL.md +182 -0
- package/rules/rust/rocket/references/REFERENCE.md +13 -0
- package/rules/rust/rocket/references/handler-patterns.md +209 -0
- package/rules/rust/sea-orm/SKILL.md +230 -0
- package/rules/rust/sea-orm/references/REFERENCE.md +13 -0
- package/rules/rust/sea-orm/references/entity-patterns.md +221 -0
- package/rules/rust/serde-serialization/SKILL.md +150 -0
- package/rules/rust/serde-serialization/references/REFERENCE.md +13 -0
- package/rules/rust/serde-serialization/references/serialization-patterns.md +199 -0
- package/rules/rust/sqlx-database/SKILL.md +140 -0
- package/rules/rust/sqlx-database/references/REFERENCE.md +13 -0
- package/rules/rust/sqlx-database/references/query-patterns.md +210 -0
- package/rules/rust/tauri/SKILL.md +180 -0
- package/rules/rust/tauri/references/REFERENCE.md +13 -0
- package/rules/rust/tauri/references/command-patterns.md +209 -0
- package/rules/rust/tokio-runtime/SKILL.md +167 -0
- package/rules/rust/tokio-runtime/references/REFERENCE.md +14 -0
- package/rules/rust/tokio-runtime/references/async-patterns.md +137 -0
- package/rules/rust/tokio-runtime/references/synchronization.md +152 -0
- package/rules/rust/tonic/SKILL.md +231 -0
- package/rules/rust/tonic/references/REFERENCE.md +13 -0
- package/rules/rust/tonic/references/service-patterns.md +213 -0
- package/rules/rust/tracing/SKILL.md +214 -0
- package/rules/rust/tracing/references/REFERENCE.md +13 -0
- package/rules/rust/tracing/references/instrumentation.md +187 -0
- package/rules/typescript/best-practices/SKILL.md +108 -0
- package/rules/typescript/best-practices/references/REFERENCE.md +68 -0
- package/rules/typescript/language/SKILL.md +72 -0
- package/rules/typescript/language/references/REFERENCE.md +67 -0
- package/rules/typescript/patterns.rule.md +85 -0
- package/rules/typescript/security/SKILL.md +59 -0
- package/rules/typescript/security/references/REFERENCE.md +113 -0
- package/rules/typescript/tooling/SKILL.md +52 -0
- package/rules/typescript/tooling/references/REFERENCE.md +110 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Tokio Runtime
|
|
3
|
+
description: Async runtime for Rust with task scheduling, I/O, and timers.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [rust, tokio, async, runtime]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/main.rs', '**/lib.rs']
|
|
8
|
+
keywords: [tokio, spawn, select, async, await]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Tokio Runtime Standards
|
|
12
|
+
|
|
13
|
+
## Runtime Setup
|
|
14
|
+
|
|
15
|
+
```rust
|
|
16
|
+
// Full runtime with all features
|
|
17
|
+
#[tokio::main]
|
|
18
|
+
async fn main() {
|
|
19
|
+
// Your async code
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Custom runtime configuration
|
|
23
|
+
#[tokio::main(flavor = "multi_thread", worker_threads = 4)]
|
|
24
|
+
async fn main() { }
|
|
25
|
+
|
|
26
|
+
// Current-thread runtime (single-threaded)
|
|
27
|
+
#[tokio::main(flavor = "current_thread")]
|
|
28
|
+
async fn main() { }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Task Spawning
|
|
32
|
+
|
|
33
|
+
```rust
|
|
34
|
+
use tokio::task;
|
|
35
|
+
|
|
36
|
+
// Spawn async task
|
|
37
|
+
let handle = tokio::spawn(async {
|
|
38
|
+
// Background work
|
|
39
|
+
expensive_computation().await
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Wait for result
|
|
43
|
+
let result = handle.await?;
|
|
44
|
+
|
|
45
|
+
// Spawn blocking task (CPU-bound work)
|
|
46
|
+
let result = task::spawn_blocking(|| {
|
|
47
|
+
// Blocking/CPU-intensive code
|
|
48
|
+
compute_hash(data)
|
|
49
|
+
}).await?;
|
|
50
|
+
|
|
51
|
+
// Detached task (fire and forget)
|
|
52
|
+
tokio::spawn(async {
|
|
53
|
+
log_event(event).await;
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Concurrency Patterns
|
|
58
|
+
|
|
59
|
+
```rust
|
|
60
|
+
use tokio::{select, join, time};
|
|
61
|
+
|
|
62
|
+
// Run multiple futures concurrently
|
|
63
|
+
let (a, b, c) = join!(task_a(), task_b(), task_c());
|
|
64
|
+
|
|
65
|
+
// Race futures, cancel losers
|
|
66
|
+
select! {
|
|
67
|
+
result = fetch_primary() => handle_primary(result),
|
|
68
|
+
result = fetch_backup() => handle_backup(result),
|
|
69
|
+
_ = time::sleep(Duration::from_secs(5)) => timeout_error(),
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Timeout wrapper
|
|
73
|
+
let result = time::timeout(
|
|
74
|
+
Duration::from_secs(30),
|
|
75
|
+
long_running_task()
|
|
76
|
+
).await?;
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Synchronization
|
|
80
|
+
|
|
81
|
+
```rust
|
|
82
|
+
use tokio::sync::{Mutex, RwLock, mpsc, broadcast, oneshot};
|
|
83
|
+
|
|
84
|
+
// Async mutex (allows holding across await)
|
|
85
|
+
let data = Arc::new(Mutex::new(vec![]));
|
|
86
|
+
{
|
|
87
|
+
let mut guard = data.lock().await;
|
|
88
|
+
guard.push(item);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// RwLock for read-heavy workloads
|
|
92
|
+
let cache = Arc::new(RwLock::new(HashMap::new()));
|
|
93
|
+
let value = cache.read().await.get(&key);
|
|
94
|
+
|
|
95
|
+
// Channels
|
|
96
|
+
let (tx, mut rx) = mpsc::channel(100);
|
|
97
|
+
tx.send(message).await?;
|
|
98
|
+
while let Some(msg) = rx.recv().await {
|
|
99
|
+
process(msg);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Oneshot for single response
|
|
103
|
+
let (tx, rx) = oneshot::channel();
|
|
104
|
+
tokio::spawn(async move { tx.send(result) });
|
|
105
|
+
let response = rx.await?;
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## I/O Operations
|
|
109
|
+
|
|
110
|
+
```rust
|
|
111
|
+
use tokio::{fs, io::{AsyncReadExt, AsyncWriteExt}, net::TcpListener};
|
|
112
|
+
|
|
113
|
+
// File I/O
|
|
114
|
+
let content = fs::read_to_string("file.txt").await?;
|
|
115
|
+
fs::write("output.txt", data).await?;
|
|
116
|
+
|
|
117
|
+
// TCP server
|
|
118
|
+
let listener = TcpListener::bind("127.0.0.1:8080").await?;
|
|
119
|
+
loop {
|
|
120
|
+
let (socket, _) = listener.accept().await?;
|
|
121
|
+
tokio::spawn(handle_connection(socket));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Buffered I/O
|
|
125
|
+
use tokio::io::{BufReader, BufWriter};
|
|
126
|
+
let reader = BufReader::new(file);
|
|
127
|
+
let mut lines = reader.lines();
|
|
128
|
+
while let Some(line) = lines.next_line().await? {
|
|
129
|
+
process(line);
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Graceful Shutdown
|
|
134
|
+
|
|
135
|
+
```rust
|
|
136
|
+
use tokio::signal;
|
|
137
|
+
|
|
138
|
+
async fn shutdown_signal() {
|
|
139
|
+
let ctrl_c = async {
|
|
140
|
+
signal::ctrl_c().await.expect("Failed to install Ctrl+C handler");
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
#[cfg(unix)]
|
|
144
|
+
let terminate = async {
|
|
145
|
+
signal::unix::signal(signal::unix::SignalKind::terminate())
|
|
146
|
+
.expect("Failed to install SIGTERM handler")
|
|
147
|
+
.recv()
|
|
148
|
+
.await;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
#[cfg(not(unix))]
|
|
152
|
+
let terminate = std::future::pending::<()>();
|
|
153
|
+
|
|
154
|
+
tokio::select! {
|
|
155
|
+
_ = ctrl_c => {},
|
|
156
|
+
_ = terminate => {},
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Best Practices
|
|
162
|
+
|
|
163
|
+
1. **Never block**: Use `spawn_blocking` for CPU-bound or blocking I/O
|
|
164
|
+
2. **Channel sizing**: Size mpsc channels appropriately to avoid backpressure
|
|
165
|
+
3. **Error propagation**: Use `JoinHandle::await?` to propagate panics
|
|
166
|
+
4. **Timeouts**: Always add timeouts to network operations
|
|
167
|
+
5. **Tracing**: Use `tokio-console` for debugging async issues
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Tokio Runtime References
|
|
2
|
+
|
|
3
|
+
## References
|
|
4
|
+
|
|
5
|
+
- [**Async Patterns**](async-patterns.md) - Spawning, joining, timeouts, select
|
|
6
|
+
- [**Synchronization**](synchronization.md) - Mutex, RwLock, channels, semaphores
|
|
7
|
+
|
|
8
|
+
## Quick Checks
|
|
9
|
+
|
|
10
|
+
- [ ] Use #[tokio::main] for async entry point
|
|
11
|
+
- [ ] Spawn tasks for concurrent work
|
|
12
|
+
- [ ] Use tokio::select! for racing futures
|
|
13
|
+
- [ ] Prefer tokio::sync over std::sync in async code
|
|
14
|
+
- [ ] Graceful shutdown with signal handling
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Tokio Async Patterns
|
|
2
|
+
|
|
3
|
+
## Task Spawning
|
|
4
|
+
|
|
5
|
+
```rust
|
|
6
|
+
use tokio::task;
|
|
7
|
+
|
|
8
|
+
// Spawn background task
|
|
9
|
+
let handle = tokio::spawn(async {
|
|
10
|
+
expensive_computation().await
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// Wait for result
|
|
14
|
+
let result = handle.await?;
|
|
15
|
+
|
|
16
|
+
// Spawn blocking (for CPU-bound or sync code)
|
|
17
|
+
let result = task::spawn_blocking(|| {
|
|
18
|
+
std::thread::sleep(Duration::from_secs(1));
|
|
19
|
+
"done"
|
|
20
|
+
}).await?;
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Concurrent Execution
|
|
24
|
+
|
|
25
|
+
```rust
|
|
26
|
+
use tokio::join;
|
|
27
|
+
use futures::future::join_all;
|
|
28
|
+
|
|
29
|
+
// Run multiple futures concurrently
|
|
30
|
+
let (user, orders, prefs) = tokio::join!(
|
|
31
|
+
fetch_user(id),
|
|
32
|
+
fetch_orders(id),
|
|
33
|
+
fetch_preferences(id),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// Run collection of futures
|
|
37
|
+
let futures = ids.iter().map(|id| fetch_user(*id));
|
|
38
|
+
let users: Vec<User> = join_all(futures).await;
|
|
39
|
+
|
|
40
|
+
// Try join - fail fast on first error
|
|
41
|
+
let (user, orders) = tokio::try_join!(
|
|
42
|
+
fetch_user(id),
|
|
43
|
+
fetch_orders(id),
|
|
44
|
+
)?;
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Select and Racing
|
|
48
|
+
|
|
49
|
+
```rust
|
|
50
|
+
use tokio::{select, time::timeout};
|
|
51
|
+
|
|
52
|
+
// Race multiple futures
|
|
53
|
+
select! {
|
|
54
|
+
result = fetch_from_primary() => {
|
|
55
|
+
println!("Primary: {:?}", result);
|
|
56
|
+
}
|
|
57
|
+
result = fetch_from_backup() => {
|
|
58
|
+
println!("Backup: {:?}", result);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Timeout
|
|
63
|
+
match timeout(Duration::from_secs(5), long_operation()).await {
|
|
64
|
+
Ok(result) => println!("Completed: {:?}", result),
|
|
65
|
+
Err(_) => println!("Timed out"),
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Select with cancellation
|
|
69
|
+
let mut interval = tokio::time::interval(Duration::from_secs(1));
|
|
70
|
+
loop {
|
|
71
|
+
select! {
|
|
72
|
+
_ = interval.tick() => {
|
|
73
|
+
println!("tick");
|
|
74
|
+
}
|
|
75
|
+
_ = shutdown_signal() => {
|
|
76
|
+
println!("shutting down");
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Channels
|
|
84
|
+
|
|
85
|
+
```rust
|
|
86
|
+
use tokio::sync::{mpsc, oneshot, broadcast};
|
|
87
|
+
|
|
88
|
+
// MPSC - multiple producers, single consumer
|
|
89
|
+
let (tx, mut rx) = mpsc::channel(100);
|
|
90
|
+
|
|
91
|
+
tokio::spawn(async move {
|
|
92
|
+
tx.send("hello").await.unwrap();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
while let Some(msg) = rx.recv().await {
|
|
96
|
+
println!("Got: {}", msg);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Oneshot - single value
|
|
100
|
+
let (tx, rx) = oneshot::channel();
|
|
101
|
+
tx.send("value").unwrap();
|
|
102
|
+
let value = rx.await?;
|
|
103
|
+
|
|
104
|
+
// Broadcast - multiple consumers
|
|
105
|
+
let (tx, _) = broadcast::channel(16);
|
|
106
|
+
let mut rx1 = tx.subscribe();
|
|
107
|
+
let mut rx2 = tx.subscribe();
|
|
108
|
+
tx.send("broadcast")?;
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Graceful Shutdown
|
|
112
|
+
|
|
113
|
+
```rust
|
|
114
|
+
use tokio::signal;
|
|
115
|
+
|
|
116
|
+
async fn shutdown_signal() {
|
|
117
|
+
let ctrl_c = async {
|
|
118
|
+
signal::ctrl_c().await.expect("failed to listen for ctrl+c");
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
#[cfg(unix)]
|
|
122
|
+
let terminate = async {
|
|
123
|
+
signal::unix::signal(signal::unix::SignalKind::terminate())
|
|
124
|
+
.expect("failed to listen for terminate")
|
|
125
|
+
.recv()
|
|
126
|
+
.await;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
#[cfg(not(unix))]
|
|
130
|
+
let terminate = std::future::pending::<()>();
|
|
131
|
+
|
|
132
|
+
tokio::select! {
|
|
133
|
+
_ = ctrl_c => {},
|
|
134
|
+
_ = terminate => {},
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Tokio Synchronization
|
|
2
|
+
|
|
3
|
+
## Mutex
|
|
4
|
+
|
|
5
|
+
```rust
|
|
6
|
+
use tokio::sync::Mutex;
|
|
7
|
+
use std::sync::Arc;
|
|
8
|
+
|
|
9
|
+
async fn shared_state() {
|
|
10
|
+
let counter = Arc::new(Mutex::new(0));
|
|
11
|
+
|
|
12
|
+
let mut handles = vec![];
|
|
13
|
+
|
|
14
|
+
for _ in 0..10 {
|
|
15
|
+
let counter = Arc::clone(&counter);
|
|
16
|
+
let handle = tokio::spawn(async move {
|
|
17
|
+
let mut lock = counter.lock().await;
|
|
18
|
+
*lock += 1;
|
|
19
|
+
});
|
|
20
|
+
handles.push(handle);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
for handle in handles {
|
|
24
|
+
handle.await.unwrap();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
println!("Counter: {}", *counter.lock().await);
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## RwLock
|
|
32
|
+
|
|
33
|
+
```rust
|
|
34
|
+
use tokio::sync::RwLock;
|
|
35
|
+
use std::sync::Arc;
|
|
36
|
+
|
|
37
|
+
struct Cache {
|
|
38
|
+
data: Arc<RwLock<HashMap<String, String>>>,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
impl Cache {
|
|
42
|
+
async fn get(&self, key: &str) -> Option<String> {
|
|
43
|
+
let read_lock = self.data.read().await;
|
|
44
|
+
read_lock.get(key).cloned()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async fn set(&self, key: String, value: String) {
|
|
48
|
+
let mut write_lock = self.data.write().await;
|
|
49
|
+
write_lock.insert(key, value);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Semaphore
|
|
55
|
+
|
|
56
|
+
```rust
|
|
57
|
+
use tokio::sync::Semaphore;
|
|
58
|
+
use std::sync::Arc;
|
|
59
|
+
|
|
60
|
+
async fn limited_concurrency() {
|
|
61
|
+
let semaphore = Arc::new(Semaphore::new(3)); // Max 3 concurrent
|
|
62
|
+
|
|
63
|
+
let mut handles = vec![];
|
|
64
|
+
|
|
65
|
+
for i in 0..10 {
|
|
66
|
+
let permit = semaphore.clone().acquire_owned().await.unwrap();
|
|
67
|
+
let handle = tokio::spawn(async move {
|
|
68
|
+
println!("Task {} started", i);
|
|
69
|
+
tokio::time::sleep(Duration::from_secs(1)).await;
|
|
70
|
+
println!("Task {} done", i);
|
|
71
|
+
drop(permit); // Release when done
|
|
72
|
+
});
|
|
73
|
+
handles.push(handle);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
for handle in handles {
|
|
77
|
+
handle.await.unwrap();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Notify
|
|
83
|
+
|
|
84
|
+
```rust
|
|
85
|
+
use tokio::sync::Notify;
|
|
86
|
+
use std::sync::Arc;
|
|
87
|
+
|
|
88
|
+
async fn wait_for_signal() {
|
|
89
|
+
let notify = Arc::new(Notify::new());
|
|
90
|
+
|
|
91
|
+
let notify_clone = notify.clone();
|
|
92
|
+
tokio::spawn(async move {
|
|
93
|
+
tokio::time::sleep(Duration::from_secs(1)).await;
|
|
94
|
+
notify_clone.notify_one(); // Wake one waiter
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
notify.notified().await; // Wait for notification
|
|
98
|
+
println!("Received signal!");
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Watch Channel
|
|
103
|
+
|
|
104
|
+
```rust
|
|
105
|
+
use tokio::sync::watch;
|
|
106
|
+
|
|
107
|
+
async fn config_updates() {
|
|
108
|
+
let (tx, mut rx) = watch::channel(Config::default());
|
|
109
|
+
|
|
110
|
+
// Watcher task
|
|
111
|
+
tokio::spawn(async move {
|
|
112
|
+
while rx.changed().await.is_ok() {
|
|
113
|
+
let config = rx.borrow();
|
|
114
|
+
println!("Config updated: {:?}", *config);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Update config
|
|
119
|
+
tx.send(Config { debug: true }).unwrap();
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Barrier
|
|
124
|
+
|
|
125
|
+
```rust
|
|
126
|
+
use tokio::sync::Barrier;
|
|
127
|
+
use std::sync::Arc;
|
|
128
|
+
|
|
129
|
+
async fn sync_tasks() {
|
|
130
|
+
let barrier = Arc::new(Barrier::new(5));
|
|
131
|
+
|
|
132
|
+
let mut handles = vec![];
|
|
133
|
+
|
|
134
|
+
for i in 0..5 {
|
|
135
|
+
let barrier = barrier.clone();
|
|
136
|
+
let handle = tokio::spawn(async move {
|
|
137
|
+
println!("Task {} preparing", i);
|
|
138
|
+
tokio::time::sleep(Duration::from_millis(i as u64 * 100)).await;
|
|
139
|
+
|
|
140
|
+
// Wait for all tasks
|
|
141
|
+
barrier.wait().await;
|
|
142
|
+
|
|
143
|
+
println!("Task {} proceeding", i);
|
|
144
|
+
});
|
|
145
|
+
handles.push(handle);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
for handle in handles {
|
|
149
|
+
handle.await.unwrap();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Tonic gRPC
|
|
3
|
+
description: gRPC framework for Rust built on Tokio and Tower.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [rust, tonic, grpc, protobuf, rpc]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/*.proto', 'build.rs']
|
|
8
|
+
keywords: [tonic, prost, Request, Response, Server, Channel]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Tonic gRPC Standards
|
|
12
|
+
|
|
13
|
+
## Proto Definition
|
|
14
|
+
|
|
15
|
+
```protobuf
|
|
16
|
+
// proto/hello.proto
|
|
17
|
+
syntax = "proto3";
|
|
18
|
+
package hello;
|
|
19
|
+
|
|
20
|
+
service Greeter {
|
|
21
|
+
rpc SayHello (HelloRequest) returns (HelloReply);
|
|
22
|
+
rpc SayHelloStream (HelloRequest) returns (stream HelloReply);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
message HelloRequest {
|
|
26
|
+
string name = 1;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
message HelloReply {
|
|
30
|
+
string message = 1;
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Build Configuration
|
|
35
|
+
|
|
36
|
+
```rust
|
|
37
|
+
// build.rs
|
|
38
|
+
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
39
|
+
tonic_build::compile_protos("proto/hello.proto")?;
|
|
40
|
+
Ok(())
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```toml
|
|
45
|
+
# Cargo.toml
|
|
46
|
+
[dependencies]
|
|
47
|
+
tonic = "0.10"
|
|
48
|
+
prost = "0.12"
|
|
49
|
+
tokio = { version = "1", features = ["full"] }
|
|
50
|
+
|
|
51
|
+
[build-dependencies]
|
|
52
|
+
tonic-build = "0.10"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Server Implementation
|
|
56
|
+
|
|
57
|
+
```rust
|
|
58
|
+
use tonic::{transport::Server, Request, Response, Status};
|
|
59
|
+
use hello::greeter_server::{Greeter, GreeterServer};
|
|
60
|
+
use hello::{HelloReply, HelloRequest};
|
|
61
|
+
|
|
62
|
+
pub mod hello {
|
|
63
|
+
tonic::include_proto!("hello");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#[derive(Default)]
|
|
67
|
+
pub struct MyGreeter {}
|
|
68
|
+
|
|
69
|
+
#[tonic::async_trait]
|
|
70
|
+
impl Greeter for MyGreeter {
|
|
71
|
+
async fn say_hello(
|
|
72
|
+
&self,
|
|
73
|
+
request: Request<HelloRequest>,
|
|
74
|
+
) -> Result<Response<HelloReply>, Status> {
|
|
75
|
+
let name = request.into_inner().name;
|
|
76
|
+
let reply = HelloReply {
|
|
77
|
+
message: format!("Hello, {}!", name),
|
|
78
|
+
};
|
|
79
|
+
Ok(Response::new(reply))
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#[tokio::main]
|
|
84
|
+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
85
|
+
let addr = "[::1]:50051".parse()?;
|
|
86
|
+
let greeter = MyGreeter::default();
|
|
87
|
+
|
|
88
|
+
Server::builder()
|
|
89
|
+
.add_service(GreeterServer::new(greeter))
|
|
90
|
+
.serve(addr)
|
|
91
|
+
.await?;
|
|
92
|
+
|
|
93
|
+
Ok(())
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Client
|
|
98
|
+
|
|
99
|
+
```rust
|
|
100
|
+
use hello::greeter_client::GreeterClient;
|
|
101
|
+
use hello::HelloRequest;
|
|
102
|
+
|
|
103
|
+
#[tokio::main]
|
|
104
|
+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
105
|
+
let mut client = GreeterClient::connect("http://[::1]:50051").await?;
|
|
106
|
+
|
|
107
|
+
let request = tonic::Request::new(HelloRequest {
|
|
108
|
+
name: "World".into(),
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
let response = client.say_hello(request).await?;
|
|
112
|
+
println!("Response: {:?}", response);
|
|
113
|
+
|
|
114
|
+
Ok(())
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Streaming
|
|
119
|
+
|
|
120
|
+
```rust
|
|
121
|
+
use tokio_stream::wrappers::ReceiverStream;
|
|
122
|
+
use futures_util::StreamExt;
|
|
123
|
+
|
|
124
|
+
#[tonic::async_trait]
|
|
125
|
+
impl Greeter for MyGreeter {
|
|
126
|
+
// Server streaming
|
|
127
|
+
type SayHelloStreamStream = ReceiverStream<Result<HelloReply, Status>>;
|
|
128
|
+
|
|
129
|
+
async fn say_hello_stream(
|
|
130
|
+
&self,
|
|
131
|
+
request: Request<HelloRequest>,
|
|
132
|
+
) -> Result<Response<Self::SayHelloStreamStream>, Status> {
|
|
133
|
+
let (tx, rx) = tokio::sync::mpsc::channel(4);
|
|
134
|
+
let name = request.into_inner().name;
|
|
135
|
+
|
|
136
|
+
tokio::spawn(async move {
|
|
137
|
+
for i in 0..5 {
|
|
138
|
+
tx.send(Ok(HelloReply {
|
|
139
|
+
message: format!("Hello #{}, {}!", i, name),
|
|
140
|
+
})).await.unwrap();
|
|
141
|
+
tokio::time::sleep(Duration::from_secs(1)).await;
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
Ok(Response::new(ReceiverStream::new(rx)))
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Client receiving stream
|
|
150
|
+
let mut stream = client.say_hello_stream(request).await?.into_inner();
|
|
151
|
+
while let Some(reply) = stream.next().await {
|
|
152
|
+
println!("Reply: {:?}", reply?);
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Interceptors
|
|
157
|
+
|
|
158
|
+
```rust
|
|
159
|
+
use tonic::{Request, Status};
|
|
160
|
+
|
|
161
|
+
fn auth_interceptor(req: Request<()>) -> Result<Request<()>, Status> {
|
|
162
|
+
let token = req.metadata()
|
|
163
|
+
.get("authorization")
|
|
164
|
+
.ok_or_else(|| Status::unauthenticated("No token"))?
|
|
165
|
+
.to_str()
|
|
166
|
+
.map_err(|_| Status::unauthenticated("Invalid token"))?;
|
|
167
|
+
|
|
168
|
+
if !validate_token(token) {
|
|
169
|
+
return Err(Status::unauthenticated("Invalid token"));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
Ok(req)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Apply interceptor
|
|
176
|
+
let greeter = GreeterServer::with_interceptor(MyGreeter::default(), auth_interceptor);
|
|
177
|
+
|
|
178
|
+
// Client with interceptor
|
|
179
|
+
let channel = Channel::from_static("http://[::1]:50051").connect().await?;
|
|
180
|
+
let client = GreeterClient::with_interceptor(channel, |mut req: Request<()>| {
|
|
181
|
+
req.metadata_mut().insert("authorization", "Bearer token".parse().unwrap());
|
|
182
|
+
Ok(req)
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Error Handling
|
|
187
|
+
|
|
188
|
+
```rust
|
|
189
|
+
use tonic::Status;
|
|
190
|
+
|
|
191
|
+
async fn my_method(&self, request: Request<Req>) -> Result<Response<Resp>, Status> {
|
|
192
|
+
let data = fetch_data()
|
|
193
|
+
.await
|
|
194
|
+
.map_err(|e| Status::internal(format!("DB error: {}", e)))?;
|
|
195
|
+
|
|
196
|
+
if data.is_empty() {
|
|
197
|
+
return Err(Status::not_found("Resource not found"));
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Status codes: ok, cancelled, unknown, invalid_argument,
|
|
201
|
+
// deadline_exceeded, not_found, already_exists, permission_denied,
|
|
202
|
+
// resource_exhausted, failed_precondition, aborted, out_of_range,
|
|
203
|
+
// unimplemented, internal, unavailable, data_loss, unauthenticated
|
|
204
|
+
|
|
205
|
+
Ok(Response::new(resp))
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## TLS
|
|
210
|
+
|
|
211
|
+
```rust
|
|
212
|
+
use tonic::transport::{Certificate, Identity, ServerTlsConfig};
|
|
213
|
+
|
|
214
|
+
let cert = std::fs::read_to_string("server.crt")?;
|
|
215
|
+
let key = std::fs::read_to_string("server.key")?;
|
|
216
|
+
let identity = Identity::from_pem(cert, key);
|
|
217
|
+
|
|
218
|
+
Server::builder()
|
|
219
|
+
.tls_config(ServerTlsConfig::new().identity(identity))?
|
|
220
|
+
.add_service(service)
|
|
221
|
+
.serve(addr)
|
|
222
|
+
.await?;
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Best Practices
|
|
226
|
+
|
|
227
|
+
1. **Proto first**: Design API in proto files
|
|
228
|
+
2. **Error codes**: Use appropriate Status codes
|
|
229
|
+
3. **Streaming**: Use for large data or real-time
|
|
230
|
+
4. **Interceptors**: Auth, logging, metrics
|
|
231
|
+
5. **Deadlines**: Set timeouts on client calls
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Tonic gRPC References
|
|
2
|
+
|
|
3
|
+
## References
|
|
4
|
+
|
|
5
|
+
- [**Service Patterns**](service-patterns.md) - Proto, server, client implementation
|
|
6
|
+
|
|
7
|
+
## Quick Checks
|
|
8
|
+
|
|
9
|
+
- [ ] Use tonic-build for code generation
|
|
10
|
+
- [ ] Implement generated service traits
|
|
11
|
+
- [ ] Streaming support (server, client, bidirectional)
|
|
12
|
+
- [ ] Interceptors for middleware
|
|
13
|
+
- [ ] Proper error handling with tonic::Status
|