Skip to content

Commit 329b063

Browse files
committed
Enable gRPC for datastore API.
1 parent fd7e7c0 commit 329b063

File tree

3 files changed

+503
-29
lines changed

3 files changed

+503
-29
lines changed

gcloud/datastore/_generated/datastore_grpc_pb2.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,21 @@
44
from grpc.framework.common import cardinality
55
from grpc.framework.interfaces.face import utilities as face_utilities
66

7+
# BEGIN: Manually added imports
8+
from gcloud.datastore._generated.datastore_pb2 import AllocateIdsRequest
9+
from gcloud.datastore._generated.datastore_pb2 import AllocateIdsResponse
10+
from gcloud.datastore._generated.datastore_pb2 import BeginTransactionRequest
11+
from gcloud.datastore._generated.datastore_pb2 import BeginTransactionResponse
12+
from gcloud.datastore._generated.datastore_pb2 import CommitRequest
13+
from gcloud.datastore._generated.datastore_pb2 import CommitResponse
14+
from gcloud.datastore._generated.datastore_pb2 import LookupRequest
15+
from gcloud.datastore._generated.datastore_pb2 import LookupResponse
16+
from gcloud.datastore._generated.datastore_pb2 import RollbackRequest
17+
from gcloud.datastore._generated.datastore_pb2 import RollbackResponse
18+
from gcloud.datastore._generated.datastore_pb2 import RunQueryRequest
19+
from gcloud.datastore._generated.datastore_pb2 import RunQueryResponse
20+
# END: Manually added imports
21+
722

823
class DatastoreStub(object):
924
"""Each RPC normalizes the partition IDs of the keys in its input entities,

gcloud/datastore/connection.py

Lines changed: 164 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,41 @@
1818

1919
from google.rpc import status_pb2
2020

21+
from gcloud._helpers import make_stub
2122
from gcloud import connection as connection_module
2223
from gcloud.environment_vars import GCD_HOST
24+
from gcloud.exceptions import Conflict
2325
from gcloud.exceptions import make_exception
2426
from gcloud.datastore._generated import datastore_pb2 as _datastore_pb2
27+
# pylint: disable=ungrouped-imports
28+
try:
29+
from grpc.beta.interfaces import StatusCode
30+
from grpc.framework.interfaces.face.face import AbortionError
31+
from gcloud.datastore._generated import datastore_grpc_pb2
32+
DATASTORE_STUB_FACTORY = datastore_grpc_pb2.beta_create_Datastore_stub
33+
except ImportError: # pragma: NO COVER
34+
_HAVE_GRPC = False
35+
DATASTORE_STUB_FACTORY = None
36+
StatusCode = None
37+
AbortionError = Exception
38+
else:
39+
_HAVE_GRPC = True
40+
# pylint: enable=ungrouped-imports
41+
42+
43+
DATASTORE_API_HOST = 'datastore.googleapis.com'
44+
"""Datastore API request host."""
45+
DATASTORE_API_PORT = 443
46+
"""Datastore API request port."""
47+
GRPC_TIMEOUT_SECONDS = 10
48+
"""The default timeout to use for API requests via gRPC."""
2549

2650

2751
class _DatastoreAPIOverHttp(object):
2852
"""Helper mapping datastore API methods.
2953
54+
Makes requests to send / receive protobuf content over HTTP/1.1.
55+
3056
Methods make bare API requests without any helpers for constructing
3157
the requests or parsing the responses.
3258
@@ -196,6 +222,139 @@ def allocate_ids(self, project, request_pb):
196222
_datastore_pb2.AllocateIdsResponse)
197223

198224

