-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Complete revamp! Spawn js/go daemons locally or remote (from the browser) #176
Conversation
e6fab0e
to
7198198
Compare
test/spawning-js-daemons.spec.js
Outdated
}) | ||
|
||
describe('setting up and init a local node', () => { | ||
const testpath1 = '/tmp/ipfstestpath1' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'/tmp' is a nogo windows, use os.tmpdir
and path.join
test/spawning-js-daemons.spec.js
Outdated
|
||
describe('daemon spawning', () => { | ||
describe('local daemon', () => { | ||
const repoPath = '/tmp/ipfsd-ctl-test' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use os.tmpdir()
test/spawning-js-daemons.spec.js
Outdated
|
||
// actually running? | ||
done = once(done) | ||
exec('kill', ['-0', pid], { cleanup: true }, () => done()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will this work on windows?
test/spawning-js-daemons.spec.js
Outdated
}) | ||
|
||
it('should not have a directory', () => { | ||
expect(fs.existsSync('/tmp/ipfstestpath1')).to.be.eql(false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
os.tmpdir()
Thanks @richardschneider! This will probably end up being reworked quite a bit, that's why I won't make any changes until we settle on what we want this module to do for us! I'll take your observations into account tho! 👍 |
After a convo with @diasdavid on IRC, this interface was proposed:
The only issue I see with returning the node is when running in remote mode (starting nodes over http/ws), which will require exposing |
I've began reworking this PR with the proposed interface. |
package.json
Outdated
"test": "aegir test -t node --timeout 50000", | ||
"test": "aegir test -t node -t browser --no-cors --timeout 50000", | ||
"test:node": "aegir test -t node --timeout 50000", | ||
"test:browser": "aegir test -t browser --no-cors --timeout 50000", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While you are at it, please remove global timeouts. Thank you :)
Looks nice! I've wanted to use non-disposable nodes but had some issues with that before, this api looks cleaner (and already more documented :) ). How does it handle shutdown? (how did it handle it before?) Seeing the shutdown function deprecated (I didn't realize there was one before) I'm guessing the daemon shuts down gracefully in the backgrund somehow when this api is closed/GC'd? |
5bbe3b5
to
b6ad854
Compare
@Powersource Thanks! I also think this is going to be more concise than what we had previously 😉 . As for shutdown, that was part of the initially proposed interface, but we went a slightly different route and instead return a controlling node which will allow you to call |
Codecov Report
@@ Coverage Diff @@
## master #176 +/- ##
==========================================
- Coverage 89.84% 88.96% -0.88%
==========================================
Files 3 11 +8
Lines 197 553 +356
==========================================
+ Hits 177 492 +315
- Misses 20 61 +41
Continue to review full report at Codecov.
|
test/exec.js
Outdated
describe.skip('exec', () => { | ||
// UPDATE: 12/06/2017 - `tail` seems to work fine on all ci systems. | ||
// I'm leaving it enabled for now. This does need a different approach for windows though. | ||
describe('exec', () => { | ||
it('SIGTERM kills hang', (done) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@richardschneider don't think tail
would work on windows, any ideas on how to make it windows compat?
A small update: The interface has been reworked and the controller is now capable of running both Go and JS ipfs nodes as well as running in the browser. I want to clean this up a little before removing the WIP - this should happen shortly. |
This requires - ipfs/js-ipfs#1134 |
@diasdavid this should be ready for review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did my first round of review. Lot's of great work here! Thank you @dryajov :)
README.md
Outdated
|
||
// IPFS_PATH will point to /tmp/ipfs_***** and will be | ||
// cleaned up when the process exits. | ||
|
||
var ipfsd = require('ipfsd-ctl') | ||
const factory = require('ipfsd-ctl') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/factory/daemonFactory
README.md
Outdated
|
||
// IPFS_PATH will point to /tmp/ipfs_***** and will be | ||
// cleaned up when the process exits. | ||
|
||
var ipfsd = require('ipfsd-ctl') | ||
const factory = require('ipfsd-ctl') | ||
const localController = factory.localController |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/localController/local
@@ -30,23 +30,92 @@ npm install --save ipfsd-ctl | |||
|
|||
IPFS daemons are already easy to start and stop, but this module is here to do it from JavaScript itself. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a diagram explaining the difference between a local spawn and a remote spawn and why both exist
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
README.md
Outdated
|
||
ipfsd.disposableApi(function (err, ipfs) { | ||
localController.spawn(function (err, ipfsd) { | ||
const ipfs = ipfsd.ctl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/const ipfs/const ipfsCtl/
README.md
Outdated
ipfsd.disposableApi(function (err, ipfs) { | ||
localController.spawn(function (err, ipfsd) { | ||
const ipfs = ipfsd.ctl | ||
const node = ipfsd.ctrl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/node/ipfsCtrl
Essentially, avoid confusing users for having examples that literally rename what the API is giving you. It is like saying "the name it gives is misleading" when in fact it is not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great point! will rename to something more meaningful.
src/daemon.js
Outdated
@@ -78,30 +78,38 @@ function parseConfig (path, callback) { | |||
], callback) | |||
} | |||
|
|||
function tempDir (isJs) { | |||
return join(os.tmpdir(), `${isJs ? 'jsipfs' : 'ipfs'}_${String(Math.random()).substr(2)}`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use the hat
module http://npmjs.com/hat
src/daemon.js
Outdated
function tempDir (isJs) { | ||
return join(os.tmpdir(), `${isJs ? 'jsipfs' : 'ipfs'}_${String(Math.random()).substr(2)}`) | ||
} | ||
|
||
/** | ||
* Controll a go-ipfs node. | ||
*/ | ||
class Node { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename the class to GoDaemon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forgot to change the comment, this now controls both, go and js nodes.
src/daemon.js
Outdated
this.exec = process.env.IPFS_EXEC || ipfsDefaultPath | ||
constructor (opts) { | ||
const rootPath = process.env.testpath ? process.env.testpath : __dirname | ||
const isJs = truthy(process.env.IPFS_JS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Weird, if the class says it is to control a gonode, why it is checking JS stuff?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above, controls both, go and js nodes.
src/local.js
Outdated
'Addresses.Swarm': [`/ip4/127.0.0.1/tcp/0`], | ||
'Addresses.API': `/ip4/127.0.0.1/tcp/0`, | ||
'Addresses.Gateway': `/ip4/127.0.0.1/tcp/0` | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't all of these be the default options of IPFS? Do we need to redefine them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is so that we can start multiple nodes on different random ports, otherwise it uses the default ports and spawning multiple nodes ends up conflicting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So perhaps this should be the default for disposable nodes? It should also be one of the options that gets passed into spawn.
test/spawning.js
Outdated
}) | ||
}) | ||
|
||
describe('validate api', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Break this set of tests into its own file.
Adding some todos based on @diasdavid review:
|
4537058
to
e571a6c
Compare
README.md
Outdated
|
||
// IPFS_PATH will point to /tmp/ipfs_***** and will be | ||
// cleaned up when the process exits. | ||
|
||
var ipfsd = require('ipfsd-ctl') | ||
const daemonFactory = require('ipfsd-ctl') | ||
const local = daemonFactory.localController |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking a little bit more about this. Why does the user need to specify a local/remote controller this way?
Wouldn't it be more simpler if there was a setup step:
const DaemonFactory = require('ipfsd-ctl')
const df = new DaemonFactory(options)
Where default options is to:
- Do local for Node.js
- Do remote with default endpoint for Browser.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about doing that at some point, but I settled on not making any assumptions on behalf of the user. I think this is still a valid discussion point, but my reasoning was basically that - let the user choose which controller it wants to use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The user can still choose. I'm not particularly liking this daemonFactory.localController
. API, I feel that the df should be an instance of a DaemonFactory and the user can pick their set up through options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The one drawback with this approach is that it forces the DF to be stateful rathern than stateless as in the case of simple "static" methods. How about a middle ground? A factory method that will return the correct controller factory? Something like (pseudocode):
class DaemonFactory {
static createFactory(options): return ControllerFactory
}
where ControllerFactory
implements the spawn
interface? Note that it doesn't have to be a class, can just as well be a plain old module.exports = function(){}
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I like DaemonFactory.create
too 👍 (no need for the Factory word again)
README.md
Outdated
|
||
ipfsd.disposableApi(function (err, ipfs) { | ||
local.spawn(function (err, ipfsd) { | ||
const ipfs = ipfsd.ctl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You missed #176 (comment)
README.md
Outdated
ipfsd.disposableApi(function (err, ipfs) { | ||
local.spawn(function (err, ipfsd) { | ||
const ipfs = ipfsd.ctl | ||
const node = ipfsd.ctrl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also missed #176 (comment)
README.md
Outdated
ipfs.id(function (err, id) { | ||
console.log(id) | ||
process.exit() | ||
node.stopDaemon() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about clean up? .cleanRepo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For disposable nodes it happens automatically.
README.md
Outdated
} | ||
|
||
const remote = daemonFactory.remoteController(port || 9999) | ||
remote.spawn(function (err, controller) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why call it here controller
if the other example is ipfsd
? Let's ensure to have consistency since for the user, these things will be the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is getting there @dryajov ! :) A few more tweeks and then we invite everyone that actively uses this to review it as well. Then it is just about polishing the code.
README.md
Outdated
const daemonFactory = require('ipfsd-ctl') | ||
const server = daemonFactory.server | ||
|
||
server.start((err) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are the defaults? Better add here an options object and exemplify that config.
README.md
Outdated
console.log(id) | ||
process.exit() | ||
ipfsCtrl.stopDaemon() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any call for cleanUp??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, there is ipfsCtrl.shutdown
which will clean up the tmp repo created for the disposable node.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the difference between:
- .stopDaemon
- .shutdown
If I stopDaemon, can I then later clean up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
stopDaemon
will kill
the process which would call shutdown
, that is registered as a process exit handle if the daemon was started as a disposable node. If the node is not disposable, shutdown will not be called and the repo not destroyed (what we want).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think shutdown
would be better if renamed to cleanup
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I stopDaemon, can I then later clean up?
Yep, that just simply calls rimraf
on the repo, so calling after the daemon is stopped is supposed to work.
README.md
Outdated
|
||
ipfsd.disposableApi(function (err, ipfs) { | ||
ipfs.id(function (err, id) { | ||
local.spawn(function (err, ipfsd) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are the options to select:
- spawning a disposable node
- spawning a node using the ~/.ipfs repo
- spawning a node using the ipfs binary available?
README.md
Outdated
#### Create factory | ||
|
||
- `daemonFactory.localController` - create a local controller | ||
- `daemonFactory.remoteController([port])` - create a remote controller, usable from browsers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's change this to make DaemonFactory a class that takes an options object in the constructor with options to enable the multiple spawning scenarios.
README.md
Outdated
|
||
> Spawn either a js-ipfs or go-ipfs node through `localController` or `remoteController` | ||
|
||
`spawn([options], cb)` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/cb/callback
README.md
Outdated
|
||
- `cb(err, {ctl: <ipfs-api instance>, ctrl: <Node (ctrl) instance>})` - a callback that receives an object with two members: | ||
- `ctl` - an [ipfs-api](https://github.com/ipfs/js-ipfs-api) instance attached to the newly created ipfs node | ||
- `ctrl` - an instance of a daemon controller object |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- callback is a function with signature function (err, ipfsd) where:
- err is an error in case any problem happens with the node spawning
- ipfsd is an object that has two properties:
- ipfsd.ctl - ...
- ipfsd.ctrl - ...
README.md
Outdated
|
||
|
||
### IPFS Daemon Controller (ctrl) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs description.
README.md
Outdated
|
||
> Stop the daemon. | ||
|
||
- function(Error) callback - function that receives an instance of `Error` on failure |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can a user start -> stop -> start - > stop multiple times? Better add a test for that :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lil more CR
package.json
Outdated
@@ -50,23 +61,37 @@ | |||
], | |||
"license": "MIT", | |||
"dependencies": { | |||
"@ljharb/eslint-config": "^12.2.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this dep really necessary??
package.json
Outdated
"detect-node": "^2.0.3", | ||
"eslint-config-standard-jsx": "^4.0.2", | ||
"go-ipfs-dep": "0.4.13", | ||
"ipfs-api": "^17.1.3", | ||
"guid": "0.0.12", | ||
"hapi": "^16.6.2", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use latest hapi?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The latest hapi v17 is a major rewrite for which there is still no updated docs. All the guides/tutorials still reference v16.
package.json
Outdated
"subcomandante": "^1.0.5", | ||
"truthy": "0.0.1" | ||
}, | ||
"devDependencies": { | ||
"aegir": "^12.2.0", | ||
"chai": "^4.1.2", | ||
"dirty-chai": "^2.0.1", | ||
"ipfs": "^0.26.0", | ||
"ipfs": "^0.27.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Watch out for the ^
src/daemon.js
Outdated
const isJs = truthy(process.env.IPFS_JS) | ||
|
||
this.opts = opts || { isJs: isJs || false } | ||
process.env.IPFS_JS = this.opts.isJs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use env vars as read only. This will mess the spawn of multiple nodes in one go.
7df0c81
to
69848c6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. And the tests are passing on Windows! Such a beauty 😃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. And the tests are passing on Windows! Such a beauty 😃
hey @pgte can you do one last review of this PR? |
@dryajov is it possible to control an already running IPFS daemon with this? If so, how? 😄 |
@hacdias it should actually be possible (tho I haven't tested it myself), with |
@diasdavid is there anything else outstanding (besides @pgte review) to get this released? |
9dcea69
to
aa8d72b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There you go.
|
||
- **`go`** - calling `DaemonFactory.create({type: 'go'})` will spawn a `go-ipfs` daemon. | ||
- **`js`** - calling `DaemonFactory.create({type: 'js'})` will spawn a `js-ipfs` daemon. | ||
- **`proc`** - calling `DaemonFactory.create({type: 'proc', exec: require('ipfs') })` will spawn an `in process js-ipfs node` using the provided code reference that implements the core IPFS API. Note that, `exec` option to `df.spawn()` is required if `type: 'proc'` is used. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need to pass in exec
when using type: 'proc'
? Couldn't it default to require('ipfs')
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would force users to bring js-ipfs
at all times and we learned that makes it hard for users that want to bundle go-ipfs in. Otherwise, it would be good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's call this embedded
instead? Seems more consistent with e.g. ipfs-companion. (proc
is also a pretty generic name.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine either way :) Unless anyone objects, I'll change it. Was trying to find a better name either way in-proc
was another option.
README.md
Outdated
- **`js`** - calling `DaemonFactory.create({type: 'js'})` will spawn a `js-ipfs` daemon. | ||
- **`proc`** - calling `DaemonFactory.create({type: 'proc', exec: require('ipfs') })` will spawn an `in process js-ipfs node` using the provided code reference that implements the core IPFS API. Note that, `exec` option to `df.spawn()` is required if `type: 'proc'` is used. | ||
|
||
#### DaemonFactory endpoint for remote spawning - `const server = DaemonFactory.createServer([options]) ` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit-pick: Trailing whitespace before the '`'.
README.md
Outdated
|
||
#### `ipfsd.apiAddr` (getter) | ||
|
||
Get the address (multiaddr) of connected IPFS API. Returns a multiaddr, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit-pick: comma instead of dot at the end of sentence.
README.md
Outdated
|
||
#### `ipfsd.repoPath` (getter) | ||
|
||
Get the current repo path. Returns string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit-pick: Missing dot after sentence end.
README.md
Outdated
Initialize a repo. | ||
|
||
`initOpts` (optional) is an object with the following properties: | ||
- `keysize` (default 2048) - The bit size of the identiy key. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: identiy -> identity
test/add-retrive.js
Outdated
expect(this.ipfsd.api).to.have.property('apiPort') | ||
}) | ||
|
||
it('should be able to store objects', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doublicated test, it's the same as the one in line 31.
test/api.js
Outdated
// Check for props in daemon | ||
expect(ipfsd).to.have.property('apiAddr') | ||
expect(ipfsd).to.have.property('gatewayAddr') | ||
expect(ipfsd.apiAddr).to.not.equal(null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: Could be written as expect(ipfsd.apiAddr).to.not.be.null()
. It's the same for ...to.be.true()
. I won't repeat that.
// TODO: skip on windows for now | ||
// TODO: running under coverage messes up the process hierarchies | ||
if (isWindows || process.env['COVERAGE']) { | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be a proper .skip()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
skip
doesn't work outside it
blocks.
expect(res.result.api.apiAddr).to.exist() | ||
expect(res.result.api.gatewayAddr).to.exist() | ||
|
||
id = res.result.id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand it correctly, you define the id
here for the rest of the tests. Shouldn't the describes
be independent and be able to be run in any order? Isn't that something for the setup phase of the tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, we could - but we'd probably end up duplicating spawn
in a separate test, since id
is generated by spawn and the rest of the tests wouldn't work without it.
}) | ||
}) | ||
|
||
let pid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as with id
before. Shouldn't the describe()
s be independent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see previous comment.
thanks @vmx fixing :) |
e29690f
to
6b4ec15
Compare
awesome stuff @vmx, please let me know if you find anything else. |
6b4ec15
to
c35f6ce
Compare
@diasdavid are we missing anything else from this PR? |
W00T 👊 🎉 🎈 ❤️ !!! |
on it! |
In order to merge this PR, we need a working PR for:
Note: This is a major blocker for the circuit effort, let's timebox a decision on this interface for the next 24h (Nov 28), if there are no objections or comments I'll go ahead with the proposed interface.
This is still mostly a POC. I'm not sure whether this is the direction we want to take, so I'm leaving it here as a starting point to help understand (for myself mostly) what we're looking for.
Basically, I added a factory that aids in spawning IPFS nodes (js and go) from the cli and the browser. The factory has the same interface as https://github.com/ipfs/js-ipfs/blob/master/test/utils/ipfs-factory-daemon/index.js, essentially
spawnNode
anddismatle
methods. This is the de facto interface we're using in js-ipfs tests.Currently, my questions are
ipfs-factory-daemon
? If we do that, we break this modules (from npmjs)@victorbjelkholm @diasdavid @dignifiedquire @haadcode
EDIT: added below section with proposed interface
To add more clarity to this issue, this is what I currently have in mind:
ipfsd-ctl
is a module intended to allow interacting with external ipfs processes. It should allow spawning, configuring and stopping ipfs nodes, for both js-ipfs and go-ipfs. Currently this module already accomplishes that, however, its current interface seems to be a bit convoluted and in need of rethinking.In addition to this, we have several other needs, such as testing, that require manipulating ipfs nodes in an easy and convenient manner from both node and browsers (as well as electron and other such environments).
The current interface looks like this
Create a new, uninitialized node.
Create a new node and initialize a repo in a temporary location, starting/stopping is up to the client. Alternatively, although the the docs don't mention that, the repo can be overridden.
Create a new node, initialize a repo in a temporary location and return an
ipfs-api
connected to that node. Alternatively, although the the docs don't mention that, the repo can be overridden.The above is the factory interface that gets exposed to consumers that returns either a Node instance in the case of
local
anddisposable
or anipfs-api
instance in the case ofdisposableApi
.What we want
EDIT:
spawn
interface with comments from Complete revamp! Spawn js/go daemons locally or remote (from the browser) #176 (comment)A simplified interface that allows starting and stopping nodes
Spawn Nodes
Where
options
is:js
bool - spawn a js or go node (default go)remote
bool - spawn a local or remote node (default false)remote
is chosen, nodes are spawned using websocketsrepoPath
string - the repository path to use for this node, ignored if node is disposabledisposable
bool - a new repo is created and initialized for each invocationconfig
- ipfs configuration optionsDEPRECATED
Shutdown Nodes
In addition to this, this factory should be consumable from browsers, our current requirement for this are browser test, that are crippled by the absence of this functionality.