Commit a7b92662 authored by davebshow's avatar davebshow
Browse files

preparing for more refactoring, clean ups, error handling etc

parent 90db2ba2
......@@ -17,11 +17,11 @@ Fire up the Gremlin Server:
$ ./bin/gremlin-server.sh
```
The `AsyncGremlinClient` communicates asynchronously with the Gremlin Server using websockets. The client uses a combination of [asyncio.coroutine](https://docs.python.org/3/library/asyncio-task.html#coroutines) and [asyncio.Task](https://docs.python.org/3/library/asyncio-task.html#task) run on Asyncio's pluggable event loop to achieve this communication.
The `GremlinClient` communicates asynchronously with the Gremlin Server using websockets. The client uses a combination of [asyncio.coroutine](https://docs.python.org/3/library/asyncio-task.html#coroutines) and [asyncio.Task](https://docs.python.org/3/library/asyncio-task.html#task) run on Asyncio's pluggable event loop to achieve this communication.
The majority of ``AsyncGremlinClient`` methods are an `asyncio.coroutine`, so you will also need to use either `asyncio` or the `aiogremlin` [Task API](#task-api). The following examples use `asyncio` to demonstrate the use of the AsyncioGremlineClient.
The majority of `GremlinClient` methods are an `asyncio.coroutine`, so you will also need to use either `asyncio` or the `aiogremlin` [Task API](#task-api). The following examples use `asyncio` to demonstrate the use of the AsyncioGremlineClient.
The Gremlin Server sends responses in chunks, so `AsyncGremlinClient.submit` returns a list of gremlin response objects:
The Gremlin Server sends responses in chunks, so `GremlinClient.submit` returns a list of gremlin response objects:
```python
>>> import asyncio
......
from .abc import AbstractBaseFactory, AbstractBaseConnection
from .abc import AbstractFactory, AbstractConnection
from .connection import WebsocketPool, AiohttpFactory
from .client import GremlinClient
from .contextmanager import GremlinContext
......
import asyncio
from abc import ABCMeta, abstractmethod
class AbstractBaseFactory(metaclass=ABCMeta):
class AbstractFactory(metaclass=ABCMeta):
@classmethod
@abstractmethod
......@@ -10,30 +9,25 @@ class AbstractBaseFactory(metaclass=ABCMeta):
pass
@property
@abstractmethod
def factory(self):
return self
pass
class AbstractBaseConnection(metaclass=ABCMeta):
def __init__(self, socket, pool=None):
self.socket = socket
self._pool = pool
class AbstractConnection(metaclass=ABCMeta):
@abstractmethod
def feed_pool(self):
if self.pool:
if self in self.pool.active_conns:
self.pool.feed_pool(self)
pass
@asyncio.coroutine
@abstractmethod
def release(self):
yield from self.close()
if self in self.pool.active_conns:
self.pool.active_conns.discard(self)
pass
@property
@abstractmethod
def pool(self):
return self._pool
pass
@property
@abstractmethod
......
......@@ -4,7 +4,7 @@ import asyncio
import aiohttp
from .abc import AbstractBaseFactory, AbstractBaseConnection
from .abc import AbstractFactory, AbstractConnection
from .exceptions import SocketClientError
from .log import INFO, conn_logger
......@@ -41,6 +41,8 @@ class WebsocketPool:
return len(self.active_conns)
def feed_pool(self, conn):
if self._closed:
raise RuntimeError("WebsocketPool is closed.")
self.active_conns.discard(conn)
self._put(conn)
......@@ -70,6 +72,8 @@ class WebsocketPool:
@asyncio.coroutine
def connect(self, uri=None, loop=None, num_retries=None):
if self._closed:
raise RuntimeError("WebsocketPool is closed.")
if num_retries is None:
num_retries = self.max_retries
uri = uri or self.uri
......@@ -111,7 +115,14 @@ class WebsocketPool:
pass
class AiohttpFactory(AbstractBaseFactory):
class BaseFactory(AbstractFactory):
@property
def factory(self):
return self
class AiohttpFactory(BaseFactory):
@classmethod
@asyncio.coroutine
......@@ -128,13 +139,34 @@ class AiohttpFactory(AbstractBaseFactory):
return AiohttpConnection(socket, pool)
class AiohttpConnection(AbstractBaseConnection):
class BaseConnection(AbstractConnection):
def __init__(self, socket, pool=None):
super().__init__(socket, pool=pool)
self.socket = socket
self._pool = pool
def feed_pool(self):
if self.pool:
if self in self.pool.active_conns:
self.pool.feed_pool(self)
@asyncio.coroutine
def release(self):
try:
yield from self.close()
finally:
if self in self.pool.active_conns:
self.pool.active_conns.discard(self)
@property
def pool(self):
return self._pool
def __str__(self):
return "{} wrapping {}".format(repr(self), repr(self.socket))
class AiohttpConnection(BaseConnection):
def __init__(self, socket, pool=None):
super().__init__(socket, pool=pool)
@property
def closed(self):
......@@ -142,7 +174,11 @@ class AiohttpConnection(AbstractBaseConnection):
@asyncio.coroutine
def close(self):
yield from self.socket.close()
if not self.socket._closed:
try:
yield from self.socket.close()
finally:
self._closed = True
@asyncio.coroutine
def send(self, message, binary=True):
......@@ -189,7 +225,7 @@ class AiohttpConnection(AbstractBaseConnection):
elif message.tp == aiohttp.MsgType.error:
raise SocketClientError(self.socket.exception())
elif message.tp == aiohttp.MsgType.closed:
raise SocketClientError("Socket closed.")
raise RuntimeError("Socket closed.")
break
finally:
yield from self.release()
......@@ -27,6 +27,7 @@ def gremlin_response_parser(connection):
finally:
yield from connection.release()
class GremlinWriter:
def __init__(self, connection):
......
"""
gizmo.response
This module defines parsers for the Gremlin Server response.
THIS MODULE WILL BE REMOVED
"""
class GremlinResponse(list):
def __init__(self, message):
"""
A subclass of list that parses and flattens the Gremlin Server's
......
"""
THIS MODULE WILL BE COMPLETELY REFACTORED
"""
import asyncio
import itertools
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment