Skip to content

Commit

Permalink
Merge branch 'rhkleijn-robust-task-retry'
Browse files Browse the repository at this point in the history
  • Loading branch information
fzumstein committed Oct 21, 2018
2 parents 26c2e43 + 76c12b0 commit 7524113
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 18 deletions.
36 changes: 20 additions & 16 deletions xlwings/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import logging
import sys
import os
import collections
# Hack to find pythoncom.dll - needed for some distribution/setups
# E.g. if python is started with the full path outside of the python path, then it almost certainly fails
cwd = os.getcwd()
Expand Down Expand Up @@ -286,7 +287,7 @@ def Exec(self, stmt, *args):
exec(stmt, globals, locals)


idle_queue = []
idle_queue = collections.deque()
idle_queue_event = win32event.CreateEvent(None, 0, 0, None)


Expand Down Expand Up @@ -324,45 +325,48 @@ def _CreateInstance_(self, reqClsid, reqIID):
msg = 'xlwings server running, clsid=%s'
logger.info(msg, clsid) if logger.hasHandlers() else print(msg % clsid)

waitables = [idle_queue_event]
while True:
timeout = TIMEOUT if idle_queue else win32event.INFINITE
rc = win32event.MsgWaitForMultipleObjects(
[idle_queue_event],
waitables,
0,
win32event.INFINITE,
timeout,
win32event.QS_ALLEVENTS
)
if rc == win32event.WAIT_OBJECT_0 or rc == win32event.WAIT_TIMEOUT:
while idle_queue:
task = idle_queue.popleft()
if not _execute_task(task):
break

while True:
pythoncom.PumpWaitingMessages()

if not idle_queue:
break

task = idle_queue.pop(0)
_execute_task(task)
elif rc == win32event.WAIT_OBJECT_0 + len(waitables):
if pythoncom.PumpWaitingMessages():
break # wm_quit

pythoncom.CoRevokeClassObject(revokeId)
pythoncom.CoUninitialize()


def _execute_task(task):
""" Execute task. Returns False if task must be retried later. """
try:
task()
except Exception as e:
if _ask_for_retry(e) and _can_retry(task):
if _ask_for_retry(e):
msg = "Retrying TaskQueue '%s'."
logger.info(msg, task) if logger.hasHandlers() else print(msg % task)
_execute_task(task)
idle_queue.appendleft(task)
return False
else:
import traceback
msg = "TaskQueue '%s' threw an exception: %s"
logger.error(msg, task, traceback.format_exc()) if logger.hasHandlers() else print(msg % (task, traceback.format_exc()))
return True


def _can_retry(task):
return hasattr(task, 'nb_remaining_call') and task.nb_remaining_call > 0

RPC_E_SERVERCALL_RETRYLATER = -2147418111
TIMEOUT = 100 # ms


def _ask_for_retry(exception):
Expand Down
2 changes: 0 additions & 2 deletions xlwings/udfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,8 @@ def __init__(self, rng, options, value, caller):
self.options = options
self.value = value
self.skip = (caller.Rows.Count, caller.Columns.Count)
self.nb_remaining_call = 10

def __call__(self, *args, **kwargs):
self.nb_remaining_call -= 1
conversion.write(
self.value,
self.range,
Expand Down

0 comments on commit 7524113

Please sign in to comment.