Skip to content

PYTHON 5212 - Use asyncio.loop.sock_connect in _async_create_connection #2383

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

Merged
merged 10 commits into from
Jun 13, 2025

Conversation

NoahStapp
Copy link
Contributor

No description provided.

@NoahStapp NoahStapp requested a review from ShaneHarvey June 12, 2025 20:07
@@ -244,7 +244,8 @@ async def _async_create_connection(address: _Address, options: PoolOptions) -> s
sock.settimeout(timeout)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True)
_set_keepalive_times(sock)
sock.connect(sa)
sock.setblocking(False)
await asyncio.get_running_loop().sock_connect(sock, sa)
Copy link
Member

Choose a reason for hiding this comment

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

We need to do the same above for unix sockets as well.

Copy link
Member

@ShaneHarvey ShaneHarvey Jun 12, 2025

Choose a reason for hiding this comment

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

Also don't we need to add more code to emulate the connect_timeout behavior now that we're using sock.setblocking(False)? Or is the async connect timeout behavior handled at a higher level?

Copy link
Contributor Author

@NoahStapp NoahStapp Jun 12, 2025

Choose a reason for hiding this comment

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

Yes: we'll have to move all socket timeout behavior out of the socket itself and into the AsyncNetworkInterface. In the middle of that now. We already do this.

Copy link
Contributor Author

@NoahStapp NoahStapp Jun 12, 2025

Choose a reason for hiding this comment

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

Sorry, specifically for encryption _async_configured_socket raw sockets. We manage AsyncNetworkInterface timeouts at a higher level already. Incorrect, we already handle raw async socket timeouts correctly to account for this change. The socket only needs to be nonblocking for creation.

Copy link
Member

@ShaneHarvey ShaneHarvey Jun 12, 2025

Choose a reason for hiding this comment

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

The problem is that _async_create_connection is called before AsyncNetworkInterface is ever created. So the timeout needs to be enforced here.

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 misunderstood what you meant. My next commit already addresses this with an asyncio.wait_for.

@NoahStapp NoahStapp requested a review from ShaneHarvey June 12, 2025 20:22
@NoahStapp
Copy link
Contributor Author

Scheduled every Evergreen task for maximum confidence in the correctness of the change.

@NoahStapp
Copy link
Contributor Author

Encryption test failures are due to ssl_context.wrap_socket not allowing non-blocking sockets when do_handshake_on_connect=True, which is the default. Will resolve tomorrow.

@NoahStapp
Copy link
Contributor Author

All test failures are known failures or persistent TLS PyPy issues.

return sock
except asyncio.TimeoutError as e:
sock.close()
raise socket.timeout("timed out") from e
Copy link
Member

Choose a reason for hiding this comment

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

Should we store the exception and carry on like we do in the sync OSError case?:

        except asyncio.TimeoutError as e:
            sock.close()
            err = socket.timeout("timed out")
            err.__cause__ = e

If not, I worry about subtle behavior differences between sync and async.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a slick workaround to the lack of from e without raise.


self.assertLessEqual(
sorted(latencies, reverse=True)[0],
0.2,
Copy link
Member

Choose a reason for hiding this comment

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

I worry only adding 100ms will be flaky, can we make this 1 full second?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call, I was slightly too optimistic about the EG host performance.

@NoahStapp NoahStapp requested a review from ShaneHarvey June 13, 2025 19:08
@NoahStapp NoahStapp merged commit 50ea823 into mongodb:master Jun 13, 2025
69 of 70 checks passed
NoahStapp added a commit to NoahStapp/mongo-python-driver that referenced this pull request Jun 13, 2025
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.

2 participants