-
Notifications
You must be signed in to change notification settings - Fork 943
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
Request/Response: change execute to be async method #2142
Request/Response: change execute to be async method #2142
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is wrong and will not work for the sync client.
I thought you were working on the changes in asyncio in another PR, where you demonstrated that execute do not need to be async.
In theory execute don't need to be async, but some of them are checking results of getValues/setValues, so those should be reworked to be out from execute in that case. I had the impression that only server-code called execute and this was ok approach. But I'll take second look of the comments and check what I missed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And btw it seems you have not analyzed the code. The execute is both sync and async (as in it returns a future). Execute splits at a lower level to async_execute when called in an async environment
Did you look at how we define the T which is the return from the mixin methods, that secures you can use the modhid as sync/async and satisfy mypy. |
you might be right that the execute in the different messages is only called from asyncio (and a couple of special examples), |
I will take a closer look, once you have a green CI. |
Yes, My initial idea was to do that change in separate PR, that I haven't yet opened. Just to make this one only async/await changes and in that point of view, simpler to review. Referring to #2127 (comment) So plan is to open separate PR that will add async_get/setValues to datastore and changes execute to use those with await, then fourth to change remote-datastore to use client as async flow. |
2162e3d
to
459913b
Compare
I'm also fine to leave this PR open until I have opened the remaining PR's, so you can check those aswell to see end goal better? |
Isn't that only in ModbusClient.execute codepath and not in server-codepath used ModbusRequest.execute ? |
Sorry you are right. |
I might not had said it correctly, but you need to attach this bottom-up, meaning e.g. this PR does not make sense until you have async datastore in place. I review each PR as a closed part (which of course can form part of bigger picture), and each PR must be understandable and have a reason (it is not a reason, to state this is needed for a future change somewhere else). This PR adds "async" to a method that have no awaits, so it does not make sense. I hope I have explained myself better....I am all in favor of having an async datastore, I just need to ensure that the code and the architecture do not break. |
That makes sense
Understandable
Yes, I'll try to get the remaining PR's open so things can be justified and revied easier. |
btw just for information, you might have noticed that asyncio.py calls self.framer.processIncomingPacket which is not async (since it is shared with the sync client) and thus giving you problems. We are currently working a lot to refactor framer, and once complete it will be totally async. In the meantime, you can replace the "lambda" with functols.partial calling the async executor, with async_execute as argument. This is not a needed change, but just to show you how to get around having 2 execute methods. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You change all server execute to be async, but execute in asyncio is still sync ?
@@ -392,7 +392,7 @@ def __init__(self, base, req, retries=0): | |||
async def delayed_resp(self): | |||
"""Send a response to a received packet.""" | |||
await asyncio.sleep(0.05) | |||
resp = self.req.execute(self.ctx) | |||
resp = await self.req.execute(self.ctx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems wrong ! the client should be affected by a server change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that is RequestExecute, so for example ReadCoilsRequest, and as that mocks server-responses, it needs to do that async execute call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct, thanks for pointing it out.
Yes, as execute is passed to callback for processIncomingPacket, and I wanted to scope down the changes as much as possible, I could have used partial there and remove the lambda, but I saw it as not required change at the moment in this scope. |
459913b
to
58cda02
Compare
58cda02
to
e6f6efa
Compare
Closing this since it changed to several small PR |
Hi, I think you are mixing #2127 and this PR, as this PR was split out from the bigger PR, which is 2127 and if you look the change of this PR, it is one of the small changes |
Sounds correct, sorry for the mistake. |
It's still draft though. |
contains only async/await edits, no functional changes otherwise
e6f6efa
to
5109f33
Compare
I rebased and re-opened the PR |
windows CI seems to fail on not having python |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes as such are OK, however I miss an await in asyncio.py where execute is called.... it seems to me that this PR guarantees that execute delivers a future.
That is already in, and was merged in #2139 |
As far as I can see it is not changed. _async_execute() still contains the check iscoroutine(), which is no longer needed. |
I'll add commit to remove it |
all serverside executes are async calls now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks.
* add _legacy_decoder to message rtu (#2119) * Add generate_ssl() to TLS client as helper. (#2120) * ASCII framer using message decode() (#2128) * SOCKET/TLS framer using message decode(). (#2129) * Fix decode for wrong mdap len. * Streamline message class. (#2133) * modbus_server: call execute in a way that those can be either coroutines or normal methods (#2139) * Clean datastore setValues. (#2145) * fixed kwargs not being expanded for actions on bit registers, adjusted tests to catch this issue (#2161) * datastore: add async_setValues/getValues methods (#2165) Co-authored-by: Ilkka Ollakka <ilkka.ollakka@cloudersolutions.com> * Request/Response: change execute to be async method (#2142) * Bump actions CI. (#2166) * Fix usage of AsyncModbusTcpClient in client docs page (#2169) * Sphinx: do not turn warnings into errors. * Add minimal devcontainer. (#2172) * Transaction id overrun. * call async datastore from modbus server (#2144) * Datastore will not return ExceptionResponse. (#2175) * Describe zero_mode in ModbusSlaveContext.__init__ (#2187) * Solve pylint error. * Show error if example is run without support files. (#2189) * Fix usage file names (#2194) * Update client.rst (#2199) * Transaction_id for serial == 0. (#2208) * Remember to remove serial writer. (#2209) * Fix writing to serial (rs485) on windows os. (#2191) Co-authored-by: jan iversen <jancasacondor@gmail.com> * test convert registers with 1234.... (#2217) * Solve serial unrequested frame. (#2219) * Log comm retries. (#2220) * prepare v3.6.9. * pylint. * Remove python 3.8 from CI. --------- Co-authored-by: Ilkka Ollakka <14361597+ilkka-ollakka@users.noreply.github.com> Co-authored-by: sumguytho <48988983+sumguytho@users.noreply.github.com> Co-authored-by: Ilkka Ollakka <ilkka.ollakka@cloudersolutions.com> Co-authored-by: Yohrog <69543220+Yohrog@users.noreply.github.com> Co-authored-by: James Cameron <90580716+jcameron-sso@users.noreply.github.com> Co-authored-by: Qi Li <160646648+qili-eaton@users.noreply.github.com> Co-authored-by: andrew-harness <75149647+andrew-harness@users.noreply.github.com>
contains only async/await edits, no functional changes otherwise. This combined with #2144 allows to utilize async datastore calls in modbus server
Split from #2127 and depends on #2139