Search code examples
pythonpython-3.xgoogle-cloud-platformgoogle-cloud-functionsgoogle-cloud-spanner

Error on writing to Google cloud spanner using Google cloud functions


I am trying to insert data into cloud spanner table using cloud functions but it is throwing the error given below.Reading data from cloud spanner is working properly but writing using both the Data Definition Language commands and batch.insert method both throws the same error. I am thinking its some kind of permissions problem! I don't know how to fix it?

Requirements file contains only google-cloud-spanner==1.7.1

Code running in cloud functions

import json
from google.cloud import spanner
INSTANCE_ID = 'AARISTA'
DATABASE_ID = 'main'
TABLE_NAME = 'userinfo'
dataDict = None

def new_user(request):
    dataDict = json.loads(request.data)# Data is available in dict format
    if dataDict['USER_ID']==None:
       return "User id empty"
    elif dataDict['IMEI'] == None:
       return "Imei number empty"
    elif dataDict['DEVICE_ID'] == None:
       return "Device ID empty"
    elif dataDict['NAME'] == None:
       return "Name field is empty"
    elif dataDict['VIRTUAL_PRIVATE_KEY']== None:
       return "User's private key cant be empty"  
    else:
       return insert_data(INSTANCE_ID,DATABASE_ID)

def insert_data(instance_id, database_id):
      spanner_client = spanner.Client()
      instance = spanner_client.instance(instance_id)
      database = instance.database(database_id)
      def insert_user(transcation):
          row_ct= transcation.execute_update("INSERT userinfo 
                   (USER_ID,DEVICE_ID,IMEI,NAME,VIRTUAL_PRIVATE_KEY) VALUES"
                                   "("+dataDict['USER_ID']+', 
                 '+dataDict['DEVICE_ID']+', '+ dataDict['IMEI']+', 
                 '+dataDict['NAME']+', 
             '+dataDict['VIRTUAL_PRIVATE_KEY']+")")

      database.run_in_transaction(insert_user)
      return 'Inserted data.'

Error logs on Cloud Functions

Traceback (most recent call last): 
  File "/env/local/lib/python3.7/site-packages/google/cloud/spanner_v1/pool.py", line 265, in get session = self._sessions.get_nowait() 
  File "/opt/python3.7/lib/python3.7/queue.py", line 198, in get_nowait return self.get(block=False)
  File "/opt/python3.7/lib/python3.7/queue.py", line 167, in get raise Empty _queue.Empty
During handling of the above exception, another exception occurred:
Traceback (most recent call last): 
  File "/env/local/lib/python3.7/site-packages/google/api_core/grpc_helpers.py", line 57, in error_remapped_callable return callable_(*args, **kwargs)
  File "/env/local/lib/python3.7/site-packages/grpc/_channel.py", line 547, in __call__ return _end_unary_response_blocking(state, call, False, None) 
  File "/env/local/lib/python3.7/site-packages/grpc/_channel.py", line 466, in _end_unary_response_blocking raise _Rendezvous(state, None, None, deadline)
grpc._channel._Rendezvous: <_Rendezvous of RPC that  terminated with: status = StatusCode.INVALID_ARGUMENT details =  "Invalid CreateSession request." debug_error_string = "{"created":"@1547373361.398535906","description":"Error received from peer","file":"src/core/lib/surface/call.cc","file_line":1036,"grpc_message":"Invalid> CreateSession request.","grpc_status":3}" > 
The above exception was the direct cause of the following exception: 
Traceback (most recent call last): 
  File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker.py", line 297, in run_http_function result = _function_handler.invoke_user_function(flask.request) 
  File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker.py", line 199, in invoke_user_function return call_user_function(request_or_event) 
  File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker.py", line 192, in call_user_function return self._user_function(request_or_event) 
  File "/user_code/main.py", line 21, in new_user return insert_data(INSTANCE_ID,DATABASE_ID) 
  File "/user_code/main.py", line 31, in insert_data database.run_in_transaction(insert_user) 
  File "/env/local/lib/python3.7/site-packages/google/cloud/spanner_v1/database.py", line 438, in run_in_transaction with SessionCheckout(self._pool) as session:
  File "/env/local/lib/python3.7/site-packages/google/cloud/spanner_v1/pool.py", line 519, in __enter__ self._session = self._pool.get(**self._kwargs)
  File "/env/local/lib/python3.7/site-packages/google/cloud/spanner_v1/pool.py", line 268, in get session.create()
  File "/env/local/lib/python3.7/site-packages/google/cloud/spanner_v1/session.py", line 116, in create session_pb = api.create_session(self._database.name, metadata=metadata, **kw)
  File "/env/local/lib/python3.7/site-packages/google/cloud/spanner_v1/gapic/spanner_client.py", line 276, in create_session request, retry=retry, timeout=timeout, metadata=metadata
  File "/env/local/lib/python3.7/site-packages/google/api_core/gapic_v1/method.py", line 143, in __call__ return wrapped_func(*args, **kwargs) 
  File "/env/local/lib/python3.7/site-packages/google/api_core/retry.py", line 270, in retry_wrapped_func on_error=on_error, 
  File "/env/local/lib/python3.7/site-packages/google/api_core/retry.py", line 179, in retry_target return target()
  File "/env/local/lib/python3.7/site-packages/google/api_core/timeout.py", line 214, in func_with_timeout return func(*args, **kwargs)
  File "/env/local/lib/python3.7/site-packages/google/api_core/grpc_helpers.py", line 59, in error_remapped_callable six.raise_from(exceptions.from_grpc_error(exc), exc) 
  File "<string>", line 3, in raise_from
google.api_core.exceptions.InvalidArgument: 400 Invalid CreateSession request.

Solution

  • I tried to reproduce this but it seems to work for me as a Python 3.7 function. I used the latest google-cloud-spanner library in requirements.txt.

    While I am unsure what would be causing your error I did notice a few other things.

    • It seemed odd to declare a global dataDict and not use the one constructed and pass it. Instead I added that as a param to the insert method.
    • The spacing of the query was a bit odd and the use of single and double quotes was odd. this made it hard to parse visually. As the function runs as python 3.7 you can also use f-strings which likely would make it even more readable.

    Here is the code I ran in a function that seemed to work.

    import json
    from google.cloud import spanner
    INSTANCE_ID = 'testinstance'
    DATABASE_ID = 'testdatabase'
    TABLE_ID = 'userinfo'
    
    def new_user(request):
        data = { 'USER_ID': '10', 'DEVICE_ID': '11' }  
        return insert_data(INSTANCE_ID, DATABASE_ID, data)
    
    def insert_data(instance_id, database_id, data):
        spanner_client = spanner.Client()
        instance = spanner_client.instance(instance_id)
        database = instance.database(database_id)
    
        def insert_user(transaction):
            query = f"INSERT {TABLE_ID} (USER_ID,DEVICE_ID) VALUES ({data['USER_ID']},{data['DEVICE_ID']})"
            row_ct = transaction.execute_update(query)
    
        database.run_in_transaction(insert_user)
        return 'Inserted data.'