git ssb

7+

dinoworm ๐Ÿ› / patchcore



Commit b78fb2776fa75902fd8505a5defc377fbbf37101

contact.obs: use additional cache to make computing reverse lookups faster

#33
Matt McKegg committed on 9/29/2017, 9:51:56 AM
Parent: 4f3e54eaa5e60f7e8551798b984fbf3d4e0886c1

Files changed

contact/obs.jschanged
contact/obs.jsView
@@ -1,6 +1,6 @@
11 var nest = require('depnest')
2-var { Value, Dict, computed } = require('mutant')
2+var { Value, computed } = require('mutant')
33 var pull = require('pull-stream')
44 var ref = require('ssb-ref')
55
66 exports.needs = nest({
@@ -13,17 +13,25 @@
1313 })
1414
1515 exports.create = function (api) {
1616 var cacheLoading = false
17- var cache = Dict()
17+ var cache = {}
18+ var reverseCache = {}
19+
1820 var sync = Value(false)
1921
2022 return nest({
2123 'contact.obs': {
22- following: following,
23- followers: followers,
24- blocking: blocking,
25- blockers: blockers
24+
25+ // states:
26+ // true = following,
27+ // null = neutral (may have unfollowed),
28+ // false = blocking
29+
30+ following: (key) => matchingValueKeys(get(key, cache), true),
31+ followers: (key) => matchingValueKeys(get(key, reverseCache), true),
32+ blocking: (key) => matchingValueKeys(get(key, cache), false),
33+ blockers: (key) => matchingValueKeys(get(key, reverseCache), true)
2634 },
2735 'sbot.hook.publish': function (msg) {
2836 if (!isContact(msg)) return
2937
@@ -35,98 +43,69 @@
3543 : msg.value.content.flagged || msg.value.content.blocking ? false
3644 : null
3745 )
3846
39- update(source, { [dest]: tristate })
47+ update(source, { [dest]: tristate }, cache)
48+ update(dest, { [source]: tristate }, reverseCache)
4049 }
4150 })
4251
43- // states:
44- // true = following,
45- // null = neutral (may have unfollowed),
46- // false = blocking
47-
48- function following (key) {
49- var obs = computed(get(key), state => {
50- return Object.keys(state)
51- .reduce((sofar, next) => {
52- if (state[next] === true) return [...sofar, next]
53- else return sofar
54- }, [])
52+ function matchingValueKeys (state, value) {
53+ var obs = computed(state, state => {
54+ return Object.keys(state).filter(key => {
55+ return state[key] === value
56+ })
5557 })
5658
5759 obs.sync = sync
5860 return obs
5961 }
6062
61- function followers (key) {
62- var obs = computed(cache, cache => {
63- return Object.keys(cache)
64- .reduce((sofar, next) => {
65- if (cache[next][key] === true) return [...sofar, next]
66- else return sofar
67- }, [])
68- })
69-
70- obs.sync = sync
71- return obs
72- }
73-
74- function blocking (key) {
75- var obs = computed(get(key), state => {
76- return Object.keys(state)
77- .reduce((sofar, next) => {
78- if (state[next] === false) return [...sofar, next]
79- else return sofar
80- }, [])
81- })
82-
83- obs.sync = sync
84- return obs
85- }
86-
87- function blockers (key) {
88- var obs = computed(cache, cache => {
89- return Object.keys(cache)
90- .reduce((sofar, next) => {
91- if (cache[next][key] === false) return [...sofar, next]
92- else return sofar
93- }, [])
94- })
95-
96- obs.sync = sync
97- return obs
98- }
99-
100-
10163 function loadCache () {
10264 pull(
10365 api.sbot.pull.stream(sbot => sbot.friends.stream({live: true})),
10466 pull.drain(item => {
10567 if (!sync()) {
106- // initial dump
68+ // populate observable cache
69+ var reverse = {}
10770 for (var source in item) {
108- if (ref.isFeed(source)) update(source, item[source])
71+ if (ref.isFeed(source)) {
72+ update(source, item[source], cache)
73+
74+ // generate reverse lookup
75+ for (var dest in item[source]) {
76+ reverse[dest] = reverse[dest] || {}
77+ reverse[dest][source] = item[source][dest]
78+ }
79+ }
10980 }
81+
82+ // populate reverse observable cache
83+ for (var dest in reverse) {
84+ update(dest, reverse[dest], reverseCache)
85+ }
86+
11087 sync.set(true)
11188 } else {
11289 // handle realtime updates
113- update(item.from, {[item.to]: item.value})
90+ update(item.from, {[item.to]: item.value}, cache)
91+ update(item.to, {[item.from]: item.value}, reverseCache)
11492 }
11593 })
11694 )
11795 }
11896
119- function update (sourceId, values) {
97+ function update (sourceId, values, lookup) {
12098 // ssb-friends: values = {
12199 // keyA: true|null|false (friend, neutral, block)
122100 // keyB: true|null|false (friend, neutral, block)
123101 // }
124- var state = get(sourceId)
102+ var state = get(sourceId, lookup)
125103 var lastState = state()
126104 var changed = false
105+
127106 for (var targetId in values) {
128- if (values[targetId] != lastState[targetId]) {
107+ if (values[targetId] !== lastState[targetId]) {
129108 lastState[targetId] = values[targetId]
130109 changed = true
131110 }
132111 }
@@ -135,21 +114,20 @@
135114 state.set(lastState)
136115 }
137116 }
138117
139- function get (id) {
118+ function get (id, lookup) {
140119 if (!ref.isFeed(id)) throw new Error('Contact state requires an id!')
141120 if (!cacheLoading) {
142121 cacheLoading = true
143122 loadCache()
144123 }
145- if (!cache.has(id)) {
146- cache.put(id, Value({}))
124+ if (!lookup[id]) {
125+ lookup[id] = Value({})
147126 }
148- return cache.get(id)
127+ return lookup[id]
149128 }
150129 }
151130
152131 function isContact (msg) {
153132 return msg.value && msg.value.content && msg.value.content.type === 'contact'
154133 }
155-

Built with git-ssb-web