Skip to content

Commit

Permalink
Add support for replication and cluster API
Browse files Browse the repository at this point in the history
  • Loading branch information
joowani committed Sep 22, 2019
1 parent 412d584 commit a9a465a
Show file tree
Hide file tree
Showing 33 changed files with 3,255 additions and 1,144 deletions.
2 changes: 1 addition & 1 deletion arango/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from arango.client import ArangoClient # noqa: F401
from arango.exceptions import * # noqa: F401 F403
from arango.http import * # noqa: F401 F403
from . import errno # noqa: F401
import arango.errno as errno # noqa: F401
9 changes: 9 additions & 0 deletions arango/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ def __init__(self, connection, executor):
self._conn = connection
self._executor = executor

@property
def conn(self):
"""Return HTTP connection object.
:return: HTTP connection.
:rtype: arango.connection.Connection
"""
return self._conn

@property
def db_name(self):
"""Return the name of the current database.
Expand Down
78 changes: 11 additions & 67 deletions arango/aql.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
AQLCacheConfigureError,
AQLCachePropertiesError
)
from arango.formatter import (
format_aql_cache,
format_aql_query,
format_aql_tracking
)
from arango.request import Request


Expand All @@ -39,45 +44,6 @@ def __init__(self, connection, executor):
def __repr__(self):
return '<AQL in {}>'.format(self._conn.db_name)

# noinspection PyMethodMayBeStatic
def _format_tracking_properties(self, body):
"""Format the tracking properties.
:param body: Response body.
:type body: dict
:return: Formatted body.
:rtype: dict
"""
body.pop('code', None)
body.pop('error', None)
if 'maxQueryStringLength' in body:
body['max_query_string_length'] = body.pop('maxQueryStringLength')
if 'maxSlowQueries' in body:
body['max_slow_queries'] = body.pop('maxSlowQueries')
if 'slowQueryThreshold' in body:
body['slow_query_threshold'] = body.pop('slowQueryThreshold')
if 'trackBindVars' in body:
body['track_bind_vars'] = body.pop('trackBindVars')
if 'trackSlowQueries' in body:
body['track_slow_queries'] = body.pop('trackSlowQueries')
return body

# noinspection PyMethodMayBeStatic
def _format_queries(self, body):
"""Format the list of queries.
:param body: Response body.
:type body: dict
:return: Formatted body.
:rtype: dict
"""
for query in body:
if 'bindVars' in query:
query['bind_vars'] = query.pop('bindVars')
if 'runTime' in query:
query['runtime'] = query.pop('runTime')
return body

@property
def cache(self):
"""Return the query cache API wrapper.
Expand Down Expand Up @@ -359,7 +325,7 @@ def queries(self):
def response_handler(resp):
if not resp.is_success:
raise AQLQueryListError(resp, request)
return self._format_queries(resp.body)
return [format_aql_query(q) for q in resp.body]

return self._execute(request, response_handler)

Expand All @@ -378,7 +344,7 @@ def slow_queries(self):
def response_handler(resp):
if not resp.is_success:
raise AQLQueryListError(resp, request)
return self._format_queries(resp.body)
return [format_aql_query(q) for q in resp.body]

return self._execute(request, response_handler)

Expand Down Expand Up @@ -416,7 +382,7 @@ def tracking(self):
def response_handler(resp):
if not resp.is_success:
raise AQLQueryTrackingGetError(resp, request)
return self._format_tracking_properties(resp.body)
return format_aql_tracking(resp.body)

return self._execute(request, response_handler)

