git ssb

0+

Dominic / ssb-ooo



Commit 01fc1dd4552fcb7a246dc2551b28a35e2b68d7f3

initial

Dominic Tarr committed on 10/30/2017, 10:31:21 AM

Files changed

.travis.ymladded
LICENSEadded
README.mdadded
index.jsadded
package.jsonadded
store.jsadded
test/index.jsadded
.travis.ymlView
@@ -1,0 +1,4 @@
1 +language: node_js
2 +node_js:
3 + - 0.6
4 + - 0.8
LICENSEView
@@ -1,0 +1,22 @@
1 +Copyright (c) 2017 'Dominic Tarr'
2 +
3 +Permission is hereby granted, free of charge,
4 +to any person obtaining a copy of this software and
5 +associated documentation files (the "Software"), to
6 +deal in the Software without restriction, including
7 +without limitation the rights to use, copy, modify,
8 +merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom
10 +the Software is furnished to do so,
11 +subject to the following conditions:
12 +
13 +The above copyright notice and this permission notice
14 +shall be included in all copies or substantial portions of the Software.
15 +
16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
20 +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
README.mdView
@@ -1,0 +1,6 @@
1 +# ssb-ooo
2 +
3 +
4 +## License
5 +
6 +MIT
index.jsView
@@ -1,0 +1,78 @@
1 +var pull = require('pull-stream')
2 +var GQ = require('gossip-query')
3 +var hash = require('ssb-keys/util').hash
4 +
5 +function getId(msg) {
6 + return '%'+hash(JSON.stringify(msg, null, 2))
7 +}
8 +
9 +var Store = require('./store')
10 +var log = console.error
11 +
12 +console.error = function (m) {
13 + log(new Error('---------------').stack)
14 + log(m)
15 +
16 +}
17 +
18 +exports.name = 'ooo'
19 +exports.version = '1.0.0'
20 +exports.manifest = {
21 + stream: 'duplex',
22 + get: 'async'
23 +}
24 +exports.permissions = {
25 + anonymous: {allow: ['stream']}
26 +}
27 +
28 +var Flume = require('flumedb')
29 +var OffsetLog = require('flumelog-offset')
30 +var mkdirp = require('mkdirp')
31 +var ViewHashtable = require('flumeview-hashtable')
32 +
33 +exports.init = function (sbot, config) {
34 + var id = sbot.id
35 +
36 + store = Store(config)
37 +
38 + var gq = GQ({
39 + check: function (key, cb) {
40 + store.keys.get(key, function (err, data) {
41 + if(data) cb(null, data.value)
42 + else
43 + sbot.get(key, function (err, msg) {
44 + cb(null, msg)
45 + })
46 + })
47 + },
48 + process: function (id, msg, cb) {
49 + if(id !== getId(msg))
50 + cb()
51 + else cb(null, msg)
52 + }
53 + })
54 +
55 + sbot.on('rpc:connect', function (rpc, isClient) {
56 + console.log('CONNECT...', id.substring(0, 5), rpc.id.substring(0, 5))
57 + if(isClient) {
58 + var stream = gq.createStream(rpc.id)
59 + pull(stream, rpc.ooo.stream(function () {}), stream)
60 + }
61 + })
62 +
63 + return {
64 + stream: function () {
65 + //called by muxrpc, so remote id is set as this.id
66 + return gq.createStream(this.id)
67 + },
68 + get: function (id, cb) {
69 + gq.query(id, function (err, msg) {
70 + if(err) return cb(err)
71 + store.add(msg, function (err, data) {
72 + cb(null, data)
73 + })
74 + })
75 + }
76 + }
77 +}
78 +
package.jsonView
@@ -1,0 +1,28 @@
1 +{
2 + "name": "ssb-ooo",
3 + "description": "",
4 + "version": "1.0.0",
5 + "homepage": "https://github.com/dominictarr/ssb-ooo",
6 + "repository": {
7 + "type": "git",
8 + "url": "git://github.com/dominictarr/ssb-ooo.git"
9 + },
10 + "dependencies": {
11 + "flumecodec": "0.0.1",
12 + "flumedb": "^0.4.2",
13 + "flumelog-offset": "^3.2.5",
14 + "flumeview-hashtable": "^1.0.2",
15 + "mkdirp": "^0.5.1",
16 + "pull-stream": "^3.6.1",
17 + "ssb-keys": "^7.0.12"
18 + },
19 + "devDependencies": {
20 + "rimraf": "^2.6.1",
21 + "tape": "^4.8.0"
22 + },
23 + "scripts": {
24 + "test": "set -e; for t in test/*.js; do node $t; done"
25 + },
26 + "author": "'Dominic Tarr' <dominic.tarr@gmail.com> (dominictarr.com)",
27 + "license": "MIT"
28 +}
store.jsView
@@ -1,0 +1,46 @@
1 +var Flume = require('flumedb')
2 +var OffsetLog = require('flumelog-offset')
3 +var mkdirp = require('mkdirp')
4 +var ViewHashTable = require('flumeview-hashtable')
5 +
6 +var codec = require('flumecodec/json')
7 +var path = require('path')
8 +var hash = require('ssb-keys/util').hash
9 +
10 +function getId(msg) {
11 + return '%'+hash(JSON.stringify(msg, null, 2))
12 +}
13 +
14 +module.exports = function (config) {
15 + //we'll store out of order messages in their own log
16 + //so that we don't interfere with the views on in in-order messages
17 + //it does mean we'll download them again later if we follow
18 + //this feed, but it makes everything simpler overall
19 + //and the point of messages is to be small
20 + //and the point of ooo messages is that there
21 + //is not really that many.
22 +
23 + var log = OffsetLog(
24 + path.join(config.path, 'ooo', 'log.offset'),
25 + {blockSize:1024*16, codec:codec}
26 + )
27 + var store = Flume(log)
28 + .use('keys', ViewHashTable(2, function (key) {
29 + var b = new Buffer(key.substring(1,7), 'base64').readUInt32BE(0)
30 + return b
31 + }))
32 +
33 + store.add = function (msg, cb) {
34 + var data = {
35 + key: getId(msg),
36 + value: msg,
37 + timestamp: Date.now()
38 + }
39 + store.append(data, function (err) {
40 + if(err) cb(err)
41 + else cb(null, data)
42 + })
43 + }
44 +
45 + return store
46 +}
test/index.jsView
@@ -1,0 +1,89 @@
1 +var tape = require('tape')
2 +var ssbKeys = require('ssb-keys')
3 +var path = require('path')
4 +var rmrf = require('rimraf')
5 +var createSbot = require('scuttlebot')
6 + .use(require('../')) //
7 +
8 +// .use(require('ssb-friends'))
9 +// .use(require('../plugins/gossip'))
10 +// .use(require('../plugins/logging'))
11 +
12 +var alice = createSbot({
13 + temp: 'ooo_a',
14 + timeout: 1000,
15 + port: 34597,
16 + keys: ssbKeys.generate()
17 +})
18 +var bob = createSbot({
19 + temp: 'ooo_b',
20 + timeout: 1000,
21 + port: 34598,
22 + host: 'localhost', timeout: 20001,
23 + replicate: {hops: 3, legacy: false},
24 + keys: ssbKeys.generate()
25 +})
26 +
27 +var carol_path = path.join('/tmp/test-ssb-ooo_carol/')
28 +require('rimraf').sync(carol_path)
29 +
30 +var carol = createSbot({
31 + path: carol_path,
32 + timeout: 1000,
33 + port: 34599,
34 + keys: ssbKeys.generate()
35 +})
36 +
37 +var m1, m2
38 +
39 +tape('connect', function (t) {
40 + alice.connect(bob.getAddress(), function (err) {
41 + if(err) throw err
42 + })
43 + carol.connect(bob.getAddress(), function (err) {
44 + if(err) throw err
45 + })
46 + var start = Date.now()
47 + alice.publish({type: 'test', msg: 'hello'}, function (err, data) {
48 + if(err) throw err
49 + console.log(data)
50 + m1 = data
51 + carol.ooo.get(data.key, function (err, _data) {
52 + t.deepEqual(_data.value, data.value, 'received the message!')
53 + console.log('time', Date.now() - start)
54 +
55 + alice.publish({type: 'test2', msg: 'hello2'}, function (err, data) {
56 + m2 = data
57 + var start = Date.now()
58 + carol.ooo.get(data.key, function (err, _data) {
59 + if(err) throw err
60 + console.log('time2', Date.now() - start)
61 + t.deepEqual(_data.value, data.value, 'received the 2nd message!')
62 + alice.close()
63 + bob.close()
64 + carol.close(t.end)
65 + })
66 + })
67 + })
68 + })
69 +})
70 +
71 +
72 +tape('reopen', function (t) {
73 + var carol = createSbot({
74 + path: carol_path,
75 + timeout: 1000,
76 + port: 34599,
77 + keys: ssbKeys.generate()
78 + })
79 +
80 + carol.ooo.get(m1.key, function (err, data) {
81 + t.deepEqual(data.value, m1.value)
82 + carol.ooo.get(m2.key, function (err, data) {
83 + t.deepEqual(data.value, m2.value)
84 + t.end()
85 + carol.close()
86 + })
87 + })
88 +})
89 +

Built with git-ssb-web