Skip to content
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

Gzip package documentation when publishing to Pursuit #659

Conversation

pete-murphy
Copy link
Contributor

Fixes #642.

result <- Run.liftAff $
result <- Run.liftAff do
gzipped <- Gzip.compress (Argonaut.stringify payload)
body <- liftEffect (Buffer.toString UTF8 gzipped)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I haven't tested this. I've tested sending a Buffer as request body directly without converting to string, but that's not currently supported in the upstream types for RequestBody purescript-web/purescript-web-fetch#15.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just passing Buffer directly gets this to pass the integration tests (e231be6). Before that, was seeing "Not in GZIP format" errors

registry # [   43.420167] registry-server-init[910]: Pushing to Pursuit...
registry # [   43.625450] registry-server-init[910]: [ERROR] Pursuit publishing failed with status 500 and body
registry # [   43.626327] registry-server-init[910]: {
registry # [   43.626781] registry-server-init[910]: "cause1":"java.util.zip.ZipException: Not in GZIP format",
registry # [   43.627595] registry-server-init[910]: "servlet":"com.github.tomakehurst.wiremock.servlet.WireMockHandlerDispatchingServlet-2dca0d64",
registry # [   43.629109] registry-server-init[910]: "cause0":"java.lang.RuntimeException: java.util.zip.ZipException: Not in GZIP format",
registry # [   43.634155] registry-server-init[910]: "message":"java.lang.RuntimeException: java.util.zip.ZipException: Not in GZIP format",
registry # [   43.635515] registry-server-init[910]: "url":"/packages",
registry # [   43.636876] registry-server-init[910]: "status":"500"
registry # [   43.637356] registry-server-init[910]: }
registry # [   43.637757] registry-server-init[910]: [ERROR] Could not publish your package to Pursuit because an error was encountered (cc: @purescript/packaging): Expected to receive a 201 status from Pursuit, but received 500 instead.

Copy link
Member

Choose a reason for hiding this comment

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

The upstream is actually https://github.com/rowtype-yoga/purescript-fetch-core, and we can more easily make changes to that library. fetch relies on fetch-core instead of web-fetch (until one day we merge them into js-fetch).

Copy link
Member

Choose a reason for hiding this comment

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

Regardless — I think your Gzip newtype workaround is a proper solution. Good intuition!

Comment on lines 16 to 25
Spec.it "Compresses a string with gzip" do
tmp <- Tmp.mkTmpDir
let
file = Path.concat [ tmp, "out.gz" ]
contents = "<contents>"
buffer <- Gzip.compress contents
FS.Aff.writeFile file buffer
result <- _.result =<< Execa.execa "gzcat" [ file ] identity
(_.stdout <$> result) `Assert.shouldEqual` Right contents
Spec.describe "compress" do
Spec.it "Compresses a string with gzip" do
tmp <- Tmp.mkTmpDir
let
file = Path.concat [ tmp, "out.gz" ]
contents = "<contents>"
buffer <- Gzip.compress contents
FS.Aff.writeFile file buffer
result <- _.result =<< Execa.execa "gzcat" [ file ] identity
(_.stdout <$> result) `Assert.shouldEqual` Right contents
Copy link
Contributor Author

@pete-murphy pete-murphy Sep 4, 2023

Choose a reason for hiding this comment

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

Odd, without the describe wrapper, the Gzip test results are lumped in with the FastGlob results.

Before:

Foreign » FastGlob
  ✓︎ Prevents directory traversal
  ✓︎ Prevents symlink directory traversal
  ✓︎ Prevents traversal to a non-existing file
  ✓︎ Compresses a string with gzip

After:

Foreign » FastGlob
  ✓︎ Prevents directory traversal
  ✓︎ Prevents symlink directory traversal
  ✓︎ Prevents traversal to a non-existing file
Foreign » Gzip » compress
  ✓︎ Compresses a string with gzip

Copy link
Contributor Author

@pete-murphy pete-murphy Sep 4, 2023

Choose a reason for hiding this comment

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

Maybe this is a bug in purescript-spec? I opened this issue purescript-spec/purescript-spec#144

Copy link
Member

Choose a reason for hiding this comment

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

Hm — seems like it. I think what you've done in this PR is fine (adding the top describe).

app/src/Fetch/Retry.purs Outdated Show resolved Hide resolved
@pete-murphy pete-murphy marked this pull request as ready for review September 4, 2023 18:25
@flip111
Copy link
Contributor

flip111 commented Sep 4, 2023

