Skip to content

[Rust] Async await - #4210

Closed
dbcfd wants to merge 2 commits into
OpenAPITools:masterfrom
dbcfd:async-await
Closed

[Rust] Async await#4210
dbcfd wants to merge 2 commits into
OpenAPITools:masterfrom
dbcfd:async-await

Conversation

@dbcfd

@dbcfddbcfd commented Oct 21, 2019

Copy link
Copy Markdown

Addresses #3865

Upgrade to use async/await by bringing in appropriate alpha releases for tokio, hyper, and reqwest. Also bring in async-trait to make api usage a little cleaner.

Requires beta compiler for Rust compiler. Expected to not be merged until after 1.39 is released.

  • Read the contribution guidelines.
  • If contributing template-only or documentation-only changes which will change sample output, build the project before.
  • Run the shell script(s) under ./bin/ (or Windows batch scripts under.\bin\windows) to update Petstore samples related to your fix. This is important, as CI jobs will verify all generator outputs of your HEAD commit, and these must match the expectations made by your contribution. You only need to run ./bin/{LANG}-petstore.sh, ./bin/openapi3/{LANG}-petstore.sh if updating the code or mustache templates for a language ({LANG}) (e.g. php, ruby, python, etc).
  • File the PR against the correct branch: master, 4.1.x, 5.0.x. Default: master.
  • Copy the technical committee to review the pull request if your PR is targeting a particular programming language.

/cc @frol@farcaller@bjgill@richardwhiuk

@auto-labeler

Copy link
Copy Markdown

👍 Thanks for opening this issue!
🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

@auto-labelerauto-labelerBot added the WIP Work in Progress label Oct 21, 2019
@JohnDoneth

JohnDoneth commented Oct 21, 2019

Copy link
Copy Markdown

LGTM! Exciting work. I like the use of async-trait to keep the API as a trait and still async. 👍

One small nit. It would be nice if the generated API functions were generated as follows:

asyncfnadd_pet(&self,body:crate::models::Pet) -> Result<(), serde_json::Value>;

... instead of the lengthier but equivalent:

fnadd_pet(&self,body:crate::models::Pet) -> Box<Future<Item = (),Error = Error<serde_json::Value>>>;

@dbcfd

dbcfd commented Oct 21, 2019

Copy link
Copy Markdown
Author

@JohnDoneth They will. Haven't run the bash scripts to update the examples yet.

Example from generated code

#[async_trait]pubtraitPetApi{asyncfnadd_pet(&self,body:crate::models::Pet) -> Result<(),Error<serde_json::Value>>;asyncfndelete_pet(&self,pet_id:i64,api_key:Option<&str>) -> Result<(),Error<serde_json::Value>>;asyncfnfind_pets_by_status(&self,status:Vec<String>) -> Result<Vec<crate::models::Pet>,Error<serde_json::Value>>;asyncfnfind_pets_by_tags(&self,tags:Vec<String>) -> Result<Vec<crate::models::Pet>,Error<serde_json::Value>>;asyncfnget_pet_by_id(&self,pet_id:i64) -> Result<crate::models::Pet,Error<serde_json::Value>>;asyncfnupdate_pet(&self,body:crate::models::Pet) -> Result<(),Error<serde_json::Value>>;asyncfnupdate_pet_with_form(&self,pet_id:i64,name:Option<&str>,status:Option<&str>) -> Result<(),Error<serde_json::Value>>;asyncfnupload_file(&self,pet_id:i64,additional_metadata:Option<&str>,file:Option<std::path::PathBuf>) -> Result<crate::models::ApiResponse,Error<serde_json::Value>>;}

@richardwhiuk

Copy link
Copy Markdown
Contributor

As per Metaswitch/swagger-rs#83, we'll want to wait for Hyper 0.13 to come out of beta before merging this.

@ctaggart

Copy link
Copy Markdown

@dbcfd, I'm trying out this branch and with -library=reqwest, the first error I ran into was

error[E0599]: no method named `PUT` found for type `&reqwest::async_impl::client::Client` in the current scope

currently:

letmut req_builder = client.PUT(uri_str.as_str());

should be:

letmut req_builder = client.put(uri_str.as_str());

It is named put, not PUT for reqwest.
https://github.com/seanmonstar/reqwest/blob/master/src/async_impl/client.rs#L648

operation.httpMethod = StringUtils.camelize(operation.httpMethod.toLowerCase(Locale.ROOT));
operation.httpMethod = StringUtils.camelize(operation.httpMethod);
} else if (REQWEST_LIBRARY.equals(getLibrary())) {
operation.httpMethod = operation.httpMethod.toLowerCase(Locale.ROOT);

@ctaggartctaggartNov 12, 2019

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be leave this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's places that require the method (e.g. .method(PUT)). Thought I had got this working, but have been working on server, so will revisit.

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart Yeah, it's still very much wip, since both hyper and reqwest are changing. Even more so, swagger-rs would take significant changes that I can't test easily, so currently just using the context portion of it to make progress. Will push up my latest work so that if people want to pitch in they can. It's a pretty signficant effort.

@ctaggart

Copy link
Copy Markdown

For our needs, these are the changes I made for the reqwest client templates ctaggart#1

  • add support for custom_auth closure
  • remove async_trait
  • use Confguration with lifetime instead of Arc

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart can you explain the async_trait removal? Changing client from a trait to just an implementation, so not needed?

@ctaggart

Copy link
Copy Markdown

It is still early days for https://github.com/dtolnay/async-trait. I hit some lifetime issues that I didn't want to troubleshoot. Our cli app doesn't need the traits or that additional dependency. I suspect that most probably don't.

@ctaggart

Copy link
Copy Markdown

It may also be a good idea to implement std::error::Error for the custom error. ctaggart@5bd94ea

@kanekv

Copy link
Copy Markdown

What can we do to speed up this effort? Anything we can help with?

@dbcfd

Copy link
Copy Markdown
Author

@kanekv One would be to update swagger-rs to work with latest hyper. I've temporarily forked just the changes needed for this library in https://github.com/dbcfd/openapi-context. Updating swagger-rs to latest hyper is a much larger effort, but one that will need to be done.

@kanekv

Copy link
Copy Markdown

@dbcfd Is it a blocker or we can just continue with your approach?

@dbcfd

Copy link
Copy Markdown
Author

@kanekv it will definitely be a blocker for final merge, unless we want to roll the context stuff into this crate.

If you're looking specifically for work on this repo, the client generator needs a revisit, pulling in some of @ctaggart changes. I've also pushed up my work on the server generator code. I likely won't have time over the next week to work on that, so feel free to work on that as well.

@kanekv

Copy link
Copy Markdown

@dbcfd Not necessarily for this repo, just looking how we can coordinate the work and get it moving. Who is working on swagger-rs transition? Is there any way we can parallelize it?

@dbcfd

Copy link
Copy Markdown
Author

I was looking at the swagger-rs transition, but realized it was fairly large on its own right, and I didn't have a great way to test the changes I would have to make. That's where the openapi-context fork came from.

The client generator and the server generator are mostly distinct from each other, so one person could finish up the client portion and split it out as its own MR.

@kanekv

Copy link
Copy Markdown

Would it be beneficial to assume we can roll context stuff in (temporarily) and make client/server based on that assumption and also get it merged until we figure out what to do with swagger-rs, at that point we can switch it back?

@dbcfd

Copy link
Copy Markdown
Author

Yeah, we could publish openapi-context as a crate, then switch to swagger-rs when it is ready. Client/server could then be worked as publishable using openapi-context crate.

@UkonnRa

Copy link
Copy Markdown
Contributor

Cool, any update?

@dbcfd

Copy link
Copy Markdown
Author

Almost have the example generated code working. Hoping to get it finished up today. At that point it should be good for people to experiment with.

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart reqwest client should work now, in addition to hyper client and the server module.

@dbcfd

Copy link
Copy Markdown
Author

@JohnDoneth samples have been updated with the result of this work now.

@UkonnRa

Copy link
Copy Markdown
Contributor

ping~

@bcourtine

Copy link
Copy Markdown
Contributor

Great job @dbcfd!

But I think replacing the current "reqwest" generator with an async version is not a good idea:
some people can prefer using a "sync" version, or can have a pre 1.39 version as requirement.

So, the two versions (sync and async) should coexist (with a generator parameter, or with a new library "reqwest-async" for example).

@dbcfd

Copy link
Copy Markdown
Author

@bcourtine The reqwest client is by default async now, and blocking is under a different api. Leaving the default reqwest client as blocking will require a PR as well.

There's a couple of ways to move this PR forward:

  • Release as is
  • Release with async flagged similar to how reqwest is
  • Create new generators, rust-async and rust-server-async

Release as is
Given that hyper and reqwest are both async by default and require 1.39, this is my preferred approach. The alternative is to keep openapi on older versions of tokio, hyper, reqwest, etc. One can achieve a synchronous interface to reqwest by doing what reqwest blocking is doing, where it runs the async functionality on a thread pool.

Release with async flagged
This not only suffers from maintaining a version on older crates, but complicates the generation as well.

Create new generators
This requires maintaining two generators, one which is on unsupported libraries, but works pre 1.39. And a second generator which requires 1.39 or higher and is on supported libraries. Given the usefulness of async/await, I don't see the old generator getting much use.

Thoughts?

@bcourtine

Copy link
Copy Markdown
Contributor

Hi @dbcfd,

I personally like a lot async/await, and the language/crates moving forward is a good thing ;-)

But Rust 1.39 was only released 3 months ago. Even if Rust is moving fast, considering a 4 months old Rust version deprecated and not supported anymore by openapi-generator seems harsh.

@wing328 What is your opinion?

@dbcfd

Copy link
Copy Markdown
Author

@bcourtine I meant the versions of the crates tokio, hyper, reqwest, etc. being deprecated. The current versions of those crates all require 1.39 or higher.

@bcourtine

Copy link
Copy Markdown
Contributor

I agree, but theses crates still have support for a pre-1.39 version ;)

@dbcfd

dbcfd commented Feb 14, 2020

Copy link
Copy Markdown
Author

@bcourtine Although these crates have pre 1.39 versions, they are not supported. Attempting to use the currently supported crates (e.g. hyper 0.13) on a 1.38 compiler will fail.

