Skip to content

Commit

Permalink
feat(neotracker): add neotracker command to neo-one build
Browse files Browse the repository at this point in the history
  • Loading branch information
afragapane committed Nov 20, 2019
1 parent a82552e commit ad7315c
Show file tree
Hide file tree
Showing 20 changed files with 2,060 additions and 119 deletions.
1 change: 1 addition & 0 deletions packages/neo-one-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"dependencies": {
"@babel/core": "^7.5.5",
"@babel/register": "^7.5.5",
"@neotracker/core": "^1.3.0",
"@neo-one/cli-common": "^2.3.0",
"@neo-one/cli-common-node": "^2.3.0",
"@neo-one/client-common": "^2.3.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* @hash 75addf13d49c998b009e371e02264bfe */
/* @hash cc22deec02b78c38de97754994eeef14 */
// tslint:disable
/* eslint-disable */
import {
Expand Down Expand Up @@ -64,7 +64,7 @@ export const createClient = <TUserAccountProviders extends UserAccountProviders<

const providers = [];
if (process.env.NODE_ENV !== 'production' || process.env.NEO_ONE_DEV === 'true') {
providers.push({ network: 'local', rpcURL: `http://${host}:10060/rpc` });
providers.push({ network: 'local', rpcURL: `http://${host}:10000/rpc` });
}
const provider = new NEOONEProvider(providers);
const userAccountProviders = getUserAccountProviders(provider);
Expand Down Expand Up @@ -145,5 +145,5 @@ export const createClient = <TUserAccountProviders extends UserAccountProviders<
};

export const createDeveloperClients = (host = 'localhost'): DeveloperClients => ({
local: new DeveloperClient(new NEOONEDataProvider({ network: 'local', rpcURL: `http://${host}:10060/rpc` })),
local: new DeveloperClient(new NEOONEDataProvider({ network: 'local', rpcURL: `http://${host}:10000/rpc` })),
});
25 changes: 25 additions & 0 deletions packages/neo-one-cli/src/__e2e__/cmd/start/neotracker.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import fetch from 'cross-fetch';
import { isRunning } from '../../../common';

describe('start network', () => {
it('starts a private network', async () => {
const execAsync = one.createExecAsync('ico');
execAsync('start network');
const config = await one.getProjectConfig('ico');

await one.until(async () => {
const [live, ready] = await Promise.all([
fetch(`http://localhost:${config.network.port}/live_health_check`),
fetch(`http://localhost:${config.network.port}/ready_health_check`),
]);
expect(live.ok).toEqual(true);
expect(ready.ok).toEqual(true);
});

execAsync('start neotracker');
await one.until(async () => {
const live = await isRunning(config.neotracker.port);
expect(live).toEqual(true);
});
});
});
35 changes: 35 additions & 0 deletions packages/neo-one-cli/src/__e2e__/cmd/stop/neotracker.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import fetch from 'cross-fetch';
import { isRunning } from '../../../common';

describe('start network', () => {
it('starts a private network', async () => {
const execAsync = one.createExecAsync('ico');
execAsync('start network');
const config = await one.getProjectConfig('ico');

await one.until(async () => {
const [live, ready] = await Promise.all([
fetch(`http://localhost:${config.network.port}/live_health_check`),
fetch(`http://localhost:${config.network.port}/ready_health_check`),
]);
expect(live.ok).toEqual(true);
expect(ready.ok).toEqual(true);
});

execAsync('start neotracker');

await one.until(async () => {
const live = await isRunning(config.neotracker.port);
expect(live).toEqual(true);
});

await one.createExec('ico')('stop neotracker');
let success = false;
try {
success = await isRunning(config.neotracker.port);
} catch {
// do nothing
}
expect(success).toEqual(false);
});
});
7 changes: 7 additions & 0 deletions packages/neo-one-cli/src/build/createTasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { findContracts } from './findContracts';
import { generateCode } from './generateCode';
import { generateCommonCode } from './generateCommonCode';
import { setupWallets } from './setupWallets';
import { startNeotracker } from './startNeotracker';
import { startNetwork } from './startNetwork';

export const createTasks = (cmd: Command, config: Configuration, reset: boolean) =>
Expand Down Expand Up @@ -95,4 +96,10 @@ export const createTasks = (cmd: Command, config: Configuration, reset: boolean)
await generateCommonCode(config, ctx.contracts, networks, ctx.sourceMaps);
},
},
{
title: 'Start NEO tracker instance',
task: async () => {
await startNeotracker(cmd, config, reset);
},
},
]);
44 changes: 44 additions & 0 deletions packages/neo-one-cli/src/build/startNeotracker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Configuration } from '@neo-one/cli-common';
import execa from 'execa';
import { isRunning } from '../common';
import { Command } from '../types';
import { findKillProcess } from '../utils';

