# All files / src autoRetry.coffee

46.34% Statements 19/41
0% Branches 0/5
0% Functions 0/19
47.5% Lines 19/40

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    971x
    1x
    1x
    1x
    1x
    1x
    1x

    1x

    1x

    1x

    1x

    1x

    1x

    1x

    1x

    1x
    1x
    1x
    1x
     logger = require "winston"
    moment = require 'moment'
    Q = require 'q'
    Channels = require('./model/channels')
    Channel = Channels.Channel
    AutoRetry = require('./model/autoRetry').AutoRetry
    Task = require('./model/tasks').Task

    exports.reachedMaxAttempts = (tx, channel) ->
      return channel.autoRetryMaxAttempts? and
      channel.autoRetryMaxAttempts > 0 and
      tx.autoRetryAttempt >= channel.autoRetryMaxAttempts

    exports.queueForRetry = (tx) ->
      retry = new AutoRetry
        transactionID: tx._id
        channelID: tx.channelID
        requestTimestamp: tx.request.timestamp
      retry.save (err) ->
        if err
          logger.error "Failed to queue transaction #{tx._id} for auto retry: #{err}"

    getChannels = (callback) -> Channel.find autoRetryEnabled: true, status: 'enabled', callback

    popTransactions = (channel, callback) ->
      to = moment().subtract channel.autoRetryPeriodMinutes-1, 'minutes'

      query =
        $and: [
            channelID: channel._id
          ,
            'requestTimestamp':
              $lte: to.toDate()
        ]

      logger.debug "Executing query autoRetry.findAndRemove(#{JSON.stringify query})"
      AutoRetry.find query, (err, transactions) ->
        return callback err if err
        return callback null, [] if transactions.length is 0
        AutoRetry.remove _id: $in: (transactions.map (t) -> t._id), (err) ->
          return callback err if err
          callback null, transactions

    createRerunTask = (transactionIDs, callback) ->
      logger.info "Rerunning failed transactions: #{transactionIDs}"
      task = new Task
        transactions: (transactionIDs.map (t) -> tid: t )
        totalTransactions: transactionIDs.length
        remainingTransactions: transactionIDs.length
        user: 'internal'

      task.save (err) ->
        logger.error err if err
        callback()

    autoRetryTask = (job, done) ->
      _taskStart = new Date()
      transactionsToRerun = []

      getChannels (err, results) ->
        promises = []

        for channel in results
          do (channel) ->
            deferred = Q.defer()

            popTransactions channel, (err, results) ->
              if err
                logger.error err
              else if results? and results.length>0
                transactionsToRerun.push tid for tid in (results.map((r) -> r.transactionID))
              deferred.resolve()

            promises.push deferred.promise

        (Q.all promises).then ->
          end = ->
            logger.debug "Auto retry task total time: #{new Date()-_taskStart} ms"
            done()
          if transactionsToRerun.length > 0
            createRerunTask transactionsToRerun, end
          else end()

    setupAgenda = (agenda) ->
      agenda.define 'auto retry failed transactions', (job, done) -> autoRetryTask job, done
      agenda.every '1 minutes', 'auto retry failed transactions'

    exports.setupAgenda = setupAgenda

    if process.env.NODE_ENV is "test"
      exports.getChannels = getChannels
      exports.popTransactions = popTransactions
      exports.createRerunTask = createRerunTask
      exports.autoRetryTask = autoRetryTask