info: default toolchain set to '1.38.0-x86_64-apple-darwin'
1.38.0-x86_64-apple-darwin installed - rustc 1.38.0 (625451e37 2019-09-23)
$ cd code/rust/
$ cargo new --lib hyper-test
Created library `hyper-test` package
$ cd hyper-test/
$ vi Cargo.toml
$ cargo build
Compiling tower-service v0.3.0
error: `core::slice::<impl [T]>::len` is not yet stable as a const fn
--> /Users/dannybrowning/.cargo/registry/src/github.com-1ecc6299db9ec823/bytes-0.5.4/src/bytes.rs:130:18
|
130 | len: bytes.len(),
| ^^^^^^^^^^^
error: aborting due to previous error

@dbcfddbcfd changed the title [WIP] [Rust] Async await[Rust] Async awaitApr 27, 2020
@dbcfddbcfd mentioned this pull request May 3, 2020
5 tasks
Incorporate hyper and reqwest with async/await support. Bring in async-trait to simplify async trait interaction.
@wing328

wing328 commented Jun 16, 2020

Copy link
Copy Markdown
Member

@dbcfd I've added an option to support async operations for reqwest.

I wonder if you can pull the latest master to give it a try.

@wing328

Copy link
Copy Markdown
Member

Closing as there's no update.

@wing328wing328 closed this Jan 25, 2021
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

WIPWork in Progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@dbcfd@JohnDoneth@richardwhiuk@ctaggart@kanekv@UkonnRa@bcourtine@wing328
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
[Rust] Async await by dbcfd · Pull Request #4210 · OpenAPITools/openapi-generator · GitHub
Skip to content

[Rust] Async await - #4210

Closed
dbcfd wants to merge 2 commits into
OpenAPITools:masterfrom
dbcfd:async-await
Closed

[Rust] Async await#4210
dbcfd wants to merge 2 commits into
OpenAPITools:masterfrom
dbcfd:async-await

Conversation

@dbcfd

@dbcfddbcfd commented Oct 21, 2019

Copy link
Copy Markdown

Addresses #3865

Upgrade to use async/await by bringing in appropriate alpha releases for tokio, hyper, and reqwest. Also bring in async-trait to make api usage a little cleaner.

Requires beta compiler for Rust compiler. Expected to not be merged until after 1.39 is released.

  • Read the contribution guidelines.
  • If contributing template-only or documentation-only changes which will change sample output, build the project before.
  • Run the shell script(s) under ./bin/ (or Windows batch scripts under.\bin\windows) to update Petstore samples related to your fix. This is important, as CI jobs will verify all generator outputs of your HEAD commit, and these must match the expectations made by your contribution. You only need to run ./bin/{LANG}-petstore.sh, ./bin/openapi3/{LANG}-petstore.sh if updating the code or mustache templates for a language ({LANG}) (e.g. php, ruby, python, etc).
  • File the PR against the correct branch: master, 4.1.x, 5.0.x. Default: master.
  • Copy the technical committee to review the pull request if your PR is targeting a particular programming language.

/cc @frol@farcaller@bjgill@richardwhiuk

@auto-labeler

Copy link
Copy Markdown

👍 Thanks for opening this issue!
🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

@auto-labelerauto-labelerBot added the WIP Work in Progress label Oct 21, 2019
@JohnDoneth

JohnDoneth commented Oct 21, 2019

Copy link
Copy Markdown

LGTM! Exciting work. I like the use of async-trait to keep the API as a trait and still async. 👍

One small nit. It would be nice if the generated API functions were generated as follows:

asyncfnadd_pet(&self,body:crate::models::Pet) -> Result<(), serde_json::Value>;

... instead of the lengthier but equivalent:

fnadd_pet(&self,body:crate::models::Pet) -> Box<Future<Item = (),Error = Error<serde_json::Value>>>;

@dbcfd

dbcfd commented Oct 21, 2019

Copy link
Copy Markdown
Author

@JohnDoneth They will. Haven't run the bash scripts to update the examples yet.

Example from generated code

#[async_trait]pubtraitPetApi{asyncfnadd_pet(&self,body:crate::models::Pet) -> Result<(),Error<serde_json::Value>>;asyncfndelete_pet(&self,pet_id:i64,api_key:Option<&str>) -> Result<(),Error<serde_json::Value>>;asyncfnfind_pets_by_status(&self,status:Vec<String>) -> Result<Vec<crate::models::Pet>,Error<serde_json::Value>>;asyncfnfind_pets_by_tags(&self,tags:Vec<String>) -> Result<Vec<crate::models::Pet>,Error<serde_json::Value>>;asyncfnget_pet_by_id(&self,pet_id:i64) -> Result<crate::models::Pet,Error<serde_json::Value>>;asyncfnupdate_pet(&self,body:crate::models::Pet) -> Result<(),Error<serde_json::Value>>;asyncfnupdate_pet_with_form(&self,pet_id:i64,name:Option<&str>,status:Option<&str>) -> Result<(),Error<serde_json::Value>>;asyncfnupload_file(&self,pet_id:i64,additional_metadata:Option<&str>,file:Option<std::path::PathBuf>) -> Result<crate::models::ApiResponse,Error<serde_json::Value>>;}

@richardwhiuk

Copy link
Copy Markdown
Contributor

As per Metaswitch/swagger-rs#83, we'll want to wait for Hyper 0.13 to come out of beta before merging this.

@ctaggart

Copy link
Copy Markdown

@dbcfd, I'm trying out this branch and with -library=reqwest, the first error I ran into was

error[E0599]: no method named `PUT` found for type `&reqwest::async_impl::client::Client` in the current scope

currently:

letmut req_builder = client.PUT(uri_str.as_str());

should be:

letmut req_builder = client.put(uri_str.as_str());

It is named put, not PUT for reqwest.
https://github.com/seanmonstar/reqwest/blob/master/src/async_impl/client.rs#L648

operation.httpMethod = StringUtils.camelize(operation.httpMethod.toLowerCase(Locale.ROOT));
operation.httpMethod = StringUtils.camelize(operation.httpMethod);
} else if (REQWEST_LIBRARY.equals(getLibrary())) {
operation.httpMethod = operation.httpMethod.toLowerCase(Locale.ROOT);

@ctaggartctaggartNov 12, 2019

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be leave this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's places that require the method (e.g. .method(PUT)). Thought I had got this working, but have been working on server, so will revisit.

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart Yeah, it's still very much wip, since both hyper and reqwest are changing. Even more so, swagger-rs would take significant changes that I can't test easily, so currently just using the context portion of it to make progress. Will push up my latest work so that if people want to pitch in they can. It's a pretty signficant effort.

@ctaggart

Copy link
Copy Markdown

For our needs, these are the changes I made for the reqwest client templates ctaggart#1

  • add support for custom_auth closure
  • remove async_trait
  • use Confguration with lifetime instead of Arc

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart can you explain the async_trait removal? Changing client from a trait to just an implementation, so not needed?

@ctaggart

Copy link
Copy Markdown

It is still early days for https://github.com/dtolnay/async-trait. I hit some lifetime issues that I didn't want to troubleshoot. Our cli app doesn't need the traits or that additional dependency. I suspect that most probably don't.

@ctaggart

Copy link
Copy Markdown

It may also be a good idea to implement std::error::Error for the custom error. ctaggart@5bd94ea

@kanekv

Copy link
Copy Markdown

What can we do to speed up this effort? Anything we can help with?

@dbcfd

Copy link
Copy Markdown
Author

@kanekv One would be to update swagger-rs to work with latest hyper. I've temporarily forked just the changes needed for this library in https://github.com/dbcfd/openapi-context. Updating swagger-rs to latest hyper is a much larger effort, but one that will need to be done.

@kanekv

Copy link
Copy Markdown

@dbcfd Is it a blocker or we can just continue with your approach?

@dbcfd

Copy link
Copy Markdown
Author

@kanekv it will definitely be a blocker for final merge, unless we want to roll the context stuff into this crate.

If you're looking specifically for work on this repo, the client generator needs a revisit, pulling in some of @ctaggart changes. I've also pushed up my work on the server generator code. I likely won't have time over the next week to work on that, so feel free to work on that as well.

@kanekv

Copy link
Copy Markdown

@dbcfd Not necessarily for this repo, just looking how we can coordinate the work and get it moving. Who is working on swagger-rs transition? Is there any way we can parallelize it?

@dbcfd

Copy link
Copy Markdown
Author

I was looking at the swagger-rs transition, but realized it was fairly large on its own right, and I didn't have a great way to test the changes I would have to make. That's where the openapi-context fork came from.

The client generator and the server generator are mostly distinct from each other, so one person could finish up the client portion and split it out as its own MR.

@kanekv

Copy link
Copy Markdown

Would it be beneficial to assume we can roll context stuff in (temporarily) and make client/server based on that assumption and also get it merged until we figure out what to do with swagger-rs, at that point we can switch it back?

@dbcfd

Copy link
Copy Markdown
Author

Yeah, we could publish openapi-context as a crate, then switch to swagger-rs when it is ready. Client/server could then be worked as publishable using openapi-context crate.

@UkonnRa

Copy link
Copy Markdown
Contributor

Cool, any update?

@dbcfd

Copy link
Copy Markdown
Author

Almost have the example generated code working. Hoping to get it finished up today. At that point it should be good for people to experiment with.

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart reqwest client should work now, in addition to hyper client and the server module.

@dbcfd

Copy link
Copy Markdown
Author

@JohnDoneth samples have been updated with the result of this work now.

@UkonnRa

Copy link
Copy Markdown
Contributor

ping~

@bcourtine

Copy link
Copy Markdown
Contributor

Great job @dbcfd!

But I think replacing the current "reqwest" generator with an async version is not a good idea:
some people can prefer using a "sync" version, or can have a pre 1.39 version as requirement.

So, the two versions (sync and async) should coexist (with a generator parameter, or with a new library "reqwest-async" for example).

@dbcfd

Copy link
Copy Markdown
Author

@bcourtine The reqwest client is by default async now, and blocking is under a different api. Leaving the default reqwest client as blocking will require a PR as well.

There's a couple of ways to move this PR forward:

  • Release as is
  • Release with async flagged similar to how reqwest is
  • Create new generators, rust-async and rust-server-async

Release as is
Given that hyper and reqwest are both async by default and require 1.39, this is my preferred approach. The alternative is to keep openapi on older versions of tokio, hyper, reqwest, etc. One can achieve a synchronous interface to reqwest by doing what reqwest blocking is doing, where it runs the async functionality on a thread pool.

Release with async flagged
This not only suffers from maintaining a version on older crates, but complicates the generation as well.

Create new generators
This requires maintaining two generators, one which is on unsupported libraries, but works pre 1.39. And a second generator which requires 1.39 or higher and is on supported libraries. Given the usefulness of async/await, I don't see the old generator getting much use.

Thoughts?

@bcourtine

Copy link
Copy Markdown
Contributor

Hi @dbcfd,

I personally like a lot async/await, and the language/crates moving forward is a good thing ;-)

But Rust 1.39 was only released 3 months ago. Even if Rust is moving fast, considering a 4 months old Rust version deprecated and not supported anymore by openapi-generator seems harsh.

@wing328 What is your opinion?

@dbcfd

Copy link
Copy Markdown
Author

@bcourtine I meant the versions of the crates tokio, hyper, reqwest, etc. being deprecated. The current versions of those crates all require 1.39 or higher.

@bcourtine

Copy link
Copy Markdown
Contributor

I agree, but theses crates still have support for a pre-1.39 version ;)

@dbcfd

dbcfd commented Feb 14, 2020

Copy link
Copy Markdown
Author

@bcourtine Although these crates have pre 1.39 versions, they are not supported. Attempting to use the currently supported crates (e.g. hyper 0.13) on a 1.38 compiler will fail.

info: default toolchain set to '1.38.0-x86_64-apple-darwin'
1.38.0-x86_64-apple-darwin installed - rustc 1.38.0 (625451e37 2019-09-23)
$ cd code/rust/
$ cargo new --lib hyper-test
Created library `hyper-test` package
$ cd hyper-test/
$ vi Cargo.toml
$ cargo build
Compiling tower-service v0.3.0
error: `core::slice::<impl [T]>::len` is not yet stable as a const fn
--> /Users/dannybrowning/.cargo/registry/src/github.com-1ecc6299db9ec823/bytes-0.5.4/src/bytes.rs:130:18
|
130 | len: bytes.len(),
| ^^^^^^^^^^^
error: aborting due to previous error

@dbcfddbcfd changed the title [WIP] [Rust] Async await[Rust] Async awaitApr 27, 2020
@dbcfddbcfd mentioned this pull request May 3, 2020
5 tasks
Incorporate hyper and reqwest with async/await support. Bring in async-trait to simplify async trait interaction.
@wing328

wing328 commented Jun 16, 2020

Copy link
Copy Markdown
Member

@dbcfd I've added an option to support async operations for reqwest.

I wonder if you can pull the latest master to give it a try.

@wing328

Copy link
Copy Markdown
Member

Closing as there's no update.

@wing328wing328 closed this Jan 25, 2021
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

WIPWork in Progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@dbcfd@JohnDoneth@richardwhiuk@ctaggart@kanekv@UkonnRa@bcourtine@wing328
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [Rust] Async await by dbcfd · Pull Request #4210 · OpenAPITools/openapi-generator · GitHub
Skip to content

[Rust] Async await - #4210

Closed
dbcfd wants to merge 2 commits into
OpenAPITools:masterfrom
dbcfd:async-await
Closed

[Rust] Async await#4210
dbcfd wants to merge 2 commits into
OpenAPITools:masterfrom
dbcfd:async-await

Conversation

@dbcfd

@dbcfddbcfd commented Oct 21, 2019

Copy link
Copy Markdown

Addresses #3865

Upgrade to use async/await by bringing in appropriate alpha releases for tokio, hyper, and reqwest. Also bring in async-trait to make api usage a little cleaner.

Requires beta compiler for Rust compiler. Expected to not be merged until after 1.39 is released.

  • Read the contribution guidelines.
  • If contributing template-only or documentation-only changes which will change sample output, build the project before.
  • Run the shell script(s) under ./bin/ (or Windows batch scripts under.\bin\windows) to update Petstore samples related to your fix. This is important, as CI jobs will verify all generator outputs of your HEAD commit, and these must match the expectations made by your contribution. You only need to run ./bin/{LANG}-petstore.sh, ./bin/openapi3/{LANG}-petstore.sh if updating the code or mustache templates for a language ({LANG}) (e.g. php, ruby, python, etc).
  • File the PR against the correct branch: master, 4.1.x, 5.0.x. Default: master.
  • Copy the technical committee to review the pull request if your PR is targeting a particular programming language.

/cc @frol@farcaller@bjgill@richardwhiuk

@auto-labeler

Copy link
Copy Markdown

👍 Thanks for opening this issue!
🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

@auto-labelerauto-labelerBot added the WIP Work in Progress label Oct 21, 2019
@JohnDoneth

JohnDoneth commented Oct 21, 2019

Copy link
Copy Markdown

LGTM! Exciting work. I like the use of async-trait to keep the API as a trait and still async. 👍

One small nit. It would be nice if the generated API functions were generated as follows:

asyncfnadd_pet(&self,body:crate::models::Pet) -> Result<(), serde_json::Value>;

... instead of the lengthier but equivalent:

fnadd_pet(&self,body:crate::models::Pet) -> Box<Future<Item = (),Error = Error<serde_json::Value>>>;

@dbcfd

dbcfd commented Oct 21, 2019

Copy link
Copy Markdown
Author

@JohnDoneth They will. Haven't run the bash scripts to update the examples yet.

Example from generated code

#[async_trait]pubtraitPetApi{asyncfnadd_pet(&self,body:crate::models::Pet) -> Result<(),Error<serde_json::Value>>;asyncfndelete_pet(&self,pet_id:i64,api_key:Option<&str>) -> Result<(),Error<serde_json::Value>>;asyncfnfind_pets_by_status(&self,status:Vec<String>) -> Result<Vec<crate::models::Pet>,Error<serde_json::Value>>;asyncfnfind_pets_by_tags(&self,tags:Vec<String>) -> Result<Vec<crate::models::Pet>,Error<serde_json::Value>>;asyncfnget_pet_by_id(&self,pet_id:i64) -> Result<crate::models::Pet,Error<serde_json::Value>>;asyncfnupdate_pet(&self,body:crate::models::Pet) -> Result<(),Error<serde_json::Value>>;asyncfnupdate_pet_with_form(&self,pet_id:i64,name:Option<&str>,status:Option<&str>) -> Result<(),Error<serde_json::Value>>;asyncfnupload_file(&self,pet_id:i64,additional_metadata:Option<&str>,file:Option<std::path::PathBuf>) -> Result<crate::models::ApiResponse,Error<serde_json::Value>>;}

@richardwhiuk

Copy link
Copy Markdown
Contributor

As per Metaswitch/swagger-rs#83, we'll want to wait for Hyper 0.13 to come out of beta before merging this.

@ctaggart

Copy link
Copy Markdown

@dbcfd, I'm trying out this branch and with -library=reqwest, the first error I ran into was

error[E0599]: no method named `PUT` found for type `&reqwest::async_impl::client::Client` in the current scope

currently:

letmut req_builder = client.PUT(uri_str.as_str());

should be:

letmut req_builder = client.put(uri_str.as_str());

It is named put, not PUT for reqwest.
https://github.com/seanmonstar/reqwest/blob/master/src/async_impl/client.rs#L648

operation.httpMethod = StringUtils.camelize(operation.httpMethod.toLowerCase(Locale.ROOT));
operation.httpMethod = StringUtils.camelize(operation.httpMethod);
} else if (REQWEST_LIBRARY.equals(getLibrary())) {
operation.httpMethod = operation.httpMethod.toLowerCase(Locale.ROOT);

@ctaggartctaggartNov 12, 2019

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be leave this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's places that require the method (e.g. .method(PUT)). Thought I had got this working, but have been working on server, so will revisit.

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart Yeah, it's still very much wip, since both hyper and reqwest are changing. Even more so, swagger-rs would take significant changes that I can't test easily, so currently just using the context portion of it to make progress. Will push up my latest work so that if people want to pitch in they can. It's a pretty signficant effort.

@ctaggart

Copy link
Copy Markdown

For our needs, these are the changes I made for the reqwest client templates ctaggart#1

  • add support for custom_auth closure
  • remove async_trait
  • use Confguration with lifetime instead of Arc

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart can you explain the async_trait removal? Changing client from a trait to just an implementation, so not needed?

@ctaggart

Copy link
Copy Markdown

It is still early days for https://github.com/dtolnay/async-trait. I hit some lifetime issues that I didn't want to troubleshoot. Our cli app doesn't need the traits or that additional dependency. I suspect that most probably don't.

@ctaggart

Copy link
Copy Markdown

It may also be a good idea to implement std::error::Error for the custom error. ctaggart@5bd94ea

@kanekv

Copy link
Copy Markdown

What can we do to speed up this effort? Anything we can help with?

@dbcfd

Copy link
Copy Markdown
Author

@kanekv One would be to update swagger-rs to work with latest hyper. I've temporarily forked just the changes needed for this library in https://github.com/dbcfd/openapi-context. Updating swagger-rs to latest hyper is a much larger effort, but one that will need to be done.

@kanekv

Copy link
Copy Markdown

@dbcfd Is it a blocker or we can just continue with your approach?

@dbcfd

Copy link
Copy Markdown
Author

@kanekv it will definitely be a blocker for final merge, unless we want to roll the context stuff into this crate.

If you're looking specifically for work on this repo, the client generator needs a revisit, pulling in some of @ctaggart changes. I've also pushed up my work on the server generator code. I likely won't have time over the next week to work on that, so feel free to work on that as well.

@kanekv

Copy link
Copy Markdown

@dbcfd Not necessarily for this repo, just looking how we can coordinate the work and get it moving. Who is working on swagger-rs transition? Is there any way we can parallelize it?

@dbcfd

Copy link
Copy Markdown
Author

I was looking at the swagger-rs transition, but realized it was fairly large on its own right, and I didn't have a great way to test the changes I would have to make. That's where the openapi-context fork came from.

The client generator and the server generator are mostly distinct from each other, so one person could finish up the client portion and split it out as its own MR.

@kanekv

Copy link
Copy Markdown

Would it be beneficial to assume we can roll context stuff in (temporarily) and make client/server based on that assumption and also get it merged until we figure out what to do with swagger-rs, at that point we can switch it back?

@dbcfd

Copy link
Copy Markdown
Author

Yeah, we could publish openapi-context as a crate, then switch to swagger-rs when it is ready. Client/server could then be worked as publishable using openapi-context crate.

@UkonnRa

Copy link
Copy Markdown
Contributor

Cool, any update?

@dbcfd

Copy link
Copy Markdown
Author

Almost have the example generated code working. Hoping to get it finished up today. At that point it should be good for people to experiment with.

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart reqwest client should work now, in addition to hyper client and the server module.

@dbcfd

Copy link
Copy Markdown
Author

@JohnDoneth samples have been updated with the result of this work now.

@UkonnRa

Copy link
Copy Markdown
Contributor

ping~

@bcourtine

Copy link
Copy Markdown
Contributor

Great job @dbcfd!

But I think replacing the current "reqwest" generator with an async version is not a good idea:
some people can prefer using a "sync" version, or can have a pre 1.39 version as requirement.

So, the two versions (sync and async) should coexist (with a generator parameter, or with a new library "reqwest-async" for example).

@dbcfd

Copy link
Copy Markdown
Author

@bcourtine The reqwest client is by default async now, and blocking is under a different api. Leaving the default reqwest client as blocking will require a PR as well.

There's a couple of ways to move this PR forward:

  • Release as is
  • Release with async flagged similar to how reqwest is
  • Create new generators, rust-async and rust-server-async

Release as is
Given that hyper and reqwest are both async by default and require 1.39, this is my preferred approach. The alternative is to keep openapi on older versions of tokio, hyper, reqwest, etc. One can achieve a synchronous interface to reqwest by doing what reqwest blocking is doing, where it runs the async functionality on a thread pool.

Release with async flagged
This not only suffers from maintaining a version on older crates, but complicates the generation as well.

Create new generators
This requires maintaining two generators, one which is on unsupported libraries, but works pre 1.39. And a second generator which requires 1.39 or higher and is on supported libraries. Given the usefulness of async/await, I don't see the old generator getting much use.

Thoughts?

@bcourtine

Copy link
Copy Markdown
Contributor

Hi @dbcfd,

I personally like a lot async/await, and the language/crates moving forward is a good thing ;-)

But Rust 1.39 was only released 3 months ago. Even if Rust is moving fast, considering a 4 months old Rust version deprecated and not supported anymore by openapi-generator seems harsh.

@wing328 What is your opinion?

@dbcfd

Copy link
Copy Markdown
Author

@bcourtine I meant the versions of the crates tokio, hyper, reqwest, etc. being deprecated. The current versions of those crates all require 1.39 or higher.

@bcourtine

Copy link
Copy Markdown
Contributor

I agree, but theses crates still have support for a pre-1.39 version ;)

@dbcfd

dbcfd commented Feb 14, 2020

Copy link
Copy Markdown
Author

@bcourtine Although these crates have pre 1.39 versions, they are not supported. Attempting to use the currently supported crates (e.g. hyper 0.13) on a 1.38 compiler will fail.

info: default toolchain set to '1.38.0-x86_64-apple-darwin'
1.38.0-x86_64-apple-darwin installed - rustc 1.38.0 (625451e37 2019-09-23)
$ cd code/rust/
$ cargo new --lib hyper-test
Created library `hyper-test` package
$ cd hyper-test/
$ vi Cargo.toml
$ cargo build
Compiling tower-service v0.3.0
error: `core::slice::<impl [T]>::len` is not yet stable as a const fn
--> /Users/dannybrowning/.cargo/registry/src/github.com-1ecc6299db9ec823/bytes-0.5.4/src/bytes.rs:130:18
|
130 | len: bytes.len(),
| ^^^^^^^^^^^
error: aborting due to previous error

@dbcfddbcfd changed the title [WIP] [Rust] Async await[Rust] Async awaitApr 27, 2020
@dbcfddbcfd mentioned this pull request May 3, 2020
5 tasks
Incorporate hyper and reqwest with async/await support. Bring in async-trait to simplify async trait interaction.
@wing328

wing328 commented Jun 16, 2020

Copy link
Copy Markdown
Member

@dbcfd I've added an option to support async operations for reqwest.

I wonder if you can pull the latest master to give it a try.

@wing328

Copy link
Copy Markdown
Member

Closing as there's no update.

@wing328wing328 closed this Jan 25, 2021
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

WIPWork in Progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@dbcfd@JohnDoneth@richardwhiuk@ctaggart@kanekv@UkonnRa@bcourtine@wing328
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [Rust] Async await by dbcfd · Pull Request #4210 · OpenAPITools/openapi-generator · GitHub
Skip to content

[Rust] Async await - #4210

Closed
dbcfd wants to merge 2 commits into
OpenAPITools:masterfrom
dbcfd:async-await
Closed

[Rust] Async await#4210
dbcfd wants to merge 2 commits into
OpenAPITools:masterfrom
dbcfd:async-await

Conversation

@dbcfd

@dbcfddbcfd commented Oct 21, 2019

Copy link
Copy Markdown

Addresses #3865

Upgrade to use async/await by bringing in appropriate alpha releases for tokio, hyper, and reqwest. Also bring in async-trait to make api usage a little cleaner.

Requires beta compiler for Rust compiler. Expected to not be merged until after 1.39 is released.

  • Read the contribution guidelines.
  • If contributing template-only or documentation-only changes which will change sample output, build the project before.
  • Run the shell script(s) under ./bin/ (or Windows batch scripts under.\bin\windows) to update Petstore samples related to your fix. This is important, as CI jobs will verify all generator outputs of your HEAD commit, and these must match the expectations made by your contribution. You only need to run ./bin/{LANG}-petstore.sh, ./bin/openapi3/{LANG}-petstore.sh if updating the code or mustache templates for a language ({LANG}) (e.g. php, ruby, python, etc).
  • File the PR against the correct branch: master, 4.1.x, 5.0.x. Default: master.
  • Copy the technical committee to review the pull request if your PR is targeting a particular programming language.

/cc @frol@farcaller@bjgill@richardwhiuk

@auto-labeler

Copy link
Copy Markdown

👍 Thanks for opening this issue!
🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

@auto-labelerauto-labelerBot added the WIP Work in Progress label Oct 21, 2019
@JohnDoneth

JohnDoneth commented Oct 21, 2019

Copy link
Copy Markdown

LGTM! Exciting work. I like the use of async-trait to keep the API as a trait and still async. 👍

One small nit. It would be nice if the generated API functions were generated as follows:

asyncfnadd_pet(&self,body:crate::models::Pet) -> Result<(), serde_json::Value>;

... instead of the lengthier but equivalent:

fnadd_pet(&self,body:crate::models::Pet) -> Box<Future<Item = (),Error = Error<serde_json::Value>>>;

@dbcfd

dbcfd commented Oct 21, 2019

Copy link
Copy Markdown
Author

@JohnDoneth They will. Haven't run the bash scripts to update the examples yet.

Example from generated code

#[async_trait]pubtraitPetApi{asyncfnadd_pet(&self,body:crate::models::Pet) -> Result<(),Error<serde_json::Value>>;asyncfndelete_pet(&self,pet_id:i64,api_key:Option<&str>) -> Result<(),Error<serde_json::Value>>;asyncfnfind_pets_by_status(&self,status:Vec<String>) -> Result<Vec<crate::models::Pet>,Error<serde_json::Value>>;asyncfnfind_pets_by_tags(&self,tags:Vec<String>) -> Result<Vec<crate::models::Pet>,Error<serde_json::Value>>;asyncfnget_pet_by_id(&self,pet_id:i64) -> Result<crate::models::Pet,Error<serde_json::Value>>;asyncfnupdate_pet(&self,body:crate::models::Pet) -> Result<(),Error<serde_json::Value>>;asyncfnupdate_pet_with_form(&self,pet_id:i64,name:Option<&str>,status:Option<&str>) -> Result<(),Error<serde_json::Value>>;asyncfnupload_file(&self,pet_id:i64,additional_metadata:Option<&str>,file:Option<std::path::PathBuf>) -> Result<crate::models::ApiResponse,Error<serde_json::Value>>;}

@richardwhiuk

Copy link
Copy Markdown
Contributor

As per Metaswitch/swagger-rs#83, we'll want to wait for Hyper 0.13 to come out of beta before merging this.

@ctaggart

Copy link
Copy Markdown

@dbcfd, I'm trying out this branch and with -library=reqwest, the first error I ran into was

error[E0599]: no method named `PUT` found for type `&reqwest::async_impl::client::Client` in the current scope

currently:

letmut req_builder = client.PUT(uri_str.as_str());

should be:

letmut req_builder = client.put(uri_str.as_str());

It is named put, not PUT for reqwest.
https://github.com/seanmonstar/reqwest/blob/master/src/async_impl/client.rs#L648

