Skip to content

Commit 02738af

Browse files
committed
updated graph db graphQL queries and tests
1 parent 83f6053 commit 02738af

File tree

9 files changed

+1135
-135
lines changed

9 files changed

+1135
-135
lines changed

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"createdb",
2020
"createrole",
2121
"createuser",
22+
"cypher",
2223
"DBIRTH",
2324
"dbuser",
2425
"DCMD",
@@ -112,7 +113,7 @@
112113
"./07_uns_graphql/src",
113114
"./07_uns_graphql/test",
114115
],
115-
"python.languageServer": "Pylance",
116+
"python.languageServer": "Default",
116117
"python.missingPackage.severity": "Error",
117118
"ruff.showNotifications": "always",
118119
"ruff.trace.server": "messages",

03_uns_graphdb/src/uns_graphdb/graphdb_handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ def connect(self, retry: int = 0) -> neo4j.Driver:
103103
----------
104104
retry: int
105105
Optional parameters to retry making a connection in case of errors.
106-
The max number of retry is `GraphDBHandler.MAX_RETRIES`
107-
The time between attempts is `GraphDBHandler.SLEEP_BTW_ATTEMPT`
106+
The max number of retry is `GraphDBHandler.max_retry`
107+
The time between attempts is `GraphDBHandler.sleep_btw_attempts`
108108
Returns:
109109
neo4j.Driver: The Neo4j driver object.
110110

07_uns_graphql/schema/uns_schema.graphql

