npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

toa-net

v1.5.4

Published

JSON-RPC 2.0 client/server over TCP net.

Downloads

74

Readme

Toa-net

JSON-RPC 2.0 client/server over TCP net.

NPM version Build Status Downloads

Features

  1. Use JSON-RPC 2.0 Specification as RPC protocol.
  2. Use RESP (Redis Serialization Protocol) or MsgP (Byte Message Protocol) as message protocol.
  3. Use JSON Web Signatures as authentication protocol.
  4. Implemented ES6 Iterable protocol.

Implementations

Examples

Simple

const net = require('toa-net')
const auth = new net.Auth('secretxxx')
const server = new net.Server(function (socket) {
  socket.on('message', (message) => {
    console.log(message)
    // { payload: { jsonrpc: '2.0', method: 'hello', params: [ 1 ] },
    //   type: 'notification' }
    // ...

    if (message.type === 'request') {
      // echo request
      socket.success(message.payload.id, message.payload.params)
    }
  })
})
server.listen(8000)

// Enable authentication for server
server.getAuthenticator = function () {
  return (signature) => auth.verify(signature)
}

const client = new net.Client()
// Enable authentication for client
client.getSignature = function () {
  return auth.sign({id: 'clientIdxxx'})
}
client.connect(8000)

client.notification('hello', [1])
client.notification('hello', [2])
client.notification('hello', [3])
client.request('echo', {a: 4})((err, res) => {
  console.log(err, res) // null { a: 4 }

  client.destroy()
  server.close()
})

Iterator

Socket is async iterable object!

const thunk = require('thunks')()
const net = require('toa-net')

// 创建服务器
const server = new net.Server(function (socket) {
  thunk(function * () {
    // 高能!!!异步迭代 socket 接收的数据,socket 关闭后迭代结束
    for (let value of socket) {
      let message = yield value
      console.log(message)
      // { payload: { jsonrpc: '2.0', method: 'hello', params: [ 1 ] },
      //   type: 'notification' }
      // ...

      if (message.type === 'request') {
        // respond to the request
        socket.success(message.payload.id, message.payload.params)
      }
    }
  })((err) => {
    console.log(err)
    process.exit(0)
  })
})
server.listen(8000)

// 创建客户端
const client = new net.Client().connect(8000)
// 向服务器发出 notification
client.notification('hello', [1])
client.notification('hello', [2])
client.notification('hello', [3])
// 向服务器发出 RPC 请求,服务器将 echo 请求数据
client.request('echo', {a: 4})((err, res) => {
  console.log(err, res) // null { a: 4 }
  client.destroy()
  server.close()
})

Bench https://github.com/toajs/toa-net/tree/master/bench

gRPC vs axon vs toa-net, 5000000 Ping/Pong messages, 1 TCP connection, Node.js v6

  1. gRPC, no-delay: 1000 cocurrency, 1240066 ms, 4032.04 ops
  2. axon, no-delay: 1000 cocurrency, 204176 ms, 148888.89 kb, 24488.68 ops
  3. toa-net, no-delay: 1000 cocurrency, 73789 ms, 263272.57 kb, 67760.78 ops

100000 Ping/Pong messages

  1. local -> local, no-delay: 1000 cocurrency, 3180ms, 31446 ops
  2. local -> local, delay 1000ms: 1000 cocurrency, 100590ms, 994 ops
  3. local -> local, delay 1000ms: 5000 cocurrency, 20869ms, 4791 ops
  4. local -> local, delay 1000ms: 10000 cocurrency, 11074ms, 9030 ops

10000 simple messages, 1000 cocurrency

// message
{
  name: 'abcdefghijklmnopqrst',
  email: '[email protected]',
  location: 'zhangjiang, shanghai, china'
}
  1. aliyun -> aws: 264321ms, 37 ops, 4.61 kb/s
  2. aws -> aliyun: 82129ms, 121 ops, 14.84 kb/s
  3. aliyun -> proxy_cn -> fiber -> proxy_us -> aws: 8056ms, 1241 ops, 151.30 kb/s

Install

npm install toa-net

API

const toaNet = require('toa-net')

Class toaNet.Server

new toaNet.Server(connectionListener)

Create RPC server.