operation.httpMethod = StringUtils.camelize(operation.httpMethod.toLowerCase(Locale.ROOT));
operation.httpMethod = StringUtils.camelize(operation.httpMethod);
} else if (REQWEST_LIBRARY.equals(getLibrary())) {
operation.httpMethod = operation.httpMethod.toLowerCase(Locale.ROOT);

@ctaggartctaggartNov 12, 2019

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be leave this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's places that require the method (e.g. .method(PUT)). Thought I had got this working, but have been working on server, so will revisit.

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart Yeah, it's still very much wip, since both hyper and reqwest are changing. Even more so, swagger-rs would take significant changes that I can't test easily, so currently just using the context portion of it to make progress. Will push up my latest work so that if people want to pitch in they can. It's a pretty signficant effort.

@ctaggart

Copy link
Copy Markdown

For our needs, these are the changes I made for the reqwest client templates ctaggart#1

  • add support for custom_auth closure
  • remove async_trait
  • use Confguration with lifetime instead of Arc

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart can you explain the async_trait removal? Changing client from a trait to just an implementation, so not needed?

@ctaggart

Copy link
Copy Markdown

It is still early days for https://github.com/dtolnay/async-trait. I hit some lifetime issues that I didn't want to troubleshoot. Our cli app doesn't need the traits or that additional dependency. I suspect that most probably don't.

@ctaggart

Copy link
Copy Markdown

It may also be a good idea to implement std::error::Error for the custom error. ctaggart@5bd94ea

@kanekv

Copy link
Copy Markdown

What can we do to speed up this effort? Anything we can help with?

@dbcfd

Copy link
Copy Markdown
Author

@kanekv One would be to update swagger-rs to work with latest hyper. I've temporarily forked just the changes needed for this library in https://github.com/dbcfd/openapi-context. Updating swagger-rs to latest hyper is a much larger effort, but one that will need to be done.

@kanekv

Copy link
Copy Markdown

@dbcfd Is it a blocker or we can just continue with your approach?

@dbcfd

Copy link
Copy Markdown
Author

@kanekv it will definitely be a blocker for final merge, unless we want to roll the context stuff into this crate.

If you're looking specifically for work on this repo, the client generator needs a revisit, pulling in some of @ctaggart changes. I've also pushed up my work on the server generator code. I likely won't have time over the next week to work on that, so feel free to work on that as well.

@kanekv

Copy link
Copy Markdown

@dbcfd Not necessarily for this repo, just looking how we can coordinate the work and get it moving. Who is working on swagger-rs transition? Is there any way we can parallelize it?

@dbcfd

Copy link
Copy Markdown
Author

I was looking at the swagger-rs transition, but realized it was fairly large on its own right, and I didn't have a great way to test the changes I would have to make. That's where the openapi-context fork came from.

The client generator and the server generator are mostly distinct from each other, so one person could finish up the client portion and split it out as its own MR.

@kanekv

Copy link
Copy Markdown

Would it be beneficial to assume we can roll context stuff in (temporarily) and make client/server based on that assumption and also get it merged until we figure out what to do with swagger-rs, at that point we can switch it back?

@dbcfd

Copy link
Copy Markdown
Author

Yeah, we could publish openapi-context as a crate, then switch to swagger-rs when it is ready. Client/server could then be worked as publishable using openapi-context crate.

@UkonnRa

Copy link
Copy Markdown
Contributor

Cool, any update?

@dbcfd

Copy link
Copy Markdown
Author

Almost have the example generated code working. Hoping to get it finished up today. At that point it should be good for people to experiment with.

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart reqwest client should work now, in addition to hyper client and the server module.

@dbcfd

Copy link
Copy Markdown
Author

@JohnDoneth samples have been updated with the result of this work now.

@UkonnRa

Copy link
Copy Markdown
Contributor

ping~

@bcourtine

Copy link
Copy Markdown
Contributor

Great job @dbcfd!

But I think replacing the current "reqwest" generator with an async version is not a good idea:
some people can prefer using a "sync" version, or can have a pre 1.39 version as requirement.

So, the two versions (sync and async) should coexist (with a generator parameter, or with a new library "reqwest-async" for example).

@dbcfd

Copy link
Copy Markdown
Author

@bcourtine The reqwest client is by default async now, and blocking is under a different api. Leaving the default reqwest client as blocking will require a PR as well.

There's a couple of ways to move this PR forward:

  • Release as is
  • Release with async flagged similar to how reqwest is
  • Create new generators, rust-async and rust-server-async

Release as is
Given that hyper and reqwest are both async by default and require 1.39, this is my preferred approach. The alternative is to keep openapi on older versions of tokio, hyper, reqwest, etc. One can achieve a synchronous interface to reqwest by doing what reqwest blocking is doing, where it runs the async functionality on a thread pool.

Release with async flagged
This not only suffers from maintaining a version on older crates, but complicates the generation as well.

Create new generators
This requires maintaining two generators, one which is on unsupported libraries, but works pre 1.39. And a second generator which requires 1.39 or higher and is on supported libraries. Given the usefulness of async/await, I don't see the old generator getting much use.

Thoughts?

@bcourtine

Copy link
Copy Markdown
Contributor

Hi @dbcfd,

I personally like a lot async/await, and the language/crates moving forward is a good thing ;-)

But Rust 1.39 was only released 3 months ago. Even if Rust is moving fast, considering a 4 months old Rust version deprecated and not supported anymore by openapi-generator seems harsh.

@wing328 What is your opinion?

@dbcfd

Copy link
Copy Markdown
Author

@bcourtine I meant the versions of the crates tokio, hyper, reqwest, etc. being deprecated. The current versions of those crates all require 1.39 or higher.

@bcourtine

Copy link
Copy Markdown
Contributor

I agree, but theses crates still have support for a pre-1.39 version ;)

@dbcfd

dbcfd commented Feb 14, 2020

Copy link
Copy Markdown
Author

@bcourtine Although these crates have pre 1.39 versions, they are not supported. Attempting to use the currently supported crates (e.g. hyper 0.13) on a 1.38 compiler will fail.

info: default toolchain set to '1.38.0-x86_64-apple-darwin'
1.38.0-x86_64-apple-darwin installed - rustc 1.38.0 (625451e37 2019-09-23)
$ cd code/rust/
$ cargo new --lib hyper-test
Created library `hyper-test` package
$ cd hyper-test/
$ vi Cargo.toml
$ cargo build
Compiling tower-service v0.3.0
error: `core::slice::<impl [T]>::len` is not yet stable as a const fn
--> /Users/dannybrowning/.cargo/registry/src/github.com-1ecc6299db9ec823/bytes-0.5.4/src/bytes.rs:130:18
|
130 | len: bytes.len(),
| ^^^^^^^^^^^
error: aborting due to previous error

@dbcfddbcfd changed the title [WIP] [Rust] Async await[Rust] Async awaitApr 27, 2020
@dbcfddbcfd mentioned this pull request May 3, 2020
5 tasks
Incorporate hyper and reqwest with async/await support. Bring in async-trait to simplify async trait interaction.
@wing328

wing328 commented Jun 16, 2020

Copy link
Copy Markdown
Member

@dbcfd I've added an option to support async operations for reqwest.

I wonder if you can pull the latest master to give it a try.

@wing328

Copy link
Copy Markdown
Member

Closing as there's no update.

@wing328wing328 closed this Jan 25, 2021
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

WIPWork in Progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@dbcfd@JohnDoneth@richardwhiuk@ctaggart@kanekv@UkonnRa@bcourtine@wing328
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' [Rust] Async await by dbcfd · Pull Request #4210 · OpenAPITools/openapi-generator · GitHub
Skip to content

[Rust] Async await - #4210

Closed
dbcfd wants to merge 2 commits into
OpenAPITools:masterfrom
dbcfd:async-await
Closed

[Rust] Async await#4210
dbcfd wants to merge 2 commits into
OpenAPITools:masterfrom
dbcfd:async-await

Conversation

@dbcfd

@dbcfddbcfd commented Oct 21, 2019

Copy link
Copy Markdown

Addresses #3865

Upgrade to use async/await by bringing in appropriate alpha releases for tokio, hyper, and reqwest. Also bring in async-trait to make api usage a little cleaner.

Requires beta compiler for Rust compiler. Expected to not be merged until after 1.39 is released.

  • Read the contribution guidelines.
  • If contributing template-only or documentation-only changes which will change sample output, build the project before.
  • Run the shell script(s) under ./bin/ (or Windows batch scripts under.\bin\windows) to update Petstore samples related to your fix. This is important, as CI jobs will verify all generator outputs of your HEAD commit, and these must match the expectations made by your contribution. You only need to run ./bin/{LANG}-petstore.sh, ./bin/openapi3/{LANG}-petstore.sh if updating the code or mustache templates for a language ({LANG}) (e.g. php, ruby, python, etc).
  • File the PR against the correct branch: master, 4.1.x, 5.0.x. Default: master.
  • Copy the technical committee to review the pull request if your PR is targeting a particular programming language.

/cc @frol@farcaller@bjgill@richardwhiuk

@auto-labeler

Copy link
Copy Markdown

👍 Thanks for opening this issue!
🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

@auto-labelerauto-labelerBot added the WIP Work in Progress label Oct 21, 2019
@JohnDoneth

JohnDoneth commented Oct 21, 2019

Copy link
Copy Markdown

LGTM! Exciting work. I like the use of async-trait to keep the API as a trait and still async. 👍

One small nit. It would be nice if the generated API functions were generated as follows:

asyncfnadd_pet(&self,body:crate::models::Pet) -> Result<(), serde_json::Value>;

... instead of the lengthier but equivalent:

fnadd_pet(&self,body:crate::models::Pet) -> Box<Future<Item = (),Error = Error<serde_json::Value>>>;

@dbcfd

dbcfd commented Oct 21, 2019

Copy link
Copy Markdown
Author

@JohnDoneth They will. Haven't run the bash scripts to update the examples yet.

Example from generated code

#[async_trait]pubtraitPetApi{asyncfnadd_pet(&self,body:crate::models::Pet) -> Result<(),Error<serde_json::Value>>;asyncfndelete_pet(&self,pet_id:i64,api_key:Option<&str>) -> Result<(),Error<serde_json::Value>>;asyncfnfind_pets_by_status(&self,status:Vec<String>) -> Result<Vec<crate::models::Pet>,Error<serde_json::Value>>;asyncfnfind_pets_by_tags(&self,tags:Vec<String>) -> Result<Vec<crate::models::Pet>,Error<serde_json::Value>>;asyncfnget_pet_by_id(&self,pet_id:i64) -> Result<crate::models::Pet,Error<serde_json::Value>>;asyncfnupdate_pet(&self,body:crate::models::Pet) -> Result<(),Error<serde_json::Value>>;asyncfnupdate_pet_with_form(&self,pet_id:i64,name:Option<&str>,status:Option<&str>) -> Result<(),Error<serde_json::Value>>;asyncfnupload_file(&self,pet_id:i64,additional_metadata:Option<&str>,file:Option<std::path::PathBuf>) -> Result<crate::models::ApiResponse,Error<serde_json::Value>>;}

@richardwhiuk

Copy link
Copy Markdown
Contributor

As per Metaswitch/swagger-rs#83, we'll want to wait for Hyper 0.13 to come out of beta before merging this.

@ctaggart

Copy link
Copy Markdown

@dbcfd, I'm trying out this branch and with -library=reqwest, the first error I ran into was

error[E0599]: no method named `PUT` found for type `&reqwest::async_impl::client::Client` in the current scope

currently:

letmut req_builder = client.PUT(uri_str.as_str());

should be:

letmut req_builder = client.put(uri_str.as_str());

It is named put, not PUT for reqwest.
https://github.com/seanmonstar/reqwest/blob/master/src/async_impl/client.rs#L648