export const startNeotracker = async (cmd: Command, config: Configuration, reset: boolean) => {
const args = cmd.args.concat(['start', 'neotracker']);
if (reset) {
await findKillProcess('neotracker', config);
}

const proc = execa(cmd.bin, reset ? args.concat(['--reset']) : args, {
cleanup: false,
detached: true,
stdio: 'ignore',
});
proc.unref();

const start = Date.now();
const timeoutMS = 30 * 1000;
let ready = false;
if (reset) {
await new Promise((resolve) => setTimeout(resolve, 3000));
}
// tslint:disable-next-line no-loop-statement
while (Date.now() - start < timeoutMS) {
try {
const response = await isRunning(config.neotracker.port);
if (response) {
ready = true;
break;
}
} catch {
// do nothing
}

await new Promise((resolve) => setTimeout(resolve, 500));
}

if (!ready) {
throw new Error('Neotracker is not ready.');
}
};
3 changes: 2 additions & 1 deletion packages/neo-one-cli/src/cmd/start/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import yargs from 'yargs';
import * as neotracker from './neotracker';
import * as network from './network';

export const command = 'start';
export const describe = 'Start NEO•ONE services.';
export const builder = (yargsBuilder: typeof yargs) => yargsBuilder.command(network);
export const builder = (yargsBuilder: typeof yargs) => yargsBuilder.command(network).command(neotracker);
55 changes: 55 additions & 0 deletions packages/neo-one-cli/src/cmd/start/neotracker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { cliLogger } from '@neo-one/logger';
import { Yarguments } from '@neo-one/utils-node';
import execa from 'execa';
import * as nodePath from 'path';
import yargs from 'yargs';
import { isRunning, start } from '../../common';
import { findKillProcess } from '../../utils';
import { writePidFile } from './writePidFile';

export const command = 'neotracker';
export const describe = 'Start a NEO tracker instance using the project configuration.';
export const builder = (yargsBuilder: typeof yargs) =>
yargsBuilder
.boolean('reset')
.describe('reset', 'Reset the NEO tracker database.')
.default('reset', false);
export const handler = (argv: Yarguments<ReturnType<typeof builder>>) => {
start(async (_cmd, config) => {
const running = await isRunning(config.neotracker.port);
if (running) {
if (argv.reset) {
await findKillProcess('neotracker', config);
} else {
cliLogger.info('NEO tracker is already running');

return undefined;
}
}

const args = [
'neotracker',
'--port',
`${config.neotracker.port}`,
'--nodeRpcUrl',
`http://localhost:${config.network.port}/rpc`,
'--dbFileName',
nodePath.resolve(config.neotracker.path, 'db.sqlite'),
];
const proc = execa(
nodePath.resolve(require.resolve('@neotracker/core/bin'), '../', 'neotracker'),
argv.reset ? args.concat(['--resetDB']) : args,
{
cleanup: false,
stdio: 'ignore',
},
);
proc.unref();

await writePidFile('neotracker', proc, config);

return async () => {
proc.kill();
};
});
};
50 changes: 3 additions & 47 deletions packages/neo-one-cli/src/cmd/start/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,9 @@ import { common, crypto } from '@neo-one/client-common';
import { cliLogger } from '@neo-one/logger';
import { FullNode } from '@neo-one/node';
import { createMain } from '@neo-one/node-neo-settings';
import * as fs from 'fs-extra';
import net from 'net';
import * as nodePath from 'path';
import yargs from 'yargs';
import { getNetworkProcessIDFile, getPrimaryKeys, start } from '../../common';