225+
class _DatastoreAPIOverGRPC(object):
226+
"""Helper mapping datastore API methods.
227+
228+
Makes requests to send / receive protobuf content over gRPC.
229+
230+
Methods make bare API requests without any helpers for constructing
231+
the requests or parsing the responses.
232+
233+
:type connection: :class:`gcloud.datastore.connection.Connection`
234+
:param connection: A connection object that contains helpful
235+
information for making requests.
236+
"""
237+
238+
def __init__(self, connection):
239+
self._stub = make_stub(connection.credentials, connection.USER_AGENT,
240+
DATASTORE_STUB_FACTORY, DATASTORE_API_HOST,
241+
DATASTORE_API_PORT)
242+
self._stub.__enter__()
243+
244+
def __del__(self):
245+
"""Destructor for object.
246+
247+
Ensures that the stub is exited so the shell can close properly.
248+
"""
249+
try:
250+
self._stub.__exit__(None, None, None)
251+
del self._stub
252+
except AttributeError:
253+
pass
254+
255+
def lookup(self, project, request_pb):
256+
"""Perform a ``lookup`` request.
257+
258+
:type project: string
259+
:param project: The project to connect to. This is
260+
usually your project name in the cloud console.
261+
262+
:type request_pb: :class:`._generated.datastore_pb2.LookupRequest`
263+
:param request_pb: The request protobuf object.
264+
265+
:rtype: :class:`._generated.datastore_pb2.LookupResponse`
266+
:returns: The returned protobuf response object.
267+
"""
268+
request_pb.project_id = project
269+
return self._stub.Lookup(request_pb, GRPC_TIMEOUT_SECONDS)
270+
271+
def run_query(self, project, request_pb):
272+
"""Perform a ``runQuery`` request.
273+
274+
:type project: string
275+
:param project: The project to connect to. This is
276+
usually your project name in the cloud console.
277+
278+
:type request_pb: :class:`._generated.datastore_pb2.RunQueryRequest`
279+
:param request_pb: The request protobuf object.
280+
281+
:rtype: :class:`._generated.datastore_pb2.RunQueryResponse`
282+
:returns: The returned protobuf response object.
283+
"""
284+
request_pb.project_id = project
285+
return self._stub.RunQuery(request_pb, GRPC_TIMEOUT_SECONDS)
286+
287+
def begin_transaction(self, project, request_pb):
288+
"""Perform a ``beginTransaction`` request.
289+
290+
:type project: string
291+
:param project: The project to connect to. This is
292+
usually your project name in the cloud console.
293+
294+
:type request_pb:
295+
:class:`._generated.datastore_pb2.BeginTransactionRequest`
296+
:param request_pb: The request protobuf object.
297+
298+
:rtype: :class:`._generated.datastore_pb2.BeginTransactionResponse`
299+
:returns: The returned protobuf response object.
300+
"""
301+
request_pb.project_id = project
302+
return self._stub.BeginTransaction(request_pb, GRPC_TIMEOUT_SECONDS)
303+
304+
def commit(self, project, request_pb):
305+
"""Perform a ``commit`` request.
306+
307+
:type project: string
308+
:param project: The project to connect to. This is
309+
usually your project name in the cloud console.
310+
311+
:type request_pb: :class:`._generated.datastore_pb2.CommitRequest`
312+
:param request_pb: The request protobuf object.
313+
314+
:rtype: :class:`._generated.datastore_pb2.CommitResponse`
315+
:returns: The returned protobuf response object.
316+
"""
317+
request_pb.project_id = project
318+
try:
319+
return self._stub.Commit(request_pb, GRPC_TIMEOUT_SECONDS)
320+
except AbortionError as exc:
321+
if exc.code == StatusCode.ABORTED:
322+
raise Conflict(exc.details)
323+
raise
324+
325+
def rollback(self, project, request_pb):
326+
"""Perform a ``rollback`` request.
327+
328+
:type project: string
329+
:param project: The project to connect to. This is
330+
usually your project name in the cloud console.
331+
332+
:type request_pb: :class:`._generated.datastore_pb2.RollbackRequest`
333+
:param request_pb: The request protobuf object.
334+
335+
:rtype: :class:`._generated.datastore_pb2.RollbackResponse`
336+
:returns: The returned protobuf response object.
337+
"""
338+
request_pb.project_id = project
339+
return self._stub.Rollback(request_pb, GRPC_TIMEOUT_SECONDS)
340+
341+
def allocate_ids(self, project, request_pb):
342+
"""Perform an ``allocateIds`` request.
343+
344+
:type project: string
345+
:param project: The project to connect to. This is
346+
usually your project name in the cloud console.
347+
348+
:type request_pb: :class:`._generated.datastore_pb2.AllocateIdsRequest`
349+
:param request_pb: The request protobuf object.
350+
351+
:rtype: :class:`._generated.datastore_pb2.AllocateIdsResponse`
352+
:returns: The returned protobuf response object.
353+
"""
354+
request_pb.project_id = project
355+
return self._stub.AllocateIds(request_pb, GRPC_TIMEOUT_SECONDS)
356+
357+
199358
class Connection(connection_module.Connection):
200359
"""A connection to the Google Cloud Datastore via the Protobuf API.
201360
@@ -213,7 +372,7 @@ class Connection(connection_module.Connection):
213372
:attr:`API_BASE_URL`.
214373
"""
215374

216-
API_BASE_URL = 'https://datastore.googleapis.com'
375+
API_BASE_URL = 'https://' + DATASTORE_API_HOST
217376
"""The base of the API call URL."""
218377

219378
API_VERSION = 'v1beta3'
@@ -236,7 +395,10 @@ def __init__(self, credentials=None, http=None, api_base_url=None):
236395
except KeyError:
237396
api_base_url = self.__class__.API_BASE_URL
238397
self.api_base_url = api_base_url
239-
self._datastore_api = _DatastoreAPIOverHttp(self)
398+
if _HAVE_GRPC:
399+
self._datastore_api = _DatastoreAPIOverGRPC(self)
400+
else:
401+
self._datastore_api = _DatastoreAPIOverHttp(self)
240402

241403
def build_api_url(self, project, method, base_url=None,
242404
api_version=None):

0 commit comments

Comments
 (0)