operation.httpMethod = StringUtils.camelize(operation.httpMethod.toLowerCase(Locale.ROOT));
operation.httpMethod = StringUtils.camelize(operation.httpMethod);
} else if (REQWEST_LIBRARY.equals(getLibrary())) {
operation.httpMethod = operation.httpMethod.toLowerCase(Locale.ROOT);

@ctaggartctaggartNov 12, 2019

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be leave this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's places that require the method (e.g. .method(PUT)). Thought I had got this working, but have been working on server, so will revisit.

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart Yeah, it's still very much wip, since both hyper and reqwest are changing. Even more so, swagger-rs would take significant changes that I can't test easily, so currently just using the context portion of it to make progress. Will push up my latest work so that if people want to pitch in they can. It's a pretty signficant effort.

@ctaggart

Copy link
Copy Markdown

For our needs, these are the changes I made for the reqwest client templates ctaggart#1

  • add support for custom_auth closure
  • remove async_trait
  • use Confguration with lifetime instead of Arc

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart can you explain the async_trait removal? Changing client from a trait to just an implementation, so not needed?

@ctaggart

Copy link
Copy Markdown

It is still early days for https://github.com/dtolnay/async-trait. I hit some lifetime issues that I didn't want to troubleshoot. Our cli app doesn't need the traits or that additional dependency. I suspect that most probably don't.

@ctaggart

Copy link
Copy Markdown

It may also be a good idea to implement std::error::Error for the custom error. ctaggart@5bd94ea

@kanekv

Copy link
Copy Markdown

What can we do to speed up this effort? Anything we can help with?

@dbcfd

Copy link
Copy Markdown
Author

@kanekv One would be to update swagger-rs to work with latest hyper. I've temporarily forked just the changes needed for this library in https://github.com/dbcfd/openapi-context. Updating swagger-rs to latest hyper is a much larger effort, but one that will need to be done.

@kanekv

Copy link
Copy Markdown

@dbcfd Is it a blocker or we can just continue with your approach?

@dbcfd

Copy link
Copy Markdown
Author

@kanekv it will definitely be a blocker for final merge, unless we want to roll the context stuff into this crate.

If you're looking specifically for work on this repo, the client generator needs a revisit, pulling in some of @ctaggart changes. I've also pushed up my work on the server generator code. I likely won't have time over the next week to work on that, so feel free to work on that as well.

@kanekv

Copy link
Copy Markdown

@dbcfd Not necessarily for this repo, just looking how we can coordinate the work and get it moving. Who is working on swagger-rs transition? Is there any way we can parallelize it?

@dbcfd

Copy link
Copy Markdown
Author

I was looking at the swagger-rs transition, but realized it was fairly large on its own right, and I didn't have a great way to test the changes I would have to make. That's where the openapi-context fork came from.

The client generator and the server generator are mostly distinct from each other, so one person could finish up the client portion and split it out as its own MR.

@kanekv

Copy link
Copy Markdown

Would it be beneficial to assume we can roll context stuff in (temporarily) and make client/server based on that assumption and also get it merged until we figure out what to do with swagger-rs, at that point we can switch it back?

@dbcfd

Copy link
Copy Markdown
Author

Yeah, we could publish openapi-context as a crate, then switch to swagger-rs when it is ready. Client/server could then be worked as publishable using openapi-context crate.

@UkonnRa

Copy link
Copy Markdown
Contributor

Cool, any update?

@dbcfd

Copy link
Copy Markdown
Author

Almost have the example generated code working. Hoping to get it finished up today. At that point it should be good for people to experiment with.

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart reqwest client should work now, in addition to hyper client and the server module.

@dbcfd

Copy link
Copy Markdown
Author

@JohnDoneth samples have been updated with the result of this work now.

@UkonnRa

Copy link
Copy Markdown
Contributor

ping~

@bcourtine

Copy link
Copy Markdown
Contributor

Great job @dbcfd!

But I think replacing the current "reqwest" generator with an async version is not a good idea:
some people can prefer using a "sync" version, or can have a pre 1.39 version as requirement.

So, the two versions (sync and async) should coexist (with a generator parameter, or with a new library "reqwest-async" for example).

@dbcfd

Copy link
Copy Markdown
Author

@bcourtine The reqwest client is by default async now, and blocking is under a different api. Leaving the default reqwest client as blocking will require a PR as well.

There's a couple of ways to move this PR forward:

  • Release as is
  • Release with async flagged similar to how reqwest is
  • Create new generators, rust-async and rust-server-async

Release as is
Given that hyper and reqwest are both async by default and require 1.39, this is my preferred approach. The alternative is to keep openapi on older versions of tokio, hyper, reqwest, etc. One can achieve a synchronous interface to reqwest by doing what reqwest blocking is doing, where it runs the async functionality on a thread pool.

Release with async flagged
This not only suffers from maintaining a version on older crates, but complicates the generation as well.

Create new generators
This requires maintaining two generators, one which is on unsupported libraries, but works pre 1.39. And a second generator which requires 1.39 or higher and is on supported libraries. Given the usefulness of async/await, I don't see the old generator getting much use.

Thoughts?

@bcourtine

Copy link
Copy Markdown
Contributor

Hi @dbcfd,

I personally like a lot async/await, and the language/crates moving forward is a good thing ;-)

But Rust 1.39 was only released 3 months ago. Even if Rust is moving fast, considering a 4 months old Rust version deprecated and not supported anymore by openapi-generator seems harsh.

@wing328 What is your opinion?

@dbcfd

Copy link
Copy Markdown
Author

@bcourtine I meant the versions of the crates tokio, hyper, reqwest, etc. being deprecated. The current versions of those crates all require 1.39 or higher.

@bcourtine

Copy link
Copy Markdown
Contributor

I agree, but theses crates still have support for a pre-1.39 version ;)

@dbcfd

dbcfd commented Feb 14, 2020

Copy link
Copy Markdown
Author

@bcourtine Although these crates have pre 1.39 versions, they are not supported. Attempting to use the currently supported crates (e.g. hyper 0.13) on a 1.38 compiler will fail.

info: default toolchain set to '1.38.0-x86_64-apple-darwin'
1.38.0-x86_64-apple-darwin installed - rustc 1.38.0 (625451e37 2019-09-23)
$ cd code/rust/
$ cargo new --lib hyper-test
Created library `hyper-test` package
$ cd hyper-test/
$ vi Cargo.toml
$ cargo build
Compiling tower-service v0.3.0
error: `core::slice::<impl [T]>::len` is not yet stable as a const fn
--> /Users/dannybrowning/.cargo/registry/src/github.com-1ecc6299db9ec823/bytes-0.5.4/src/bytes.rs:130:18
|
130 | len: bytes.len(),
| ^^^^^^^^^^^
error: aborting due to previous error

@dbcfddbcfd changed the title [WIP] [Rust] Async await[Rust] Async awaitApr 27, 2020
@dbcfddbcfd mentioned this pull request May 3, 2020
5 tasks
Incorporate hyper and reqwest with async/await support. Bring in async-trait to simplify async trait interaction.
@wing328

wing328 commented Jun 16, 2020

Copy link
Copy Markdown
Member

@dbcfd I've added an option to support async operations for reqwest.

I wonder if you can pull the latest master to give it a try.

@wing328

Copy link
Copy Markdown
Member

Closing as there's no update.

@wing328wing328 closed this Jan 25, 2021
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

WIPWork in Progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@dbcfd@JohnDoneth@richardwhiuk@ctaggart@kanekv@UkonnRa@bcourtine@wing328
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [Rust] Async await by dbcfd · Pull Request #4210 · OpenAPITools/openapi-generator · GitHub
Skip to content

[Rust] Async await - #4210

Closed
dbcfd wants to merge 2 commits into
OpenAPITools:masterfrom
dbcfd:async-await
Closed

[Rust] Async await#4210
dbcfd wants to merge 2 commits into
OpenAPITools:masterfrom
dbcfd:async-await

Conversation

@dbcfd

@dbcfddbcfd commented Oct 21, 2019

Copy link
Copy Markdown

Addresses #3865

Upgrade to use async/await by bringing in appropriate alpha releases for tokio, hyper, and reqwest. Also bring in async-trait to make api usage a little cleaner.

Requires beta compiler for Rust compiler. Expected to not be merged until after 1.39 is released.

  • Read the contribution guidelines.
  • If contributing template-only or documentation-only changes which will change sample output, build the project before.
  • Run the shell script(s) under ./bin/ (or Windows batch scripts under.\bin\windows) to update Petstore samples related to your fix. This is important, as CI jobs will verify all generator outputs of your HEAD commit, and these must match the expectations made by your contribution. You only need to run ./bin/{LANG}-petstore.sh, ./bin/openapi3/{LANG}-petstore.sh if updating the code or mustache templates for a language ({LANG}) (e.g. php, ruby, python, etc).
  • File the PR against the correct branch: master, 4.1.x, 5.0.x. Default: master.
  • Copy the technical committee to review the pull request if your PR is targeting a particular programming language.

/cc @frol@farcaller@bjgill@richardwhiuk

@auto-labeler

Copy link
Copy Markdown

👍 Thanks for opening this issue!
🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

@auto-labelerauto-labelerBot added the WIP Work in Progress label Oct 21, 2019
@JohnDoneth

JohnDoneth commented Oct 21, 2019

Copy link
Copy Markdown

LGTM! Exciting work. I like the use of async-trait to keep the API as a trait and still async. 👍

One small nit. It would be nice if the generated API functions were generated as follows:

asyncfnadd_pet(&self,body:crate::models::Pet) -> Result<(), serde_json::Value>;

... instead of the lengthier but equivalent:

fnadd_pet(&self,body:crate::models::Pet) -> Box<Future<Item = (),Error = Error<serde_json::Value>>>;

@dbcfd

dbcfd commented Oct 21, 2019

Copy link
Copy Markdown
Author

@JohnDoneth They will. Haven't run the bash scripts to update the examples yet.

Example from generated code