async function isRunning(port: number) {
let resolve: (running: boolean) => void;
let reject: (err: Error) => void;
// tslint:disable-next-line promise-must-complete
const promise = new Promise<boolean>((resolver, rejector) => {
resolve = resolver;
reject = rejector;
});

const cleanup = () => {
client.removeAllListeners('connect');
client.removeAllListeners('error');
client.end();
client.destroy();
client.unref();
};

const onConnect = () => {
resolve(true);
cleanup();
};

const onError = (error: Error) => {
// tslint:disable-next-line no-any
if ((error as any).code !== 'ECONNREFUSED') {
reject(error);
} else {
resolve(false);
}
cleanup();
};

const client = new net.Socket();
client.once('connect', onConnect);
client.once('error', onError);
client.connect({ port, host: '127.0.0.1' });

return promise;
}
import { getPrimaryKeys, isRunning, start } from '../../common';
import { writePidFile } from './writePidFile';

export const command = 'network';
export const describe = 'Start a NEO•ONE development network using the project configuration.';
Expand Down Expand Up @@ -88,9 +46,7 @@ export const handler = () => {

await fullNode.start();

const pidFile = getNetworkProcessIDFile(config);
await fs.ensureDir(nodePath.dirname(pidFile));
await fs.writeFile(pidFile, process.pid);
await writePidFile('network', process, config);

return async () => {
await fullNode.stop();
Expand Down
15 changes: 15 additions & 0 deletions packages/neo-one-cli/src/cmd/start/writePidFile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Configuration } from '@neo-one/cli-common';
import { ExecaChildProcess } from 'execa';
import * as fs from 'fs-extra';
import * as nodePath from 'path';
import { getProcessIDFile } from '../../common';

export const writePidFile = async (
name: 'network' | 'neotracker',
proc: NodeJS.Process | ExecaChildProcess,
config: Configuration,
) => {
const pidFile = getProcessIDFile(config, name);
await fs.ensureDir(nodePath.dirname(pidFile));
await fs.writeFile(pidFile, proc.pid);
};
3 changes: 2 additions & 1 deletion packages/neo-one-cli/src/cmd/stop/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import yargs from 'yargs';
import * as neotracker from './neotracker';
import * as network from './network';

export const command = 'stop';
export const describe = 'Stop NEO•ONE services.';
export const builder = (yargsBuilder: typeof yargs) => yargsBuilder.command(network);
export const builder = (yargsBuilder: typeof yargs) => yargsBuilder.command(network).command(neotracker);
12 changes: 12 additions & 0 deletions packages/neo-one-cli/src/cmd/stop/neotracker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import yargs from 'yargs';
import { start } from '../../common';
import { findKillProcess } from '../../utils';

export const command = 'neotracker';
export const describe = 'Stops the local neotracker instance.';
export const builder = (yargsBuilder: typeof yargs) => yargsBuilder;
export const handler = () => {
start(async (_cmd, config) => {
await findKillProcess('neotracker', config);
});
};
20 changes: 3 additions & 17 deletions packages/neo-one-cli/src/cmd/stop/network.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,12 @@
import * as fs from 'fs-extra';
import yargs from 'yargs';
import { getNetworkProcessIDFile, start } from '../../common';
import { killProcess } from '../../utils';
import { start } from '../../common';
import { findKillProcess } from '../../utils';

export const command = 'network';
export const describe = 'Stops the local development network.';
export const builder = (yargsBuilder: typeof yargs) => yargsBuilder;
export const handler = () => {
start(async (_cmd, config) => {
const file = getNetworkProcessIDFile(config);
let pid: number | undefined;
try {
const contents = await fs.readFile(file, 'utf8');
pid = parseInt(contents, 10);
} catch (err) {
if (err.code !== 'ENOENT') {
throw err;
}
}

if (pid !== undefined) {
await killProcess(pid);
}
await findKillProcess('network', config);
});
};
4 changes: 0 additions & 4 deletions packages/neo-one-cli/src/common/getNetworkProcessIDFile.ts

This file was deleted.

5 changes: 5 additions & 0 deletions packages/neo-one-cli/src/common/getProcessIDFile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Configuration } from '@neo-one/cli-common';
import * as nodePath from 'path';

export const getProcessIDFile = (config: Configuration, process: 'network' | 'neotracker') =>
nodePath.resolve(config[process].path, '.pid');
3 changes: 2 additions & 1 deletion packages/neo-one-cli/src/common/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './deployed';
export * from './getNetworkProcessIDFile';
export * from './getProcessIDFile';
export * from './getPrimaryKeys';
export * from './isRunning';
export * from './load';
export * from './loadClient';
export * from './paths';
Expand Down
Loading

0 comments on commit ad7315c

Please sign in to comment.