git ssb

0+

mixmix / ssb-testing-guide



Commit c43b221ba14d52bab66a39600ac72c74b12c762f

reduce flumeview-level && return live state of subs, needs refactor

Kieran committed on 5/25/2018, 1:28:26 AM
Parent: 9881ae44565d5783671b359a9bf7c0a0dbdabd49

Files changed

difficult/ex2/index.jsadded
difficult/ex2/index.test.jsadded
package.jsonchanged
difficult/ex2/index.jsView
@@ -1,0 +1,110 @@
1 +const flumeView = require('flumeview-level')
2 +const pull = require('pull-stream')
3 +const defer = require('pull-defer')
4 +const get = require('lodash/get')
5 +const NAME = 'channels'
6 +const VERSION = 1
7 +
8 +const getAuthor = (msg) => get(msg, 'value.author')
9 +const getContent = (msg) => get(msg, 'value.content')
10 +const getTimestamp = (msg) => get(msg, 'value.timestamp')
11 +
12 +module.exports = {
13 + name: NAME,
14 + version: VERSION,
15 + manifest: {
16 + read: 'source',
17 + subscriptions: 'source',
18 + getUserSubscriptions: 'async',
19 + popular: 'async'
20 + },
21 + init: function (server, config) {
22 + const view = server._flumeUse(
23 + NAME,
24 + flumeView(VERSION, map)
25 + )
26 +
27 + return { read: view.read, subscriptions, popular }
28 +
29 + function map (msg, seq) {
30 + const content = getContent(msg)
31 + if (isChannelSubscription()) {
32 + return [
33 + [content.channel, getAuthor(msg), getTimestamp(msg), content.subscribed]
34 + ]
35 + }
36 +
37 + function isChannelSubscription () {
38 + return content.channel &&
39 + (typeof content.subscribed !== undefined)
40 + }
41 + }
42 +
43 + function subscriptions (opts) {
44 + const query = Object.assign({}, {
45 + live: true,
46 + keys: true,
47 + values: false,
48 + seq: false
49 + }, opts)
50 +
51 + return view.read(query)
52 + }
53 +
54 + function getUserSubscriptions (feedId, cb) {
55 + pull(
56 + view.read({ keys: false, values: true }),
57 + pull.collect((err, msgs) => {
58 +
59 + })
60 + )
61 + }
62 +
63 + function popular (opts, cb) {
64 + if (typeof opts === 'function') return popular({}, opts)
65 + // opts = Object.assign({}, opts, { keys: true, values: false, seq: false })
66 + }
67 +
68 + }
69 +}
70 +
71 + // function subscriptions (opts) {
72 + // const query = Object.assign({}, {
73 + // live: true,
74 + // keys: true,
75 + // values: false,
76 + // seq: false
77 + // }, opts)
78 +
79 + // var source = defer.source(query)
80 +
81 + // // Do a { live: false } request to get collection of current subscribed channels
82 + // var getOpts = { live: false, keys: false, values: false, seq: false }
83 +
84 + // getSubscribedChannels(getOpts, (err, msgs) => {
85 + // if (err) throw err
86 +
87 + // source.resolve(
88 + // // pull stream without a sink returns a source
89 + // pull(
90 + // pull.values(msgs),
91 + // pull.filter(msg => !msg.sync)
92 + // )
93 + // )
94 + // })
95 +
96 + // // Return collection as source to a pull stream
97 + // return source
98 + // }
99 +
100 + // function getSubscribedChannels (opts, cb) {
101 + // // reduced state of subscriptions to be up to date
102 + // pull(
103 + // view.read(opts),
104 + // pull.collect((err, msgs) => {
105 + // if (err) return cb(err)
106 + // // return an up to date collection
107 + // cb(null, msgs)
108 + // })
109 + // )
110 + // }
difficult/ex2/index.test.jsView
@@ -1,0 +1,121 @@
1 +const test = require('tape')
2 +const Server = require('scuttle-testbot')
3 +const pull = require('pull-stream')
4 +
5 +test('[Difficult] Exercise 2 - Get a live stream list of channels a given user is subscribed to', assert => {
6 + Server.use(require('./index'))
7 + const server = Server()
8 + // A channel can be subscribed to and unsubscribed from,
9 + // therefore we need to draw the current state of a user's relationship with a given channel
10 +
11 + assert.plan(1)
12 +
13 + // Construct two independent identities to ensure we narrow the field
14 + const grace = server.createFeed()
15 + const elvis = server.createFeed()
16 +
17 + // Pre-populate before setting up live stream
18 + grace.publish({ type: 'channel', channel: 'mycology', subscribed: true }, (err, msg) => {
19 + grace.publish({ type: 'channel', channel: 'mycology', subscribed: false }, (err, msg) => {
20 +
21 + var collection
22 +
23 + pull(
24 + server.channels.read({ values: false, keys: true, live: true }),
25 + pull.filter(msg => !msg.sync),
26 + pull.filter(msg => msg.key !== undefined), // no idea why { key: undefined, seq: undefined } is coming through
27 + pull.drain(msg => {
28 + collection = reduce(collection, msg)
29 +
30 + if (msg.key[0] === 'ruby') {
31 + result = {}
32 + result[grace.id] = [
33 + { channel: 'mycology', subscribed: true },
34 + { channel: 'ruby', subscribed: true }
35 + ]
36 + result[elvis.id] = [
37 + { channel: 'mycology', subscribed: true },
38 + { channel: 'scuttlebutt', subscribed: false }
39 + ]
40 +
41 + assert.deepEqual(collection, result)
42 + server.close()
43 + }
44 +
45 + function reduce (collection, msg) {
46 + collection = collection || {}
47 + const [ channel, author, timestamp, subscribed ] = msg.key
48 + collection[author] = collection[author] || []
49 + var channelIndex = collection[author].findIndex(sub => sub.channel === channel)
50 + if (channelIndex !== -1) collection[author][channelIndex].subscribed = subscribed
51 + else collection[author].push({ channel, subscribed })
52 + return collection
53 + }
54 +
55 + })
56 + )
57 +
58 + grace.publish({ type: 'channel', channel: 'mycology', subscribed: true }, (err, msg) => {
59 + elvis.publish({ type: 'channel', channel: 'mycology', subscribed: true }, (err, msg) => {
60 + elvis.publish({ type: 'channel', channel: 'scuttlebutt', subscribed: true }, (err, msg) => {
61 + elvis.publish({ type: 'channel', channel: 'scuttlebutt', subscribed: false }, (err, msg) => {
62 + grace.publish({ type: 'channel', channel: 'ruby', subscribed: true }, () => {
63 + // these should now stream through to live pull stream above
64 + })
65 + })
66 + })
67 + })
68 + })
69 + })
70 + })
71 +})
72 +
73 +// test('get a list of channels ordered by how many people subscribed to each', assert => {
74 +// Server.use(require('./index'))
75 +// const server = Server()
76 +
77 +// assert.plan(1)
78 +
79 +// var grace = server.createFeed()
80 +// var elvis = server.createFeed()
81 +
82 +
83 +// function cb (msg) {
84 +// server.channels.popular
85 +// }
86 +
87 +// server.close()
88 +// assert.end()
89 +// })
90 +
91 +// (source) get a list of channels a given user is subscribed to
92 +// this needs to be a live stream in some way
93 +// probably the reduced state of channels you're currently subscribed to, then { sync: true } followed by live updates from now on... (to discuss)
94 +// (async) a list of all channels
95 +// ordered by how many subscribed to each
96 +
97 +// grace.publish({ type: 'post', channel: 'mycology', text: 'fly agarics all over' }, (err, msg) => {
98 +// elvis.publish({ type: 'post', channel: 'mycology', text: 'lets talk about clathrus archerii' }, (err, msg) => {
99 +// elvis.publish({ type: 'post', channel: 'mycology', text: 'no lets talk about stinkhorns' }, (err, msg) => {
100 +// elvis.publish({ type: 'post', channel: 'mycology', text: 'id like to talk about mycelium' }, (err, msg) => {
101 + // // Get current state
102 + // pull(
103 + // server.channels.subscriptions({ live: false }),
104 + // pull.collect((err, collection) => {
105 + // // Stream new messages
106 + // pull(
107 + // server.channels.subscriptions({ live: true }), // defaults to { live: true }
108 + // pull.filter(msg => !msg.sync),
109 + // pull.drain(msg => {
110 + // console.log(msg)
111 + // collection.reduce((state, msg) => {
112 +
113 + // }, {})
114 + // if (msg.key[0] === 'ruby') {
115 + // assert.end()
116 + // server.close()
117 + // }
118 + // })
119 + // )
120 + // })
121 + // )
package.jsonView
@@ -18,8 +18,9 @@
1818 "homepage": "https://github.com/ssbc/ssb-testing-guide#readme",
1919 "dependencies": {
2020 "flumeview-level": "^3.0.4",
2121 "flumeview-reduce": "^1.3.13",
22 + "lodash": "^4.17.10",
2223 "pull-stream": "^3.6.8",
2324 "scuttle-testbot": "^1.1.6",
2425 "ssb-backlinks": "^0.7.1",
2526 "ssb-sort": "^1.1.0",

Built with git-ssb-web