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

fix: stub.serve() shutdown #108

Merged
merged 6 commits into from
Dec 5, 2022

Conversation

thundergolfer
Copy link
Contributor

@thundergolfer thundergolfer commented Dec 3, 2022

stub.serve() is currently unable to await app.disconnect() and stop an app, because async_utils.on_shutdown(AioClient.stop_env_client()) runs before the disconnect call and disconnects the client. (it's a race that the disconnect() never wins)

I tried a couple dozen things, but can't get around the fact that once Ctrl + C has initiated the async loop's shutdown, you can't control the ordering of the app disconnection and the client stop.

The proper fix is probably to rewrite all client usage to be done by context manager, but that's much more involved than this stop-gap I've done here.


Ref: Shutdown hook is from https://github.com/modal-labs/modal/pull/2957.

@erikbern
Copy link
Contributor

erikbern commented Dec 4, 2022

This doesn't seem 100% obvious to me – what if someone wants to call stub.serve from within their code? They might not expect the client to get torn down when stub.serve finishes. Maybe it's a weird case.

@thundergolfer
Copy link
Contributor Author

I think that's a weird case. The .serve() blocks and doesn't return, so it only really finishes when a termination is sent, such as SIGTERM or SIGINT or SIGKILL.

@erikbern
Copy link
Contributor

erikbern commented Dec 5, 2022

Would prefer to solve it in a nicer way – fine to merge this but let's at least add some comments explaining what's the purpose of this code. Would also prefer to add a test.

modal/client.py Outdated
@@ -137,7 +139,16 @@ async def _start(self):

logger.debug("Client: Done starting")

async def set_pre_stop(self, pre_stop: Callable[[], None]):
Copy link
Contributor

Choose a reason for hiding this comment

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

This wouldn't have to be an async method right?

@thundergolfer
Copy link
Contributor Author

thundergolfer commented Dec 5, 2022

Agree that this is not a nice solution, but prefer to defer the biggest refactor until after webhook updates are shipped. Will add the comments + test though 👍

@erikbern
Copy link
Contributor

erikbern commented Dec 5, 2022

If it's hard to add the test, it's not the end of the world to skip it. Would be great to add some comments though!

@thundergolfer thundergolfer force-pushed the jonathon/fix-stub-serve-shutdown-dec1 branch from f2a48f2 to 942efa6 Compare December 5, 2022 19:31
@thundergolfer thundergolfer force-pushed the jonathon/fix-stub-serve-shutdown-dec1 branch from 867bd4e to 60207ca Compare December 5, 2022 21:26
stub = Stub()
fake_disconnect = AsyncMock()
with modal.client.Client(servicer.remote_addr, api_pb2.CLIENT_TYPE_CLIENT, ("foo-id", "foo-secret")) as client:
with patch.object(modal.app._App, "disconnect", fake_disconnect):
Copy link
Contributor

@erikbern erikbern Dec 5, 2022

Choose a reason for hiding this comment

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

Awesome with test!

Instead of mocking the app, you could probably just see if the AppClientDisconnect call was called on the servicer fixture

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cheers, I'll try that 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, seems doing that has triggered the need for @skip_in_github

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A mock-y test that runs in CI is probably better than a non-mock test that doesn't run in CI, so I'll go back to that.

Copy link
Contributor Author

@thundergolfer thundergolfer Dec 5, 2022

Choose a reason for hiding this comment

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

Damn, the mock is flaky too.

This issue would be solved by solving MOD-533.

@thundergolfer thundergolfer force-pushed the jonathon/fix-stub-serve-shutdown-dec1 branch from fcbf901 to cd708fc Compare December 5, 2022 22:31
@thundergolfer thundergolfer merged commit 4481d52 into main Dec 5, 2022
@thundergolfer thundergolfer deleted the jonathon/fix-stub-serve-shutdown-dec1 branch December 5, 2022 22:39
@freider
Copy link
Contributor

freider commented Mar 14, 2024

Attempt at removing this here: #1523

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.

3 participants