azure blob存储节点js v10-应用程序引发了未捕获的异常并被终止

时间:2019-04-19 08:38:35

标签: node.js azure azure-blob-storage

Env:

  • nodejs 10.15.2,表达为4.16.4
  • 使用Azure应用服务以及本地测试环境
  • 使用“ @ azure / storage-blob”:“ ^ 10.3.0”

我正在创建一个快速应用程序,以将blob上载/从azure blob存储下载。 一切正常:可以上传Blob,设置元数据,下载Blob等。 但是:当中止程序超时时,它们会引起意外的异常,从而终止节点进程。

错误堆栈为:

Fri Apr 19 2019 07:38:28 GMT+0000 (Greenwich Mean Time): Application has thrown an uncaught exception and is terminated:
Error: The request was aborted
    at new RestError (D:\home\site\wwwroot\node_modules\@azure\ms-rest-js\dist\msRest.node.js:1397:28)
    at a.<anonymous> (D:\home\site\wwwroot\node_modules\mql\node_modules\@azure\storage-blob\dist\index.js:1:11269)
    at D:\home\site\wwwroot\node_modules\mql\node_modules\@azure\storage-blob\dist\index.js:1:1277
    at Array.forEach (<anonymous>)
    at a.abort (D:\home\site\wwwroot\node_modules\mql\node_modules\@azure\storage-blob\dist\index.js:1:1255)
    at Timeout.<anonymous> (D:\home\site\wwwroot\node_modules\mql\node_modules\@azure\storage-blob\dist\index.js:1:519)
    at ontimeout (timers.js:436:11)
    at tryOnTimeout (timers.js:300:5)
    at unrefdHandle (timers.js:520:7)
    at Timer.processTimers (timers.js:222:12)

在我的本地dev-env中,我对未捕获的异常设置了一个断点,并发现:

  • 事件最终被引发到e​​vent.js中(发出)

  • 它是由RetriableReadableStream(@ azure / storage-blob / dist / esm / lib / utils / RetriableReadableStream)引起的,请参阅“ aborter.addEventListener”:

    function RetriableReadableStream(aborter, source, getter, offset, count, options) {
        if (options === void 0) { options = {}; }
        var _this = _super.call(this) || this;
        _this.retries = 0;
        _this.aborter = aborter;
        _this.getter = getter;
        _this.source = source;
        _this.start = offset;
        _this.offset = offset;
        _this.end = offset + count - 1;
        _this.maxRetryRequests =
            options.maxRetryRequests && options.maxRetryRequests >= 0
                ? options.maxRetryRequests
                : 0;
        _this.progress = options.progress;
        _this.options = options;
        aborter.addEventListener("abort", function () {
            _this.source.pause();
            _this.emit("error", new RestError("The request was aborted", RestError.REQUEST_ABORTED_ERROR));
        });
...
  • 这又是由堕胎者造成的:
    Aborter.prototype.abort = function () {
        var _this = this;
        if (this.aborted) {
            return;
        }
        this.cancelTimer();
        if (this.onabort) {
            this.onabort.call(this);
        }
        this.abortEventListeners.forEach(function (listener) {
            listener.call(_this);
        });
        this.children.forEach(function (child) { return child.cancelByParent(); });
        this._aborted = true;
    };

我的堕胎者是这样创建的:

    createAborter(): Aborter {
        let aborter = Aborter.timeout(5 * ONE_MINUTE);
        aborter.onabort = () => {
            console.warn(`AzureBlog.createAborter.onAbort: Request was aborted.`);
        }
        return aborter;
    }

...,我的下载内容如下:

    async download(blobName: string): Promise<NodeJS.ReadableStream> {
        const blockBlobURL = this.getBlockBlobUrl(blobName);
        const downloadResponse = await blockBlobURL.download(this.createAborter(), 0);
        if (!downloadResponse) {
            throw new Error(`Download returned undefined.`);
        }
        if (!downloadResponse.readableStreamBody) {
            throw new Error(`downloadResponse.readableStreamBody is undefined.`);
        }
        return downloadResponse.readableStreamBody;
    }

...,我像这样将其流式传输到客户端:

self.expressApp.route('/download')
    .get(jsonParser, async (req: Request, resp: Response) => {
      handleDownload(req, resp);
    }).post(jsonParser, async (req: Request, resp: Response) => {
      handleDownload(req, resp);
    });

    ...

      let blobReadStream = await self.azureBlobStore.download(id);
      blobReadStream.pipe(resp);

如上所述,一切正常,直到超时为止。我不明白的是:

  • 为什么有人在没有允许lib使用者抓住它的情况下在基础库中引发未捕获的错误? (顺便说一句,天蓝色的gremlin nodejs也有同样的问题)
  • 我的中止程序“ onAbort()”仅添加了另一个事件侦听器。我是否必须删除所有其他侦听器以防止该错误?
  • 为什么“中止”听众会被解雇?所有请求(下载,上游等)都可以在几秒钟内正常工作。在成功请求后,samples / docu并没有说明手动销毁/禁用中止程序。

我认为我误解了Aborter概念。因此,非常感谢您的帮助。

非常感谢!

0 个答案:

没有答案