#[async_trait]pubtraitPetApi{asyncfnadd_pet(&self,body:crate::models::Pet) -> Result<(),Error<serde_json::Value>>;asyncfndelete_pet(&self,pet_id:i64,api_key:Option<&str>) -> Result<(),Error<serde_json::Value>>;asyncfnfind_pets_by_status(&self,status:Vec<String>) -> Result<Vec<crate::models::Pet>,Error<serde_json::Value>>;asyncfnfind_pets_by_tags(&self,tags:Vec<String>) -> Result<Vec<crate::models::Pet>,Error<serde_json::Value>>;asyncfnget_pet_by_id(&self,pet_id:i64) -> Result<crate::models::Pet,Error<serde_json::Value>>;asyncfnupdate_pet(&self,body:crate::models::Pet) -> Result<(),Error<serde_json::Value>>;asyncfnupdate_pet_with_form(&self,pet_id:i64,name:Option<&str>,status:Option<&str>) -> Result<(),Error<serde_json::Value>>;asyncfnupload_file(&self,pet_id:i64,additional_metadata:Option<&str>,file:Option<std::path::PathBuf>) -> Result<crate::models::ApiResponse,Error<serde_json::Value>>;}

@richardwhiuk

Copy link
Copy Markdown
Contributor

As per Metaswitch/swagger-rs#83, we'll want to wait for Hyper 0.13 to come out of beta before merging this.

@ctaggart

Copy link
Copy Markdown

@dbcfd, I'm trying out this branch and with -library=reqwest, the first error I ran into was

error[E0599]: no method named `PUT` found for type `&reqwest::async_impl::client::Client` in the current scope

currently:

letmut req_builder = client.PUT(uri_str.as_str());

should be:

letmut req_builder = client.put(uri_str.as_str());

It is named put, not PUT for reqwest.
https://github.com/seanmonstar/reqwest/blob/master/src/async_impl/client.rs#L648

operation.httpMethod = StringUtils.camelize(operation.httpMethod.toLowerCase(Locale.ROOT));
operation.httpMethod = StringUtils.camelize(operation.httpMethod);
} else if (REQWEST_LIBRARY.equals(getLibrary())) {
operation.httpMethod = operation.httpMethod.toLowerCase(Locale.ROOT);

@ctaggartctaggartNov 12, 2019

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be leave this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's places that require the method (e.g. .method(PUT)). Thought I had got this working, but have been working on server, so will revisit.

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart Yeah, it's still very much wip, since both hyper and reqwest are changing. Even more so, swagger-rs would take significant changes that I can't test easily, so currently just using the context portion of it to make progress. Will push up my latest work so that if people want to pitch in they can. It's a pretty signficant effort.

@ctaggart

Copy link
Copy Markdown

For our needs, these are the changes I made for the reqwest client templates ctaggart#1

  • add support for custom_auth closure
  • remove async_trait
  • use Confguration with lifetime instead of Arc

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart can you explain the async_trait removal? Changing client from a trait to just an implementation, so not needed?

@ctaggart

Copy link
Copy Markdown

It is still early days for https://github.com/dtolnay/async-trait. I hit some lifetime issues that I didn't want to troubleshoot. Our cli app doesn't need the traits or that additional dependency. I suspect that most probably don't.

@ctaggart

Copy link
Copy Markdown

It may also be a good idea to implement std::error::Error for the custom error. ctaggart@5bd94ea

@kanekv

Copy link
Copy Markdown

What can we do to speed up this effort? Anything we can help with?

@dbcfd

Copy link
Copy Markdown
Author

@kanekv One would be to update swagger-rs to work with latest hyper. I've temporarily forked just the changes needed for this library in https://github.com/dbcfd/openapi-context. Updating swagger-rs to latest hyper is a much larger effort, but one that will need to be done.

@kanekv

Copy link
Copy Markdown

@dbcfd Is it a blocker or we can just continue with your approach?

@dbcfd

Copy link
Copy Markdown
Author

@kanekv it will definitely be a blocker for final merge, unless we want to roll the context stuff into this crate.

If you're looking specifically for work on this repo, the client generator needs a revisit, pulling in some of @ctaggart changes. I've also pushed up my work on the server generator code. I likely won't have time over the next week to work on that, so feel free to work on that as well.

@kanekv

Copy link
Copy Markdown

@dbcfd Not necessarily for this repo, just looking how we can coordinate the work and get it moving. Who is working on swagger-rs transition? Is there any way we can parallelize it?

@dbcfd

Copy link
Copy Markdown
Author

I was looking at the swagger-rs transition, but realized it was fairly large on its own right, and I didn't have a great way to test the changes I would have to make. That's where the openapi-context fork came from.

The client generator and the server generator are mostly distinct from each other, so one person could finish up the client portion and split it out as its own MR.

@kanekv

Copy link
Copy Markdown

Would it be beneficial to assume we can roll context stuff in (temporarily) and make client/server based on that assumption and also get it merged until we figure out what to do with swagger-rs, at that point we can switch it back?

@dbcfd

Copy link
Copy Markdown
Author

Yeah, we could publish openapi-context as a crate, then switch to swagger-rs when it is ready. Client/server could then be worked as publishable using openapi-context crate.

@UkonnRa

Copy link
Copy Markdown
Contributor

Cool, any update?

@dbcfd

Copy link
Copy Markdown
Author

Almost have the example generated code working. Hoping to get it finished up today. At that point it should be good for people to experiment with.

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart reqwest client should work now, in addition to hyper client and the server module.

@dbcfd

Copy link
Copy Markdown
Author

@JohnDoneth samples have been updated with the result of this work now.

@UkonnRa

Copy link
Copy Markdown
Contributor

ping~

@bcourtine

Copy link
Copy Markdown
Contributor

Great job @dbcfd!

But I think replacing the current "reqwest" generator with an async version is not a good idea:
some people can prefer using a "sync" version, or can have a pre 1.39 version as requirement.

So, the two versions (sync and async) should coexist (with a generator parameter, or with a new library "reqwest-async" for example).

@dbcfd

Copy link
Copy Markdown
Author

@bcourtine The reqwest client is by default async now, and blocking is under a different api. Leaving the default reqwest client as blocking will require a PR as well.

There's a couple of ways to move this PR forward:

  • Release as is
  • Release with async flagged similar to how reqwest is
  • Create new generators, rust-async and rust-server-async

Release as is
Given that hyper and reqwest are both async by default and require 1.39, this is my preferred approach. The alternative is to keep openapi on older versions of tokio, hyper, reqwest, etc. One can achieve a synchronous interface to reqwest by doing what reqwest blocking is doing, where it runs the async functionality on a thread pool.

Release with async flagged
This not only suffers from maintaining a version on older crates, but complicates the generation as well.

Create new generators
This requires maintaining two generators, one which is on unsupported libraries, but works pre 1.39. And a second generator which requires 1.39 or higher and is on supported libraries. Given the usefulness of async/await, I don't see the old generator getting much use.

Thoughts?

@bcourtine

Copy link
Copy Markdown
Contributor

Hi @dbcfd,

I personally like a lot async/await, and the language/crates moving forward is a good thing ;-)

But Rust 1.39 was only released 3 months ago. Even if Rust is moving fast, considering a 4 months old Rust version deprecated and not supported anymore by openapi-generator seems harsh.

@wing328 What is your opinion?

@dbcfd

Copy link
Copy Markdown
Author

@bcourtine I meant the versions of the crates tokio, hyper, reqwest, etc. being deprecated. The current versions of those crates all require 1.39 or higher.

@bcourtine

Copy link
Copy Markdown
Contributor

I agree, but theses crates still have support for a pre-1.39 version ;)

@dbcfd

dbcfd commented Feb 14, 2020

Copy link
Copy Markdown
Author

@bcourtine Although these crates have pre 1.39 versions, they are not supported. Attempting to use the currently supported crates (e.g. hyper 0.13) on a 1.38 compiler will fail.

info: default toolchain set to '1.38.0-x86_64-apple-darwin'
1.38.0-x86_64-apple-darwin installed - rustc 1.38.0 (625451e37 2019-09-23)
$ cd code/rust/
$ cargo new --lib hyper-test
Created library `hyper-test` package
$ cd hyper-test/
$ vi Cargo.toml
$ cargo build
Compiling tower-service v0.3.0
error: `core::slice::<impl [T]>::len` is not yet stable as a const fn
--> /Users/dannybrowning/.cargo/registry/src/github.com-1ecc6299db9ec823/bytes-0.5.4/src/bytes.rs:130:18
|
130 | len: bytes.len(),
| ^^^^^^^^^^^
error: aborting due to previous error

@dbcfddbcfd changed the title [WIP] [Rust] Async await[Rust] Async awaitApr 27, 2020
@dbcfddbcfd mentioned this pull request May 3, 2020
5 tasks
Incorporate hyper and reqwest with async/await support. Bring in async-trait to simplify async trait interaction.
@wing328

wing328 commented Jun 16, 2020

Copy link
Copy Markdown
Member

@dbcfd I've added an option to support async operations for reqwest.

I wonder if you can pull the latest master to give it a try.

@wing328

Copy link
Copy Markdown
Member

Closing as there's no update.

@wing328wing328 closed this Jan 25, 2021
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

WIPWork in Progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@dbcfd@JohnDoneth@richardwhiuk@ctaggart@kanekv@UkonnRa@bcourtine@wing328
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); [Rust] Async await by dbcfd · Pull Request #4210 · OpenAPITools/openapi-generator · GitHub
Skip to content

[Rust] Async await - #4210

Closed
dbcfd wants to merge 2 commits into
OpenAPITools:masterfrom
dbcfd:async-await
Closed

[Rust] Async await#4210
dbcfd wants to merge 2 commits into
OpenAPITools:masterfrom
dbcfd:async-await

Conversation

@dbcfd

@dbcfddbcfd commented Oct 21, 2019

Copy link
Copy Markdown

Addresses #3865

Upgrade to use async/await by bringing in appropriate alpha releases for tokio, hyper, and reqwest. Also bring in async-trait to make api usage a little cleaner.

Requires beta compiler for Rust compiler. Expected to not be merged until after 1.39 is released.

  • Read the contribution guidelines.
  • If contributing template-only or documentation-only changes which will change sample output, build the project before.
  • Run the shell script(s) under ./bin/ (or Windows batch scripts under.\bin\windows) to update Petstore samples related to your fix. This is important, as CI jobs will verify all generator outputs of your HEAD commit, and these must match the expectations made by your contribution. You only need to run ./bin/{LANG}-petstore.sh, ./bin/openapi3/{LANG}-petstore.sh if updating the code or mustache templates for a language ({LANG}) (e.g. php, ruby, python, etc).
  • File the PR against the correct branch: master, 4.1.x, 5.0.x. Default: master.
  • Copy the technical committee to review the pull request if your PR is targeting a particular programming language.

/cc @frol@farcaller@bjgill@richardwhiuk

