1

What am I doing wrong? Why is the function timing out?

I have a blob triggered function which works totally fine:

const Jimp = require("jimp");

module.exports = function(context, myBlob) {
  const correlation = context.bindings.inputBlob.correlation;
  const inputImage = context.bindings.inputBlob.image;
  const imageName = context.bindings.inputBlob.imageName;

  context.log(
    correlation + "Attempting to convert this image to a tiff: " + imageName
  ); 
  Jimp.read(Buffer.from(inputImage, "base64"), function(err, image) {
    image.getBuffer(Jimp.MIME_TIFF, function(error, tiff) {
      const response = {
        myimage: tiff.toString("base64"),
        correlation: correlation
      };
      context.bindings.outputBlob = response
      context.log(
        correlation + "Successfully converted " + imageName + " to tiff."
      );
      context.done();
    });
  });
};

Here is the function.json file:

{
  "bindings": [
    {
      "name": "myBlob",
      "type": "blobTrigger",
      "direction": "in",
      "path": "images-in/{destination}/{name}",
      "connection": "AZURE_STORAGE_CONNECTION_STRING"
    },
    {
      "name": "inputBlob",
      "type": "blob",
      "direction": "in",
      "path": "images-in/{destination}/{name}",
      "connection": "AZURE_STORAGE_CONNECTION_STRING"
    },
    {
      "type": "blob",
      "name": "outputBlob",
      "path": "{destination}/{name}.tiff",
      "connection": "AZURE_STORAGE_CONNECTION_STRING",
      "direction": "out"
    }
  ],
  "disabled": false
}

The way it works:

  1. drop a blob into a specific location
  2. output blob will be generated by the function in another location (the whole process takes no longer than about 5 seconds).

I decided that I needed the function to be http-triggered, so I made the following changes:

const Jimp = require("jimp");

module.exports = function(context, req) {

  Jimp.read(Buffer.from(req.body, "base64"), function(err, image) {
    image.getBuffer(Jimp.MIME_TIFF, function(error, tiff) {
      const response = {
        myimage: tiff.toString("base64"),
        correlation: "yeeeeees"
      };


    });
      context.res = {
          body: response
      };
      context.done();
  });


};

function.json:

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}

However, I am getting a 500:

enter image description here

The telemetry is showing the following:

enter image description here

What am I doing wrong? Why is the function timing out?

I've made the following update to the function:

const Jimp = require("jimp");

module.exports = function (context, req) {
    const text = Buffer.from(req.body, "base64").toString("utf-8");

    Jimp.read(text, function(err, image) {
    if (err) {
      context.res = {
        body: err
      };
      context.done();
    }

    image.getBuffer(Jimp.MIME_TIFF, function(error, tiff) {
      if (error) {
        context.res = {
          body: error
        };
        context.done();
      }
      const response = {
        myimage: tiff.toString("base64"),
        correlation: "yeeeeees"
      };
      context.res = {
        body: response
      };
      context.done();
    });
  });
};

This yielded the following nonsensical response:

{
  "errno": -4058,
  "code": "ENOENT",
  "syscall": "open",
  "path": "D:\\home\\site\\wwwroot\\$R\u0005������{\u001av��r��Ū�O�$z�ނ)",
  "methodName": "constructor"
}
Alex Gordon
  • 57,446
  • 287
  • 670
  • 1,062
  • You're second code has an invalid reference to `response` (out of scope) and you are calling `done` too soon. Should be placed in the inner callback (which is executed later). Possibly this is not the correct representation of your code? – trincot Dec 15 '19 at 10:52
  • thanks! i've attempted to use the code from the answer below, however, i'm still getting timeouts – Alex Gordon Dec 15 '19 at 11:40

1 Answers1

2

If you check your node.js logs in Azure, you would see an error like response is not defined because your scope where you defined response is different then where you used.

So basically you are not able to call context.done(); function and that is why your request throwing timeout exception.

Using async/await will help you to not have this kind of problems. Please check this code example to understand what could go wrong.

const Jimp = require("jimp");

module.exports = function(context, req) {

  Jimp.read(Buffer.from(req.body, "base64"), function(err, image) {

    if(err){
      context.res = {
          body: err
      };
      context.done();
    }

    image.getBuffer(Jimp.MIME_TIFF, function(error, tiff) {
      if(error){
        context.res = {
          body: error
        };
        context.done();
      }
      const response = {
        myimage: tiff.toString("base64"),
        correlation: "yeeeeees"
      };
      context.res = {
        body: response 
      };
      context.done();
    });
  });
};
hurricane
  • 6,521
  • 2
  • 34
  • 44