Skip to content

Refactor response format and iterate over pageable items #2665

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ Use these instructions for test generation as well.
- Field and function names are snake_case.
- Parameter names are snake_case.
- Crate and module names are snake_case.
- Keep `use` directives at the top of the module in which they are used, and avoid placing them inside functions or blocks unless absolutely necessary.
- Prefer using `crate` in `use` directives to refer to types anywhere in the current crate instead of using it's name, or relative paths like `super` or `self`.
- Prefer merging new `use` directives into existing ones rather than creating new `use` blocks.
- Prioritize safety, efficiency, and correctness.
- Respect Rust's ownership and borrowing rules.
- Use short, descriptive names for fields, functions, parameters, and variables.
Expand All @@ -29,6 +32,7 @@ Use these instructions for test generation as well.
- Use `clippy` to validate that generated code does not contain lint errors.
- If you have trouble generating safe, efficient, maintainable, and lint-free code, insert a `TODO` comment describing what should happen.
- All imported types, constants, functions, modules, and macros should be imported explicitly. Never import `*`.
- Do not modify generated code, found in `generated` subdirectories. These files are generated by external tools and should not be edited manually.

## Test Generation

Expand All @@ -38,3 +42,4 @@ Use these instructions for test generation as well.
- The `tests` module should be conditioned on `#[cfg(test)]`.
- The `tests` module should always import APIs from `super`.
- Do not begin test function names with "test" unless necessary to disambiguate from the function being tested.
- Test functions do not need to be public.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 15 additions & 15 deletions eng/emitter-package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions eng/emitter-package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"main": "dist/src/index.js",
"dependencies": {
"@azure-tools/typespec-rust": "0.14.2"
"@azure-tools/typespec-rust": "0.15.0"
},
"devDependencies": {
"@azure-tools/typespec-azure-core": "0.56.0",
"@azure-tools/typespec-azure-rulesets": "0.56.0",
"@azure-tools/typespec-client-generator-core": "0.56.2",
"@azure-tools/typespec-client-generator-core": "0.56.3",
"@typespec/compiler": "1.0.0",
"@typespec/http": "1.0.1",
"@typespec/openapi": "1.0.0",
"@typespec/rest": "0.70.0",
"@typespec/versioning": "0.70.0",
"@typespec/xml": "0.70.0"
}
}
}
8 changes: 7 additions & 1 deletion sdk/core/azure_core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@
### Features Added

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

### Breaking Changes

- Removed `AccessToken::is_expired()`
- A `Pager` now asynchronously iterates over items across all pages. Call `Pager::into_pages()` to get a `PageIterator` to asynchronously iterate over all pages.
- Removed `AccessToken::is_expired()`.
- Renamed `PagerResult::Continue` to `More` and its `continuation` field to `next`.
- Renamed `PagerResult::Complete` to `Done`.
- Renamed `PageStream` to `ItemIterator`.

### Bugs Fixed

Expand Down
2 changes: 1 addition & 1 deletion sdk/core/azure_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ edition.workspace = true
rust-version.workspace = true

[dependencies]
async-lock = { workspace = true }
async-lock.workspace = true
async-trait.workspace = true
bytes.workspace = true
futures.workspace = true
Expand Down
40 changes: 35 additions & 5 deletions sdk/core/azure_core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ so that once you learn how to use these APIs in one client library, you will kno
Typically, you will not need to install `azure_core`;
it will be installed for you when you install one of the client libraries using it.
In case you want to install it explicitly - to implement your own client library, for example -
you can find the crates.io package [here][Package (crates.io)].
you can find the [package on crates.io][Package (crates.io)].

## Key concepts

Expand Down Expand Up @@ -178,7 +178,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

### Consuming service methods returning `Pager<T>`

If a service call returns multiple values in pages, it would return `Result<Pager<T>>` as a result. You can iterator over each page's vector of results.
If a service call returns multiple values in pages, it would return `Result<Pager<T>>` as a result. You can iterate all items from all pages.

```rust no_run
use azure_identity::DefaultAzureCredential;
Expand All @@ -195,8 +195,39 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
None,
)?;

// get a stream
let mut pager = client.list_secret_properties(None)?.into_stream();
// get a stream of items
let mut pager = client.list_secret_properties(None)?;

// poll the pager until there are no more SecretListResults
while let Some(secret) = pager.try_next().await? {
// get the secret name from the ID
let name = secret.resource_id()?.name;
println!("Found secret with name: {}", name);
}

Ok(())
}
```

To instead iterate over all pages, call `into_pages()` on the returned `Pager`.

```rust no_run
use azure_identity::DefaultAzureCredential;
use azure_security_keyvault_secrets::{ResourceExt, SecretClient};
use futures::TryStreamExt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// create a client
let credential = DefaultAzureCredential::new()?;
let client = SecretClient::new(
"https://<your-key-vault-name>.vault.azure.net/",
credential.clone(),
None,
)?;

// get a stream of pages
let mut pager = client.list_secret_properties(None)?.into_pages();

// poll the pager until there are no more SecretListResults
while let Some(secrets) = pager.try_next().await? {
Expand All @@ -213,7 +244,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}
```

<!-- ## Troubleshooting -->
## Troubleshooting

### Logging
Expand Down
11 changes: 9 additions & 2 deletions sdk/core/azure_core/benches/benchmarks.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use azure_core::http::{
headers::Headers, response::Response, HttpClient, Method, Request, StatusCode, Url,
headers::Headers, HttpClient, Method, RawResponse, Request, StatusCode, Url,
};
use azure_core_test::http::MockHttpClient;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
Expand Down Expand Up @@ -30,7 +30,14 @@ fn http_transport_test(c: &mut Criterion) {

// client to be used in the benchmark
let mock_client = Arc::new(MockHttpClient::new(move |_| {
async move { Ok(Response::from_bytes(StatusCode::Ok, Headers::new(), vec![])) }.boxed()
async move {
Ok(RawResponse::from_bytes(
StatusCode::Ok,
Headers::new(),
vec![],
))
}
.boxed()
})) as Arc<dyn HttpClient>;

// requests to be used in the benchmark
Expand Down
8 changes: 6 additions & 2 deletions sdk/core/azure_core/src/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ pub use options::*;
pub use pager::*;
pub use pipeline::*;
pub use request::{Body, Request, RequestContent};
pub use response::{Model, Response};
pub use response::{RawResponse, Response};

pub use typespec_client_core::http::response;
pub use typespec_client_core::http::{
new_http_client, AppendToUrlQuery, Context, HttpClient, Method, StatusCode, Url,
new_http_client, AppendToUrlQuery, Context, Format, HttpClient, JsonFormat, Method, StatusCode,
Url,
};

#[cfg(feature = "xml")]
pub use typespec_client_core::http::XmlFormat;
Loading