1 2
import reduct, { Injector } from 'reduct'
2 2
import { create as createLogger } from './common/log'
3 2
const log = createLogger('app')
4

5 2
import Config from './services/config'
6 2
import RouteBroadcaster from './services/route-broadcaster'
7 2
import Accounts from './services/accounts'
8 2
import RateBackend from './services/rate-backend'
9 2
import MiddlewareManager from './services/middleware-manager'
10 2
import AdminApi from './services/admin-api'
11 2
import * as Prometheus from 'prom-client'
12

13 2
const version = require('../package.json').version
14

15 2
const listen = (
16
  config: Config,
17
  accounts: Accounts,
18
  backend: RateBackend,
19
  routeBroadcaster: RouteBroadcaster,
20
  middlewareManager: MiddlewareManager,
21
  adminApi: AdminApi
22 2
) => () => {
23
  // Start a coroutine that connects to the backend and
24
  // subscribes to all the accounts in the background
25 0
  return (async function () {
26 0
    adminApi.listen()
27

28 0
    try {
29 0
      await backend.connect()
30
    } catch (error) {
31 0
      log.error(error)
32 0
      process.exit(1)
33
    }
34

35 0
    await middlewareManager.setup()
36

37
    // If we have no configured ILP address, try to get one via ILDCP
38 0
    await accounts.loadIlpAddress()
39

40 2
    if (config.routeBroadcastEnabled) {
41 0
      routeBroadcaster.start()
42
    }
43

44
    // Connect other plugins, give up after initialConnectTimeout
45 0
    await new Promise((resolve, reject) => {
46 0
      const connectTimeout = setTimeout(() => {
47 0
        log.warn('one or more accounts failed to connect within the time limit, continuing anyway.')
48 0
        resolve()
49
      }, config.initialConnectTimeout)
50 0
      accounts.connect({ timeout: config.initialConnectTimeout })
51
        .then(() => {
52 0
          clearTimeout(connectTimeout)
53 0
          resolve()
54
        }, reject)
55
    })
56

57 0
    await middlewareManager.startup()
58

59 2
    if (config.collectDefaultMetrics) {
60 0
      Prometheus.collectDefaultMetrics()
61
    }
62

63 0
    log.info('connector ready (republic attitude). address=%s version=%s', accounts.getOwnAddress(), version)
64 0
  })().catch((err) => log.error(err))
65
}
66

67 2
const addPlugin = (
68
  accounts: Accounts,
69
  routeBroadcaster: RouteBroadcaster,
70
  middlewareManager: MiddlewareManager
71 2
) => async (
72
  id: string,
73
  options: any
74
) => {
75 2
  accounts.add(id, options)
76 2
  const plugin = accounts.getPlugin(id)
77 2
  await middlewareManager.addPlugin(id, plugin)
78

79 2
  await plugin.connect({ timeout: Infinity })
80 2
  routeBroadcaster.track(id)
81 2
  routeBroadcaster.reloadLocalRoutes()
82
}
83

84 2
const removePlugin = (
85
  accounts: Accounts,
86
  routeBroadcaster: RouteBroadcaster,
87
  middlewareManager: MiddlewareManager
88 2
) => async (
89
  id: string
90
) => {
91 2
  const plugin = accounts.getPlugin(id)
92 2
  await middlewareManager.removePlugin(id, plugin)
93 2
  await plugin.disconnect()
94 2
  routeBroadcaster.untrack(id)
95 2
  accounts.remove(id)
96 2
  routeBroadcaster.reloadLocalRoutes()
97
}
98

99 2
const getPlugin = (
100
  accounts: Accounts
101 2
) => (
102
  id: string
103 0
) => accounts.getPlugin(id)
104

105 2
const shutdown = (
106
  accounts: Accounts,
107
  routeBroadcaster: RouteBroadcaster,
108
  middlewareManager: MiddlewareManager
109 2
) => async () => {
110 0
  routeBroadcaster.stop()
111 0
  await accounts.disconnect()
112 0
  await middlewareManager.teardown()
113
}
114

115 2
export default function createApp (opts?: object, container?: Injector) {
116 2
  const deps = container || reduct()
117

118 2
  const config = deps(Config)
119

120 2
  try {
121 2
    if (opts) {
122 0
      config.loadFromOpts(opts)
123
    } else {
124 2
      config.loadFromEnv()
125
    }
126
  } catch (err) {
127 2
    if (err.name === 'InvalidJsonBodyError') {
128 0
      log.warn('config validation error.')
129 0
      err.debugPrint(log.warn.bind(log))
130 0
      log.error('invalid configuration, shutting down.')
131 0
      throw new Error('failed to initialize due to invalid configuration.')
132
    }
133

134 0
    throw err
135
  }
136

137 2
  const accounts = deps(Accounts)
138 2
  const routeBroadcaster = deps(RouteBroadcaster)
139 2
  const backend = deps(RateBackend)
140 2
  const middlewareManager = deps(MiddlewareManager)
141 2
  const adminApi = deps(AdminApi)
142

143 2
  const credentials = config.accounts
144 2
  for (let id of Object.keys(credentials)) {
145 2
    accounts.add(id, credentials[id])
146
  }
147

148 2
  return {
149
    config,
150
    listen: listen(config, accounts, backend, routeBroadcaster, middlewareManager, adminApi),
151
    addPlugin: addPlugin(accounts, routeBroadcaster, middlewareManager),
152
    removePlugin: removePlugin(accounts, routeBroadcaster, middlewareManager),
153
    getPlugin: getPlugin(accounts),
154
    shutdown: shutdown(accounts, routeBroadcaster, middlewareManager)
155
  }
156
}

Read our documentation on viewing source code .

Loading