Rusty Rob
Rusty Rob

Reputation: 17173

google.storage.object.finalize not triggering firebase cloud function

I have a firebase app, when user uploads photo to storage, it triggers a generatethumbnail cloud function. All standard code, it worked fine, i deployed on Feb 24th 2019. Now when I Upload a photo, nothing happens. I look in storage and the photo is there, but when i look at the logs for firebase cloud functions, the generateThumbnail function hasn't been called. How can I debug / fix this? I was thinking of just redeploying my code, or perhaps upgrading my libraries etc in case there have been breaking changes?

Here's my code:

import * as functions from 'firebase-functions';

// import * as Storage from '@google-cloud/storage';
// const gcs = new Storage();


import * as admin from 'firebase-admin';
const gcs = admin.storage()
const firestore = admin.firestore();

import { tmpdir } from 'os';
import { join, dirname } from 'path';

import * as sharp from 'sharp';
import * as fs from 'fs-extra';

export const generateThumbs = functions.storage
  .object()
  .onFinalize(async object => {
    const bucket = gcs.bucket(object.bucket);
    const filePath = object.name;
    const parts = filePath.split('/');
    const fileName = parts.pop();
    const propertyID = parts.pop();
    // console.log(`got property id ${propertyID}`)
    const bucketDir = dirname(filePath);

    const workingDir = join(tmpdir(), 'thumbs');
    const tmpFilePath = join(workingDir, fileName);

    if (fileName.includes('thumb@') || !object.contentType.includes('image')) {
      console.log('exiting function');
      return false;
    }

    // 1. Ensure thumbnail dir exists
    await fs.ensureDir(workingDir);

    // 2. Download Source File
    await bucket.file(filePath).download({
      destination: tmpFilePath
    });

    // 3. Resize the images and define an array of upload promises
    const sizes = [256];

    let thumbLocation = '';
    const uploadPromises = sizes.map(async size => {
      const thumbName = `thumb@${size}_${fileName}`;
      const thumbPath = join(workingDir, thumbName);

      // Resize source image
      await sharp(tmpFilePath)
        .resize(256, 171)
        .toFile(thumbPath);

      thumbLocation = join(bucketDir, thumbName);
      // Upload to GCS
      return bucket.upload(thumbPath, {
        destination: thumbLocation
      });
    });

    // 4. Run the upload operations
    await Promise.all(uploadPromises);

    // 5. Cleanup remove the tmp/thumbs from the filesystem
    await fs.remove(workingDir);

    let photoURL = ''
    const hour = 1000 * 60 * 60;
    const year = hour * 24 * 365;
    const EXP = Date.now() + year * 10;
    await bucket.file(filePath).getSignedUrl({
      action: 'read',
      expires: EXP
    }).then(signedUrls => {
      photoURL = signedUrls[0];
    });

    let thumbURL = '';
    await bucket.file(thumbLocation).getSignedUrl({
      action: 'read',
      expires: EXP
    }).then(signedUrls => {
      thumbURL = signedUrls[0];
    });

    if (!(photoURL && thumbURL)) {
      return Promise.resolve('Error no thumbs');
    }

    const propertyRef = firestore.collection('properties').doc(propertyID);
    return firestore.runTransaction(t => {
      return t.get(propertyRef)
        .then(doc => {
          if (!doc.exists) {
            console.log(`doc does not exist ${propertyID}`)
            return;
          }
          let photos = doc.data().photos;
          photos = photos || [];
          photos.push({
            big: photoURL,
            small: thumbURL,
          });
          t.update(propertyRef, { photos: photos });
        });
    });
  });

enter image description here enter image description here

Upvotes: 0

Views: 1174

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 599011

All standard code, it worked fine, i deployed on Feb 24th 2019.

Until a month or so ago Cloud Functions would get deactivated by the system if they'd been inactive for 30 days or more. This behavior has since been changed, since it was quite unintuitive to most developers. But you will need to redeploy your Cloud Functions once more to opt in to the new behavior.

Upvotes: 1

Related Questions