From 95365fa0634353999f96a1262d1a35d3b77314b4 Mon Sep 17 00:00:00 2001 From: Richard Schneider Date: Thu, 15 Feb 2018 23:38:13 +1300 Subject: [PATCH] feat: ipfs shutdown (#1200) * feat: route to shutdown daemon * feat: cli and http-api shutdown * chore: argggh fix the command count * chore: merge conflicts * chore: rebasing * chore: fix rebase errors * docs: add ipfs.shutdown * fix: always report state error when stopping * chore: documentation is 'stop' not 'shutdown' * fix: generic stop * fix: package.json --- README.md | 2 +- src/cli/commands/shutdown.js | 17 +++++++++++++++++ src/core/components/stop.js | 8 ++++---- src/core/index.js | 1 + src/http/api/resources/index.js | 1 + src/http/api/resources/shutdown.js | 14 ++++++++++++++ src/http/api/routes/index.js | 1 + src/http/api/routes/shutdown.js | 13 +++++++++++++ test/cli/commands.js | 2 +- test/core/interface/generic.js | 2 +- 10 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 src/cli/commands/shutdown.js create mode 100644 src/http/api/resources/shutdown.js create mode 100644 src/http/api/routes/shutdown.js diff --git a/README.md b/README.md index cb3373644f..e82d81d104 100644 --- a/README.md +++ b/README.md @@ -332,7 +332,7 @@ A complete API definition is in the works. Meanwhile, you can learn how to you u - `ipfs.ping()` - `ipfs.init([options], callback)` - `ipfs.start([callback])` - - `ipfs.stop([callback])` + - [`ipfs.stop([callback])`](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/MISCELLANEOUS.md#stop) - `ipfs.isOnline()` - [config](https://github.com/ipfs/interface-ipfs-core/tree/master/SPEC/CONFIG.md) diff --git a/src/cli/commands/shutdown.js b/src/cli/commands/shutdown.js new file mode 100644 index 0000000000..99c6e8d6a7 --- /dev/null +++ b/src/cli/commands/shutdown.js @@ -0,0 +1,17 @@ +'use strict' + +module.exports = { + command: 'shutdown', + + describe: 'Shut down the ipfs daemon', + + builder: {}, + + handler (argv) { + argv.ipfs.shutdown((err) => { + if (err) { + throw err + } + }) + } +} diff --git a/src/core/components/stop.js b/src/core/components/stop.js index ad3957b546..a39900d09c 100644 --- a/src/core/components/stop.js +++ b/src/core/components/stop.js @@ -13,6 +13,10 @@ module.exports = (self) => { return callback(new Error('Already stopped')) } + if (self.state.state() !== 'running') { + return callback(new Error('Not able to stop from state: ' + self.state.state())) + } + const done = (err) => { if (err) { self.emit('error', err) @@ -23,10 +27,6 @@ module.exports = (self) => { callback() } - if (self.state.state() !== 'running') { - return done(new Error('Not able to stop from state: ' + self.state.state())) - } - self.state.stop() self._blockService.unsetExchange() self._bitswap.stop() diff --git a/src/core/index.js b/src/core/index.js index b0e5719b2f..83cc20cd37 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -77,6 +77,7 @@ class IPFS extends EventEmitter { this.preStart = components.preStart(this) this.start = components.start(this) this.stop = components.stop(this) + this.shutdown = this.stop this.isOnline = components.isOnline(this) // - interface-ipfs-core defined API this.version = components.version(this) diff --git a/src/http/api/resources/index.js b/src/http/api/resources/index.js index 42eec1d0b0..efc7785dbd 100644 --- a/src/http/api/resources/index.js +++ b/src/http/api/resources/index.js @@ -1,6 +1,7 @@ 'use strict' exports.version = require('./version') +exports.shutdown = require('./shutdown') exports.id = require('./id') exports.bootstrap = require('./bootstrap') exports.repo = require('./repo') diff --git a/src/http/api/resources/shutdown.js b/src/http/api/resources/shutdown.js new file mode 100644 index 0000000000..56f137cc91 --- /dev/null +++ b/src/http/api/resources/shutdown.js @@ -0,0 +1,14 @@ +'use strict' + +exports = module.exports + +/* + * Stop the daemon. + * + * Returns an empty response to the caller then + * on the next 'tick' emits SIGTERM. + */ +exports.do = (request, reply) => { + setImmediate(() => process.emit('SIGTERM')) + return reply() +} diff --git a/src/http/api/routes/index.js b/src/http/api/routes/index.js index 9e405ae6b5..aeba5f1427 100644 --- a/src/http/api/routes/index.js +++ b/src/http/api/routes/index.js @@ -2,6 +2,7 @@ module.exports = (server) => { require('./version')(server) + require('./shutdown')(server) require('./id')(server) require('./bootstrap')(server) require('./block')(server) diff --git a/src/http/api/routes/shutdown.js b/src/http/api/routes/shutdown.js new file mode 100644 index 0000000000..b3d8c9f8ef --- /dev/null +++ b/src/http/api/routes/shutdown.js @@ -0,0 +1,13 @@ +'use strict' + +const resources = require('./../resources') + +module.exports = (server) => { + const api = server.select('API') + + api.route({ + method: '*', + path: '/api/v0/shutdown', + handler: resources.shutdown.do + }) +} diff --git a/test/cli/commands.js b/test/cli/commands.js index 1fabdc857f..50afc3240e 100644 --- a/test/cli/commands.js +++ b/test/cli/commands.js @@ -4,7 +4,7 @@ const expect = require('chai').expect const runOnAndOff = require('../utils/on-and-off') -const commandCount = 67 +const commandCount = 68 describe('commands', () => runOnAndOff((thing) => { let ipfs diff --git a/test/core/interface/generic.js b/test/core/interface/generic.js index b1b4fcca72..2393eed5f0 100644 --- a/test/core/interface/generic.js +++ b/test/core/interface/generic.js @@ -26,7 +26,7 @@ const common = { }) }, teardown: function (callback) { - // Stopped by the tests themselves + // No need to stop, because the test suite does a 'stop' test. // parallel(nodes.map((node) => (cb) => node.stop(cb)), callback) callback() }