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

Display an actual TCP port app is bound to #3034

Merged
merged 28 commits into from
Nov 23, 2023

Conversation

develop7
Copy link
Collaborator

@develop7 develop7 commented Nov 1, 2023

Documents and properly handles the special value of 0 for server-port config. Before this PR, the value was passed through and handled by the platform's getaddrinfo implementation, seemingly resulting in binding to a random port. This PR makes it official and binds to random port explicitly.

Other changes it introduces:

  • Simplifies app starting logic, moving platform-dependent POSIX-specific code to PostgREST.Unix, making it the only file with the LANGUAGE CPP pragma and reducing the amount of indirection. Pretty sure the indirection in question was here on purpose, let me know if that's still the case — tests do pass, things work fine, so I've decided to give it a shot.
  • Recent releases of network and all Windows released since 5 years ago actually do support Unix domain sockets, so I've taken a chance to prepare code for making use of those: replaced setFileMode with its twin function from unix-compat and used Network.Socket.isUnixDomainSocketAvailable to check such sockets' availability in runtime. All that's left to pull the plug is to upgrade network.
  • makes PostgREST.Unix.installSignalHandlers more explicit, avoiding potential circular dependency between PostgREST.Unix and PostgREST.AppState
  • slightly decreases test coverage. The cases missed seem to be trivial to me and would require considerable effort to be tested properly.

Fixes #2420

Old TODO TODO:
  • test
  • document special server-port value of 0; done in server-port can be 0 postgrest-docs#695
  • get runtime error for Unix socket on unsupported platforms back (right now it degraded to compile error)
  • fix Windows build
  • fix the crash in, presumably, Admin.reachMainApp I was binding a socket, but didn't listen it 😖

@steve-chavez
Copy link
Member

@develop7 Good initiative fixing this!

I see the CI failures. That happens because the Admin.hs doesn't keep track of the assigned random port.

I believe the correct fix is the one that Wolfgang mentioned on #2174 (comment). Basically store the socket on AppState and use it on Admin.hs. Then some code can be removed from Admin, like the getAddrInfo part.

(I don't recall why I didn't make like that on the first place, but seems it should work)

@develop7
Copy link
Collaborator Author

develop7 commented Nov 2, 2023

I believe the correct fix is the one that Wolfgang mentioned on #2174 (comment). Basically store the socket on AppState and use it on Admin.hs. Then some code can be removed from Admin, like the getAddrInfo part.

Yep, on it; the 47df6c2 is more of a PoC

@develop7
Copy link
Collaborator Author

develop7 commented Nov 2, 2023

BTW since Warp.runSettings passes the port number through, it should handle special values like 0 properly as well, by returning actual port number.

@develop7
Copy link
Collaborator Author

develop7 commented Nov 2, 2023

So Warp.runSettings does pass the port number to streaming-commons' bindPortTCP, which has sister function bindRandomPortTCP, which returns port actually bound; we could use it to handle the special case of 0 on our side. Let me explore this for a bit.

@develop7
Copy link
Collaborator Author

develop7 commented Nov 3, 2023

Not sure whether it's better to store port number along in the AppState, along with app socket, or read port number directly out of socket. I chose the latter for the places where actual Warp instances are run, but initSockets is currently a bit inconsistent on this matter

@steve-chavez
Copy link
Member

@develop7 It's starting to look better! Seems you need to add streaming-commons to cabal to clear the errors on CI.

Not sure whether it's better to store port number along in the AppState, along with app socket, or read port number directly out of socket. I chose the latter..

Yeah, the less state we can keep the better.

@develop7
Copy link
Collaborator Author

develop7 commented Nov 6, 2023

@steve-chavez done and done, but now every single IO test under test_io.py is failing (see https://github.com/PostgREST/postgrest/actions/runs/6772230579/job/18404342720?pr=3034#step:4:269). It seems to timeout getting the 200 response from admin interface.

@develop7
Copy link
Collaborator Author

develop7 commented Nov 9, 2023

Okay, I've just reproduced the crash in Admin.reachMainApp. It's probably caused by reusing the Socket from AppState to send to it; one shouldn't do that.

@develop7
Copy link
Collaborator Author

develop7 commented Nov 9, 2023

https://hackage.haskell.org/package/network-3.1.4.0/docs/Network-Socket.html#v:isUnixDomainSocketAvailable says

AF_UNIX is supported on Windows since 3.1.3.0. So, this variable is True on all platforms.

Does it mean we can have UNIX sockets on Windows?

@develop7
Copy link
Collaborator Author

develop7 commented Nov 9, 2023

Does it mean we can have UNIX sockets on Windows?

Per haskell/network#549 (comment): any supported version of Windows has it. It's a "yes".

Comment on lines -151 to -153
, directory >= 1.2.6 && < 1.4
exposed-modules:
PostgREST.Unix
Copy link
Member

@steve-chavez steve-chavez Nov 17, 2023

Choose a reason for hiding this comment

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

@develop7 Any concerns on windows? Maybe we should allow running tests on windows on CI to be extra sure (can be done on another PR).

Copy link
Collaborator Author

@develop7 develop7 Nov 17, 2023

Choose a reason for hiding this comment

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

That'd be only fair, since Windows got first-class support

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We cannot enable all tests on Windows right off the bat, but specs & doctests should be fine

postgrest.cabal Outdated Show resolved Hide resolved
postgrest.cabal Outdated Show resolved Hide resolved
postgrest.cabal Outdated
, swagger2 >= 2.4 && < 2.9
, text >= 1.2.2 && < 1.3
, time >= 1.6 && < 1.12
, timeit >= 2.0 && < 2.1
, unordered-containers >= 0.2.8 && < 0.3
, unix-compat >= 0.6 && < 0.7
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
, unix-compat >= 0.6 && < 0.7
, unix-compat >= 0.5.4 && < 0.6

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yup, that should do it

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That'd did it

Comment on lines 53 to 54
-- The code for resolving the "*4", "!4", "*6", "!6", "*" special values is taken from
-- https://hackage.haskell.org/package/streaming-commons-0.2.2.4/docs/src/Data.Streaming.Network.html#bindPortGenEx
Copy link
Member

Choose a reason for hiding this comment

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

This is no longer the case right? Will remove.

@steve-chavez steve-chavez merged commit df97a50 into PostgREST:main Nov 23, 2023
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Bogus Listening on port 0 message, provide useful info
2 participants