fsprojects / SwaggerProvider

F# generative Type Provider for Swagger
https://fsprojects.github.io/SwaggerProvider/
The Unlicense
262 stars 58 forks source link

OpenApiClientProvider with Stripe's open API hangs (3MB json) #150

Open vrescobar opened 4 years ago

vrescobar commented 4 years ago

Description

The autocompletion hangs and stops working when using OpenApiClientProvider with Stripe's open API. No visible error happens anywhere.

Repro steps

  1. Try to use OpenApiClientProvider with the stripe API
open SwaggerProvider

let [<Literal>] Schema = "https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.sdk.json"
// __SOURCE_DIRECTORY__ + "/openapi/stripe.spec3.json"
type Stripe = OpenApiClientProvider<Schema>

let main argv =
    let stripe = Stripe.Client()
    // the autocompletion dies or stops working at this point

That JSON file is about 3MB

Expected behaviour

I would expect to work as with any other open API or to get a visible error somewhere

Actual behavior

The autocompletion dies or stops working and doesn't seem to recover. To wait a large amount of time does not help.

Known workarounds

None:

Related information

Thorium commented 4 years ago

A workaround I use is using the Stripe .NET library. But it's not painless. It's quite low-level library, I have over 500 lines of F# code around it. They change and rename and release new versions all the time, and don't mind the backward compatibility: Not keeping up

A payment system should be a generic component. That would be so nice to have an out-of-box working payment solution for new F# projects. There is nothing project specific, "I just want to make an online-payment". I would be willing to help creating this kind of library...

But the workflows are more complex than you initially think: A customer may want to store a card (Stripe PaymentApiCardId), but the card will expire. A customer can call to you and ask for a (partial) refund. A customer can call to the card company and dispute the transaction. Stripe can respond to a webhook, but you have to have the transaction state-fully stored. And another topic is the EU PSD2 SCA regulations... and local country specific payment regulations.

A generic library is hard to make if you have to include a data storage (some kind of database) and a web-server endpoint for webhooks and also a way of redirecting users to 3D Secure. Suddenly you have to make decisions about technology and that is not generic anymore.

Thorium commented 4 years ago

Digging a bit this, it seems to me that the reading of the network schema, parsing it, etc, takes only 2.5 seconds total. But after that, there is some background process, involving ProvidedTypes.fs, that generates a temp-dll (like \AppData\Local\Temp\tmp434F.dll) of having the types. It will finish in around 50 seconds in my computer, and then it's actually done.

This is my little FSI script I used to test what happens:

#I @"C:\git\SwaggerProvider\src\SwaggerProvider.DesignTime\obj\Debug\netstandard2.0\"
#r @"C:\git\SwaggerProvider\src\SwaggerProvider.Runtime\bin\Debug\netstandard2.0\SwaggerProvider.Runtime.dll"
let [<Literal>] Schema = "https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.sdk.json";;
let t = System.DateTime.Now;; //#time didn't give correct results so let's user the old way...
type Stripe = SwaggerProvider.OpenApiClientProvider<Schema, PreferAsync = true>;;
printfn "%f" (System.DateTime.Now-t).TotalSeconds;;

What could be done to fix this, is lazy schema exploration:

toburger commented 3 years ago

I'm also experiencing a substantial slow down when consuming a bigger OpenApi file like https://api.tourism.testingmachine.eu/swagger/v1/swagger.json.

Thorium commented 3 years ago

We have a solution for Stripe now: https://github.com/simontreanor/FunStripe

toburger commented 3 years ago

Nice! But I've experienced those issues also with other OpenAPI services (not 3MB though) and it would be nice to have a solution for those performance problems.

jkone27 commented 3 years ago

I also had issues of slowdown with bigger openapi files, would be great if there could be some perf optimization, or improve caching (or generate some offline schema that could be re-used from file system, once the generation has happened already?) This type provider is awesome 💌

Thorium commented 3 months ago

There are a lot of nested types. The time is spent on ProvidedTypes.fs on method .Compile(isHostedExecution) This takes 7 seconds wait: // phase 2 - emit member definitions This takes 45 seconds wait: // phase 3 - emit member code Most of the time in these 2: // Emit the constructor (if any) // Emit the methods

If iterateTypes function could just run parallel on nestedTypes, that could help a lot. However the parameter f is doing operations on non-theadsafe manner. So using Array.Parallel.iter would need a major refactor to avoid causing erros.

Thorium commented 3 months ago

As this is TP issue in general, I did open issue for the SDK: https://github.com/fsprojects/FSharp.TypeProviders.SDK/issues/341