-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7e9804f
commit 6fc5b43
Showing
12 changed files
with
197 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,3 +35,4 @@ node_modules | |
lib | ||
jsconfig.json | ||
typings | ||
example.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
language: node_js | ||
node_js: | ||
- '5' | ||
- '4' | ||
|
||
script: npm test | ||
after_script: "npm install coveralls@2 && cat ./coverage/lcov.info | coveralls" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,60 @@ | ||
# billow | ||
# billow | ||
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) | ||
[![Build Status](https://travis-ci.org/DavidCai1993/billow.svg?branch=master)](https://travis-ci.org/DavidCai1993/billow) | ||
[![Coverage Status](https://coveralls.io/repos/github/DavidCai1993/billow/badge.svg?branch=master)](https://coveralls.io/github/DavidCai1993/billow?branch=master) | ||
|
||
A stream pipeline based message processing framework. | ||
|
||
## Install | ||
|
||
``` | ||
npm install billow | ||
``` | ||
|
||
## Usage | ||
|
||
```js | ||
'use strict' | ||
const { Billow, Flow, Droplet } = require('billow') | ||
|
||
let billow = new Billow({ separator: '\r\n' }) | ||
let flowOne = new Flow({ events: ['error', 'dropletError'] }) | ||
let flowTwo = new Flow({ events: ['error', 'dropletError'] }) | ||
|
||
flowOne.on('error', console.error).on('dropletError', console.error) | ||
flowTwo.on('error', console.error).on('dropletError', console.error) | ||
|
||
flowOne.addDroplets([ | ||
new Droplet({ | ||
handler: async function (chunk, encoding) { | ||
return await Promise.resolve(`${chunk.toString()}==`) | ||
} | ||
}), | ||
new Droplet({ | ||
handler: function (chunk, encoding) { | ||
console.log(chunk.toString()) | ||
} | ||
}) | ||
]) | ||
|
||
flowTwo.addDroplets([ | ||
new Droplet({ | ||
handler: async function (chunk, encoding) { | ||
return await Promise.resolve(`${chunk.toString()}~~`) | ||
} | ||
}), | ||
new Droplet({ | ||
handler: function (chunk, encoding) { | ||
console.log(chunk.toString()) | ||
} | ||
}) | ||
]) | ||
|
||
billow.addFlow(flowOne).addFlow(flowTwo).write('billow!\r\nbillow!\r\n') | ||
// billow!== | ||
// billow!~~ | ||
// billow!== | ||
// billow!~~ | ||
``` | ||
|
||
## How it works |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
'use strict' | ||
const { Writable } = require('stream') | ||
const Flow = require('./flow') | ||
const BlackHole = require('./black-hole') | ||
const { last } = require('./utils') | ||
|
||
class Billow extends Writable { | ||
constructor ({ separator = '\r\n', highWaterMark = 16384 } = {}) { | ||
super({ highWaterMark }) | ||
this.separator = separator | ||
this.blackHole = new BlackHole() | ||
this.flows = [] | ||
} | ||
|
||
_write (chunk, encoding, next) { | ||
if (!this.separator) for (let flow of this.flows) { flow.droplets[0].write(chunk) } | ||
if (this._buffer) chunk = Buffer.concat([this._buffer, chunk]) | ||
|
||
let start = 0 | ||
let index = chunk.indexOf(this.separator) | ||
|
||
while (~index) { | ||
let buffer = chunk.slice(start, index) | ||
for (let flow of this.flows) { flow.droplets[0].write(buffer) } | ||
|
||
start = index + Buffer.byteLength(this.separator) | ||
index = chunk.indexOf(this.separator, start) | ||
} | ||
|
||
this._buffer = chunk.slice(start) | ||
next() | ||
} | ||
|
||
addFlow (flow) { | ||
if (!(flow instanceof Flow)) throw new TypeError(`${flow} should be an instance of Flow`) | ||
|
||
last(flow.droplets).pipe(this.blackHole) | ||
this.flows.push(flow) | ||
|
||
return this | ||
} | ||
} | ||
|
||
module.exports = Billow |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
'use strict' | ||
const { Writable } = require('stream') | ||
|
||
class BlackHole extends Writable { | ||
_write (chunk, encoding, next) { next() } | ||
} | ||
|
||
module.exports = BlackHole |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,6 @@ | ||
'use strict' | ||
const { Writable } = require('stream') | ||
const Billow = require('./billow') | ||
const Flow = require('./flow') | ||
const Droplet = require('./droplet') | ||
|
||
class Billow extends Writable { | ||
constructor ({ separator = '\r\n', highWaterMark = 16384 } = {}) { | ||
super({ highWaterMark }) | ||
this.separator = separator | ||
this.flows = [] | ||
} | ||
|
||
_write (chunk, encoding, next) { | ||
if (!this.separator) for (let flow of this.flows) { flow[0].write(chunk) } | ||
if (this._buffer) chunk = Buffer.concat([this._buffer, chunk]) | ||
|
||
let start = 0 | ||
let index = chunk.indexOf(this.separator) | ||
|
||
while (~index) { | ||
let buffer = chunk.slice(start, index) | ||
for (let flow of this.flows) { flow[0].write(buffer) } | ||
|
||
start = index + Buffer.byteLength(this.separator) | ||
index = chunk.indexOf(this.separator, start) | ||
} | ||
|
||
this._buffer = chunk.slice(start) | ||
next() | ||
} | ||
|
||
addFlow (flow) { | ||
if (!(flow instanceof Flow)) throw new TypeError(`${flow} should be an instance of Flow`) | ||
this.flows.push(flow) | ||
} | ||
} | ||
|
||
module.exports = Billow | ||
module.exports = { Billow, Flow, Droplet } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* global describe, it */ | ||
require('should') | ||
const Flow = require('../src/flow') | ||
const Droplet = require('../src/droplet') | ||
|
||
describe('Droplet test', function () { | ||
it('Should throw when pass wrong handler', function () { | ||
(function () { | ||
let _ = new Droplet() | ||
_ | ||
}).should.throw(/should be a function/) | ||
}) | ||
|
||
it('Should handle async function correctly', function (done) { | ||
let droplet1 = new Droplet({ | ||
handler: async function (chunk) { | ||
return await Promise.resolve(`${chunk.toString()}__`) | ||
} | ||
}) | ||
|
||
let droplet2 = new Droplet({ | ||
handler: async function (chunk) { | ||
await Promise.resolve(null) | ||
return `${chunk.toString()}__` | ||
} | ||
}) | ||
|
||
let droplet3 = new Droplet({ | ||
handler: async function (chunk) { | ||
chunk.toString().should.eql('test____') | ||
return done() | ||
} | ||
}) | ||
|
||
let flow = new Flow() | ||
flow.addDroplets([droplet1, droplet2, droplet3]) | ||
flow.droplets[0].write('test') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,33 @@ | ||
/* global describe, it */ | ||
require('should') | ||
const Flow = require('../src/flow') | ||
const Droplet = require('../src/droplet') | ||
|
||
describe('Flow test', function () { | ||
it('Should throw when add wrong droplets', function () { | ||
let flow = new Flow(); | ||
(function () { flow.addDroplets('wrongDroplets') }).should.throw(/should be an instance of Droplets/) | ||
(function () { flow.addDroplets('wrongDroplets') }).should.throw(/should be an instance of Droplet/) | ||
}) | ||
|
||
it('Should pipe data through streams', function () { | ||
let flow = new Flow() | ||
let count = 0 | ||
flow.addDroplets(new Droplet({ | ||
handler: async function (chunk) { | ||
chunk.toString().should.eql('test') | ||
count.should.eql(0) | ||
count++ | ||
} | ||
})) | ||
|
||
flow.addDroplets(new Droplet({ | ||
handler: async function (chunk) { | ||
chunk.toString().should.eql('test') | ||
count.should.eql(1) | ||
count++ | ||
} | ||
})) | ||
|
||
flow.droplets[0].write('test') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters