Skip to content

Commit

Permalink
Do not call the async wrapper calls with the separate thread
Browse files Browse the repository at this point in the history
* Do not run method with the distinct thread

* Move test_asynchronous.py to pytests
  • Loading branch information
vzhestkov authored May 15, 2024
1 parent d57472b commit 4021f93
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 104 deletions.
25 changes: 2 additions & 23 deletions salt/utils/asynchronous.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@
Helpers/utils for working with tornado asynchronous stuff
"""


import contextlib
import logging
import sys
import threading

import salt.ext.tornado.concurrent
import salt.ext.tornado.ioloop
Expand Down Expand Up @@ -111,30 +108,12 @@ def __getattr__(self, key):

def _wrap(self, key):
def wrap(*args, **kwargs):
results = []
thread = threading.Thread(
target=self._target,
args=(key, args, kwargs, results, self.io_loop),
return self.io_loop.run_sync(
lambda: getattr(self.obj, key)(*args, **kwargs)
)
thread.start()
thread.join()
if results[0]:
return results[1]
else:
exc_info = results[1]
raise exc_info[1].with_traceback(exc_info[2])

return wrap

def _target(self, key, args, kwargs, results, io_loop):
try:
result = io_loop.run_sync(lambda: getattr(self.obj, key)(*args, **kwargs))
results.append(True)
results.append(result)
except Exception: # pylint: disable=broad-except
results.append(False)
results.append(sys.exc_info())

def __enter__(self):
return self

Expand Down
92 changes: 92 additions & 0 deletions tests/pytests/unit/utils/test_asynchronous.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import tornado.gen
import tornado.ioloop

import salt.utils.asynchronous as asynchronous


class HelperA:

async_methods = [
"sleep",
]

def __init__(self, io_loop=None):
pass

@tornado.gen.coroutine
def sleep(self):
yield tornado.gen.sleep(0.1)
raise tornado.gen.Return(True)


class HelperB:

async_methods = [
"sleep",
]

def __init__(self, a=None, io_loop=None):
if a is None:
a = asynchronous.SyncWrapper(HelperA)
self.a = a

@tornado.gen.coroutine
def sleep(self):
yield tornado.gen.sleep(0.1)
self.a.sleep()
raise tornado.gen.Return(False)


def test_helpers():
"""
Test that the helper classes do what we expect within a regular asynchronous env
"""
io_loop = tornado.ioloop.IOLoop(make_current=False)
ret = io_loop.run_sync(lambda: HelperA().sleep())
assert ret is True

ret = io_loop.run_sync(lambda: HelperB().sleep())
assert ret is False


def test_basic_wrap():
"""
Test that we can wrap an asynchronous caller.
"""
sync = asynchronous.SyncWrapper(HelperA)
ret = sync.sleep()
assert ret is True


def test_basic_wrap_series():
"""
Test that we can wrap an asynchronous caller and call the method in series.
"""
sync = asynchronous.SyncWrapper(HelperA)
ret = sync.sleep()
assert ret is True
ret = sync.sleep()
assert ret is True


def test_double():
"""
Test when the asynchronous wrapper object itself creates a wrap of another thing
This works fine since the second wrap is based on the first's IOLoop so we
don't have to worry about complex start/stop mechanics
"""
sync = asynchronous.SyncWrapper(HelperB)
ret = sync.sleep()
assert ret is False


def test_double_sameloop():
"""
Test asynchronous wrappers initiated from the same IOLoop, to ensure that
we don't wire up both to the same IOLoop (since it causes MANY problems).
"""
a = asynchronous.SyncWrapper(HelperA)
sync = asynchronous.SyncWrapper(HelperB, (a,))
ret = sync.sleep()
assert ret is False
81 changes: 0 additions & 81 deletions tests/unit/utils/test_asynchronous.py

This file was deleted.

0 comments on commit 4021f93

Please sign in to comment.