Google Cloud Functions image processing 图像处理需要几分钟

Google Cloud Functions image processing takes minutes for image processing

我正在使用云功能做什么:

  1. 正在将 url 下载到 /tmp 目录。
  2. 运行 转换为创建最大尺寸 (600*600) 的缩略图。
  3. 将其存储在 Firebase 存储中。
  4. 正在写回 Firebase 实时数据库。

整个操作需要将近 2-3 分钟,如果我并行执行 5-6 个函数,则只有 1-2 个完成。 这是代码。请让我知道在这方面可以做什么:

'use strict';

const functions = require('firebase-functions');
const gcs = require('@google-cloud/storage')();
//const exec = require('child-process-promise').exec;
const image_downloader = require('image-downloader');
const spawn = require('child-process-promise').spawn;
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

const LOCAL_TMP_FOLDER = '/tmp/';

// File extension for the created JPEG files.
const JPEG_EXTENSION = 'jpg';

const MAX_HEIGHT = 600;
const MAX_WIDTH = 600;
const bucket_name='-----------';
//const THUMB_SUFFIX = '_thumb';

exports.moderator = functions.database
    .ref('/users/{user_id}/photo_processing/{photo_processing_id}').onWrite(event => {
      const photo_data = event.data.val();
      if(!photo_data){
        return;
      }
      const user_id=event.params.user_id;
      const fileName=`${event.params.photo_processing_id}.jpg`;
      const fileLocation=`/tmp/${fileName}`;
      const modifiedfileName=`${event.params.user_id}_${fileName}`;
      const modifiedfileLocation=`/tmp/${modifiedfileName}`;

      console.log("fileName fileLocation modifiedfileName modifiedfileLocation",fileName,fileLocation,modifiedfileName,modifiedfileLocation);
      const options = {
          url: photo_data.source,
          dest: fileLocation,                  // Save to /path/to/dest/image.jpg
          done: function(err, filename, image) {
              if (err) {
                    console.log('error occured', err);
              }
              console.log('File saved to', filename);

        // Uploading the JPEG image.
         const bucket = gcs.bucket(bucket_name);
         const destinationUrl=`photos/${modifiedfileName}`;
         return spawn('convert', [fileLocation, '-thumbnail', `${MAX_WIDTH}x${MAX_HEIGHT}>`, modifiedfileLocation]).then(() => {
           console.log('Thumbnail created at', modifiedfileLocation);
            return bucket.upload(modifiedfileLocation, {
                destination: destinationUrl
                }).then(() => {
                console.log('JPEG image uploaded to Storage at',modifiedfileName );
                 return admin.database().ref(`/users/${user_id}/photos`).push(destinationUrl);
        });
      })
      }
    }
      image_downloader(options);

  });

我能够解决 this.Problem 是云函数应该 return 一个承诺,否则它们会表现得很奇怪。

这是可行的解决方案:

'use strict';

const functions = require('firebase-functions');
//const mkdirp = require('mkdirp-promise');
const gcs = require('@google-cloud/storage')();
//const exec = require('child-process-promise').exec;
const image_downloader = require('image-downloader');
const spawn = require('child-process-promise').spawn;
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

const LOCAL_TMP_FOLDER = '/tmp/';

// File extension for the created JPEG files.
const JPEG_EXTENSION = 'jpg';

const MAX_HEIGHT = 600;
const MAX_WIDTH = 600;
const bucket_name='--------';
//const THUMB_SUFFIX = '_thumb';

const fetch=(source,filename,fileLocation)=> new Promise((resolve,reject)=>{
  console.log("details passed to fetch method",source,filename,fileLocation);

  const options = {
      url: source,
      dest: fileLocation,                  // Save to /path/to/dest/image.jpg
      done: function(err, filename, image) {
          if (err) {
                reject(err);
                console.log('error occured', err);
          }
          resolve(filename);
          console.log('File saved to', filename);
        }
  }

    image_downloader(options);
});


exports.moderator = functions.database
    .ref('/users/{user_id}/photo_processing/{photo_processing_id}').onWrite(event => {
      const photo_data = event.data.val();
      if(!photo_data){
        return;
      }
      const user_id=event.params.user_id;
      //console.log("photo data came to the firebase funciotn",photo_data);
      //console.log('user_id passed', event.params.user_id);
      //console.log('photo_processing_id passed', event.params.photo_processing_id);
      const fileName=`${event.params.photo_processing_id}.jpg`;
      const fileLocation=`/tmp/${fileName}`;
      const modifiedfileName=`${event.params.user_id}_${fileName}`;
      const modifiedfileLocation=`/tmp/${modifiedfileName}`;
      const is_profile=photo_data.is_profile;
      const created_time=photo_data.created_time;
      console.log("fileName fileLocation modifiedfileName modifiedfileLocation",fileName,fileLocation,modifiedfileName,modifiedfileLocation);

      const bucket = gcs.bucket(bucket_name);
      const destinationUrl=`photos/${modifiedfileName}`;
      return fetch(photo_data.source,fileName,fileLocation).then(()=>
        {
          return spawn('convert', [fileLocation, '-thumbnail', `${MAX_WIDTH}x${MAX_HEIGHT}>`, modifiedfileLocation]).then(() =>
          {
            console.log('Thumbnail created at', modifiedfileLocation);
            return bucket.upload(modifiedfileLocation, {
             destination: destinationUrl
             }).then(() => {
                  console.log('JPEG image uploaded to Storage at',modifiedfileName );
                  const photo_data_to_save={url:destinationUrl,created_time};
                  if(is_profile){
                    photo_data_to_save.is_profile=true;
                  }
                   admin.database().ref(`/users/${user_id}/userData/photos`).push(photo_data_to_save);
                   return null;
                })

     });
   })
  });