CORD-762 add simple retry mechanism, support for invoke
Change-Id: Ied583aaa9261adec353f061b9d29211d12dc95c7
diff --git a/xos/xos_client/xosapi/orm.py b/xos/xos_client/xosapi/orm.py
index 96de59d..d23c1b1 100644
--- a/xos/xos_client/xosapi/orm.py
+++ b/xos/xos_client/xosapi/orm.py
@@ -20,7 +20,9 @@
"""
import functools
+import grpc
from google.protobuf.empty_pb2 import Empty
+import time
from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default()
@@ -246,9 +248,10 @@
self.objects = ORMObjectManager(stub, model_name, package_name)
class ORMStub(object):
- def __init__(self, stub, package_name):
+ def __init__(self, stub, package_name, invoker=None):
self.grpc_stub = stub
self.all_model_names = []
+ self.invoker = invoker
for name in dir(stub):
if name.startswith("Get"):
@@ -261,8 +264,28 @@
return self.all_model_names
def invoke(self, name, request):
- method = getattr(self.grpc_stub, name)
- return method(request)
+ if self.invoker:
+ # Hook in place to call Chameleon's invoke method, as soon as we
+ # have rewritten the synchronizer to use reactor.
+ return self.invoker.invoke(self.grpc_stub.__class__, name, request, metadata={}).result[0]
+ else:
+ # Our own retry mechanism. This works fine if there is a temporary
+ # failure in connectivity, but does not re-download gRPC schema.
+ while True:
+ backoff = [0.5, 1, 2, 4, 8]
+ try:
+ method = getattr(self.grpc_stub, name)
+ return method(request)
+ except grpc._channel._Rendezvous, e:
+ code = e.code()
+ if code == grpc.StatusCode.UNAVAILABLE:
+ if not backoff:
+ raise Exception("No more retries on %s" % name)
+ time.sleep(backoff.pop(0))
+ else:
+ raise
+ except:
+ raise
def make_ID(self, id):
return _sym_db._classes["xos.ID"](id=id)