Skip to content

Commit f61ed20

Browse files
authored
PYTHON-1204: Make graph metadata handling more robust (scylladb#47)
* Make graph metadata handling more robust
1 parent d338e66 commit f61ed20

File tree

2 files changed

+71
-25
lines changed

2 files changed

+71
-25
lines changed

cassandra/metadata.py

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2843,26 +2843,7 @@ def __init__(self, connection, timeout):
28432843

28442844
def get_all_keyspaces(self):
28452845
for keyspace_meta in super(SchemaParserDSE68, self).get_all_keyspaces():
2846-
2847-
def _build_table_graph_metadata(table_meta):
2848-
for row in self.keyspace_table_vertex_rows[keyspace_meta.name][table_meta.name]:
2849-
vertex_meta = self._build_table_vertex_metadata(row)
2850-
table_meta.vertex = vertex_meta
2851-
2852-
for row in self.keyspace_table_edge_rows[keyspace_meta.name][table_meta.name]:
2853-
edge_meta = self._build_table_edge_metadata(keyspace_meta, row)
2854-
table_meta.edge = edge_meta
2855-
2856-
# Make sure we process vertices before edges
2857-
for t in [t for t in six.itervalues(keyspace_meta.tables)
2858-
if t.name in self.keyspace_table_vertex_rows[keyspace_meta.name]]:
2859-
_build_table_graph_metadata(t)
2860-
2861-
# all other tables...
2862-
for t in [t for t in six.itervalues(keyspace_meta.tables)
2863-
if t.name not in self.keyspace_table_vertex_rows[keyspace_meta.name]]:
2864-
_build_table_graph_metadata(t)
2865-
2846+
self._build_graph_metadata(keyspace_meta)
28662847
yield keyspace_meta
28672848

28682849
def get_table(self, keyspaces, keyspace, table):
@@ -2877,10 +2858,16 @@ def get_table(self, keyspaces, keyspace, table):
28772858
vertices_result = self._handle_results(vertices_success, vertices_result)
28782859
edges_result = self._handle_results(edges_success, edges_result)
28792860

2880-
if vertices_result:
2881-
table_meta.vertex = self._build_table_vertex_metadata(vertices_result[0])
2882-
elif edges_result:
2883-
table_meta.edge = self._build_table_edge_metadata(keyspaces[keyspace], edges_result[0])
2861+
try:
2862+
if vertices_result:
2863+
table_meta.vertex = self._build_table_vertex_metadata(vertices_result[0])
2864+
elif edges_result:
2865+
table_meta.edge = self._build_table_edge_metadata(keyspaces[keyspace], edges_result[0])
2866+
except Exception:
2867+
table_meta.vertex = None
2868+
table_meta.edge = None
2869+
table_meta._exc_info = sys.exc_info()
2870+
log.exception("Error while parsing graph metadata for table %s.%s.", keyspace, table)
28842871

28852872
return table_meta
28862873

@@ -2893,6 +2880,32 @@ def _build_keyspace_metadata_internal(row):
28932880
graph_engine = row.get("graph_engine", None)
28942881
return KeyspaceMetadata(name, durable_writes, replication_class, replication, graph_engine)
28952882

2883+
def _build_graph_metadata(self, keyspace_meta):
2884+
2885+
def _build_table_graph_metadata(table_meta):
2886+
for row in self.keyspace_table_vertex_rows[keyspace_meta.name][table_meta.name]:
2887+
table_meta.vertex = self._build_table_vertex_metadata(row)
2888+
2889+
for row in self.keyspace_table_edge_rows[keyspace_meta.name][table_meta.name]:
2890+
table_meta.egde = self._build_table_edge_metadata(keyspace_meta, row)
2891+
2892+
try:
2893+
# Make sure we process vertices before edges
2894+
for table_meta in [t for t in six.itervalues(keyspace_meta.tables)
2895+
if t.name in self.keyspace_table_vertex_rows[keyspace_meta.name]]:
2896+
_build_table_graph_metadata(table_meta)
2897+
2898+
# all other tables...
2899+
for table_meta in [t for t in six.itervalues(keyspace_meta.tables)
2900+
if t.name not in self.keyspace_table_vertex_rows[keyspace_meta.name]]:
2901+
_build_table_graph_metadata(table_meta)
2902+
except Exception:
2903+
# schema error, remove all graph metadata for this keyspace
2904+
for t in six.itervalues(keyspace_meta.tables):
2905+
t.edge = t.vertex = None
2906+
keyspace_meta._exc_info = sys.exc_info()
2907+
log.exception("Error while parsing graph metadata for keyspace %s", keyspace_meta.name)
2908+
28962909
@staticmethod
28972910
def _build_table_vertex_metadata(row):
28982911
return VertexMetadata(row.get("keyspace_name"), row.get("table_name"),

tests/integration/advanced/test_adv_metadata.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414

1515
from packaging.version import Version
1616

17+
from cassandra.cluster import Cluster
1718
from tests.integration import (BasicExistingKeyspaceUnitTestCase, BasicSharedKeyspaceUnitTestCase,
1819
BasicSharedKeyspaceUnitTestCaseRF1,
1920
greaterthanorequaldse51, greaterthanorequaldse60,
2021
greaterthanorequaldse68, use_single_node,
21-
DSE_VERSION, requiredse)
22+
DSE_VERSION, requiredse, PROTOCOL_VERSION)
2223

2324
try:
2425
import unittest2 as unittest
@@ -361,3 +362,35 @@ def test_edge_metadata(self):
361362
self.assertEqual(edge_meta.to_label, 'rocksolidsoftware')
362363
self.assertEqual(edge_meta.to_partition_key_columns, ['company_name', 'software_name'])
363364
self.assertEqual(edge_meta.to_clustering_columns, ['software_version'])
365+
366+
367+
@greaterthanorequaldse68
368+
class GraphMetadataSchemaErrorTests(BasicExistingKeyspaceUnitTestCase):
369+
"""
370+
Test that we can connect when the graph schema is broken.
371+
"""
372+
373+
def test_connection_on_graph_schema_error(self):
374+
self.session = self.cluster.connect()
375+
376+
self.session.execute("""
377+
CREATE KEYSPACE %s WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1} and graph_engine = 'Core';
378+
""" % (self.ks_name,))
379+
380+
self.session.execute("""
381+
CREATE TABLE %s.person (name text PRIMARY KEY) WITH VERTEX LABEL;
382+
""" % (self.ks_name,))
383+
384+
self.session.execute("""
385+
CREATE TABLE %s.software(company text, name text, version int, PRIMARY KEY((company, name), version)) WITH VERTEX LABEL rocksolidsoftware;
386+
""" % (self.ks_name,))
387+
388+
self.session.execute("""
389+
CREATE TABLE %s.contributors (contributor text, company_name text, software_name text, software_version int,
390+
PRIMARY KEY (contributor, company_name, software_name, software_version) )
391+
WITH CLUSTERING ORDER BY (company_name ASC, software_name ASC, software_version ASC)
392+
AND EDGE LABEL contrib FROM person(contributor) TO rocksolidsoftware((company_name, software_name), software_version);
393+
""" % (self.ks_name,))
394+
395+
self.session.execute('TRUNCATE system_schema.vertices')
396+
Cluster(protocol_version=PROTOCOL_VERSION).connect().shutdown()

0 commit comments

Comments
 (0)