diff --git a/src/controllers/index.js b/src/controllers/index.js index 67f9c2a..3c1ecf4 100644 --- a/src/controllers/index.js +++ b/src/controllers/index.js @@ -20,10 +20,14 @@ import UseCases from '../use-cases/index.js' // Load the REST API Controllers. import RESTControllers from './rest-api/index.js' +// Load the time controller library +import TimerControllers from './timer-controllers.js' + class Controllers { constructor (localConfig = {}) { this.adapters = new Adapters() this.useCases = new UseCases({ adapters: this.adapters }) + this.timerControllers = new TimerControllers({ adapters: this.adapters, useCases: this.useCases }) } // Spin up any adapter libraries that have async startup needs. @@ -53,10 +57,11 @@ class Controllers { // Wait for any startup processes to complete for the Adapters libraries. // await this.adapters.start() - // Attach the REST controllers to the Koa app. - // this.attachRESTControllers(app) - + // Attach JSON RPC controllers this.attachRPCControllers() + + // Attach and start the timer controllers + this.timerControllers.startTimers() } // Add the JSON RPC router to the ipfs-coord adapter. diff --git a/src/controllers/timer-controllers.js b/src/controllers/timer-controllers.js new file mode 100644 index 0000000..21b4bda --- /dev/null +++ b/src/controllers/timer-controllers.js @@ -0,0 +1,65 @@ +/* + This Controller library is concerned with timer-based functions that are + kicked off periodicially. +*/ + +import config from '../../config/index.js' + +class TimerControllers { + constructor (localConfig = {}) { + // Dependency Injection. + this.adapters = localConfig.adapters + if (!this.adapters) { + throw new Error( + 'Instance of Adapters library required when instantiating Timer Controller libraries.' + ) + } + this.useCases = localConfig.useCases + if (!this.useCases) { + throw new Error( + 'Instance of Use Cases library required when instantiating Timer Controller libraries.' + ) + } + + this.debugLevel = localConfig.debugLevel + + // Encapsulate dependencies + this.config = config + + // Bind 'this' object to all subfunctions. + this.exampleTimerFunc = this.exampleTimerFunc.bind(this) + + this.startTimers() + } + + // Start all the time-based controllers. + startTimers () { + // Any new timer control functions can be added here. They will be started + // when the server starts. + this.optimizeWalletHandle = setInterval(this.exampleTimerFunc, 60000 * 10) + + return true + } + + stopTimers () { + clearInterval(this.optimizeWalletHandle) + } + + // Replace this example function with your own timer handler. + exampleTimerFunc (negativeTest) { + try { + console.log('Example timer controller executed.') + + if (negativeTest) throw new Error('test error') + + return true + } catch (err) { + console.error('Error in exampleTimerFunc(): ', err) + + // Note: Do not throw an error. This is a top-level function. + return false + } + } +} + +export default TimerControllers diff --git a/test/unit/controllers/controllers.unit.js b/test/unit/controllers/controllers.unit.js index 2f93c1b..15742b7 100644 --- a/test/unit/controllers/controllers.unit.js +++ b/test/unit/controllers/controllers.unit.js @@ -28,6 +28,9 @@ describe('#Controllers', () => { attachRPCRouter: () => {} } + // Mock the timer controllers + sandbox.stub(uut.timerControllers, 'startTimers').returns() + const app = { use: () => {} } diff --git a/test/unit/controllers/timer-controllers.unit.js b/test/unit/controllers/timer-controllers.unit.js new file mode 100644 index 0000000..3f5e377 --- /dev/null +++ b/test/unit/controllers/timer-controllers.unit.js @@ -0,0 +1,72 @@ +/* + Unit tests for the timer-controller.js Controller library +*/ + +// Public npm libraries +import { assert } from 'chai' +import sinon from 'sinon' + +// Local libraries +import TimerControllers from '../../../src/controllers/timer-controllers.js' +import adapters from '../mocks/adapters/index.js' +import UseCasesMock from '../mocks/use-cases/index.js' + +describe('#Timer-Controllers', () => { + let uut + let sandbox + + beforeEach(() => { + sandbox = sinon.createSandbox() + + const useCases = new UseCasesMock() + uut = new TimerControllers({ adapters, useCases }) + }) + + afterEach(() => { + sandbox.restore() + + uut.stopTimers() + }) + + describe('#constructor', () => { + it('should throw an error if adapters are not passed in', () => { + try { + uut = new TimerControllers() + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Adapters library required when instantiating Timer Controller libraries.' + ) + } + }) + + it('should throw an error if useCases are not passed in', () => { + try { + uut = new TimerControllers({ adapters }) + + assert.fail('Unexpected code path') + } catch (err) { + assert.include( + err.message, + 'Instance of Use Cases library required when instantiating Timer Controller libraries.' + ) + } + }) + }) + + describe('#exampleTimerFunc', () => { + it('should kick off the Use Case', async () => { + const result = await uut.exampleTimerFunc() + + assert.equal(result, true) + }) + + it('should return false on error', async () => { + const result = await uut.exampleTimerFunc(true) + + assert.equal(result, false) + }) + }) +})