mirror of
https://github.com/vincentbernat/i3wm-configuration.git
synced 2025-06-24 10:48:35 +02:00
i3-companion: rework dampener to be easier to understand
We have a worker running as long as there is work. The optional sleep is not implemented. There is a slight semantic difference: the work is not postponed indefinitely.
This commit is contained in:
parent
9b0bb1ce76
commit
f56b995d5a
1 changed files with 26 additions and 28 deletions
|
@ -105,16 +105,17 @@ def dampen(sleep, *, unless=None, retry=0):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(fn):
|
def decorator(fn):
|
||||||
async def fn_now(me, retry, *args, **kwargs):
|
async def worker():
|
||||||
if unless is None or not unless(*args, **kwargs):
|
while True:
|
||||||
await asyncio.sleep(sleep)
|
await asyncio.sleep(sleep)
|
||||||
me["sleeping"] = False
|
|
||||||
|
|
||||||
# From here, we do not expect to be cancelled. Ensure only
|
retry, args, kwargs = fn.queue
|
||||||
# one of us is running.
|
fn.queue = None
|
||||||
async with fn.lock:
|
|
||||||
|
# Execute the work
|
||||||
|
logger.debug(f"execute work for {fn}")
|
||||||
try:
|
try:
|
||||||
return await fn(*args, **kwargs)
|
await fn(*args, **kwargs)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if not retry:
|
if not retry:
|
||||||
logger.exception(f"while executing {fn}: %s", e)
|
logger.exception(f"while executing {fn}: %s", e)
|
||||||
|
@ -125,32 +126,29 @@ def dampen(sleep, *, unless=None, retry=0):
|
||||||
retry,
|
retry,
|
||||||
str(e),
|
str(e),
|
||||||
)
|
)
|
||||||
# Run again, unless we have something already scheduled
|
|
||||||
if fn.last_task["sleeping"]:
|
# Retry, unless we have something already scheduled
|
||||||
|
if fn.queue is not None:
|
||||||
return
|
return
|
||||||
fn.last_task = dict(sleeping=True)
|
fn.queue = (retry, args, kwargs)
|
||||||
fn.last_task["task"] = asyncio.create_task(
|
# Do we still have something to do?
|
||||||
fn_now(fn.last_task, retry, *args, **kwargs)
|
if fn.queue is None:
|
||||||
)
|
break
|
||||||
|
|
||||||
|
# No more work
|
||||||
|
logger.debug(f"no more work for {fn}")
|
||||||
|
fn.worker = None
|
||||||
|
|
||||||
@functools.wraps(fn)
|
@functools.wraps(fn)
|
||||||
async def wrapper(*args, **kwargs):
|
async def wrapper(*args, **kwargs):
|
||||||
# Initialize a lock (we need an active loop for that)
|
fn.queue = (retry, args, kwargs)
|
||||||
if fn.lock is None:
|
if fn.worker is None:
|
||||||
fn.lock = asyncio.Lock()
|
logger.debug(f"create new worker for {fn}")
|
||||||
|
fn.worker = asyncio.create_task(worker())
|
||||||
|
else:
|
||||||
|
logger.debug(f"enqueue new work for {fn}")
|
||||||
|
|
||||||
# If possible, cancel last task if it's sleeping
|
fn.worker = None
|
||||||
if fn.last_task is not None and fn.last_task["sleeping"]:
|
|
||||||
logger.debug(f"cancel call to {fn}")
|
|
||||||
fn.last_task["task"].cancel()
|
|
||||||
logger.debug(f"dampening call to {fn}")
|
|
||||||
fn.last_task = dict(sleeping=True)
|
|
||||||
fn.last_task["task"] = asyncio.create_task(
|
|
||||||
fn_now(fn.last_task, retry, *args, **kwargs)
|
|
||||||
)
|
|
||||||
|
|
||||||
fn.last_task = None
|
|
||||||
fn.lock = None
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue