فهرست منبع

uristream can now retry failed streams

Gil Pedersen 13 سال پیش
والد
کامیت
813a6b150a
1فایلهای تغییر یافته به همراه23 افزوده شده و 9 حذف شده
  1. 23 9
      lib/uristream.js

+ 23 - 9
lib/uristream.js

@@ -49,6 +49,9 @@ function setupHttp(uri, options, dst) {
   var tries = 10;
   var tries = 10;
   var fetch = probe ? request.head : request.get;
   var fetch = probe ? request.head : request.get;
 
 
+  // attach empty 'error' listener to keep dst from ever throwing
+  dst.on('error', noop);
+
   function fetchHttp(start) {
   function fetchHttp(start) {
     if (start > 0)
     if (start > 0)
       headers['range'] = 'bytes=' + start + '-';
       headers['range'] = 'bytes=' + start + '-';
@@ -61,12 +64,22 @@ function setupHttp(uri, options, dst) {
     req.on('error', noop);
     req.on('error', noop);
     req.on('response', onresponse);
     req.on('response', onresponse);
 
 
+    var failed = false;
     function failOrRetry(err, temporary) {
     function failOrRetry(err, temporary) {
+      if (failed) return;
+      failed = true;
+
       req.abort();
       req.abort();
-      // remap error to partial error if we have received any data
-      if (start + accum !== 0)
-        err = new PartialError(err, start - offset + accum, (size !== -1) ? start - offset + size : size);
-      return dst.emit('error', err);
+      if (--tries <= 0) {
+        // remap error to partial error if we have received any data
+        if (start + accum !== 0)
+          err = new PartialError(err, start - offset + accum, (size !== -1) ? start - offset + size : size);
+        return dst.emit('error', err);
+      }
+      debug('retrying at ' + (start + accum));
+
+      // TODO: delay retry?
+      fetchHttp(start + accum);
     }
     }
 
 
     function reqcleanup() {
     function reqcleanup() {
@@ -104,14 +117,18 @@ function setupHttp(uri, options, dst) {
       oncemore(stream).once('end', 'error', function(err) {
       oncemore(stream).once('end', 'error', function(err) {
         dst._read = noop;
         dst._read = noop;
         if (err) return failOrRetry(err);
         if (err) return failOrRetry(err);
-        dst.push(null);
+        if (!failed)
+          dst.push(null);
       });
       });
       dst._read = function(n) {
       dst._read = function(n) {
         stream.resume();
         stream.resume();
       };
       };
 
 
       // allow aborting the request
       // allow aborting the request
-      dst.abort = req.abort.bind(req);
+      dst.abort = function() {
+        tries = 0;
+        req.abort();
+      }
 
 
       // forward all future errors to response stream
       // forward all future errors to response stream
       req.on('error', function(err) {
       req.on('error', function(err) {
@@ -133,9 +150,6 @@ function setupHttp(uri, options, dst) {
         });
         });
       }
       }
 
 
-      // attach empty 'error' listener to keep it from ever throwing
-      dst.on('error', noop);
-
       if (!dst.meta) {
       if (!dst.meta) {
         // extract meta information from header
         // extract meta information from header
         var typeparts = /^(.+?\/.+?)(?:;\w*.*)?$/.exec(res.headers['content-type']) || [null, 'application/octet-stream'],
         var typeparts = /^(.+?\/.+?)(?:;\w*.*)?$/.exec(res.headers['content-type']) || [null, 'application/octet-stream'],