Expand Down Expand Up @@ -456,7 +422,7 @@ def set_tracking(self,
def response_handler(resp):
if not resp.is_success:
raise AQLQueryTrackingSetError(resp, request)
return self._format_tracking_properties(resp.body)
return format_aql_tracking(resp.body)

return self._execute(request, response_handler)

Expand Down Expand Up @@ -554,28 +520,6 @@ class AQLQueryCache(APIWrapper):
def __repr__(self):
return '<AQLQueryCache in {}>'.format(self._conn.db_name)

# noinspection PyMethodMayBeStatic
def _format_cache_properties(self, body):
"""Format the query cache properties.
:param body: Response body.
:type body: dict
:return: Formatted body.
:rtype: dict
"""
body.pop('code', None)
body.pop('error', None)

if 'maxResults' in body:
body['max_results'] = body.pop('maxResults')
if 'maxResultsSize' in body:
body['max_results_size'] = body.pop('maxResultsSize')
if 'maxEntrySize' in body:
body['max_entry_size'] = body.pop('maxEntrySize')
if 'includeSystem' in body:
body['include_system'] = body.pop('includeSystem')
return body

def properties(self):
"""Return the query cache properties.
Expand All @@ -591,7 +535,7 @@ def properties(self):
def response_handler(resp):
if not resp.is_success:
raise AQLCachePropertiesError(resp, request)
return self._format_cache_properties(resp.body)
return format_aql_cache(resp.body)

return self._execute(request, response_handler)

Expand Down Expand Up @@ -642,7 +586,7 @@ def configure(self,
def response_handler(resp):
if not resp.is_success:
raise AQLCacheConfigureError(resp, request)
return self._format_cache_properties(resp.body)
return format_aql_cache(resp.body)

return self._execute(request, response_handler)

Expand Down
124 changes: 124 additions & 0 deletions arango/cluster.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
from __future__ import absolute_import, unicode_literals

__all__ = ['Cluster']

from arango.api import APIWrapper
from arango.exceptions import (
ClusterHealthError,
ClusterMaintenanceModeError,
ClusterServerIDError,
ClusterServerRoleError,
ClusterStatisticsError,
)
from arango.request import Request


class Cluster(APIWrapper): # pragma: no cover

def __init__(self, connection, executor):
super(Cluster, self).__init__(connection, executor)

def server_id(self):
"""Return the server ID.
:return: Server ID.
:rtype: str | unicode
:raise arango.exceptions.ClusterServerIDError: If retrieval fails.
"""
request = Request(
method='get',
endpoint='/_admin/server/id'
)

def response_handler(resp):
if resp.is_success:
return resp.body['id']
raise ClusterServerIDError(resp, request)

return self._execute(request, response_handler)

def server_role(self):
"""Return the server role.
:return: Server role. Possible values are "SINGLE" (server which is
not in a cluster), "COORDINATOR" (cluster coordinator), "PRIMARY",
"SECONDARY", "AGENT" (Agency node in a cluster) or "UNDEFINED".
:rtype: str | unicode
:raise arango.exceptions.ClusterServerRoleError: If retrieval fails.
"""
request = Request(
method='get',
endpoint='/_admin/server/role'
)

def response_handler(resp):
if resp.is_success:
return resp.body['role']
raise ClusterServerRoleError(resp, request)

return self._execute(request, response_handler)

def statistics(self, server_id):
"""Return the cluster statistics for the given server.
:param server_id: Server ID.
:type server_id: str | unicode
:return: Cluster statistics for the given server.
:rtype: dict
:raise arango.exceptions.ClusterStatisticsError: If retrieval fails.
"""
request = Request(
method='get',
endpoint='/_admin/clusterStatistics',
params={'DBserver': server_id}
)

def response_handler(resp):
if resp.is_success:
return resp.body
raise ClusterStatisticsError(resp, request)

return self._execute(request, response_handler)

def health(self):
"""Return the cluster health.
:return: Cluster health.
:rtype: dict
:raise arango.exceptions.ClusterHealthError: If retrieval fails.
"""
request = Request(
method='get',
endpoint='/_admin/cluster/health',
)

def response_handler(resp):
if resp.is_success:
resp.body.pop('error')
resp.body.pop('code')
return resp.body
raise ClusterHealthError(resp, request)

return self._execute(request, response_handler)

def toggle_maintenance_mode(self, mode):
"""Enable or disable the cluster supervision (agency) maintenance mode.
:param mode: Maintenance mode. Allowed values are "on" and "off".
:type mode: str | unicode
:return: Result of the operation.
:rtype: dict
:raise arango.exceptions.ClusterMaintenanceModeError: If toggle fails.
"""
request = Request(
method='put',
endpoint='/_admin/cluster/maintenance',
data='"{}"'.format(mode)
)

def response_handler(resp):
if resp.is_success:
return resp.body
raise ClusterMaintenanceModeError(resp, request)

return self._execute(request, response_handler)
Loading

0 comments on commit a9a465a

Please sign in to comment.