UNPKG

2.9 kBtext/coffeescriptView Raw
1async = require 'async'
2GoogleAPIAdminSDK = require "#{__dirname}/google_api_admin_sdk"
3url = require 'url'
4quest = require 'quest'
5MailParser = (require 'mailparser').MailParser
6http_parser = require 'http-string-parser'
7_ = require 'underscore'
8retry = require 'retry'
9
10class Batch
11 constructor: (google_opts) ->
12 @queries = []
13 @google_api = new GoogleAPIAdminSDK google_opts
14
15 go: (queries, cb) ->
16 return cb null, [] if queries.length is 0
17
18 async.waterfall [
19 (cb_wf) =>
20 @google_api.tokeninfo (err, result) =>
21 if err?
22 @google_api.request_refresh_token cb_wf
23 else
24 cb_wf null, null
25 (dontcare, cb_wf) =>
26 boundary = '===============7330845974216740156=='
27 request_body = _.map(queries, (query) ->
28 pathname = (url.parse query._opts.uri).pathname
29 method = query._opts.method?.toUpperCase() ? "GET"
30 body = "\n--#{boundary}\nContent-Type: application/http\n\n#{method} #{pathname} HTTP/1.1"
31 if (query._opts.json? and query._opts.json isnt true)
32 content_body = JSON.stringify query._opts.json
33 body += "\nContent-Type: application/json"
34 body += "\ncontent-length: #{content_body.length}"
35 body += "\n\n#{content_body}"
36 body
37 ).join('') + "\n--#{boundary}--"
38
39 options =
40 method: 'post'
41 uri: "https://www.googleapis.com/batch"
42 body: request_body
43 headers:
44 Authorization: "Bearer #{@google_api.options.token.access}"
45 'content-type': "multipart/mixed; boundary=\"#{boundary}\""
46
47 operation = retry.operation { maxTimeout: 3 * 60 * 1000, retries: 15 }
48 operation.attempt ->
49 quest options, (err, res, body) ->
50 return null if res.statusCode is 503 and operation.retry(new Error(""))
51 cb_wf err, res, body
52 (res, body, cb_wf) =>
53 unless res.statusCode is 200
54 return cb_wf new Error "Batch API responded with code #{res.statusCode}"
55
56 # It is unlikely the above retry logic will work since it would mean the entire batch
57 # request failed to go through.
58 # What is more likely to happen is that individual requests within the batch could fail.
59 # And so what is returned to the cb of Batch.go is an array of responses.
60 mail_parser = new MailParser()
61 mail_parser.end "Content-type: #{res.headers['content-type']}\r\n\r\n#{body}"
62 mail_parser.on 'end', (mail) ->
63 cb_wf null, _(mail.attachments).map (result) ->
64 parsed_response = http_parser.parseResponse result.content.toString()
65 parsed_response.body = JSON.parse parsed_response.body if parsed_response.body
66 parsed_response.statusCode = +parsed_response.statusCode
67 parsed_response
68 ], cb
69
70module.exports = Batch