Consider a way to get the operation name from the poller
When we create a poller, such as in:
https://github.com/googleapis/google-cloud-rust/blob/9f00dffe46fe5d50d9f7e3181c7e65d85be4ac8d/guide/samples/src/lro.rs#L118-L139
One may want to cancel the polling operation after a few iterations, or otherwise save it for future use. We need a way to get the operation name, and maybe even a way to start a poller given the operation name (and the types).
For this issue we need to determine if such a change would require a breaking change or not. If it does not require a breaking change, we save the design and we can remove this issue from the milestone. If we do need a breaking change then we need to fix it.
I just prototyped a solution and it does not require changing any APIs. I am removing this from the stabilization milestone.
While no breaking changes are needed, I cannot get this to work without larger changes to *-wkt. I am going to save the main ideas so we can do this later.
Background
The basic idea is to extend the Poller trait to include a suspend(self) method. The implementation looks like this:
fn suspend(self) -> Option<super::PollerSnapshot<ResponseType, MetadataType>> {
self.operation.map(|name| super::PollerSnapshot::new(name))
}
As you would expect, the PollerSnapshot holds the name of the operation and the types:
#[derive(Clone, Debug, PartialEq)]
pub struct PollerSnapshot<R, M> {
name: String,
response: PhantomData<R>,
metadata: PhantomData<M>,
}
We would want to implement a resume_poller function in the client. Returning a builder (so we can add polling options):
pub fn resume_poller<R, M>(
&self,
snapshot: lro::PollerSnapshot<R, M>,
) -> super::builder::workflows::ResumePoller<R, M>
The builder would provide a resume() function:
pub fn resume(self) -> impl lro::Poller<R, M> {
// ... skip some stuff ...
lro::internal::new_poller(polling_error_policy, polling_backoff_policy, start, query)
}
Problem
The issue is working with unit types. To call new_poller() you need R and M to satisfy a number of bounds:
R: wkt::message::Message
+ serde::ser::Serialize
+ serde::de::DeserializeOwned
+ Send
+ Sync
+ 'static,
But () does not implement wkt::message::Message. I am not sure I want to introduce that implementation. And no amount of trickery will allow us to inject a new trait implementation generic on T: wkt::message::Message and also on ().
Useful ideas for any future implementation
The implementation of resume() uses GetOperation() for both start and query:
pub fn resume(self) -> impl lro::Poller<R, M> {
let stub = self.inner.stub.clone();
let mut options = self.inner.options.clone();
options.set_retry_policy(gax::retry_policy::NeverRetry);
let query = move |name| {
let stub = stub.clone();
let options = options.clone();
async {
let op = GetOperation::new(stub)
.set_name(name)
.with_options(options)
.send()
.await?;
Ok(lro::internal::Operation::<R, M>::new(op))
}
};
let inner = query.clone();
let snapshot = self.snapshot;
let start = move || {
let name = snapshot.name().to_string();
let q = inner.clone();
async move { q(name).await }
};
let polling_error_policy = self
.inner
.stub
.get_polling_error_policy(&self.inner.options);
let polling_backoff_policy = self
.inner
.stub
.get_polling_backoff_policy(&self.inner.options);
lro::internal::new_poller(polling_error_policy, polling_backoff_policy, start, query)
}