Synchronous call initiated through a response of an async call drops the results of the sync call.
Badhi opened this issue · 4 comments
I have created a sample plugin that recreates my issue below.
- lua in
test_plugin/lua/test_plugin/init.lua
M = {}
function M.run()
vim.fn.Start(1)
vim.fn.Start(2)
end
function M.update(data)
print(vim.fn.GetData(data))
end
return M
- python in
test_plugin/rplugin/python3/test_plugin.py
import pynvim
import logging
@pynvim.plugin
class TestPlugin(object):
def __init__(self, nvim : pynvim.Nvim):
logging.basicConfig(filename = 'test.log', level='DEBUG')
self.nvim = nvim
@pynvim.function('Start', sync=False)
def start(self, args):
logging.debug('start called')
d = args[0]
self.nvim.exec_lua("require'test_plugin'.update(...)", d, async_ = True)
@pynvim.function('GetData', sync = True)
def getData(self, args):
logging.debug('getdata called')
d = args[0]
return d
Here, when i call lua require'test_plugin'.run()
I could see both start
and getData
functions in python getting called twice but the return values of the getData
function is never captured by the neovim
Also, if I remove one of the vim.fn.Start
calls in run()
function, everything works fine.
Appreciate if someone can help me with this and check if I'm not using the pynvim
apis incorrectly
but the return values of the
getData
function is never captured by the neovim
The code is only calling print() on the values. Maybe the printed message is not shown because of redraw? Try appending the GetData() results to a list, then check the contents of that list.
Hi @justinmk,
Thanks for the suggestion. I tried to add the results to the list and check the results with a new call and I could see the list is still empty.
But I was able to fix the issue in a different way, but not sure if it just hides the real issue or if that is the real "usage" of the API
The fix was to schedule all the work that is done in the update
function to the next in the event loop by using vim.schedule
like below
function M.update(data)
vim.schedule(function()
print(vim.fn.GetData(data))
end)
end
I think it makes sense since we first have to give up the current call state that was initiated by rpc call to process other rpc calls?
I could see the list is still empty.
Are you certain that start()
is called in your example (debug('start called')
is written to the logs)?
I think it makes sense since we first have to give up the current call state that was initiated by rpc call to process other rpc calls?
It's certainly tricky when the "call stack" is multiply-bidirectional.
Thanks for providing this test case and info. This is something we should either document, detect, or actually support.
Are you certain that start() is called in your example (debug('start called') is written to the logs)?
Yes, following is the log output for the failing scenario (I have enabled some debug logs in pynvim as well)
DEBUG:root:start called
DEBUG:root:start called
DEBUG:pynvim.plugin.host:calling request handler for "test_plugin/rplugin/python3/test_plugin.py:function:GetData", args: "[[1]]"
DEBUG:root:getdata called
DEBUG:pynvim.plugin.host:request handler for 'test_plugin/rplugin/python3/test_plugin.py:function:GetData [[1]]' returns: 1
DEBUG:pynvim.plugin.host:calling request handler for "test_plugin/rplugin/python3/test_plugin.py:function:GetData", args: "[[2]]"
DEBUG:root:getdata called
DEBUG:pynvim.plugin.host:request handler for 'test_plugin/rplugin/python3/test_plugin.py:function:GetData [[2]]' returns: 2