Lines changed: 99 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,102 @@ type Query {
7777
"""
7878
getUnsNodes(topics: [MQTTTopicInput!]!): [UNSNode!]!
7979

80-
"""
81-
Get all UNSNodes published which have specific attributes.Option binary_operator input allows chaining the list of property_keys. If NULL, property_keys will be ORed- OR: Either of the property_keys must exist in the same node. If only one property_keys provided will be ignored- AND: All property_keys must exist in same node. If only one property_keys provided will be ignored- NOT: None of the provided property_keys should exist in the same nodeOther criteria - topics will always be ANDed to the query filter
82-
"""
83-
getUnsNodesByProperty(propertyKeys: [String!]!, binaryOperator: BinaryOperator, topics: [MQTTTopicInput!]): [UNSNode!]!
80+
"Get all UNSNodes published which have specific attribute name as 'property_keys'. \n Optionally Filter results with list of topics. \nIf topics are provided then optional boolean value exclude_topics attribute can be set to true .\nto exclude the nodes which match the topics.\n"
81+
getUnsNodesByProperty(propertyKeys: [String!]!, topics: [MQTTTopicInput!], excludeTopics: Boolean = false): [UNSNode!]!
8482

85-
"""
86-
Get consolidation of sparkplugB nodes. MQTT wildcards are supportedEnsure that the topics are all in the SparkplugB namespace i.e. starts with 'spBv1.0/' Format of an SpB topic is spBv1.0/ <group_id> / <message_type> / <edge_node_id> / [<device_id>]
87-
"""
88-
getSpbNodes(topics: [MQTTTopicInput!]!): [UNSNode!]!
83+
"""Get all the SPBNode by the provided metric name"""
84+
getSpbNodesByMetric(metricNames: [String!]!): [SPBNode!]!
85+
}
86+
87+
type SPBDataSet {
88+
numOfColumns: Union!
89+
columns: [String!]!
90+
types: [String!]!
91+
rows: [SPBDataSetRow!]!
92+
}
93+
94+
type SPBDataSetRow {
95+
elements: [SPBDataSetValue!]!
96+
}
97+
98+
type SPBDataSetValue {
99+
value: SPBPrimitive!
100+
}
101+
102+
type SPBMetadata {
103+
isMultiPart: Boolean
104+
contentType: String
105+
size: Union
106+
seq: Union
107+
fileName: String
108+
fileType: String
109+
md5: String
110+
description: String
111+
}
112+
113+
type SPBMetric {
114+
name: String!
115+
alias: Union
116+
timestamp: DateTime!
117+
datatype: String!
118+
isHistorical: Boolean
119+
isTransient: Boolean
120+
isNull: Boolean
121+
metadata: SPBMetadata
122+
properties: SPBPropertySet
123+
value: SPBPrimitiveBytesPayloadSPBDataSetSPBTemplate!
124+
}
125+
126+
type SPBNode {
127+
topic: String!
128+
timestamp: DateTime!
129+
metrics: [SPBMetric!]!
130+
seq: Union!
131+
uuid: ID
132+
body: Base64
133+
}
134+
135+
"""
136+
Wrapper for primitive types in Sparkplug.: int, float, str, bool, list
137+
Needed because GraphQL does not support str for unions.
138+
Data is converted to its String representation for convenience.
139+
Use the datatype to convert to actual type if needed
140+
"""
141+
type SPBPrimitive {
142+
data: String!
143+
}
144+
145+
union SPBPrimitiveBytesPayloadSPBDataSetSPBTemplate = SPBPrimitive | BytesPayload | SPBDataSet | SPBTemplate
146+
147+
union SPBPrimitiveSPBPropertySetSPBPropertySetList = SPBPrimitive | SPBPropertySet | SPBPropertySetList
148+
149+
type SPBPropertySet {
150+
keys: [String!]!
151+
values: [SPBPropertyValue!]!
152+
}
153+
154+
type SPBPropertySetList {
155+
propertysets: [SPBPropertySet!]!
156+
}
157+
158+
type SPBPropertyValue {
159+
isNull: Boolean
160+
datatype: String!
161+
value: SPBPrimitiveSPBPropertySetSPBPropertySetList!
162+
}
163+
164+
type SPBTemplate {
165+
version: String
166+
metrics: [SPBMetric!]!
167+
parameters: [SPBTemplateParameter!]
168+
templateRef: String
169+
isDefinition: Boolean
170+
}
171+
172+
type SPBTemplateParameter {
173+
name: String!
174+
datatype: String!
175+
value: SPBPrimitive!
89176
}
90177

91178
type StreamingMessage {
@@ -112,4 +199,7 @@ type UNSNode {
112199
payload: JSONPayload!
113200
created: DateTime!
114201
lastUpdated: DateTime!
115-
}
202+
}
203+
204+
"""Int 64 field since GraphQL doesn't support int64, only int 32"""
205+
scalar Union

07_uns_graphql/src/uns_graphql/backend/graphdb.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
Encapsulates integration with the Graph database database
1919
"""
2020

21+
import asyncio
2122
import logging
2223

2324
from neo4j import AsyncDriver, AsyncGraphDatabase, AsyncResult, Record
@@ -26,6 +27,9 @@
2627

2728
LOGGER = logging.getLogger(__name__)
2829

30+
MAX_RETRIES = 5
31+
SLEEP_BTW_ATTEMPT = 10
32+
2933

3034
class GraphDB:
3135
"""
@@ -37,17 +41,24 @@ class GraphDB:
3741
_graphdb_driver: AsyncDriver = None
3842

3943
@classmethod
40-
async def get_graphdb_driver(cls) -> AsyncDriver:
44+
async def get_graphdb_driver(cls, retry: int = 0) -> AsyncDriver:
4145
"""
4246
Returns the Neo4j async driver which is the connection to the database.
4347
4448
Validates if the current driver is still connected, and if not, creates a new connection.
4549
The driver is cached and reused for subsequent requests to avoid creating multiple connections.
50+
Parameters
51+
----------
52+
retry: int
53+
Optional parameters to retry making a connection in case of errors.
54+
The max number of retry is `MAX_RETRIES`
55+
The time between attempts is `SLEEP_BTW_ATTEMPT` seconds
4656
4757
Returns:
4858
AsyncDriver: The Neo4j async driver.
4959
"""
5060
LOGGER.debug("GraphDB driver requested")
61+
current_loop = asyncio.get_event_loop()
5162
if cls._graphdb_driver is None:
5263
LOGGER.info("Creating a new GraphDB driver")
5364
cls._graphdb_driver = AsyncGraphDatabase.driver(
@@ -60,11 +71,13 @@ async def get_graphdb_driver(cls) -> AsyncDriver:
6071
LOGGER.error("Failed to verify GraphDB driver connectivity: %s", str(ex), stack_info=True, exc_info=True)
6172
# In case of connectivity failure, close the existing driver and create a new one
6273
await cls.release_graphdb_driver()
63-
cls._graphdb_driver = AsyncGraphDatabase.driver(
64-
uri=GraphDBConfig.conn_url, auth=(GraphDBConfig.user, GraphDBConfig.password)
65-
)
66-
await cls._graphdb_driver.verify_connectivity()
67-
LOGGER.info("Reconnected to GraphDB driver")
74+
if retry >= MAX_RETRIES:
75+
LOGGER.error("No. of retries exceeded %s", str(MAX_RETRIES), stack_info=True, exc_info=True)
76+
raise ex # Re-raise the exception after cleanup
77+
78+
await asyncio.sleep(SLEEP_BTW_ATTEMPT)
79+
cls._graphdb_driver = await cls.get_graphdb_driver(retry + 1)
80+
LOGGER.info("Trying to Reconnect to GraphDB driver")
6881

6982
return cls._graphdb_driver
7083

0 commit comments

Comments
 (0)