const server = new net.Server(function (socket) {
  socket.on('message', (message) => {
    console.log(message)
  })
})
server.listen(8000)
  1. connectionListener: Required, Type: Function.

Event: 'close'

Event: 'error'

Event: 'listening'

server.getAuthenticator()

Abstract method. Should be overridden to enable authentication.

Default:

server.getAuthenticator = function () {
  return null // Disable authentication
}

Enable authentication:

const auth = new net.Auth('secretxxx')

server.getAuthenticator = function () {
  return (signature) => auth.verify(signature)
}

server.address()

Returns the bound address.

server.connections: RingPool

server.connections.length

Returns the number of concurrent connections on the server.

server.connections.next()

Return a socket in turn. Return null if no socket available.

server.close([callback])

Closes the server.

server.listen(...)

Same as node.js server.listen


Class toaNet.Client

Event: 'close'

Event: 'connect'

Event: 'auth'

Event: 'message'

Event: 'drain'

Event: 'end'

Event: 'error'

Event: 'timeout'

new toaNet.Client([options])

Creates RPC client.

const client = new net.Client().connect(8000)
  • options.retryDelay: Optional, Type: Number, Default: 500 ms. Sets time interval for reconnection.

  • options.maxAttempts: Optional, Type: Number, Default: 50. Sets max attempts for reconnection.

  • options.tcpTimeout: Optional, Type: Number, Default: 0. Sets the socket to timeout after timeout milliseconds of inactivity on the socket.

  • options.tcpNoDelay: Optional, Type: Boolean, Default: true. Disables the Nagle algorithm.

  • options.tcpKeepAlive: Optional, Type: Boolean, Default: true. Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket.

client.connect(...)

Same as node.js socket.connect

client.connect('tcp://127.0.0.1:33333')

client.getSignature()

Abstract method. Should be overridden to enable authentication.

Default:

client.getSignature = function () {
  return '' // Disable authentication
}

Enable authentication:

const auth = new net.Auth('secretxxx')

client.getSignature = function () {
  return auth.sign({id: 'example'})
}

client.request(method[, params])

Creates a JSON-RPC 2.0 request to another side. Returns thunk function.

client.request('echo', {name: 'zensh'})((err, res) => {
  console.log(err, res)
})
  1. method: Required, Type: String.
  2. params: Optional, Type: Object|Array.

client.notification(method[, params])

Creates a JSON-RPC 2.0 notification to another side. No return.

client.notification('hello', {name: 'zensh'})
  1. method: Required, Type: String.
  2. params: Optional, Type: Object|Array.

client.success(id, result)

Respond success result to the request of id. No return.

client.success(1, 'OK')
  1. id: Required, Type: String|Integer, the request's id.
  2. result: Required, Type: Mixed.

client.error(id, error)

Respond error to the request of id. No return.

client.error(1, new Error('some error'))
  1. id: Required, Type: String|Integer, the request's id.
  2. error: Required, Type: Error.

client.createError(error[, code, data])

client.createError(message[, code, data])

client.createError(code[, data])

client.throw(error[, code, data])

client.throw(message[, code, data])

client.throw(code[, data])

client.handleJsonRpc(jsonRpc, handleFn)

client.address()

client.destroy()

client[Symbol.iterator]()


Class toaNet.Auth

new toaNet.Auth(options)

Creates auth object for Server and Client.

const auth = new net.Auth({
  expiresIn: 3600,
  secrets: ['secretxxx1', 'secretxxx2', 'secretxxx3']
})
  1. options.secrets: Required, Type: String or a Array of string.
  2. options.expiresIn: Optional, Type: Number, Default: 3600 seconds.
  3. options.algorithm: Optional, Type: String, Default: 'HS256'.

auth.sign(payload)

Returns a new signature string.

let signature = auth.sign({id: 'xxxxxxId'})

auth.verify(signature)

Verify the signature, return payload object if success, or throw a error.

let session = auth.verify(signature)

auth.decode(signature)

Try decode the signature, return payload object if success, or null.

let signature = auth.decode(signature)

Advance API

Class toaNet.Resp

Class toaNet.Queue

Class toaNet.Socket

Class toaNet.RingPool

Class toaNet.RPCCommand

toaNet.jsonrpc

License

Toa-net is licensed under the MIT license. Copyright © 2016-2018 Toajs.