1 | import { create as createLogger } from '../common/log'
|
2 | const log = createLogger('alert-middleware')
|
3 | import { Middleware, MiddlewareCallback, Pipelines } from '../types/middleware'
|
4 | import * as IlpPacket from 'ilp-packet'
|
5 |
|
6 | const { T04_INSUFFICIENT_LIQUIDITY } = IlpPacket.Errors.codes
|
7 |
|
8 | export interface Alert {
|
9 | id: number
|
10 | accountId: string
|
11 | triggeredBy: string
|
12 | message: string
|
13 | count: number
|
14 | createdAt: Date
|
15 | updatedAt: Date
|
16 | }
|
17 |
|
18 | export default class AlertMiddleware implements Middleware {
|
19 | private alerts: {[id: number]: Alert} = {}
|
20 | private nextAlertId: number = Date.now()
|
21 |
|
22 | async applyToPipelines (pipelines: Pipelines, accountId: string) {
|
23 | pipelines.outgoingData.insertLast({
|
24 | name: 'alert',
|
25 | method: async (data: Buffer, next: MiddlewareCallback<Buffer, Buffer>) => {
|
26 | const result = await next(data)
|
27 | if (result[0] !== IlpPacket.Type.TYPE_ILP_REJECT) return result
|
28 |
|
29 | const rejectPacket = IlpPacket.deserializeIlpReject(result)
|
30 | if (rejectPacket.code !== T04_INSUFFICIENT_LIQUIDITY) return result
|
31 |
|
32 |
|
33 |
|
34 |
|
35 | if (rejectPacket.message !== 'exceeded maximum balance.') return result
|
36 |
|
37 | const { triggeredBy } = rejectPacket
|
38 | log.warn('generating alert for account=%s triggeredBy=%s message="%s"', accountId, triggeredBy, rejectPacket.message)
|
39 | this.addAlert(accountId, triggeredBy, rejectPacket.message)
|
40 |
|
41 | return result
|
42 | }
|
43 | })
|
44 | }
|
45 |
|
46 | getAlerts (): Alert[] {
|
47 | return Object.keys(this.alerts)
|
48 | .map((id) => this.alerts[id])
|
49 | .sort((a, b) => a.id - b.id)
|
50 | }
|
51 |
|
52 | dismissAlert (id: number) {
|
53 | delete this.alerts[id]
|
54 | }
|
55 |
|
56 | private addAlert (accountId: string, triggeredBy: string, message: string) {
|
57 | const alert = Object.keys(this.alerts)
|
58 | .map((alertId) => this.alerts[alertId])
|
59 | .find((alert) =>
|
60 | alert.accountId === accountId &&
|
61 | alert.triggeredBy === triggeredBy &&
|
62 | alert.message === message)
|
63 | if (alert) {
|
64 | alert.count++
|
65 | alert.updatedAt = new Date()
|
66 | return
|
67 | }
|
68 |
|
69 | const id = this.nextAlertId++
|
70 | const now = new Date()
|
71 | this.alerts[id] = {
|
72 | id,
|
73 | accountId,
|
74 | triggeredBy,
|
75 | message,
|
76 | count: 1,
|
77 | createdAt: now,
|
78 | updatedAt: now
|
79 | }
|
80 | }
|
81 | }
|