Nodejs 16 Google Cloud Function导致间歇性的“截断响应体”,

3pvhb19x  于 2023-06-22  发布在  Node.js
关注(0)|答案(1)|浏览(161)

我有一个QR码onRequest谷歌云函数,运行在第二代。我正在使用qrcode package生成简单的QR码,就像你在这里看到的一样。

第二代GCF能够处理大量的呼叫。然而,虽然大多数QR码返回到调用程序,但许多QR码返回为黑色正方形,而不是QR码,然后在GCF日志中,我看到以下消息:
截断响应体。通常意味着请求超时或应用程序在响应完成之前退出。
正如你在下面的代码中所看到的,我有一个示例总是在运行,有足够的处理能力,并且应该没有超时问题来动态生成这些超级简单的QR码png。
在1,000个调用中,只有大约5%的结果是黑色方块和Truncated response消息。
我想知道我是否有某种承诺的问题,而不是等待'ing适当?也想知道,是什么产生了这个截断消息?GCF跟踪没有给予更多细节。
注意:发送到QR码中编码的数据始终是相同的格式,即int。

GCF的qrCode.ts脚本

import { onRequest } from 'firebase-functions/v2/https'
import { logger } from 'firebase-functions/v2'

import QRCode from 'qrcode'
import express from 'express'
import cors from 'cors'
import { kDebug } from './lib/constants'
import { normalizedSku } from './lib/helperFunctions'

const app = express()

// Automatically allow cross-origin requests
app.use(cors({ origin: true }))
// Support json encoded bodies and url encoded bodies
app.use(express.urlencoded({ extended: true }))

// Save the qrcode to memory in GCF and return as a file
const filepath = '/tmp/qrcode.png'

/**
 * Save the QR code to file.
 * @param {string} qrCodePlainText The plain text that makes up QR code.
 * @param {unknown} options The QR code package options.
 * @return {boolean} Whether the QR code was saved to file.
 */
async function saveQrCodeToFile(qrCodePlainText: string, options: unknown): Promise<boolean> {
  try {
    await QRCode.toFile(filepath, qrCodePlainText, options)
    return true
  } catch (error) {
    logger.error(error)
    return false
  }
}

/**
 * QR Code image generator. The value in GET will be decoded and set as the plain text in the
 * generated qr code, which is returned as a png.
 *
 * https://github.com/soldair/node-qrcode
 */
app.get('/qrCode/:data', async (req, res) => {
  let qrCodeData = req.params.data
  // Inches, e.g. a value of 1 will result in a 1"x1" qrcode. The max is 10.
  const inchesParam = req.query.inches
  const returnToDataUrl = req.query.returnToDataUrl === 'true'
  const isSku = req.query.isSku === 'true'

  try {
    if (kDebug) {
      logger.info('req.params', req.params)
      logger.info('req.query', req.query)
    }

    if (!qrCodeData) {
      throw Error('Missing QR Code data param')
    }

    if (!inchesParam) {
      throw Error('Missing inches param')
    }

    // Will return NaN if not a number
    const inches = parseFloat(inchesParam as string)

    if (isNaN(inches)) {
      throw Error(`${inchesParam} is not a number`)
    }

    if (kDebug) {
      logger.info(`QR Code dimensions: ${inches}"x${inches}"`)
    }

    if (inches > 10) {
      throw Error('Inches param cannot be greater than 10')
    }

    // If this is a sku then normalize the data
    if (isSku) {
      qrCodeData = normalizedSku(qrCodeData)
    }

    const options = {
      margin: 2,
    }

    // Convert inches to pixels for digital devices. 1" = 96px
    options['width'] = Math.round(inches * 96)

    if (kDebug) {
      logger.info(options)
    }

    const qrCodePlainText = decodeURIComponent(qrCodeData)

    if (returnToDataUrl) {
      res.send(await QRCode.toDataURL(qrCodePlainText))
      return
    } else {
      if (!(await saveQrCodeToFile(qrCodePlainText, options))) {
        throw Error(`QR code failed for ${qrCodeData}.`)
      }
      res.sendFile(filepath)
    }
  } catch (e) {
    if (kDebug) {
      logger.error(e)
    }

    res.status(400).send(e.toString())
  }
})

exports.endpoint = onRequest(
  { timeoutSeconds: 60, region: ['us-east4'], memory: '2GiB', minInstances: 1 },
  app,
)
ecbunoof

ecbunoof1#

toFile不返回promise。它使用了一个回调API,并且您没有指定回调,因此您的代码会继续尝试在完成写入之前发送文件。

相关问题