@auto-labeler

Copy link
Copy Markdown

👍 Thanks for opening this issue!
🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

@auto-labelerauto-labelerBot added the WIP Work in Progress label Oct 21, 2019
@JohnDoneth

JohnDoneth commented Oct 21, 2019

Copy link
Copy Markdown

LGTM! Exciting work. I like the use of async-trait to keep the API as a trait and still async. 👍

One small nit. It would be nice if the generated API functions were generated as follows:

asyncfnadd_pet(&self,body:crate::models::Pet) -> Result<(), serde_json::Value>;

... instead of the lengthier but equivalent:

fnadd_pet(&self,body:crate::models::Pet) -> Box<Future<Item = (),Error = Error<serde_json::Value>>>;

@dbcfd

dbcfd commented Oct 21, 2019

Copy link
Copy Markdown
Author

@JohnDoneth They will. Haven't run the bash scripts to update the examples yet.

Example from generated code

#[async_trait]pubtraitPetApi{asyncfnadd_pet(&self,body:crate::models::Pet) -> Result<(),Error<serde_json::Value>>;asyncfndelete_pet(&self,pet_id:i64,api_key:Option<&str>) -> Result<(),Error<serde_json::Value>>;asyncfnfind_pets_by_status(&self,status:Vec<String>) -> Result<Vec<crate::models::Pet>,Error<serde_json::Value>>;asyncfnfind_pets_by_tags(&self,tags:Vec<String>) -> Result<Vec<crate::models::Pet>,Error<serde_json::Value>>;asyncfnget_pet_by_id(&self,pet_id:i64) -> Result<crate::models::Pet,Error<serde_json::Value>>;asyncfnupdate_pet(&self,body:crate::models::Pet) -> Result<(),Error<serde_json::Value>>;asyncfnupdate_pet_with_form(&self,pet_id:i64,name:Option<&str>,status:Option<&str>) -> Result<(),Error<serde_json::Value>>;asyncfnupload_file(&self,pet_id:i64,additional_metadata:Option<&str>,file:Option<std::path::PathBuf>) -> Result<crate::models::ApiResponse,Error<serde_json::Value>>;}

@richardwhiuk

Copy link
Copy Markdown
Contributor

As per Metaswitch/swagger-rs#83, we'll want to wait for Hyper 0.13 to come out of beta before merging this.

@ctaggart

Copy link
Copy Markdown

@dbcfd, I'm trying out this branch and with -library=reqwest, the first error I ran into was

error[E0599]: no method named `PUT` found for type `&reqwest::async_impl::client::Client` in the current scope

currently:

letmut req_builder = client.PUT(uri_str.as_str());

should be:

letmut req_builder = client.put(uri_str.as_str());

It is named put, not PUT for reqwest.
https://github.com/seanmonstar/reqwest/blob/master/src/async_impl/client.rs#L648

operation.httpMethod = StringUtils.camelize(operation.httpMethod.toLowerCase(Locale.ROOT));
operation.httpMethod = StringUtils.camelize(operation.httpMethod);
} else if (REQWEST_LIBRARY.equals(getLibrary())) {
operation.httpMethod = operation.httpMethod.toLowerCase(Locale.ROOT);

@ctaggartctaggartNov 12, 2019

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be leave this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's places that require the method (e.g. .method(PUT)). Thought I had got this working, but have been working on server, so will revisit.

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart Yeah, it's still very much wip, since both hyper and reqwest are changing. Even more so, swagger-rs would take significant changes that I can't test easily, so currently just using the context portion of it to make progress. Will push up my latest work so that if people want to pitch in they can. It's a pretty signficant effort.

@ctaggart

Copy link
Copy Markdown

For our needs, these are the changes I made for the reqwest client templates ctaggart#1

  • add support for custom_auth closure
  • remove async_trait
  • use Confguration with lifetime instead of Arc

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart can you explain the async_trait removal? Changing client from a trait to just an implementation, so not needed?

@ctaggart

Copy link
Copy Markdown

It is still early days for https://github.com/dtolnay/async-trait. I hit some lifetime issues that I didn't want to troubleshoot. Our cli app doesn't need the traits or that additional dependency. I suspect that most probably don't.

@ctaggart

Copy link
Copy Markdown

It may also be a good idea to implement std::error::Error for the custom error. ctaggart@5bd94ea

@kanekv

Copy link
Copy Markdown

What can we do to speed up this effort? Anything we can help with?

@dbcfd

Copy link
Copy Markdown
Author

@kanekv One would be to update swagger-rs to work with latest hyper. I've temporarily forked just the changes needed for this library in https://github.com/dbcfd/openapi-context. Updating swagger-rs to latest hyper is a much larger effort, but one that will need to be done.

@kanekv

Copy link
Copy Markdown

@dbcfd Is it a blocker or we can just continue with your approach?

@dbcfd

Copy link
Copy Markdown
Author

@kanekv it will definitely be a blocker for final merge, unless we want to roll the context stuff into this crate.

If you're looking specifically for work on this repo, the client generator needs a revisit, pulling in some of @ctaggart changes. I've also pushed up my work on the server generator code. I likely won't have time over the next week to work on that, so feel free to work on that as well.

@kanekv

Copy link
Copy Markdown

@dbcfd Not necessarily for this repo, just looking how we can coordinate the work and get it moving. Who is working on swagger-rs transition? Is there any way we can parallelize it?

@dbcfd

Copy link
Copy Markdown
Author

I was looking at the swagger-rs transition, but realized it was fairly large on its own right, and I didn't have a great way to test the changes I would have to make. That's where the openapi-context fork came from.

The client generator and the server generator are mostly distinct from each other, so one person could finish up the client portion and split it out as its own MR.

@kanekv

Copy link
Copy Markdown

Would it be beneficial to assume we can roll context stuff in (temporarily) and make client/server based on that assumption and also get it merged until we figure out what to do with swagger-rs, at that point we can switch it back?

@dbcfd

Copy link
Copy Markdown
Author

Yeah, we could publish openapi-context as a crate, then switch to swagger-rs when it is ready. Client/server could then be worked as publishable using openapi-context crate.

@UkonnRa

Copy link
Copy Markdown
Contributor

Cool, any update?

@dbcfd

Copy link
Copy Markdown
Author

Almost have the example generated code working. Hoping to get it finished up today. At that point it should be good for people to experiment with.

@dbcfd

Copy link
Copy Markdown
Author

@ctaggart reqwest client should work now, in addition to hyper client and the server module.

@dbcfd

Copy link
Copy Markdown
Author

@JohnDoneth samples have been updated with the result of this work now.

@UkonnRa

Copy link
Copy Markdown
Contributor

ping~

@bcourtine

Copy link
Copy Markdown
Contributor

Great job @dbcfd!

But I think replacing the current "reqwest" generator with an async version is not a good idea:
some people can prefer using a "sync" version, or can have a pre 1.39 version as requirement.

So, the two versions (sync and async) should coexist (with a generator parameter, or with a new library "reqwest-async" for example).

@dbcfd

Copy link
Copy Markdown
Author

@bcourtine The reqwest client is by default async now, and blocking is under a different api. Leaving the default reqwest client as blocking will require a PR as well.

There's a couple of ways to move this PR forward:

  • Release as is
  • Release with async flagged similar to how reqwest is
  • Create new generators, rust-async and rust-server-async

Release as is
Given that hyper and reqwest are both async by default and require 1.39, this is my preferred approach. The alternative is to keep openapi on older versions of tokio, hyper, reqwest, etc. One can achieve a synchronous interface to reqwest by doing what reqwest blocking is doing, where it runs the async functionality on a thread pool.

Release with async flagged
This not only suffers from maintaining a version on older crates, but complicates the generation as well.

Create new generators
This requires maintaining two generators, one which is on unsupported libraries, but works pre 1.39. And a second generator which requires 1.39 or higher and is on supported libraries. Given the usefulness of async/await, I don't see the old generator getting much use.

Thoughts?

@bcourtine

Copy link
Copy Markdown
Contributor

Hi @dbcfd,

I personally like a lot async/await, and the language/crates moving forward is a good thing ;-)

But Rust 1.39 was only released 3 months ago. Even if Rust is moving fast, considering a 4 months old Rust version deprecated and not supported anymore by openapi-generator seems harsh.

@wing328 What is your opinion?

@dbcfd

Copy link
Copy Markdown
Author

@bcourtine I meant the versions of the crates tokio, hyper, reqwest, etc. being deprecated. The current versions of those crates all require 1.39 or higher.

@bcourtine

Copy link
Copy Markdown
Contributor

I agree, but theses crates still have support for a pre-1.39 version ;)

@dbcfd

dbcfd commented Feb 14, 2020

Copy link
Copy Markdown
Author

@bcourtine Although these crates have pre 1.39 versions, they are not supported. Attempting to use the currently supported crates (e.g. hyper 0.13) on a 1.38 compiler will fail.

info: default toolchain set to '1.38.0-x86_64-apple-darwin'
1.38.0-x86_64-apple-darwin installed - rustc 1.38.0 (625451e37 2019-09-23)
$ cd code/rust/
$ cargo new --lib hyper-test
Created library `hyper-test` package
$ cd hyper-test/
$ vi Cargo.toml
$ cargo build
Compiling tower-service v0.3.0
error: `core::slice::<impl [T]>::len` is not yet stable as a const fn
--> /Users/dannybrowning/.cargo/registry/src/github.com-1ecc6299db9ec823/bytes-0.5.4/src/bytes.rs:130:18
|
130 | len: bytes.len(),
| ^^^^^^^^^^^
error: aborting due to previous error

@dbcfddbcfd changed the title [WIP] [Rust] Async await[Rust] Async awaitApr 27, 2020
@dbcfddbcfd mentioned this pull request May 3, 2020
5 tasks
Incorporate hyper and reqwest with async/await support. Bring in async-trait to simplify async trait interaction.
@wing328

wing328 commented Jun 16, 2020

Copy link
Copy Markdown
Member

@dbcfd I've added an option to support async operations for reqwest.

I wonder if you can pull the latest master to give it a try.

@wing328

Copy link
Copy Markdown
Member

Closing as there's no update.

@wing328wing328 closed this Jan 25, 2021
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

WIPWork in Progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@dbcfd@JohnDoneth@richardwhiuk@ctaggart@kanekv@UkonnRa@bcourtine@wing328