-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace Affjax with Fetch #657
Replace Affjax with Fetch #657
Conversation
@@ -35,6 +34,7 @@ package: | |||
- integers | |||
- js-date | |||
- js-uri | |||
- js-promise-aff |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a transitive dependency of fetch
, so it incurs no overhead.
@@ -2,7 +2,6 @@ module Registry.App.CLI.Git where | |||
|
|||
import Registry.App.Prelude | |||
|
|||
import Affjax (URL) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
URL
is just a type alias for String
, defined by Affjax.
Since the alias was used throughout the app, I've redefined the same alias in Registry.App.Prelude
.
-> Extra.Aff (RetryResult e b) | ||
withRetryRequest retry onAffjaxError onAffjaxResponse request = | ||
withRetry retry (map (Either.either (Either.Left <<< onAffjaxError) onAffjaxResponse) (Affjax.Node.request request)) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lines 158-187, were lifted and rewritten for use in the module Fetch.Retry
app/src/Fetch/Retry.purs
Outdated
runRequest :: Aff CoreResponse.Response | ||
runRequest = Promise.Aff.toAffE fetch | ||
let runRequest :: Aff Response | ||
runRequest = Fetch.fetch url r |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type signature of withRetryRequest
was copied and adapted directly from the fetch
source code. The only difference in these signatures is the return types.
The error message seems to be about ambiguous type variables, but I don't have a clue about to constrain the type any futher.
Error Message:
[1/1 NoInstanceFound] app/src/Fetch/Retry.purs:49:20
49 runRequest = Fetch.fetch url r
^^^^^^^^^^^^^^^
No type class instance was found for
Prim.Row.Union input5
t1
( body :: String
, cache :: RequestCache
, credentials :: RequestCredentials
, headers :: Record t2
, integrity :: Integrity
, method :: Method
, mode :: RequestMode
, referrer :: Referrer
, referrerPolicy :: ReferrerPolicy
)
The instance head contains unknown type variables. Consider adding a type annotation.
while applying a function fetch
of type Union @Type t0 t1
( body :: String
, cache :: RequestCache
, credentials :: RequestCredentials
, headers :: Record t2
, integrity :: Integrity
, method :: Method
, mode :: RequestMode
, referrer :: Referrer
, referrerPolicy :: ReferrerPolicy
)
=> Union @Type t3 t4
( body :: RequestBody
, cache :: String
, credentials :: String
, headers :: Headers
, integrity :: String
, method :: String
, mode :: String
, referrer :: String
, referrerPolicy :: String
)
=> ToCoreRequestOptions t0 t3 => String
-> Record t0
-> Aff
{ arrayBuffer :: ...
, blob :: ...
, body :: ...
, headers :: Headers
, json :: ...
, ok :: Boolean
, redirected :: Boolean
, status :: Int
, statusText :: String
, text :: ...
, url :: String
}
to argument url
while inferring the type of fetch url
in value declaration withRetryRequest
where input5 is a rigid type variable
bound at (line 0, column 0 - line 0, column 0)
t0 is an unknown type
t3 is an unknown type
t1 is an unknown type
t4 is an unknown type
t2 is an unknown type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a relevant thread on the Discourse: https://discourse.purescript.org/t/specialize-function-via-annotation/3616. The fix there also applies here, this compiles
withRetryRequest
:: forall input output thruIn thruOut headers
. Union input thruIn (HighlevelRequestOptions headers String)
=> Union output thruOut CoreRequest.UnsafeRequestOptions
=> ToCoreRequestOptions input output
=> String
-> { | input }
-> Aff (RetryResult RetryRequestError Response)
withRetryRequest url r = do
let
runRequest :: Aff Response
- runRequest = fetch url r
+ runRequest = fetchWithProxy (Proxy :: Proxy thruIn) url r
retryRequest runRequest
+ fetchWithProxy
+ :: forall input output thruIn thruOut headers
+ . Union input thruIn (HighlevelRequestOptions headers String)
+ => Union output thruOut CoreRequest.UnsafeRequestOptions
+ => ToCoreRequestOptions input output
+ => Proxy thruIn
+ -> String
+ -> { | input }
+ -> Aff Response
+ fetchWithProxy _ url r = do
+ request <- liftEffect $ new url $ Request.convert r
+ cResponse <- Promise.Aff.toAffE $ Core.fetch request
+ pure $ Response.convert cResponse
Visible type applications (https://github.com/purescript/purescript/releases/tag/v0.15.10) is a new feature in PureScript which lets us leave out the Proxy
argument, so this also compiles
withRetryRequest
:: forall input output thruIn thruOut headers
. Union input thruIn (HighlevelRequestOptions headers String)
=> Union output thruOut CoreRequest.UnsafeRequestOptions
=> ToCoreRequestOptions input output
=> String
-> { | input }
-> Aff (RetryResult RetryRequestError Response)
withRetryRequest url r = do
let
runRequest :: Aff Response
- runRequest = fetchWithProxy (Proxy :: Proxy thruIn) url r
+ runRequest = fetch @thruIn url r
retryRequest runRequest
- fetchWithProxy
- :: forall input output thruIn thruOut headers
+ fetch
+ :: forall input output @thruIn thruOut headers
. Union input thruIn (HighlevelRequestOptions headers String)
=> Union output thruOut CoreRequest.UnsafeRequestOptions
=> ToCoreRequestOptions input output
- => Proxy thruIn
- -> String
+ => String
-> { | input }
-> Aff Response
- fetchWithProxy _ url r = do
+ fetch url r = do
request <- liftEffect $ new url $ Request.convert r
cResponse <- Promise.Aff.toAffE $ Core.fetch request
pure $ Response.convert cResponse
The only difference from the fetch
source code is the @thruIn
.
Sorry it doesn't help much with this PR, but it seems like it would be worthwhile to expose @thruIn
in the fetch
implementation upstream to use with VTAs (and maybe the other type parameters as well? not sure what the heuristic is).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can add this to fetch so we can use vta here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're using 0.15.10 in the registry so feel free to use VTAs if you'd like.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great. I have just tagged a new version (v3.0.0) of fetch with the vta change.
@thomashoneyman I've tried a few different approaches to reimplementing See these 2 commits for the two main approaches I tried: On the bright side, I was able to port the rest of the application to use the new fetch based api, just haven't figured out how to implement the retry helper in a way to satisfy the type checker. |
@pete-murphy Thanks for the help! @thomashoneyman |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a great start! Thanks for your work to puzzle out a good way to get fetch working with the retry function. I have a few comments, but overall this looks quite close.
@MonoidMusician A bit of an odd error in the tests, coming from the solver:
The only thing that would affect the solver here are dependency updates; I know that there were recently changes to |
@thomashoneyman Alright, I resolved the comments you left & squashed down to 1 commit. |
@thomashoneyman I manually tested the one failing test against different registry versions, and found the last version that works is 35.1.0, and the first failing version is 35.2.0. |
Looks like that corresponds with ordered-collections being updated to 3.1.0: Release is here, looks like a pretty major rewrite of the internals: I'll have to review separately and see if the change to behavior is benign or not. |
, timeout: Nothing | ||
, url | ||
result <- Run.liftAff $ Fetch.withRetryRequest url | ||
{ headers: { accept: "application/json" } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be “Accept” the way it is above?
The code looks good — I’ll give this a try later today and hopefully we can get it merged! |
@thomashoneyman I don't see an obvious reason why the error message would have changed, assuming both the old Data.Map and new one are both correct. The API surface I used is pretty small. Maybe traversal order changed somewhere? But it's a pretty benign change to that error message so I don't think it's a big deal. The algorithm should still be correct. |
This is certainly possible. Both old and new |
Resolves #643
Replaces Affjax with Fetch.
I recommend reviewing
Fetch.Retry
first, the rest of changes are pretty mechanical.There's probably a case to be made for moving some or all of the
Fetch.Retry
module into the actual fetch package.Just let me know what you want to do.