Skip to main content

qcs_api_client_openapi/apis/
quantum_processors_api.rs

1// Copyright 2026 Rigetti Computing
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/*
16 * Rigetti QCS API
17 *
18 * # Introduction  This is the documentation for the Rigetti QCS HTTP API.  You can find out more about Rigetti at [https://rigetti.com](https://rigetti.com), and also interact with QCS via the web at [https://qcs.rigetti.com](https://qcs.rigetti.com).  This API is documented in **OpenAPI format** and so is compatible with the dozens of language-specific client generators available [here](https://github.com/OpenAPITools/openapi-generator) and elsewhere on the web.  # Principles  This API follows REST design principles where appropriate, and otherwise an HTTP RPC paradigm. We adhere to the Google [API Improvement Proposals](https://google.aip.dev/general) where reasonable to provide a consistent, intuitive developer experience. HTTP response codes match their specifications, and error messages fit a common format.  # Authentication  All access to the QCS API requires OAuth2 authentication provided by Okta. You can request access [here](https://www.rigetti.com/get-quantum). Once you have a user account, you can download your access token from QCS [here](https://qcs.rigetti.com/auth/token).   That access token is valid for 24 hours after issuance. The value of `access_token` within the JSON file is the token used for authentication (don't use the entire JSON file).  Authenticate requests using the `Authorization` header and a `Bearer` prefix:  ``` curl --header \"Authorization: Bearer eyJraW...Iow\" ```  # Quantum Processor Access  Access to the quantum processors themselves is not yet provided directly by this HTTP API, but is instead performed over ZeroMQ/[rpcq](https://github.com/rigetti/rpcq). Until that changes, we suggest using [pyquil](https://github.com/rigetti/pyquil) to build and execute quantum programs via the Legacy API.  # Legacy API  Our legacy HTTP API remains accessible at https://forest-server.qcs.rigetti.com, and it shares a source of truth with this API's services. You can use either service with the same user account and means of authentication. We strongly recommend using the API documented here, as the legacy API is on the path to deprecation.
19 *
20 * The version of the OpenAPI document: 2020-07-31
21 * Contact: support@rigetti.com
22 * Generated by: https://openapi-generator.tech
23 */
24
25use super::{ContentType, Error, configuration};
26use crate::{apis::ResponseContent, models};
27use ::qcs_api_client_common::backoff::{
28    BackoffBuilder, ExponentialBackoff, duration_from_io_error, duration_from_reqwest_error,
29    duration_from_response,
30};
31#[cfg(feature = "tracing")]
32use qcs_api_client_common::configuration::tokens::TokenRefresher;
33use qcs_dependencies_client::reqwest::{self, StatusCode};
34use serde::{Deserialize, Serialize};
35
36#[cfg(feature = "clap")]
37#[allow(unused, reason = "not used in all templates, but required in some")]
38use ::{miette::IntoDiagnostic as _, qcs_api_client_common::clap_utils::JsonMaybeStdin};
39
40/// Serialize command-line arguments for [`get_default_endpoint`]
41#[cfg(feature = "clap")]
42#[derive(Debug, clap::Args)]
43pub struct GetDefaultEndpointClapParams {
44    #[arg(long)]
45    pub quantum_processor_id: String,
46}
47
48#[cfg(feature = "clap")]
49impl GetDefaultEndpointClapParams {
50    pub async fn execute(
51        self,
52        configuration: &configuration::Configuration,
53    ) -> Result<models::Endpoint, miette::Error> {
54        get_default_endpoint(configuration, self.quantum_processor_id.as_str())
55            .await
56            .into_diagnostic()
57    }
58}
59
60/// Serialize command-line arguments for [`get_instruction_set_architecture`]
61#[cfg(feature = "clap")]
62#[derive(Debug, clap::Args)]
63pub struct GetInstructionSetArchitectureClapParams {
64    #[arg(long)]
65    pub quantum_processor_id: String,
66}
67
68#[cfg(feature = "clap")]
69impl GetInstructionSetArchitectureClapParams {
70    pub async fn execute(
71        self,
72        configuration: &configuration::Configuration,
73    ) -> Result<models::InstructionSetArchitecture, miette::Error> {
74        get_instruction_set_architecture(configuration, self.quantum_processor_id.as_str())
75            .await
76            .into_diagnostic()
77    }
78}
79
80/// Serialize command-line arguments for [`get_quantum_processor`]
81#[cfg(feature = "clap")]
82#[derive(Debug, clap::Args)]
83pub struct GetQuantumProcessorClapParams {
84    #[arg(long)]
85    pub quantum_processor_id: String,
86}
87
88#[cfg(feature = "clap")]
89impl GetQuantumProcessorClapParams {
90    pub async fn execute(
91        self,
92        configuration: &configuration::Configuration,
93    ) -> Result<models::QuantumProcessor, miette::Error> {
94        get_quantum_processor(configuration, self.quantum_processor_id.as_str())
95            .await
96            .into_diagnostic()
97    }
98}
99
100/// Serialize command-line arguments for [`get_quantum_processor_accessors`]
101#[cfg(feature = "clap")]
102#[derive(Debug, clap::Args)]
103pub struct GetQuantumProcessorAccessorsClapParams {
104    #[arg(long)]
105    pub quantum_processor_id: String,
106}
107
108#[cfg(feature = "clap")]
109impl GetQuantumProcessorAccessorsClapParams {
110    pub async fn execute(
111        self,
112        configuration: &configuration::Configuration,
113    ) -> Result<models::ListQuantumProcessorAccessorsResponse, miette::Error> {
114        get_quantum_processor_accessors(configuration, self.quantum_processor_id.as_str())
115            .await
116            .into_diagnostic()
117    }
118}
119
120/// Serialize command-line arguments for [`list_instruction_set_architectures`]
121#[cfg(feature = "clap")]
122#[derive(Debug, clap::Args)]
123pub struct ListInstructionSetArchitecturesClapParams {
124    #[arg(long)]
125    pub page_size: Option<u64>,
126    #[arg(long)]
127    pub page_token: Option<String>,
128}
129
130#[cfg(feature = "clap")]
131impl ListInstructionSetArchitecturesClapParams {
132    pub async fn execute(
133        self,
134        configuration: &configuration::Configuration,
135    ) -> Result<models::ListInstructionSetArchitectureResponse, miette::Error> {
136        list_instruction_set_architectures(
137            configuration,
138            self.page_size,
139            self.page_token.as_deref(),
140        )
141        .await
142        .into_diagnostic()
143    }
144}
145
146/// Serialize command-line arguments for [`list_quantum_processors`]
147#[cfg(feature = "clap")]
148#[derive(Debug, clap::Args)]
149pub struct ListQuantumProcessorsClapParams {
150    #[arg(long)]
151    pub page_size: Option<u64>,
152    #[arg(long)]
153    pub page_token: Option<String>,
154}
155
156#[cfg(feature = "clap")]
157impl ListQuantumProcessorsClapParams {
158    pub async fn execute(
159        self,
160        configuration: &configuration::Configuration,
161    ) -> Result<models::ListQuantumProcessorsResponse, miette::Error> {
162        list_quantum_processors(configuration, self.page_size, self.page_token.as_deref())
163            .await
164            .into_diagnostic()
165    }
166}
167
168/// struct for typed errors of method [`get_default_endpoint`]
169#[derive(Debug, Clone, Serialize, Deserialize)]
170#[serde(untagged)]
171pub enum GetDefaultEndpointError {
172    Status422(models::ValidationError),
173    DefaultResponse(models::Error),
174    UnknownValue(serde_json::Value),
175}
176
177/// struct for typed errors of method [`get_instruction_set_architecture`]
178#[derive(Debug, Clone, Serialize, Deserialize)]
179#[serde(untagged)]
180pub enum GetInstructionSetArchitectureError {
181    Status422(models::ValidationError),
182    DefaultResponse(models::Error),
183    UnknownValue(serde_json::Value),
184}
185
186/// struct for typed errors of method [`get_quantum_processor`]
187#[derive(Debug, Clone, Serialize, Deserialize)]
188#[serde(untagged)]
189pub enum GetQuantumProcessorError {
190    Status422(models::ValidationError),
191    DefaultResponse(models::Error),
192    UnknownValue(serde_json::Value),
193}
194
195/// struct for typed errors of method [`get_quantum_processor_accessors`]
196#[derive(Debug, Clone, Serialize, Deserialize)]
197#[serde(untagged)]
198pub enum GetQuantumProcessorAccessorsError {
199    Status422(models::ValidationError),
200    DefaultResponse(models::Error),
201    UnknownValue(serde_json::Value),
202}
203
204/// struct for typed errors of method [`list_instruction_set_architectures`]
205#[derive(Debug, Clone, Serialize, Deserialize)]
206#[serde(untagged)]
207pub enum ListInstructionSetArchitecturesError {
208    Status422(models::ValidationError),
209    DefaultResponse(models::Error),
210    UnknownValue(serde_json::Value),
211}
212
213/// struct for typed errors of method [`list_quantum_processors`]
214#[derive(Debug, Clone, Serialize, Deserialize)]
215#[serde(untagged)]
216pub enum ListQuantumProcessorsError {
217    Status422(models::ValidationError),
218    DefaultResponse(models::Error),
219    UnknownValue(serde_json::Value),
220}
221
222async fn get_default_endpoint_inner(
223    configuration: &configuration::Configuration,
224    backoff: &mut ExponentialBackoff,
225    quantum_processor_id: &str,
226) -> Result<models::Endpoint, Error<GetDefaultEndpointError>> {
227    let local_var_configuration = configuration;
228    // add a prefix to parameters to efficiently prevent name collisions
229    let p_path_quantum_processor_id = quantum_processor_id;
230
231    let local_var_client = &local_var_configuration.client;
232
233    let local_var_uri_str = format!(
234        "{}/v1/quantumProcessors/{quantumProcessorId}/endpoints:getDefault",
235        local_var_configuration.qcs_config.api_url(),
236        quantumProcessorId = crate::apis::urlencode(p_path_quantum_processor_id)
237    );
238    let mut local_var_req_builder =
239        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
240
241    #[cfg(feature = "tracing")]
242    {
243        // Ignore parsing errors if the URL is invalid for some reason.
244        // If it is invalid, it will turn up as an error later when actually making the request.
245        let local_var_do_tracing = local_var_uri_str
246            .parse::<::url::Url>()
247            .ok()
248            .is_none_or(|url| {
249                configuration
250                    .qcs_config
251                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
252            });
253
254        if local_var_do_tracing {
255            ::tracing::debug!(
256                url=%local_var_uri_str,
257                method="GET",
258                "making get_default_endpoint request",
259            );
260        }
261    }
262
263    // Use the QCS Bearer token if a client OAuthSession is present,
264    // but do not require one when the security schema says it is optional.
265    {
266        use qcs_api_client_common::configuration::TokenError;
267
268        #[allow(
269            clippy::nonminimal_bool,
270            clippy::eq_op,
271            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
272        )]
273        let is_jwt_bearer_optional: bool = false || "JWTBearer" == "JWTBearerOptional";
274
275        let token = local_var_configuration
276            .qcs_config
277            .get_bearer_access_token()
278            .await;
279
280        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
281            // the client is configured without any OAuthSession, but this call does not require one.
282            #[cfg(feature = "tracing")]
283            tracing::debug!(
284                "No client credentials found, but this call does not require authentication."
285            );
286        } else {
287            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
288        }
289    }
290
291    let local_var_req = local_var_req_builder.build()?;
292    let local_var_resp = local_var_client.execute(local_var_req).await?;
293
294    let local_var_status = local_var_resp.status();
295    let local_var_raw_content_type = local_var_resp
296        .headers()
297        .get("content-type")
298        .and_then(|v| v.to_str().ok())
299        .unwrap_or("application/octet-stream")
300        .to_string();
301    let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
302
303    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
304        let local_var_content = local_var_resp.text().await?;
305        match local_var_content_type {
306            ContentType::Json => serde_path_to_error::deserialize(
307                &mut serde_json::Deserializer::from_str(&local_var_content),
308            )
309            .map_err(Error::from),
310            ContentType::Text => Err(Error::InvalidContentType {
311                content_type: local_var_raw_content_type,
312                return_type: "models::Endpoint",
313            }),
314            ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
315                content_type: unknown_type,
316                return_type: "models::Endpoint",
317            }),
318        }
319    } else {
320        let local_var_retry_delay =
321            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
322        let local_var_content = local_var_resp.text().await?;
323        let local_var_entity: Option<GetDefaultEndpointError> =
324            serde_json::from_str(&local_var_content).ok();
325        let local_var_error = ResponseContent {
326            status: local_var_status,
327            content: local_var_content,
328            entity: local_var_entity,
329            retry_delay: local_var_retry_delay,
330        };
331        Err(Error::ResponseError(local_var_error))
332    }
333}
334
335/// If no endpoint is set as the default, return \"not found.\"
336pub async fn get_default_endpoint(
337    configuration: &configuration::Configuration,
338    quantum_processor_id: &str,
339) -> Result<models::Endpoint, Error<GetDefaultEndpointError>> {
340    let mut backoff = configuration.backoff.build();
341    let mut refreshed_credentials = false;
342    let method = reqwest::Method::GET;
343    loop {
344        let result =
345            get_default_endpoint_inner(configuration, &mut backoff, quantum_processor_id.clone())
346                .await;
347
348        match result {
349            Ok(result) => return Ok(result),
350            Err(Error::ResponseError(response)) => {
351                if !refreshed_credentials
352                    && matches!(
353                        response.status,
354                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
355                    )
356                {
357                    // Attempt to refresh credentials
358                    match configuration.qcs_config.refresh().await {
359                        Ok(_) => {
360                            refreshed_credentials = true;
361                            continue;
362                        }
363                        Err(::qcs_api_client_common::configuration::TokenError::Write {
364                            error,
365                            oauth_session: _,
366                        }) => {
367                            // Token refresh succeeded but persistence failed
368                            // The token is already in memory and will be used for this request
369                            #[cfg(feature = "tracing")]
370                            tracing::warn!(
371                                "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
372                                error
373                            );
374                            refreshed_credentials = true;
375                            continue;
376                        }
377                        Err(e) => return Err(e.into()),
378                    }
379                } else if let Some(duration) = response.retry_delay {
380                    tokio::time::sleep(duration).await;
381                    continue;
382                }
383
384                return Err(Error::ResponseError(response));
385            }
386            Err(Error::Reqwest(error)) => {
387                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
388                    tokio::time::sleep(duration).await;
389                    continue;
390                }
391
392                return Err(Error::Reqwest(error));
393            }
394            Err(Error::Io(error)) => {
395                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
396                    tokio::time::sleep(duration).await;
397                    continue;
398                }
399
400                return Err(Error::Io(error));
401            }
402            Err(error) => return Err(error),
403        }
404    }
405}
406async fn get_instruction_set_architecture_inner(
407    configuration: &configuration::Configuration,
408    backoff: &mut ExponentialBackoff,
409    quantum_processor_id: &str,
410) -> Result<models::InstructionSetArchitecture, Error<GetInstructionSetArchitectureError>> {
411    let local_var_configuration = configuration;
412    // add a prefix to parameters to efficiently prevent name collisions
413    let p_path_quantum_processor_id = quantum_processor_id;
414
415    let local_var_client = &local_var_configuration.client;
416
417    let local_var_uri_str = format!(
418        "{}/v1/quantumProcessors/{quantum_processor_id}/instructionSetArchitecture",
419        local_var_configuration.qcs_config.api_url(),
420        quantum_processor_id = crate::apis::urlencode(p_path_quantum_processor_id)
421    );
422    let mut local_var_req_builder =
423        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
424
425    #[cfg(feature = "tracing")]
426    {
427        // Ignore parsing errors if the URL is invalid for some reason.
428        // If it is invalid, it will turn up as an error later when actually making the request.
429        let local_var_do_tracing = local_var_uri_str
430            .parse::<::url::Url>()
431            .ok()
432            .is_none_or(|url| {
433                configuration
434                    .qcs_config
435                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
436            });
437
438        if local_var_do_tracing {
439            ::tracing::debug!(
440                url=%local_var_uri_str,
441                method="GET",
442                "making get_instruction_set_architecture request",
443            );
444        }
445    }
446
447    // Use the QCS Bearer token if a client OAuthSession is present,
448    // but do not require one when the security schema says it is optional.
449    {
450        use qcs_api_client_common::configuration::TokenError;
451
452        #[allow(
453            clippy::nonminimal_bool,
454            clippy::eq_op,
455            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
456        )]
457        let is_jwt_bearer_optional: bool = false || "JWTBearerOptional" == "JWTBearerOptional";
458
459        let token = local_var_configuration
460            .qcs_config
461            .get_bearer_access_token()
462            .await;
463
464        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
465            // the client is configured without any OAuthSession, but this call does not require one.
466            #[cfg(feature = "tracing")]
467            tracing::debug!(
468                "No client credentials found, but this call does not require authentication."
469            );
470        } else {
471            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
472        }
473    }
474
475    let local_var_req = local_var_req_builder.build()?;
476    let local_var_resp = local_var_client.execute(local_var_req).await?;
477
478    let local_var_status = local_var_resp.status();
479    let local_var_raw_content_type = local_var_resp
480        .headers()
481        .get("content-type")
482        .and_then(|v| v.to_str().ok())
483        .unwrap_or("application/octet-stream")
484        .to_string();
485    let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
486
487    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
488        let local_var_content = local_var_resp.text().await?;
489        match local_var_content_type {
490            ContentType::Json => serde_path_to_error::deserialize(
491                &mut serde_json::Deserializer::from_str(&local_var_content),
492            )
493            .map_err(Error::from),
494            ContentType::Text => Err(Error::InvalidContentType {
495                content_type: local_var_raw_content_type,
496                return_type: "models::InstructionSetArchitecture",
497            }),
498            ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
499                content_type: unknown_type,
500                return_type: "models::InstructionSetArchitecture",
501            }),
502        }
503    } else {
504        let local_var_retry_delay =
505            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
506        let local_var_content = local_var_resp.text().await?;
507        let local_var_entity: Option<GetInstructionSetArchitectureError> =
508            serde_json::from_str(&local_var_content).ok();
509        let local_var_error = ResponseContent {
510            status: local_var_status,
511            content: local_var_content,
512            entity: local_var_entity,
513            retry_delay: local_var_retry_delay,
514        };
515        Err(Error::ResponseError(local_var_error))
516    }
517}
518
519pub async fn get_instruction_set_architecture(
520    configuration: &configuration::Configuration,
521    quantum_processor_id: &str,
522) -> Result<models::InstructionSetArchitecture, Error<GetInstructionSetArchitectureError>> {
523    let mut backoff = configuration.backoff.build();
524    let mut refreshed_credentials = false;
525    let method = reqwest::Method::GET;
526    loop {
527        let result = get_instruction_set_architecture_inner(
528            configuration,
529            &mut backoff,
530            quantum_processor_id.clone(),
531        )
532        .await;
533
534        match result {
535            Ok(result) => return Ok(result),
536            Err(Error::ResponseError(response)) => {
537                if !refreshed_credentials
538                    && matches!(
539                        response.status,
540                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
541                    )
542                {
543                    // Attempt to refresh credentials
544                    match configuration.qcs_config.refresh().await {
545                        Ok(_) => {
546                            refreshed_credentials = true;
547                            continue;
548                        }
549                        Err(::qcs_api_client_common::configuration::TokenError::Write {
550                            error,
551                            oauth_session: _,
552                        }) => {
553                            // Token refresh succeeded but persistence failed
554                            // The token is already in memory and will be used for this request
555                            #[cfg(feature = "tracing")]
556                            tracing::warn!(
557                                "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
558                                error
559                            );
560                            refreshed_credentials = true;
561                            continue;
562                        }
563                        Err(e) => return Err(e.into()),
564                    }
565                } else if let Some(duration) = response.retry_delay {
566                    tokio::time::sleep(duration).await;
567                    continue;
568                }
569
570                return Err(Error::ResponseError(response));
571            }
572            Err(Error::Reqwest(error)) => {
573                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
574                    tokio::time::sleep(duration).await;
575                    continue;
576                }
577
578                return Err(Error::Reqwest(error));
579            }
580            Err(Error::Io(error)) => {
581                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
582                    tokio::time::sleep(duration).await;
583                    continue;
584                }
585
586                return Err(Error::Io(error));
587            }
588            Err(error) => return Err(error),
589        }
590    }
591}
592async fn get_quantum_processor_inner(
593    configuration: &configuration::Configuration,
594    backoff: &mut ExponentialBackoff,
595    quantum_processor_id: &str,
596) -> Result<models::QuantumProcessor, Error<GetQuantumProcessorError>> {
597    let local_var_configuration = configuration;
598    // add a prefix to parameters to efficiently prevent name collisions
599    let p_path_quantum_processor_id = quantum_processor_id;
600
601    let local_var_client = &local_var_configuration.client;
602
603    let local_var_uri_str = format!(
604        "{}/v1/quantumProcessors/{quantum_processor_id}",
605        local_var_configuration.qcs_config.api_url(),
606        quantum_processor_id = crate::apis::urlencode(p_path_quantum_processor_id)
607    );
608    let mut local_var_req_builder =
609        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
610
611    #[cfg(feature = "tracing")]
612    {
613        // Ignore parsing errors if the URL is invalid for some reason.
614        // If it is invalid, it will turn up as an error later when actually making the request.
615        let local_var_do_tracing = local_var_uri_str
616            .parse::<::url::Url>()
617            .ok()
618            .is_none_or(|url| {
619                configuration
620                    .qcs_config
621                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
622            });
623
624        if local_var_do_tracing {
625            ::tracing::debug!(
626                url=%local_var_uri_str,
627                method="GET",
628                "making get_quantum_processor request",
629            );
630        }
631    }
632
633    // Use the QCS Bearer token if a client OAuthSession is present,
634    // but do not require one when the security schema says it is optional.
635    {
636        use qcs_api_client_common::configuration::TokenError;
637
638        #[allow(
639            clippy::nonminimal_bool,
640            clippy::eq_op,
641            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
642        )]
643        let is_jwt_bearer_optional: bool = false || "JWTBearerOptional" == "JWTBearerOptional";
644
645        let token = local_var_configuration
646            .qcs_config
647            .get_bearer_access_token()
648            .await;
649
650        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
651            // the client is configured without any OAuthSession, but this call does not require one.
652            #[cfg(feature = "tracing")]
653            tracing::debug!(
654                "No client credentials found, but this call does not require authentication."
655            );
656        } else {
657            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
658        }
659    }
660
661    let local_var_req = local_var_req_builder.build()?;
662    let local_var_resp = local_var_client.execute(local_var_req).await?;
663
664    let local_var_status = local_var_resp.status();
665    let local_var_raw_content_type = local_var_resp
666        .headers()
667        .get("content-type")
668        .and_then(|v| v.to_str().ok())
669        .unwrap_or("application/octet-stream")
670        .to_string();
671    let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
672
673    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
674        let local_var_content = local_var_resp.text().await?;
675        match local_var_content_type {
676            ContentType::Json => serde_path_to_error::deserialize(
677                &mut serde_json::Deserializer::from_str(&local_var_content),
678            )
679            .map_err(Error::from),
680            ContentType::Text => Err(Error::InvalidContentType {
681                content_type: local_var_raw_content_type,
682                return_type: "models::QuantumProcessor",
683            }),
684            ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
685                content_type: unknown_type,
686                return_type: "models::QuantumProcessor",
687            }),
688        }
689    } else {
690        let local_var_retry_delay =
691            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
692        let local_var_content = local_var_resp.text().await?;
693        let local_var_entity: Option<GetQuantumProcessorError> =
694            serde_json::from_str(&local_var_content).ok();
695        let local_var_error = ResponseContent {
696            status: local_var_status,
697            content: local_var_content,
698            entity: local_var_entity,
699            retry_delay: local_var_retry_delay,
700        };
701        Err(Error::ResponseError(local_var_error))
702    }
703}
704
705/// Retrieve a single `QuantumProcessor` by ID.
706pub async fn get_quantum_processor(
707    configuration: &configuration::Configuration,
708    quantum_processor_id: &str,
709) -> Result<models::QuantumProcessor, Error<GetQuantumProcessorError>> {
710    let mut backoff = configuration.backoff.build();
711    let mut refreshed_credentials = false;
712    let method = reqwest::Method::GET;
713    loop {
714        let result =
715            get_quantum_processor_inner(configuration, &mut backoff, quantum_processor_id.clone())
716                .await;
717
718        match result {
719            Ok(result) => return Ok(result),
720            Err(Error::ResponseError(response)) => {
721                if !refreshed_credentials
722                    && matches!(
723                        response.status,
724                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
725                    )
726                {
727                    // Attempt to refresh credentials
728                    match configuration.qcs_config.refresh().await {
729                        Ok(_) => {
730                            refreshed_credentials = true;
731                            continue;
732                        }
733                        Err(::qcs_api_client_common::configuration::TokenError::Write {
734                            error,
735                            oauth_session: _,
736                        }) => {
737                            // Token refresh succeeded but persistence failed
738                            // The token is already in memory and will be used for this request
739                            #[cfg(feature = "tracing")]
740                            tracing::warn!(
741                                "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
742                                error
743                            );
744                            refreshed_credentials = true;
745                            continue;
746                        }
747                        Err(e) => return Err(e.into()),
748                    }
749                } else if let Some(duration) = response.retry_delay {
750                    tokio::time::sleep(duration).await;
751                    continue;
752                }
753
754                return Err(Error::ResponseError(response));
755            }
756            Err(Error::Reqwest(error)) => {
757                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
758                    tokio::time::sleep(duration).await;
759                    continue;
760                }
761
762                return Err(Error::Reqwest(error));
763            }
764            Err(Error::Io(error)) => {
765                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
766                    tokio::time::sleep(duration).await;
767                    continue;
768                }
769
770                return Err(Error::Io(error));
771            }
772            Err(error) => return Err(error),
773        }
774    }
775}
776async fn get_quantum_processor_accessors_inner(
777    configuration: &configuration::Configuration,
778    backoff: &mut ExponentialBackoff,
779    quantum_processor_id: &str,
780) -> Result<models::ListQuantumProcessorAccessorsResponse, Error<GetQuantumProcessorAccessorsError>>
781{
782    let local_var_configuration = configuration;
783    // add a prefix to parameters to efficiently prevent name collisions
784    let p_path_quantum_processor_id = quantum_processor_id;
785
786    let local_var_client = &local_var_configuration.client;
787
788    let local_var_uri_str = format!(
789        "{}/v1/quantumProcessors/{quantum_processor_id}/accessors",
790        local_var_configuration.qcs_config.api_url(),
791        quantum_processor_id = crate::apis::urlencode(p_path_quantum_processor_id)
792    );
793    let mut local_var_req_builder =
794        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
795
796    #[cfg(feature = "tracing")]
797    {
798        // Ignore parsing errors if the URL is invalid for some reason.
799        // If it is invalid, it will turn up as an error later when actually making the request.
800        let local_var_do_tracing = local_var_uri_str
801            .parse::<::url::Url>()
802            .ok()
803            .is_none_or(|url| {
804                configuration
805                    .qcs_config
806                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
807            });
808
809        if local_var_do_tracing {
810            ::tracing::debug!(
811                url=%local_var_uri_str,
812                method="GET",
813                "making get_quantum_processor_accessors request",
814            );
815        }
816    }
817
818    // Use the QCS Bearer token if a client OAuthSession is present,
819    // but do not require one when the security schema says it is optional.
820    {
821        use qcs_api_client_common::configuration::TokenError;
822
823        #[allow(
824            clippy::nonminimal_bool,
825            clippy::eq_op,
826            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
827        )]
828        let is_jwt_bearer_optional: bool = false || "JWTBearerOptional" == "JWTBearerOptional";
829
830        let token = local_var_configuration
831            .qcs_config
832            .get_bearer_access_token()
833            .await;
834
835        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
836            // the client is configured without any OAuthSession, but this call does not require one.
837            #[cfg(feature = "tracing")]
838            tracing::debug!(
839                "No client credentials found, but this call does not require authentication."
840            );
841        } else {
842            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
843        }
844    }
845
846    let local_var_req = local_var_req_builder.build()?;
847    let local_var_resp = local_var_client.execute(local_var_req).await?;
848
849    let local_var_status = local_var_resp.status();
850    let local_var_raw_content_type = local_var_resp
851        .headers()
852        .get("content-type")
853        .and_then(|v| v.to_str().ok())
854        .unwrap_or("application/octet-stream")
855        .to_string();
856    let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
857
858    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
859        let local_var_content = local_var_resp.text().await?;
860        match local_var_content_type {
861            ContentType::Json => serde_path_to_error::deserialize(
862                &mut serde_json::Deserializer::from_str(&local_var_content),
863            )
864            .map_err(Error::from),
865            ContentType::Text => Err(Error::InvalidContentType {
866                content_type: local_var_raw_content_type,
867                return_type: "models::ListQuantumProcessorAccessorsResponse",
868            }),
869            ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
870                content_type: unknown_type,
871                return_type: "models::ListQuantumProcessorAccessorsResponse",
872            }),
873        }
874    } else {
875        let local_var_retry_delay =
876            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
877        let local_var_content = local_var_resp.text().await?;
878        let local_var_entity: Option<GetQuantumProcessorAccessorsError> =
879            serde_json::from_str(&local_var_content).ok();
880        let local_var_error = ResponseContent {
881            status: local_var_status,
882            content: local_var_content,
883            entity: local_var_entity,
884            retry_delay: local_var_retry_delay,
885        };
886        Err(Error::ResponseError(local_var_error))
887    }
888}
889
890/// Retrieve a single `QuantumProcessor` by ID.
891pub async fn get_quantum_processor_accessors(
892    configuration: &configuration::Configuration,
893    quantum_processor_id: &str,
894) -> Result<models::ListQuantumProcessorAccessorsResponse, Error<GetQuantumProcessorAccessorsError>>
895{
896    let mut backoff = configuration.backoff.build();
897    let mut refreshed_credentials = false;
898    let method = reqwest::Method::GET;
899    loop {
900        let result = get_quantum_processor_accessors_inner(
901            configuration,
902            &mut backoff,
903            quantum_processor_id.clone(),
904        )
905        .await;
906
907        match result {
908            Ok(result) => return Ok(result),
909            Err(Error::ResponseError(response)) => {
910                if !refreshed_credentials
911                    && matches!(
912                        response.status,
913                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
914                    )
915                {
916                    // Attempt to refresh credentials
917                    match configuration.qcs_config.refresh().await {
918                        Ok(_) => {
919                            refreshed_credentials = true;
920                            continue;
921                        }
922                        Err(::qcs_api_client_common::configuration::TokenError::Write {
923                            error,
924                            oauth_session: _,
925                        }) => {
926                            // Token refresh succeeded but persistence failed
927                            // The token is already in memory and will be used for this request
928                            #[cfg(feature = "tracing")]
929                            tracing::warn!(
930                                "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
931                                error
932                            );
933                            refreshed_credentials = true;
934                            continue;
935                        }
936                        Err(e) => return Err(e.into()),
937                    }
938                } else if let Some(duration) = response.retry_delay {
939                    tokio::time::sleep(duration).await;
940                    continue;
941                }
942
943                return Err(Error::ResponseError(response));
944            }
945            Err(Error::Reqwest(error)) => {
946                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
947                    tokio::time::sleep(duration).await;
948                    continue;
949                }
950
951                return Err(Error::Reqwest(error));
952            }
953            Err(Error::Io(error)) => {
954                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
955                    tokio::time::sleep(duration).await;
956                    continue;
957                }
958
959                return Err(Error::Io(error));
960            }
961            Err(error) => return Err(error),
962        }
963    }
964}
965async fn list_instruction_set_architectures_inner(
966    configuration: &configuration::Configuration,
967    backoff: &mut ExponentialBackoff,
968    page_size: Option<u64>,
969    page_token: Option<&str>,
970) -> Result<
971    models::ListInstructionSetArchitectureResponse,
972    Error<ListInstructionSetArchitecturesError>,
973> {
974    let local_var_configuration = configuration;
975    // add a prefix to parameters to efficiently prevent name collisions
976    let p_query_page_size = page_size;
977    let p_query_page_token = page_token;
978
979    let local_var_client = &local_var_configuration.client;
980
981    let local_var_uri_str = format!(
982        "{}/v1/instructionSetArchitectures",
983        local_var_configuration.qcs_config.api_url()
984    );
985    let mut local_var_req_builder =
986        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
987
988    #[cfg(feature = "tracing")]
989    {
990        // Ignore parsing errors if the URL is invalid for some reason.
991        // If it is invalid, it will turn up as an error later when actually making the request.
992        let local_var_do_tracing = local_var_uri_str
993            .parse::<::url::Url>()
994            .ok()
995            .is_none_or(|url| {
996                configuration
997                    .qcs_config
998                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
999            });
1000
1001        if local_var_do_tracing {
1002            ::tracing::debug!(
1003                url=%local_var_uri_str,
1004                method="GET",
1005                "making list_instruction_set_architectures request",
1006            );
1007        }
1008    }
1009
1010    if let Some(ref local_var_str) = p_query_page_size {
1011        local_var_req_builder =
1012            local_var_req_builder.query(&[("pageSize", &local_var_str.to_string())]);
1013    }
1014    if let Some(ref local_var_str) = p_query_page_token {
1015        local_var_req_builder =
1016            local_var_req_builder.query(&[("pageToken", &local_var_str.to_string())]);
1017    }
1018
1019    // Use the QCS Bearer token if a client OAuthSession is present,
1020    // but do not require one when the security schema says it is optional.
1021    {
1022        use qcs_api_client_common::configuration::TokenError;
1023
1024        #[allow(
1025            clippy::nonminimal_bool,
1026            clippy::eq_op,
1027            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
1028        )]
1029        let is_jwt_bearer_optional: bool = false || "JWTBearerOptional" == "JWTBearerOptional";
1030
1031        let token = local_var_configuration
1032            .qcs_config
1033            .get_bearer_access_token()
1034            .await;
1035
1036        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
1037            // the client is configured without any OAuthSession, but this call does not require one.
1038            #[cfg(feature = "tracing")]
1039            tracing::debug!(
1040                "No client credentials found, but this call does not require authentication."
1041            );
1042        } else {
1043            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
1044        }
1045    }
1046
1047    let local_var_req = local_var_req_builder.build()?;
1048    let local_var_resp = local_var_client.execute(local_var_req).await?;
1049
1050    let local_var_status = local_var_resp.status();
1051    let local_var_raw_content_type = local_var_resp
1052        .headers()
1053        .get("content-type")
1054        .and_then(|v| v.to_str().ok())
1055        .unwrap_or("application/octet-stream")
1056        .to_string();
1057    let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
1058
1059    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
1060        let local_var_content = local_var_resp.text().await?;
1061        match local_var_content_type {
1062            ContentType::Json => serde_path_to_error::deserialize(
1063                &mut serde_json::Deserializer::from_str(&local_var_content),
1064            )
1065            .map_err(Error::from),
1066            ContentType::Text => Err(Error::InvalidContentType {
1067                content_type: local_var_raw_content_type,
1068                return_type: "models::ListInstructionSetArchitectureResponse",
1069            }),
1070            ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
1071                content_type: unknown_type,
1072                return_type: "models::ListInstructionSetArchitectureResponse",
1073            }),
1074        }
1075    } else {
1076        let local_var_retry_delay =
1077            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
1078        let local_var_content = local_var_resp.text().await?;
1079        let local_var_entity: Option<ListInstructionSetArchitecturesError> =
1080            serde_json::from_str(&local_var_content).ok();
1081        let local_var_error = ResponseContent {
1082            status: local_var_status,
1083            content: local_var_content,
1084            entity: local_var_entity,
1085            retry_delay: local_var_retry_delay,
1086        };
1087        Err(Error::ResponseError(local_var_error))
1088    }
1089}
1090
1091pub async fn list_instruction_set_architectures(
1092    configuration: &configuration::Configuration,
1093    page_size: Option<u64>,
1094    page_token: Option<&str>,
1095) -> Result<
1096    models::ListInstructionSetArchitectureResponse,
1097    Error<ListInstructionSetArchitecturesError>,
1098> {
1099    let mut backoff = configuration.backoff.build();
1100    let mut refreshed_credentials = false;
1101    let method = reqwest::Method::GET;
1102    loop {
1103        let result = list_instruction_set_architectures_inner(
1104            configuration,
1105            &mut backoff,
1106            page_size.clone(),
1107            page_token.clone(),
1108        )
1109        .await;
1110
1111        match result {
1112            Ok(result) => return Ok(result),
1113            Err(Error::ResponseError(response)) => {
1114                if !refreshed_credentials
1115                    && matches!(
1116                        response.status,
1117                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
1118                    )
1119                {
1120                    // Attempt to refresh credentials
1121                    match configuration.qcs_config.refresh().await {
1122                        Ok(_) => {
1123                            refreshed_credentials = true;
1124                            continue;
1125                        }
1126                        Err(::qcs_api_client_common::configuration::TokenError::Write {
1127                            error,
1128                            oauth_session: _,
1129                        }) => {
1130                            // Token refresh succeeded but persistence failed
1131                            // The token is already in memory and will be used for this request
1132                            #[cfg(feature = "tracing")]
1133                            tracing::warn!(
1134                                "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
1135                                error
1136                            );
1137                            refreshed_credentials = true;
1138                            continue;
1139                        }
1140                        Err(e) => return Err(e.into()),
1141                    }
1142                } else if let Some(duration) = response.retry_delay {
1143                    tokio::time::sleep(duration).await;
1144                    continue;
1145                }
1146
1147                return Err(Error::ResponseError(response));
1148            }
1149            Err(Error::Reqwest(error)) => {
1150                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
1151                    tokio::time::sleep(duration).await;
1152                    continue;
1153                }
1154
1155                return Err(Error::Reqwest(error));
1156            }
1157            Err(Error::Io(error)) => {
1158                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
1159                    tokio::time::sleep(duration).await;
1160                    continue;
1161                }
1162
1163                return Err(Error::Io(error));
1164            }
1165            Err(error) => return Err(error),
1166        }
1167    }
1168}
1169async fn list_quantum_processors_inner(
1170    configuration: &configuration::Configuration,
1171    backoff: &mut ExponentialBackoff,
1172    page_size: Option<u64>,
1173    page_token: Option<&str>,
1174) -> Result<models::ListQuantumProcessorsResponse, Error<ListQuantumProcessorsError>> {
1175    let local_var_configuration = configuration;
1176    // add a prefix to parameters to efficiently prevent name collisions
1177    let p_query_page_size = page_size;
1178    let p_query_page_token = page_token;
1179
1180    let local_var_client = &local_var_configuration.client;
1181
1182    let local_var_uri_str = format!(
1183        "{}/v1/quantumProcessors",
1184        local_var_configuration.qcs_config.api_url()
1185    );
1186    let mut local_var_req_builder =
1187        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
1188
1189    #[cfg(feature = "tracing")]
1190    {
1191        // Ignore parsing errors if the URL is invalid for some reason.
1192        // If it is invalid, it will turn up as an error later when actually making the request.
1193        let local_var_do_tracing = local_var_uri_str
1194            .parse::<::url::Url>()
1195            .ok()
1196            .is_none_or(|url| {
1197                configuration
1198                    .qcs_config
1199                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
1200            });
1201
1202        if local_var_do_tracing {
1203            ::tracing::debug!(
1204                url=%local_var_uri_str,
1205                method="GET",
1206                "making list_quantum_processors request",
1207            );
1208        }
1209    }
1210
1211    if let Some(ref local_var_str) = p_query_page_size {
1212        local_var_req_builder =
1213            local_var_req_builder.query(&[("pageSize", &local_var_str.to_string())]);
1214    }
1215    if let Some(ref local_var_str) = p_query_page_token {
1216        local_var_req_builder =
1217            local_var_req_builder.query(&[("pageToken", &local_var_str.to_string())]);
1218    }
1219
1220    // Use the QCS Bearer token if a client OAuthSession is present,
1221    // but do not require one when the security schema says it is optional.
1222    {
1223        use qcs_api_client_common::configuration::TokenError;
1224
1225        #[allow(
1226            clippy::nonminimal_bool,
1227            clippy::eq_op,
1228            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
1229        )]
1230        let is_jwt_bearer_optional: bool = false || "JWTBearerOptional" == "JWTBearerOptional";
1231
1232        let token = local_var_configuration
1233            .qcs_config
1234            .get_bearer_access_token()
1235            .await;
1236
1237        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
1238            // the client is configured without any OAuthSession, but this call does not require one.
1239            #[cfg(feature = "tracing")]
1240            tracing::debug!(
1241                "No client credentials found, but this call does not require authentication."
1242            );
1243        } else {
1244            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
1245        }
1246    }
1247
1248    let local_var_req = local_var_req_builder.build()?;
1249    let local_var_resp = local_var_client.execute(local_var_req).await?;
1250
1251    let local_var_status = local_var_resp.status();
1252    let local_var_raw_content_type = local_var_resp
1253        .headers()
1254        .get("content-type")
1255        .and_then(|v| v.to_str().ok())
1256        .unwrap_or("application/octet-stream")
1257        .to_string();
1258    let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
1259
1260    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
1261        let local_var_content = local_var_resp.text().await?;
1262        match local_var_content_type {
1263            ContentType::Json => serde_path_to_error::deserialize(
1264                &mut serde_json::Deserializer::from_str(&local_var_content),
1265            )
1266            .map_err(Error::from),
1267            ContentType::Text => Err(Error::InvalidContentType {
1268                content_type: local_var_raw_content_type,
1269                return_type: "models::ListQuantumProcessorsResponse",
1270            }),
1271            ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
1272                content_type: unknown_type,
1273                return_type: "models::ListQuantumProcessorsResponse",
1274            }),
1275        }
1276    } else {
1277        let local_var_retry_delay =
1278            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
1279        let local_var_content = local_var_resp.text().await?;
1280        let local_var_entity: Option<ListQuantumProcessorsError> =
1281            serde_json::from_str(&local_var_content).ok();
1282        let local_var_error = ResponseContent {
1283            status: local_var_status,
1284            content: local_var_content,
1285            entity: local_var_entity,
1286            retry_delay: local_var_retry_delay,
1287        };
1288        Err(Error::ResponseError(local_var_error))
1289    }
1290}
1291
1292/// List the [`QuantumProcessor`]s that this user is authorized to access.  If no auth token is provided, only public processors will be returned.
1293pub async fn list_quantum_processors(
1294    configuration: &configuration::Configuration,
1295    page_size: Option<u64>,
1296    page_token: Option<&str>,
1297) -> Result<models::ListQuantumProcessorsResponse, Error<ListQuantumProcessorsError>> {
1298    let mut backoff = configuration.backoff.build();
1299    let mut refreshed_credentials = false;
1300    let method = reqwest::Method::GET;
1301    loop {
1302        let result = list_quantum_processors_inner(
1303            configuration,
1304            &mut backoff,
1305            page_size.clone(),
1306            page_token.clone(),
1307        )
1308        .await;
1309
1310        match result {
1311            Ok(result) => return Ok(result),
1312            Err(Error::ResponseError(response)) => {
1313                if !refreshed_credentials
1314                    && matches!(
1315                        response.status,
1316                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
1317                    )
1318                {
1319                    // Attempt to refresh credentials
1320                    match configuration.qcs_config.refresh().await {
1321                        Ok(_) => {
1322                            refreshed_credentials = true;
1323                            continue;
1324                        }
1325                        Err(::qcs_api_client_common::configuration::TokenError::Write {
1326                            error,
1327                            oauth_session: _,
1328                        }) => {
1329                            // Token refresh succeeded but persistence failed
1330                            // The token is already in memory and will be used for this request
1331                            #[cfg(feature = "tracing")]
1332                            tracing::warn!(
1333                                "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
1334                                error
1335                            );
1336                            refreshed_credentials = true;
1337                            continue;
1338                        }
1339                        Err(e) => return Err(e.into()),
1340                    }
1341                } else if let Some(duration) = response.retry_delay {
1342                    tokio::time::sleep(duration).await;
1343                    continue;
1344                }
1345
1346                return Err(Error::ResponseError(response));
1347            }
1348            Err(Error::Reqwest(error)) => {
1349                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
1350                    tokio::time::sleep(duration).await;
1351                    continue;
1352                }
1353
1354                return Err(Error::Reqwest(error));
1355            }
1356            Err(Error::Io(error)) => {
1357                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
1358                    tokio::time::sleep(duration).await;
1359                    continue;
1360                }
1361
1362                return Err(Error::Io(error));
1363            }
1364            Err(error) => return Err(error),
1365        }
1366    }
1367}