mixmaxhq/batchelor

Updated to latest, getting error parsing batch response from gmail

Closed this issue · 4 comments

Hey guys, I just switched to latest to get the concurrency fix, but getting this:

/server/auth/node_modules/batchelor/lib/batchelor.js:167
boundary = boundaryRegex.exec(responseObj.headers['content-type'])[2],
^
TypeError: Cannot read property '2' of null
at Request. (/server/auth/node_modules/batchelor/lib/batchelor.js:167:73)
at Request.emit (events.js:107:17)
at Request.onRequestResponse (/server/auth/node_modules/request/request.js:1139:10)
at ClientRequest.emit (events.js:107:17)
at HTTPParser.parserOnIncomingClient as onIncoming
at HTTPParser.parserOnHeadersComplete (_http_common.js:111:23)
at TLSSocket.socketOnData (_http_client.js:310:20)
at TLSSocket.emit (events.js:107:17)
at readableAddChunk (_stream_readable.js:163:16)
at TLSSocket.Readable.push (_stream_readable.js:126:10)

I have verfied the content-type header is present and valid. If I switch back to older version of Batchelor and make same request, it parses fine.

Can you show me an example of code please. Show me your initialise code and where you add requests. (remove any sensitive info)

Hey James! Here is how I'm calling Batchelor. Basically working through a
list of email message IDs, sending message detail requests off to gmail in
batches of 100. I am using the async module to control
synchronous/asynchronous behavior of node.

var batch = new Batchelor ({

// Batchelor.init({
'uri':'https://www.googleapis.com/batch',
'method':'POST',
'auth': {
'bearer': token
},
'headers': {
'Content-Type': 'multipart/mixed;'
}
});

