防止Azure函数递归执行

问题描述 投票:0回答:1

我创建了一个由 EventGrid 订阅事件触发的 Azure 函数,当新的 Blob 上传到 Blob 存储时会触发该事件。

我正在使用此功能来调整上传的图像的大小,它将调整大小的图像上传到same容器

问题是该函数将触发新的上传事件,该事件是在函数本身内部完成的,因此它将再次执行。原始图像和调整大小的图像应该存储在同一个容器中,所以我无法阻止这种情况,只是根据容器名称过滤事件订阅。

EventGrid 订阅有一个用于高级过滤的部分,在本节中我们可以根据有效负载中的

data
对象过滤事件,这将是一个好主意,但我找不到在
 中放置任何自定义字段的方法从 azure 函数上传调整大小的图像时的 data
对象,以便我可以基于该对象过滤事件。

功能实现:

const stream = require('stream');
const Jimp = require('jimp');

const {
  Aborter,
  BlobServiceClient,
  StorageSharedKeyCredential,
} = require("@azure/storage-blob");

const ONE_MEGABYTE = 1024 * 1024;
const uploadOptions = { bufferSize: 4 * ONE_MEGABYTE, maxBuffers: 20 };

// const containerName = process.env.BLOB_CONTAINER_NAME;
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
const accessKey = process.env.AZURE_STORAGE_ACCOUNT_ACCESS_KEY;

const sharedKeyCredential = new StorageSharedKeyCredential(
  accountName,
  accessKey);
const blobServiceClient = new BlobServiceClient(
  `https://${accountName}.blob.core.windows.net`,
  sharedKeyCredential
);

module.exports = async (context, event, inputBlob) => {  
  context.log(`Function started`);
  context.log(`event: ${JSON.stringify(event)}`);

  const widthInPixels = 100;
  const blobUrl = context.bindingData.data.url;
  const blobUrlArray = blobUrl.split("/");
  const blobFileName = blobUrlArray[blobUrlArray.length - 1];
  const blobExt = blobFileName.slice(blobFileName.lastIndexOf(".") + 1);
  const blobName = blobFileName.slice(0, blobFileName.lastIndexOf("."));
  const blobName_thumb = `${blobName}_t.${blobExt}`;

  const containerName = blobUrlArray[blobUrlArray.length - 2];

  const image = await Jimp.read(inputBlob);
  const thumbnail = image.resize(widthInPixels, Jimp.AUTO);
  const thumbnailBuffer = await thumbnail.getBufferAsync(Jimp.AUTO);
  const readStream = stream.PassThrough();
  readStream.end(thumbnailBuffer);

  const containerClient = blobServiceClient.getContainerClient(containerName);
  const blockBlobClient = containerClient.getBlockBlobClient(blobName_thumb);
  context.log(`blockBlobClient created`);
  try {
      await blockBlobClient.uploadStream(readStream,
            uploadOptions.bufferSize,
            uploadOptions.maxBuffers,
            { blobHTTPHeaders: { blobContentType: "image/jpeg" } });
      context.log(`File uploaded`);
  } catch (err) {

    context.log(err.message);

  } finally {

    context.done();

  }
};

绑定:

{
  "bindings": [
    {
      "name": "event",
      "direction": "in",
      "type": "eventGridTrigger"
    },
    {
      "name": "inputBlob",
      "direction": "in",
      "type": "blob",
      "path": "{data.url}",
      "connection": "AzureWebJobsStorage",
      "dataType": "binary"
    }
  ]
}

这是使用 Azure 函数触发 blob 存储事件时的一个非常基本的问题,而且很奇怪,我在庞大的 azure 文档中找不到这方面的正确描述!

node.js azure azure-functions azure-blob-storage azure-eventgrid
1个回答
0
投票

EventGrid Subscription 有一个高级过滤的部分,在本节中,我们可以根据有效负载中的数据对象过滤事件,这将是一个好主意,但我找不到一种方法来将任何自定义字段放入数据对象中从 azure 函数上传调整大小的图像,以便我可以根据该图像过滤事件。

正确的,您不能在数据对象中放置任何内容,因为您无法控制事件的创建。这当然是因为该事件是由 Azure 平台生成的。

这给你留下了两个选择。要么使用上传文件的暂存容器,并让函数调整文件大小并将它们放入最终容器中,要么创建一种机制,防止处理新创建的缩略图。

也许在你的函数中你可以检查 blob 的名称,如果它是缩略图,它们就会结束处理。或者在缩略图 blob 中包含元数据,并在执行时检查元数据是否存在,并且仅当未设置元数据时,才执行调整大小逻辑。

© www.soinside.com 2019 - 2024. All rights reserved.