20 releases (4 breaking)
Uses new Rust 2024
| new 0.5.4 | Mar 12, 2026 |
|---|---|
| 0.5.2 | Mar 11, 2026 |
| 0.4.1 | Mar 9, 2026 |
| 0.3.2 | Mar 6, 2026 |
| 0.1.0 | Jan 25, 2026 |
#1523 in Procedural macros
545 downloads per month
Used in 25 crates
(18 directly)
105KB
2K
SLoC
ModKit Macros
This crate contains the proc-macros used by modkit.
In most crates you should import macros from modkit (it re-exports them):
use modkit::{module, lifecycle};
If you depend on cf-modkit-macros directly, the Rust crate name is modkit_macros:
use modkit_macros::{module, lifecycle, grpc_client};
Macros
#[module(...)]
Attribute macro for declaring a ModKit module and registering it via inventory.
Parameters:
name = "..."(required)deps = ["..."](optional)capabilities = [..](optional)- Allowed values:
db,rest,rest_host,stateful,system,grpc_hub,grpc
- Allowed values:
ctor = <expr>(optional)- If omitted, the macro uses
Default::default()(so your type must implementDefault).
- If omitted, the macro uses
client = <path::to::Trait>(optional)- Current behavior: compile-time checks (object-safe +
Send + Sync + 'static) and definesMODULE_NAME. - It does not generate ClientHub registration helpers.
- Current behavior: compile-time checks (object-safe +
lifecycle(...)(optional, used forstatefulmodules)entry = "serve"(default:"serve")stop_timeout = "30s"(default:"30s"; supportsms,s,m,h)await_ready/await_ready = true|false(default:false)
Example (stateful, no ready gating):
use modkit::module;
use tokio_util::sync::CancellationToken;
#[derive(Default)]
#[module(
name = "demo",
capabilities = [stateful],
lifecycle(entry = "serve", stop_timeout = "1s")
)]
pub struct Demo;
impl Demo {
async fn serve(&self, _cancel: CancellationToken) -> anyhow::Result<()> {
Ok(())
}
}
Example (stateful, with ready gating):
use modkit::module;
use tokio_util::sync::CancellationToken;
#[derive(Default)]
#[module(
name = "demo_ready",
capabilities = [stateful],
lifecycle(entry = "serve", await_ready, stop_timeout = "1s")
)]
pub struct DemoReady;
impl DemoReady {
async fn serve(
&self,
_cancel: CancellationToken,
_ready: modkit::lifecycle::ReadySignal,
) -> anyhow::Result<()> {
Ok(())
}
}
#[lifecycle(...)]
Attribute macro applied to an impl block. It generates a modkit::lifecycle::Runnable impl and an into_module() helper.
Parameters:
method = "serve"(required)stop_timeout = "30s"(optional)await_ready/await_ready = true|false(optional)
Notes:
- If
await_readyis enabled, the runner method must accept aReadySignalas the 3rd argument.
#[grpc_client(...)]
Attribute macro applied to an empty struct. It generates a wrapper struct with:
connect(uri)andconnect_with_config(uri, cfg)usingmodkit_transport_grpc::client::connect_with_stackfrom_channel(Channel)inner_mut()- a compile-time check that the generated client type implements the API trait
Parameters:
api = "path::to::Trait"(required; string literal path)tonic = "path::to::TonicClient<Channel>"(required; string literal type)package = "..."(optional; currently unused)
Minimal example:
use modkit::grpc_client;
#[grpc_client(
api = "crate::MyApi",
tonic = "my_proto::my_service_client::MyServiceClient<tonic::transport::Channel>",
)]
pub struct MyGrpcClient;
// You still implement `MyApi` manually for the generated client type.
See also
Dependencies
~185–570KB
~13K SLoC