//Need to break this up into multiple batches of 100
var path = '';
var batchReqCount = 0;
var batchCount = 0;
var batchRequests = [];
user.batch = batch;
async.eachSeries(user.messageList,function(message, callback) {
       //add request to current batch
       path =

'/gmail/v1/users/'+user.email_address+'/messages/'+message.id +
'?format=raw';
console.log(path);
user.batch.add({
'method':'GET',
'path':path,
'callback': function(response){
//console.log('Gmail GET response: ',response);
user.messages.push(response);
}
});

       batchReqCount++;
       if (batchReqCount == config.inbox_sync.batch_size) {
           //time to send this off
           batchCount++;
           console.log('Sending batch ', batchCount, ' of ',

config.inbox_sync.batch_size, ' requests to gmail for: ',
user.email_address);
user.batch.run(function(response){
console.log('received batch response for:
',user.email_address);
user.batch.reset();
batchRequests = [];
batchReqCount = 0;
saveMsgs( user, function (err) {
if (err) {
console.log('saveMsgs returned error:',
err, ' for ',user.email_address);
callback(err);
return;
}
console.log('Retrieved ',
config.inbox_sync.batch_size, 'new messages from Gmail and Stored in
DB for: ',
user.email_address);
//update label message counts
labelDB.updateLabelMsgCounts(user.id,function(err) {
if (err) {
console.error('updateLabelMsgCounts
returned error:',err)
callback(err);
return;
}
console.log('updateLabelMsgCounts: COMPLETE');
callback();
});
});
});
}
else
callback();
},
function(err) {
if (err) {
console.error('Error occured: ', err);
return;
}

       //sendoff final batch
       if (batchReqCount > 0 ) {
           console.log('Sending Final batch of ',  batchReqCount,

' requests to gmail...');
user.batch.run(function(response){
console.log('received batch response for:',
user.email_address);
saveMsgs(user, function () {
console.log('batchProcessing: COMPLETE for
',user.email_address);
batch_cb();
});
});
}
else {
console.log('batchProcessing: COMPLETE for
',user.email_address);
batch_cb();
}
});

I was starting to think my issue was related to :

https://github.com/caolan/async#binding-a-context-to-an-iterator

but am not getting any obvious null access errors or the like. The
code where the parse is failing -

// Get the boundary
var boundaryRegex = /^multipart/.+?(?:;
boundary=(?:(?:"(.+)")|(?:([^\s]+))))$/i,
boundary = boundaryRegex.exec(responseObj.headers['content-type'])[2],
responseBody = { 'parts': [], 'errors': 0 };

in batchelor.js is identical between older and latest versions of batchelor
so not sure whats up.

Thanks for any help you can provide
Brian

On Tue, Apr 7, 2015 at 3:39 AM, James Haley notifications@github.com
wrote:

Can you show me an example of code please. Show me your initialise code
and where you add requests. (remove any sensitive info)


Reply to this email directly or view it on GitHub
#10 (comment).

FYI, I just replaced the async code with user.messageList.foreach() to
eliminate potential cause but getting same result.

On Tue, Apr 7, 2015 at 5:38 AM, Brian Fernandes brian@codeq.com wrote:

Hey James! Here is how I'm calling Batchelor. Basically working through a
list of email message IDs, sending message detail requests off to gmail in
batches of 100. I am using the async module to control
synchronous/asynchronous behavior of node.

var batch = new Batchelor ({

// Batchelor.init({
'uri':'https://www.googleapis.com/batch',
'method':'POST',
'auth': {
'bearer': token
},
'headers': {
'Content-Type': 'multipart/mixed;'
}
});

//Need to break this up into multiple batches of 100
var path = '';
var batchReqCount = 0;
var batchCount = 0;
var batchRequests = [];
user.batch = batch;
async.eachSeries(user.messageList,function(message, callback) {
       //add request to current batch
       path = '/gmail/v1/users/'+user.email_address+'/messages/'+message.id + '?format=raw';
        console.log(path);
        user.batch.add({
           'method':'GET',
           'path':path,
           'callback': function(response){
               //console.log('Gmail GET response: ',response);
               user.messages.push(response);
           }
       });

       batchReqCount++;
       if (batchReqCount == config.inbox_sync.batch_size) {
           //time to send this off
           batchCount++;
           console.log('Sending batch ', batchCount, ' of ',   config.inbox_sync.batch_size, ' requests to gmail for: ', user.email_address);
           user.batch.run(function(response){
               console.log('received batch response for: ',user.email_address);
               user.batch.reset();
               batchRequests = [];
               batchReqCount = 0;
               saveMsgs( user, function (err) {
                       if (err) {
                           console.log('saveMsgs returned error:', err, ' for ',user.email_address);
                           callback(err);
                           return;
                       }
                   console.log('Retrieved ', config.inbox_sync.batch_size, 'new messages from Gmail and Stored in DB for: ',
                   user.email_address);
                   //update label message counts
                   labelDB.updateLabelMsgCounts(user.id,function(err) {
                       if (err) {
                           console.error('updateLabelMsgCounts returned error:',err)
                           callback(err);
                           return;
                       }
                       console.log('updateLabelMsgCounts: COMPLETE');
                       callback();
                   });
               });
           });
       }
       else
        callback();
    },
    function(err) {
       if (err) {
           console.error('Error occured: ', err);
            return;
       }

       //sendoff final batch
       if (batchReqCount > 0 ) {
           console.log('Sending Final batch of ',  batchReqCount, ' requests to gmail...');
           user.batch.run(function(response){
               console.log('received batch response for:', user.email_address);
               saveMsgs(user, function () {
                   console.log('batchProcessing: COMPLETE for ',user.email_address);
                   batch_cb();
               });
            });
       }
       else {
            console.log('batchProcessing: COMPLETE for ',user.email_address);
            batch_cb();
        }
   });

I was starting to think my issue was related to :

https://github.com/caolan/async#binding-a-context-to-an-iterator

but am not getting any obvious null access errors or the like. The code where the parse is failing -

// Get the boundary
var boundaryRegex = /^multipart/.+?(?:; boundary=(?:(?:"(.+)")|(?:([^\s]+))))$/i,
boundary = boundaryRegex.exec(responseObj.headers['content-type'])[2],
responseBody = { 'parts': [], 'errors': 0 };

in batchelor.js is identical between older and latest versions of
batchelor so not sure whats up.

Thanks for any help you can provide
Brian

On Tue, Apr 7, 2015 at 3:39 AM, James Haley notifications@github.com
wrote:

Can you show me an example of code please. Show me your initialise code
and where you add requests. (remove any sensitive info)


Reply to this email directly or view it on GitHub
#10 (comment).

The issue relates to pull request #9. Request adds a semi-colon after the content-type header. Remove this from your code and all should be find.