Hey i reviewed your PR looks good to me. There is an opportunity to tweak the compression algorithm if needed. The gzip function takes a second parameter with options and you can set the compression level there with other parameters https://nodejs.org/api/zlib.html#zlibgzipbuffer-options-callback

@pete-murphy
Copy link
Contributor Author

Hey i reviewed your PR looks good to me. There is an opportunity to tweak the compression algorithm if needed. The gzip function takes a second parameter with options and you can set the compression level there with other parameters https://nodejs.org/api/zlib.html#zlibgzipbuffer-options-callback

Thanks! I have no experience optimizing compression so I have no idea what would be the best settings here and would be open to recommendations. I'm hoping that since (I think) there haven't been any issues publishing via Pulp using the default settings for zlib.createGzip, we might be safe using the defaults here 🤞 .

@thomashoneyman
Copy link
Member

I'm sorry for my slow reviews this week — I'm only somewhat available, and will be fully back online next week. I'm going to take a quick look through your PR but don't have the time right now to test it out. I promise to get this over the line by next week, however, should it appear to have no issues. Thanks for taking the time to work on this!

Copy link
Member

@thomashoneyman thomashoneyman left a comment

Choose a reason for hiding this comment

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

This is a nice, small patch! It looks totally fine to me module some minor review comments. I might be able to test it tomorrow, in which case I'll get it merged. Thanks!

@@ -22,16 +22,16 @@ data RetryRequestError
| StatusError Response

withRetryRequest
:: forall input output thruIn thruOut headers
. Union input thruIn (HighlevelRequestOptions headers String)
:: forall input output thruIn thruOut headers @body
Copy link
Member

Choose a reason for hiding this comment

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

Is this VTA actually used? I don't see it in the body of the function.

Copy link
Contributor Author

@pete-murphy pete-murphy Sep 5, 2023

Choose a reason for hiding this comment

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

Before these changes, the body option of withRetryRequest was fixed to String, but I've replaced the definition of fetch below with fetchBody from the purescript-fetch library.

Because body could now be any ToRequestBody body => body, I needed to specify @String in these call sites (the compiler didn't seem to infer as String without the VTA, from what I tried)

result <- Run.liftAff $ Fetch.withRetryRequest @String url
Run.liftAff $ Fetch.withRetryRequest @String archiveUrl {}
response <- Run.liftAff $ Fetch.withRetryRequest @String packageUrl {}

Copy link
Contributor Author

@pete-murphy pete-murphy Sep 5, 2023

Choose a reason for hiding this comment

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

An alternative that comes to mind, to avoid adding those @String changes, would be keeping both fetch and fetchWithBody implementations copied from purescript-fetch and then adding a retryWithRequestBody so we don't have to update call sites of retryWithRequest

Copy link
Contributor Author

@pete-murphy pete-murphy Sep 5, 2023

Choose a reason for hiding this comment

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

I needed to specify @String in these call sites (the compiler didn't seem to infer as String without the VTA, from what I tried)

Hm, nevermind, trying again without VTAs and type inference is working fine. I think at one point there was an explicit ToRequestBody body constraint that required the type annotation. I copied the constraint from the upstream definition of fetchBody, but from what I can tell it's not really necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed here 0a02e14

Comment on lines 19 to 24
foreign import toRequestBodyImpl :: Buffer -> RequestBody

newtype Gzip = Gzip Buffer

instance ToRequestBody Gzip where
toRequestBody (Gzip buffer) = toRequestBodyImpl buffer
Copy link
Member

Choose a reason for hiding this comment

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

I typically like to write functions like this one with unsafeCoerce (since it's a straightforward coercion) instead of a as a foreign import, because you can tell at a glance how it works instead of having to look at the FFI to see if there's anything interesting happening.

Would you mind reimplementing the foreign import as something like this?

-- could also be 'gzipToRequestBody :: Gzip -> RequestBody' and the instance:
--   instance ToRequestBody Gzip where
--     toRequestBody = gzipToRequestBody
coerceToRequestBody :: Buffer -> RequestBody
coerceToRequestBody = unsafeCoerce

Copy link
Contributor Author

@pete-murphy pete-murphy Sep 5, 2023

Choose a reason for hiding this comment

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

Updated here 74cca55 with a link to rowtype-yoga/purescript-fetch#11

@thomashoneyman thomashoneyman merged commit 1b9fc7d into purescript:master Sep 12, 2023
@thomashoneyman
Copy link
Member

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Gzip package documentation when sending to Pursuit
3 participants