Skip to content

Commit 10c69cb

Browse files
committed
maintain graph version
1 parent aa9c89d commit 10c69cb

File tree

3 files changed

+46
-21
lines changed

3 files changed

+46
-21
lines changed

redisgraph/exceptions.py

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class VersionMismatchException(Exception):
2+
def __init__(self, version):
3+
self.version = version
4+

redisgraph/graph.py

+26-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from .util import *
22
from .query_result import QueryResult
3+
from .exceptions import VersionMismatchException
34

45
class Graph(object):
56
"""
@@ -11,7 +12,7 @@ def __init__(self, name, redis_con):
1112
Create a new graph.
1213
"""
1314
self.name = name # Graph key
14-
self.version = None # Graph version
15+
self.version = 0 # Graph version
1516
self.redis_con = redis_con
1617
self.nodes = {}
1718
self.edges = []
@@ -143,16 +144,37 @@ def query(self, q, params=None, timeout=None):
143144
"""
144145
Executes a query against the graph.
145146
"""
147+
148+
# maintain original 'q'
149+
query = q
150+
151+
# handle query parameters
146152
if params is not None:
147-
q = self.build_params_header(params) + q
153+
query = self.build_params_header(params) + query
154+
155+
# construct query command
156+
# ask for compact result-set format
157+
# specify known version
158+
command = ["GRAPH.QUERY", self.name, query, "--compact", "version", self.version]
148159

149-
command = ["GRAPH.QUERY", self.name, q, "--compact"]
160+
# include timeout is specified
150161
if timeout:
151162
if not isinstance(timeout, int):
152163
raise Exception("Timeout argument must be a positive integer")
153164
command += ["timeout", timeout]
165+
166+
# issue query
154167
response = self.redis_con.execute_command(*command)
155-
return QueryResult(self, response)
168+
169+
try:
170+
return QueryResult(self, response)
171+
except VersionMismatchException as e:
172+
# client view over the graph schema is out of sync
173+
# set client version and refresh local schema
174+
self.version = e.version
175+
self._refresh_schema()
176+
# re-issue query
177+
return self.query(q, params, timeout)
156178

157179
def _execution_plan_to_string(self, plan):
158180
return "\n".join(plan)

redisgraph/query_result.py

+16-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from .node import Node
22
from .edge import Edge
33
from .path import Path
4+
from .exceptions import VersionMismatchException
45
from prettytable import PrettyTable
56
from redis import ResponseError
67

@@ -14,11 +15,10 @@
1415
INDICES_DELETED = "Indices deleted"
1516
CACHED_EXECUTION = "Cached execution"
1617
INTERNAL_EXECUTION_TIME = 'internal execution time'
17-
GRAPH_VERSION = 'Graph version'
1818

1919
STATS = [LABELS_ADDED, NODES_CREATED, PROPERTIES_SET, RELATIONSHIPS_CREATED,
2020
NODES_DELETED, RELATIONSHIPS_DELETED, INDICES_CREATED, INDICES_DELETED,
21-
CACHED_EXECUTION, INTERNAL_EXECUTION_TIME, GRAPH_VERSION]
21+
CACHED_EXECUTION, INTERNAL_EXECUTION_TIME]
2222

2323
class ResultSetColumnTypes(object):
2424
COLUMN_UNKNOWN = 0
@@ -45,24 +45,27 @@ def __init__(self, graph, response):
4545
self.header = []
4646
self.result_set = []
4747

48-
# If we encountered a run-time error, the last response element will be an exception.
49-
if isinstance(response[-1], ResponseError):
50-
raise response[-1]
48+
# incase of an error an exception will be raised
49+
self._check_for_errors(response)
5150

5251
if len(response) == 1:
5352
self.parse_statistics(response[0])
5453
else:
55-
# start by parsing statistics, see if the reported graph version
56-
# matches the one we have
54+
# start by parsing statistics, matches the one we have
5755
self.parse_statistics(response[-1]) # Last element.
56+
self.parse_results(response)
5857

59-
if(graph.version != self.graph_version):
60-
# graph version miss-match, this is an indication that
61-
# the graph schema was modified, sync it.
62-
graph.version = self.graph_version
63-
graph._refresh_schema()
58+
def _check_for_errors(self, response):
59+
if isinstance(response[0], ResponseError):
60+
error = response[0]
61+
if str(error) == "version mismatch":
62+
version = response[1]
63+
error = VersionMismatchException(version)
64+
raise error
6465

65-
self.parse_results(response)
66+
# If we encountered a run-time error, the last response element will be an exception.
67+
if isinstance(response[-1], ResponseError):
68+
raise response[-1]
6669

6770
def parse_results(self, raw_result_set):
6871
self.header = self.parse_header(raw_result_set)
@@ -286,7 +289,3 @@ def cached_execution(self):
286289
def run_time_ms(self):
287290
return self._get_stat(INTERNAL_EXECUTION_TIME)
288291

289-
@property
290-
def graph_version(self):
291-
return self._get_stat(GRAPH_VERSION)
292-

0 commit comments

Comments
 (0)