Cloud function does not create/store document in firestore

68 Views Asked by At

I have the following cloud function:

const { Firestore, Timestamp } = require('@google-cloud/firestore');
const { ImageAnnotatorClient } = require('@google-cloud/vision');

const client = new ImageAnnotatorClient();
const projectId = "*project-id*";
const databaseId = "*database-id*";
const db = new Firestore({ projectId, databaseId });
console.log('Firestore database client:', db);
console.log("Firestore database ID: ", db.databaseId);


exports.processImage = async (event, context) => {
  // Check if event data is present
  if (!event || !event.name || !event.bucket) {
    console.error('Invalid Cloud Storage event. Exiting.');
    return;
  }

  const filePath = event.name;
  const bucketName = event.bucket;
  const fileName = filePath.split('/').pop();
  
  // Prepare image for the Vision API
  const imageUri = `gs://${bucketName}/${filePath}`;

  console.log(`Calling Vision API for image: ${imageUri}`);
  
  // Call the Vision API
  try {
    const [result] = await client.labelDetection(imageUri);
    const labels = result.labelAnnotations.map(label => label.description);
    console.log(`Labels detected: ${labels.join(', ')}`);
    
    // Store the labels in Firestore
    const docRef = db.collection('photo-ai-db').doc(fileName);
    console.log(`Writing to Firestore document: ${docRef.path}`);
    try {
      // Set document data with merge option to create document if it doesn't exist
      await docRef.update({ labels, processedAt: Timestamp.now() });
      await docRef.set({ labels, processedAt: Timestamp.now() }, { merge: true });
      console.log(`Processed image ${fileName} and stored labels in Firestore.`);
    } catch (error) {
      console.error('Error writing to Firestore:', error);
    }
  } catch (error) {
    console.error('Error calling Vision API:', error);
  }
};

This is my firestore database, I've manually created these collections because I keep getting the error below, so I thought if I created them, I might get somewhere.

The function reads from cloud storage (it seems to read correctly because the labels that are being extracted in the logs are correct). The issue is that it doesn't store the labels in firestore.

enter image description here

Logs:

DEFAULT 2024-03-27T05:18:24.393704Z Firestore database client: Firestore {
DEFAULT 2024-03-27T05:18:24.393731Z _settings: {
DEFAULT 2024-03-27T05:18:24.393739Z projectId: '*project-id*',
DEFAULT 2024-03-27T05:18:24.393745Z databaseId: '*database-id*',
DEFAULT 2024-03-27T05:18:24.393751Z libName: 'gccl',
DEFAULT 2024-03-27T05:18:24.393757Z libVersion: '4.15.1'
DEFAULT 2024-03-27T05:18:24.393762Z },
DEFAULT 2024-03-27T05:18:24.393768Z _settingsFrozen: false,
DEFAULT 2024-03-27T05:18:24.393774Z _serializer: Serializer {
DEFAULT 2024-03-27T05:18:24.393781Z createReference: [Function (anonymous)],
DEFAULT 2024-03-27T05:18:24.393787Z createInteger: [Function (anonymous)],
DEFAULT 2024-03-27T05:18:24.393794Z allowUndefined: false
DEFAULT 2024-03-27T05:18:24.393799Z },
DEFAULT 2024-03-27T05:18:24.393805Z _projectId: '*project-id*',
DEFAULT 2024-03-27T05:18:24.393811Z registeredListenersCount: 0,
DEFAULT 2024-03-27T05:18:24.393816Z bulkWritersCount: 0,
DEFAULT 2024-03-27T05:18:24.393823Z _backoffSettings: { initialDelayMs: 100, maxDelayMs: 60000, backoffFactor: 1.3 },
DEFAULT 2024-03-27T05:18:24.393830Z _clientPool: ClientPool {
DEFAULT 2024-03-27T05:18:24.393836Z concurrentOperationLimit: 100,
DEFAULT 2024-03-27T05:18:24.393841Z maxIdleClients: 1,
DEFAULT 2024-03-27T05:18:24.393847Z clientFactory: [Function (anonymous)],
DEFAULT 2024-03-27T05:18:24.393854Z clientDestructor: [Function (anonymous)],
DEFAULT 2024-03-27T05:18:24.393860Z activeClients: Map(0) {},
DEFAULT 2024-03-27T05:18:24.393865Z failedClients: Set(0) {},
DEFAULT 2024-03-27T05:18:24.393870Z terminated: false,
DEFAULT 2024-03-27T05:18:24.393876Z terminateDeferred: Deferred {
DEFAULT 2024-03-27T05:18:24.393882Z resolve: [Function (anonymous)],
DEFAULT 2024-03-27T05:18:24.393888Z reject: [Function (anonymous)],
DEFAULT 2024-03-27T05:18:24.393893Z promise: [Promise]
DEFAULT 2024-03-27T05:18:24.393899Z }
DEFAULT 2024-03-27T05:18:24.393904Z }
DEFAULT 2024-03-27T05:18:24.393910Z }
DEFAULT 2024-03-27T05:18:24.394410Z Firestore database ID: undefined
INFO 2024-03-27T05:18:24.491815Z Default STARTUP TCP probe succeeded after 1 attempt for container "worker" on port 8080.
INFO 2024-03-27T05:18:24.592803Z [protoPayload.serviceName: run.googleapis.com] [protoPayload.methodName: v1] [protoPayload.resourceName: namespaces/*project-id*/revisions/processimage-00014-yac] Ready condition status changed to True for Revision processimage-00014-yac.
INFO 2024-03-27T05:18:26.098282Z [protoPayload.serviceName: run.googleapis.com] [protoPayload.methodName: v1] [protoPayload.resourceName: namespaces/*project-id*/services/processimage] Ready condition status changed to True for Service processimage.
NOTICE 2024-03-27T05:18:26.595138638Z [protoPayload.serviceName: cloudfunctions.googleapis.com] [protoPayload.methodName: google.cloud.functions.v2.FunctionService.UpdateFunction] [protoPayload.resourceName: projects/*project-id*/locations/us-central1/functions/processimage] [protoPayload.authenticationInfo.principalEmail: [email protected]] audit_log, method: "google.cloud.functions.v2.FunctionService.UpdateFunction", principal_email: "[email protected]"
INFO 2024-03-27T05:18:32.701075Z [httpRequest.requestMethod: POST] [httpRequest.status: 204] [httpRequest.responseSize: 592 B] [httpRequest.latency: 723 ms] [httpRequest.userAgent: curl 7.74.0] https://us-central1-project-id.cloudfunctions.net/processimage
DEFAULT 2024-03-27T05:18:32.759563Z Calling Vision API for image: gs://ece9016-raw-images/teeth-label.jpg
DEFAULT 2024-03-27T05:18:33.257399Z Labels detected: Eye, Mouth, Human body, Jaw, Gesture, Ear, Font, Happy, Tooth, Drawing
DEFAULT 2024-03-27T05:18:33.258075Z Writing to Firestore document: photo-ai-db/teeth-label.jpg
DEFAULT 2024-03-27T05:18:33.435653Z Error writing to Firestore: Error: 5 NOT_FOUND:
DEFAULT 2024-03-27T05:18:33.435678Z at Object.callErrorFromStatus (/workspace/node_modules/@grpc/grpc-js/build/src/call.js:31:19)
DEFAULT 2024-03-27T05:18:33.435684Z at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client.js:190:52)
DEFAULT 2024-03-27T05:18:33.435691Z at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:365:141)
DEFAULT 2024-03-27T05:18:33.435695Z at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:328:181)
DEFAULT 2024-03-27T05:18:33.435700Z at /workspace/node_modules/@grpc/grpc-js/build/src/call-stream.js:188:78
DEFAULT 2024-03-27T05:18:33.435705Z at process.processTicksAndRejections (node:internal/process/task_queues:77:11)
DEFAULT 2024-03-27T05:18:33.435711Z for call at
DEFAULT 2024-03-27T05:18:33.435717Z at ServiceClientImpl.makeUnaryRequest (/workspace/node_modules/@grpc/grpc-js/build/src/client.js:160:30)
DEFAULT 2024-03-27T05:18:33.435722Z at ServiceClientImpl.<anonymous> (/workspace/node_modules/@grpc/grpc-js/build/src/make-client.js:105:19)
DEFAULT 2024-03-27T05:18:33.435727Z at /workspace/node_modules/@google-cloud/firestore/build/src/v1/firestore_client.js:205:29
DEFAULT 2024-03-27T05:18:33.435732Z at /workspace/node_modules/google-gax/build/src/normalCalls/timeout.js:44:16
DEFAULT 2024-03-27T05:18:33.435737Z at repeat (/workspace/node_modules/google-gax/build/src/normalCalls/retries.js:80:25)
DEFAULT 2024-03-27T05:18:33.435742Z at /workspace/node_modules/google-gax/build/src/normalCalls/retries.js:118:13
DEFAULT 2024-03-27T05:18:33.435753Z at OngoingCallPromise.call (/workspace/node_modules/google-gax/build/src/call.js:67:27)
DEFAULT 2024-03-27T05:18:33.435758Z at NormalApiCaller.call (/workspace/node_modules/google-gax/build/src/normalCalls/normalApiCaller.js:34:19)
DEFAULT 2024-03-27T05:18:33.435764Z at /workspace/node_modules/google-gax/build/src/createApiCall.js:81:30
DEFAULT 2024-03-27T05:18:33.435768Z Caused by: Error
DEFAULT 2024-03-27T05:18:33.435774Z at WriteBatch.commit (/workspace/node_modules/@google-cloud/firestore/build/src/write-batch.js:417:23)
DEFAULT 2024-03-27T05:18:33.435780Z at DocumentReference.update (/workspace/node_modules/@google-cloud/firestore/build/src/reference.js:393:14)
DEFAULT 2024-03-27T05:18:33.435785Z at exports.processImage (/workspace/index.js:39:20) {
DEFAULT 2024-03-27T05:18:33.435789Z code: 5,
DEFAULT 2024-03-27T05:18:33.435793Z details: '',
DEFAULT 2024-03-27T05:18:33.435797Z metadata: Metadata { internalRepr: Map(0) {}, options: {} },
DEFAULT 2024-03-27T05:18:33.435803Z note: 'Exception occurred in retry method that was not classified as transient'
DEFAULT 2024-03-27T05:18:33.435807Z }
1

There are 1 best solutions below

4
Roopa M On BEST ANSWER

I replicated your issue with your code and found out you are trying to update documents even before they are created or exist. Hence, you are getting Error: 5 NOT\_FOUND. And you are unable to create documents or collections as you are stuck at error.

Update

Steps I followed are :

try {
       await docRef.set({ labels, processedAt: Timestamp.now() }, { merge: true });

      console.log(`Processed image ${fileName} and stored labels in Firestore.`);
    } catch (error) {
      console.error('Error writing to Firestore:', error);
    }

Package.json

{
  "dependencies": {
    "@firebase/app": "^0.9.29",
    "@firebase/auth": "^1.6.2",
    "@firebase/firestore": "^4.5.0",
    "@google-cloud/firestore": "^7.5.0",
    "@google-cloud/vision": "^4.1.0"
  }
}

  • And left everything as default. Deployed the function.
  • Made changes to cloud storage and finally, I can see changes in firestore as well.