Skip to content
This repository has been archived by the owner on Jul 1, 2021. It is now read-only.

Implement UDP communication services for discv5 #816

Merged
merged 3 commits into from
Jul 23, 2019

Conversation

jannikluhn
Copy link
Contributor

@jannikluhn jannikluhn commented Jul 21, 2019

Add two simple services that read and write data to and from a UDP socket.

To-Do

  • Fix async fixtures: For some reason they don't work even though they should ("RuntimeError: Cannot be used outside of a run context")
  • Tell CI to run tests with trio_mode enabled
  • Fix type hints if possible
  • Clean up commit history

Cute Animal Picture

animal-animal-photography-avian-2629372

Copy link
Member

@pipermerriam pipermerriam left a comment

Choose a reason for hiding this comment

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

Architecturally I'm inclined to suggest modeling this in a similar manner to the p2p.transport.Transport abstraction. This allows you to fully abstract away the underlying networking in testing scenarios.

Now, the current model does have this property in that it appears you could just wire up some trio channels and pretend they had networking behind them.

I'd be completely fine with you iterating on this a bit over some pull requests so this doesn't need to block this PR but something worth considering as you start getting deeper into testing this and want to do things like have multiple peers sending messages to each other.

logger = logging.getLogger('p2p.discv5.channel_services.DatagramReceiver')

async with incoming_datagram_send_channel:
while True:
Copy link
Member

Choose a reason for hiding this comment

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

I think this should be something like while manager.is_running so the loop can exit naturally in the event of a cancellation being triggered externally.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will change because it looks cleaner than a while True. But I don't think it actually changes anything as cancellation would just raise an exception during one of the awaits.

received_datagram = await receive_channel.receive()

assert received_datagram.datagram == data
assert received_datagram.sender == sender_address
Copy link
Member

Choose a reason for hiding this comment

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

I think you should probably assert that you have property access on these by doing assert received_datagram.sender.address == ... because I think that this will evaluate truthy if sender is just a plain tuple (but I'm not 100% sure)

@jannikluhn
Copy link
Contributor Author

Now, the current model does have this property in that it appears you could just wire up some trio channels and pretend they had networking behind them.

Yes, the intention is that there are separate services for each processing step (socket, decoding, decryption, handshake, ...) that just receive data from some channel and send it to another. This should make it possible to test all components fully independently.

@jannikluhn jannikluhn force-pushed the udp-channel-services branch from 904084b to db5769a Compare July 22, 2019 11:39
@pipermerriam
Copy link
Member

This should make it possible to test all components fully independently.

Cool, sounds like you've got a vision for this so I'll wait to see how it comes together.

@jannikluhn jannikluhn force-pushed the udp-channel-services branch from 2ed5ea9 to 377d7ad Compare July 23, 2019 09:27
@@ -170,7 +170,7 @@ def cancel(self) -> None:
...


LogicFnType = Callable[[ManagerAPI, VarArg(), KwArg()], Awaitable[Any]]
LogicFnType = Callable[..., Awaitable[Any]]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Couldn't get the type hints to work otherwise. In fact, I think it's impossible to do this properly right now. See python/mypy#5876 (comment)

Copy link
Member

Choose a reason for hiding this comment

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

I kind of suspected this was going to be the case.

@jannikluhn jannikluhn force-pushed the udp-channel-services branch from 5a824dc to 88a3127 Compare July 23, 2019 09:50
await incoming_datagram_send_channel.send(incoming_datagram)


@as_service
Copy link
Member

Choose a reason for hiding this comment

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

not for this PR but thinking about API. Maybe we could have this decorator optionally accept some arguments.

@as_service(manager=True)
async def UsesManager(manager: ManagerAPI):
    ...

@as_service
async def DoesNotUseManager():
    ...

Might be nice to not always have to include the manager argument for services that don't use it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 sounds like a good idea. Most services will also do some logging, so the same could be done for a logger instance for convenience (might be confusing though, not sure).

@jannikluhn jannikluhn force-pushed the udp-channel-services branch from 88a3127 to 8954a11 Compare July 23, 2019 17:03
@jannikluhn jannikluhn merged commit 82e7243 into ethereum:master Jul 23, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants