Skip to content

Commit 5d74ed4

Browse files
Create an AsyncRuntime trait (#2664)
* Fixed #2506, creating an AsyncRuntime trait which can be used by customers to replace the async runtime * CI pipeline fixes * wasm32 clippy fixes * Fixed typo * Minor test cleanup * PR feedback * PR feedback * doctest fixes * Added text to README.md describing how to set the async runtime used by the SDK * Update sdk/core/azure_core/CHANGELOG.md Co-authored-by: Heath Stewart <heaths@outlook.com> * Policheck feedback --------- Co-authored-by: Heath Stewart <heaths@outlook.com>
1 parent 9f46e84 commit 5d74ed4

File tree

14 files changed

+362
-197
lines changed

14 files changed

+362
-197
lines changed

sdk/core/azure_core/CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
### Features Added
66

7+
- Added `get_async_runtime()` and `set_async_runtime()` to allow customers to replace
8+
the asynchronous runtime used by the Azure SDK.
9+
710
### Breaking Changes
811

912
### Bugs Fixed
@@ -16,7 +19,7 @@
1619

1720
- Added `#[safe]` attribute helper for `SafeDebug` derive macro to show or hide types and members as appropriate.
1821
- Added `Page` trait to facilitate the `ItemIterator`.
19-
- Added `PageIterator` to asynchronously iterator all pages.
22+
- Added `PageIterator` to asynchronously iterate all pages.
2023

2124
### Breaking Changes
2225

sdk/core/azure_core/README.md

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ you can find the [package on crates.io][Package (crates.io)].
2020

2121
The main shared concepts of `azure_core` - and Azure SDK libraries using `azure_core` - include:
2222

23-
- Configuring service clients, e.g. configuring retries, logging (`ClientOptions`).
24-
- Accessing HTTP response details (`Response<T>`).
25-
- Paging and asynchronous streams (`Pager<T>`).
26-
- Errors from service requests in a consistent fashion. (`azure_core::Error`).
27-
- Customizing requests (`ClientOptions`).
28-
- Abstractions for representing Azure SDK credentials. (`TokenCredentials`).
23+
- Configuring service clients, e.g. configuring retries, logging (`ClientOptions`).
24+
- Accessing HTTP response details (`Response<T>`).
25+
- Paging and asynchronous streams (`Pager<T>`).
26+
- Errors from service requests in a consistent fashion. (`azure_core::Error`).
27+
- Customizing requests (`ClientOptions`).
28+
- Abstractions for representing Azure SDK credentials. (`TokenCredentials`).
2929

3030
### Thread safety
3131

@@ -34,23 +34,25 @@ We guarantee that all client instance methods are thread-safe and independent of
3434
### Additional concepts
3535

3636
<!-- CLIENT COMMON BAR -->
37+
3738
[Client options](#configuring-service-clients-using-clientoptions) |
3839
[Accessing the response](#accessing-http-response-details-using-responset) |
3940
[Handling Errors Results](#handling-errors-results) |
4041
[Consuming Service Methods Returning `Pager<T>`](#consuming-service-methods-returning-pagert)
42+
4143
<!-- CLIENT COMMON BAR -->
4244

4345
## Features
4446

45-
- `debug`: enables extra information for developers e.g., emitting all fields in `std::fmt::Debug` implementation.
46-
- `hmac_openssl`: configures HMAC using `openssl`.
47-
- `hmac_rust`: configures HMAC using pure Rust.
48-
- `reqwest` (default): enables and sets `reqwest` as the default `HttpClient`. Enables `reqwest`'s `native-tls` feature.
49-
- `reqwest_deflate` (default): enables deflate compression for `reqwest`.
50-
- `reqwest_gzip` (default): enables gzip compression for `reqwest`.
51-
- `reqwest_rustls`: enables `reqwest`'s `rustls-tls-native-roots-no-provider` feature,
52-
- `tokio`: enables and sets `tokio` as the default async runtime.
53-
- `xml`: enables XML support.
47+
- `debug`: enables extra information for developers e.g., emitting all fields in `std::fmt::Debug` implementation.
48+
- `hmac_openssl`: configures HMAC using `openssl`.
49+
- `hmac_rust`: configures HMAC using pure Rust.
50+
- `reqwest` (default): enables and sets `reqwest` as the default `HttpClient`. Enables `reqwest`'s `native-tls` feature.
51+
- `reqwest_deflate` (default): enables deflate compression for `reqwest`.
52+
- `reqwest_gzip` (default): enables gzip compression for `reqwest`.
53+
- `reqwest_rustls`: enables `reqwest`'s `rustls-tls-native-roots-no-provider` feature,
54+
- `tokio`: enables and sets `tokio` as the default async runtime.
55+
- `xml`: enables XML support.
5456

5557
## Examples
5658

@@ -244,6 +246,36 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
244246
}
245247
```
246248

249+
### Replacing the async runtime
250+
251+
Internally, the Azure SDK uses either the `tokio` async runtime (with the `tokio` feature), or it implements asynchronous functionality using functions in the `std` namespace.
252+
253+
If your application uses a different asynchronous runtime, you can replace the asynchronous runtime used for internal functions by providing your own implementation of the `azure_core::async_runtime::AsyncRuntime` trait.
254+
255+
You provide the implementation by calling the `set_async_runtime()` API:
256+
257+
```rust no_run
258+
use azure_core::async_runtime::{
259+
set_async_runtime, AsyncRuntime, TaskFuture, SpawnedTask};
260+
use std::sync::Arc;
261+
use futures::FutureExt;
262+
263+
struct CustomRuntime;
264+
265+
impl AsyncRuntime for CustomRuntime {
266+
fn spawn(&self, f: TaskFuture) -> SpawnedTask {
267+
unimplemented!("Custom spawn not implemented");
268+
}
269+
fn sleep(&self, duration: std::time::Duration) -> TaskFuture {
270+
unimplemented!("Custom sleep not implemented");
271+
}
272+
}
273+
274+
set_async_runtime(Arc::new(CustomRuntime)).expect("Failed to set async runtime");
275+
```
276+
277+
There can only be one async runtime set in a given process, so attempts to set the async runtime multiple times will fail.
278+
247279
## Troubleshooting
248280

249281
### Logging

sdk/core/azure_core/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ pub mod fs;
1515
pub mod hmac;
1616
pub mod http;
1717
pub mod process;
18-
pub mod task;
1918

2019
#[cfg(feature = "test")]
2120
pub mod test;
@@ -24,7 +23,7 @@ pub use constants::*;
2423

2524
// Re-export modules in typespec_client_core such that azure_core-based crates don't need to reference it directly.
2625
pub use typespec_client_core::{
27-
base64, create_enum, create_extensible_enum, date,
26+
async_runtime, base64, create_enum, create_extensible_enum, date,
2827
error::{self, Error, Result},
2928
fmt, json, sleep, stream, Bytes, Uuid,
3029
};

sdk/core/azure_core/src/task/tokio_spawn.rs

Lines changed: 0 additions & 20 deletions
This file was deleted.

sdk/eventhubs/azure_messaging_eventhubs/src/common/authorizer.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ use super::recoverable_connection::RecoverableConnection;
55
use crate::error::{ErrorKind, EventHubsError};
66
use async_lock::Mutex as AsyncMutex;
77
use azure_core::{
8+
async_runtime::{get_async_runtime, SpawnedTask},
89
credentials::{AccessToken, TokenCredential},
910
error::ErrorKind as AzureErrorKind,
1011
http::Url,
11-
task::{new_task_spawner, SpawnedTask},
1212
Result,
1313
};
1414
use azure_core_amqp::AmqpClaimsBasedSecurityApis as _;
@@ -113,8 +113,8 @@ impl Authorizer {
113113
self.authorization_refresher.get_or_init(|| {
114114
debug!("Starting authorization refresh task.");
115115
let self_clone = self.clone();
116-
let spawner = new_task_spawner();
117-
spawner.spawn(Box::pin(self_clone.refresh_tokens_task()))
116+
let async_runtime = get_async_runtime();
117+
async_runtime.spawn(Box::pin(self_clone.refresh_tokens_task()))
118118
});
119119
} else {
120120
debug!("Token already exists for path: {path}");

sdk/typespec/typespec_client_core/CHANGELOG.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
### Features Added
66

7+
- Added `get_async_runtime()` and `set_async_runtime()` to allow customers to replace
8+
the default asynchronous runtime with another.
9+
710
### Breaking Changes
811

912
### Bugs Fixed
@@ -28,29 +31,29 @@
2831

2932
### Breaking Changes
3033

31-
- The `reqwest_rustls` feature enables `rustls-tls-native-roots-no-provider` instead of `rustls-tls-native-roots` to remove the dependency on the `ring` crate.
34+
- The `reqwest_rustls` feature enables `rustls-tls-native-roots-no-provider` instead of `rustls-tls-native-roots` to remove the dependency on the `ring` crate.
3235

3336
### Other Changes
3437

35-
- Deriving `SafeDebug` formats non-exhaustive types by default. Enable `debug` feature to format normal `Debug` output.
36-
- Updated dependencies.
38+
- Deriving `SafeDebug` formats non-exhaustive types by default. Enable `debug` feature to format normal `Debug` output.
39+
- Updated dependencies.
3740

3841
## 0.2.0 (2025-04-08)
3942

4043
### Breaking Changes
4144

42-
- Consolidated all the `tokio` features into a single feature named `tokio`. Traits remain separate but `tokio` support is enabled with a single feature.
43-
- Removed `Header` re-export from `http` module. It is still defined in the `http::headers` module.
44-
- Removed `http-types` dependency and implemented `Method` instead.
45-
- Removed `Pager`.
46-
- Removed `parsing` module.
45+
- Consolidated all the `tokio` features into a single feature named `tokio`. Traits remain separate but `tokio` support is enabled with a single feature.
46+
- Removed `Header` re-export from `http` module. It is still defined in the `http::headers` module.
47+
- Removed `http-types` dependency and implemented `Method` instead.
48+
- Removed `Pager`.
49+
- Removed `parsing` module.
4750

4851
### Other Changes
4952

50-
- Use `std::sync::LazyLock` added in rustc 1.80 instead of `once_cell::sync::Lazy`.
53+
- Use `std::sync::LazyLock` added in rustc 1.80 instead of `once_cell::sync::Lazy`.
5154

5255
## 0.1.0 (2025-02-18)
5356

5457
### Features Added
5558

56-
- Initial supported release.
59+
- Initial supported release.

0 commit comments

Comments
 (0)