Skip to content

Commit

Permalink
Refactor towards three-layer architecture
Browse files Browse the repository at this point in the history
Create app container
Pass services down into lower layers (lower layers don't require singletons from src/services)

TODO:
- Move common utils (e.g., services/log) to `common`
- BalanceCache not used by default (i.e., caching is behind feature
  flag) and not a singleton.
  • Loading branch information
Alan Cohen committed Mar 23, 2016
1 parent e5b5c21 commit dceb9c1
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 127 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"koa": "^1.0.0",
"koa-compress": "^1.0.6",
"koa-mag": "^1.0.4",
"koa-passport": "^1.2.0",
"koa-passport": "^1.3.0",
"koa-route": "^2.4.2",
"koa-static": "^1.4.5",
"lodash": "^3.5.0",
Expand Down
99 changes: 81 additions & 18 deletions src/app.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,102 @@
'use strict'

const _ = require('lodash')
const co = require('co')
const metadata = require('./controllers/metadata')
const health = require('./controllers/health')
const pairs = require('./controllers/pairs')
const quote = require('./controllers/quote')
const notifications = require('./controllers/notifications')
const subscriptions = require('./models/subscriptions')
const compress = require('koa-compress')
const serve = require('koa-static')
const route = require('koa-route')
const errorHandler = require('five-bells-shared/middlewares/error-handler')
const koa = require('koa')
const path = require('path')
const log = require('./services/log')
const logger = require('koa-mag')
const passport = require('koa-passport')
const app = module.exports = koa()
const Passport = require('koa-passport').KoaPassport
const log = require('./services/log')

function listen (koaApp, config, backend, ledgers) {
if (config.getIn(['server', 'secure'])) {
const spdy = require('spdy')
const tls = config.get('tls')

const options = {
port: config.getIn(['server', 'port']),
host: config.getIn(['server', 'bind_ip']),
key: tls.key,
cert: tls.cert,
ca: tls.ca,
crl: tls.crl,
requestCert: config.getIn(['auth', 'client_certificates_enabled']),

// Certificates are checked in the passport-client-cert middleware
// Authorization check is disabled here to allow clients to connect
// to some endpoints without presenting client certificates, or using a
// different authentication method (e.g., Basic Auth)
rejectUnauthorized: false
}

spdy.createServer(
options, koaApp.callback()).listen(config.getIn(['server', 'port']))
} else {
koaApp.listen(config.getIn(['server', 'port']))
}

log('app').info('connector listening on ' + config.getIn(['server', 'bind_ip']) + ':' +
config.getIn(['server', 'port']))
log('app').info('public at ' + config.getIn(['server', 'base_uri']))
for (let pair of config.get('tradingPairs')) {
log('app').info('pair', pair)
}

// Start a coroutine that connects to the backend and
// subscribes to all the ledgers in the background
co(function * () {
yield backend.connect()

yield subscriptions.subscribePairs(config.get('tradingPairs'), ledgers, config)
}).catch(function (err) {
log('app').error(typeof err === 'object' && err.stack || err)
})
}

function createApp (config, backend, ledgers) {
const koaApp = koa()

koaApp.context.config = config
koaApp.context.backend = backend
koaApp.context.ledgers = ledgers

// Configure passport
const passport = new Passport()
require('./services/auth')(passport, config)

// Logger
koaApp.use(logger())
koaApp.use(errorHandler({log: log('error-handler')}))
koaApp.use(passport.initialize())

// Configure passport
require('./services/auth')
koaApp.use(route.get('/', metadata.getResource))
koaApp.use(route.get('/health', health.getResource))
koaApp.use(route.get('/pairs', pairs.getCollection))

// Logger
app.use(logger())
app.use(errorHandler({log: log('error-handler')}))
app.use(passport.initialize())
koaApp.use(route.get('/quote', quote.get))

app.use(route.get('/', metadata.getResource))
app.use(route.get('/health', health.getResource))
app.use(route.get('/pairs', pairs.getCollection))
koaApp.use(route.post('/notifications', notifications.post))

app.use(route.get('/quote', quote.get))
// Serve static files
koaApp.use(serve(path.join(__dirname, 'public')))

app.use(route.post('/notifications', notifications.post))
// Compress
koaApp.use(compress())

// Serve static files
app.use(serve(path.join(__dirname, 'public')))
return {
koaApp: koaApp,
listen: _.partial(listen, koaApp, config, backend, ledgers)
}
}

// Compress
app.use(compress())
module.exports = createApp
2 changes: 1 addition & 1 deletion src/controllers/notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ exports.post = function * postNotification () {
const notification = yield requestUtil.validateBody(this, 'Notification')
log.debug('Got notification: ' + JSON.stringify(notification))
try {
yield model.processNotification(notification)
yield model.processNotification(notification, this.config, this.backend, this.ledgers)
} catch (e) {
if (!(e instanceof UnacceptableExpiryError)) {
log.error('Notification handling received critical error: ' + e)
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/pairs.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ const model = require('../models/pairs')
*/
/* eslint-enable */
exports.getCollection = function * getCollection () {
this.body = model.getPairs()
this.body = model.getPairs(this.config)
}
3 changes: 2 additions & 1 deletion src/controllers/quote.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ const model = require('../models/quote')
/* eslint-enable */

exports.get = function * () {
this.body = yield model.getQuote(this.query)
this.body = yield model.getQuote(
this.query, this.ledgers, this.backend, this.config)
}

60 changes: 7 additions & 53 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,19 @@
'use strict'
const co = require('co')
const ledgers = require('./services/ledgers')
const config = require('./services/config')
const log = require('./services/log')
const backend = require('./services/backend')
const subscriptions = require('./models/subscriptions')
const app = require('./app')
const ledgersService = require('./services/ledgers')
const balanceCache = require('./services/balance-cache')
const createApp = require('./app')

function listen () {
if (config.getIn(['server', 'secure'])) {
const spdy = require('spdy')
const tls = config.get('tls')

const options = {
port: config.getIn(['server', 'port']),
host: config.getIn(['server', 'bind_ip']),
key: tls.key,
cert: tls.cert,
ca: tls.ca,
crl: tls.crl,
requestCert: config.getIn(['auth', 'client_certificates_enabled']),

// Certificates are checked in the passport-client-cert middleware
// Authorization check is disabled here to allow clients to connect
// to some endpoints without presenting client certificates, or using a
// different authentication method (e.g., Basic Auth)
rejectUnauthorized: false
}

spdy.createServer(
options, app.callback()).listen(config.getIn(['server', 'port']))
} else {
app.listen(config.getIn(['server', 'port']))
}

log('app').info('connector listening on ' + config.getIn(['server', 'bind_ip']) + ':' +
config.getIn(['server', 'port']))
log('app').info('public at ' + config.getIn(['server', 'base_uri']))
for (let pair of config.get('tradingPairs')) {
log('app').info('pair', pair)
}

// Start a coroutine that connects to the backend and
// subscribes to all the ledgers in the background
co(function * () {
yield backend.connect()

yield subscriptions.subscribePairs(config.get('tradingPairs'), ledgersService, config)
}).catch(function (err) {
log('app').error(typeof err === 'object' && err.stack || err)
})
}
const connector = createApp(config, backend, ledgers)

module.exports = {
app: app,
listen: listen,
app: connector.koaApp,
listen: connector.listen,
addLedger: ledgers.addLedger.bind(ledgers),
_test: {
BalanceCache: require('./lib/balance-cache'),
balanceCache: require('./services/balance-cache'),
balanceCache: balanceCache,
loadConnectorConfig: require('./lib/config'),
config: require('./services/config'),
logger: require('./services/log'),
Expand All @@ -68,5 +22,5 @@ module.exports = {
}

if (!module.parent) {
listen()
connector.listen()
}
5 changes: 3 additions & 2 deletions src/models/notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

const payments = require('./payments')

function * processNotification (notification) {
function * processNotification (notification, config, backend, ledgers) {
if (notification.event === 'transfer.update') {
yield payments.updateTransfer(notification.resource, notification.related_resources)
yield payments.updateTransfer(
notification.resource, notification.related_resources, config, backend, ledgers)
}
}

Expand Down
4 changes: 1 addition & 3 deletions src/models/pairs.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
'use strict'

const config = require('../services/config')

function getPairs () {
function getPairs (config) {
const tradingPairs = config.get('tradingPairs')
return tradingPairs.map((pair) => {
const currencies = pair.map(function (currencyLedgerString) {
Expand Down
Loading

0 comments on commit dceb9c1

Please sign in to comment.