All files retrycf.ts

93.22% Statements 55/59
94.74% Branches 36/38
93.33% Functions 14/15
98.08% Lines 51/52
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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120  1x 5x 5x   10x 5x     1x 1x   1x           1x 1x 1x 1x             1x   1x   1x   1x   1x 4x 4x 4x 1x   4x 4x 4x               4x 4x 4x 4x           1x 22x 3x   19x 4x   15x 4x   11x                 1x 11x 11x 11x 5x   6x 1x   5x 2x 1x     1x     3x           1x 1x 1x                            
import * as functions from 'firebase-functions'
import * as FirebaseFirestore from '@google-cloud/firestore'
 
let _firestore: FirebaseFirestore.Firestore
let _maxRetryCount: number = 2
 
/**
 * Initialize in your index.ts.
 * @param adminOptions functions.config().firebase
 * @param options maxRetryCount
 */
export const initialize = (adminOptions: any, options?: { maxRetryCount: number }) => {
  _firestore = new FirebaseFirestore.Firestore(adminOptions)
  if (options) {
    _maxRetryCount = options.maxRetryCount
  }
}
 
/**
 * Retrycf.Status
 */E
export enum Status {
  /** should not retry */
  ShouldNotRetry = 'ShouldNotRetry',
  /** should retry */
  ShouldRetry = 'ShouldRetry',
  /** retry failed */
  RetryFailed = 'RetryFailed'
}
 
/**
 * Parameters to be saved by setRetry()
 */
export interface IRetry {
  /** retry count */
  count: number
  /** Record retry reason */
  errors: { createdAt: Date, error: any, stack: string }[]
}
 
const makeRetry = (data: any, error: Error): IRetry => {
  const currentError = { createdAt: new Date(), error: error.toString(), stack: error.stack || '' }
  let retry = { count: 0, errors: new Array() }
  if (data.retry && data.retry.count) {
    retry = data.retry
  }
 
  retry.count += 1
  retry.errors.push(currentError)
  return retry
}
 
/**
 * save retry parameters.
 * @param ref event.data.ref
 * @param data event.data.data()
 * @param error Error
 */
export const setRetry = async (ref: FirebaseFirestore.DocumentReference, data: any, error: Error): Promise<IRetry> => {
  const retry = makeRetry(data, error)
  await ref.update({ retry: retry })
  return retry
}
 
/**
 * Get retry count from data
 * @param data event.data.data()
 */
const getRetryCount = (data?: any) => {
  if (data === undefined) {
    return undefined
  }
  if (data.retry === undefined) {
    return undefined
  }
  if (data.retry.count === undefined) {
    return undefined
  }
  return data.retry.count
}
 
/**
 * If retry.count is increasing from previousData, it returns ShouldRetry.
 * If retry.count is increased from previousData and it exceeds max retry count, RetryFailed is returned.
 * @param data event.data.data()
 * @param previousData event.data.previous.data()
 * @param maxRetryCount optional. If you change maxRetryCount, set number.
 */
export const retryStatus = (data: any, previousData: any, maxRetryCount: number = _maxRetryCount): Status => {
  const currentCount: number | undefined = getRetryCount(data)
  const previousCount: number | undefined = getRetryCount(previousData)
 
  if (currentCount === undefined) {
    return Status.ShouldNotRetry
  }
 
  if (previousCount === undefined && currentCount === 1) {
    return Status.ShouldRetry
  }
 
  if (previousCount !== undefined && currentCount === previousCount + 1) {
    if (currentCount > maxRetryCount) {
      return Status.RetryFailed
    } else {
      return Status.ShouldRetry
    }
  }
 
  return Status.ShouldNotRetry
}
 
/**
 * update retry to {}.
 * @param ref event.data.ref
 */
export const clear = async (ref: FirebaseFirestore.DocumentReference) => {
  await ref.update({ retry: {} })
  return {}
}