-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow adding people back into a group #94
Changes from 9 commits
0bbdb6f
dac5f95
3300be8
2adacce
6ab4392
78f7a2f
2f5dd62
f78855e
4a11afc
60048d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -119,47 +119,50 @@ function init (ssb, config) { | |
} | ||
|
||
pull( | ||
listen.addMember(ssb), | ||
// combined listeners so we process them in a deterministic order on client restarts | ||
listen.mutateMembers(ssb), | ||
pull.asyncMap((m, cb) => { | ||
const { root, groupKey } = m.value.content | ||
ssb.get({ id: root, meta: true }, (err, groupInitMsg) => { | ||
if (err) throw err | ||
|
||
const groupId = buildGroupId({ groupInitMsg, groupKey }) | ||
const authors = unique([ | ||
groupInitMsg.value.author, | ||
m.value.author, | ||
...m.value.content.recps.filter(isFeed) | ||
]) | ||
|
||
const record = keystore.group.get(groupId) | ||
// if we haven't been in the group since before, register the group | ||
if (record == null) { | ||
return keystore.group.add(groupId, { key: groupKey, root }, (err) => { | ||
if (err) return cb(err) | ||
if (m.value.content.type === 'group/add-member') { | ||
const { root, groupKey, recps } = m.value.content | ||
const membersAdded = recps.slice(1) | ||
|
||
ssb.get({ id: root, meta: true }, (err, groupInitMsg) => { | ||
if (err) throw err | ||
|
||
const groupId = buildGroupId({ groupInitMsg, groupKey }) | ||
const authors = unique([ | ||
groupInitMsg.value.author, | ||
m.value.author, | ||
...m.value.content.recps.filter(isFeed) | ||
]) | ||
|
||
//const record = keystore.group.get(groupId) | ||
//const inGroup = record && record.excluded === undefined | ||
|
||
if (membersAdded.includes(ssb.id)){// && !inGroup) { | ||
return keystore.group.add(groupId, { key: groupKey, root }, (err) => { | ||
if (err) return cb(err) | ||
processAuthors(groupId, authors, m.value.author, cb) | ||
}) | ||
} else { | ||
processAuthors(groupId, authors, m.value.author, cb) | ||
}) | ||
} | ||
}) | ||
} else { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. make this an |
||
// if exclude member msg | ||
|
||
const excludes = m.value.content.excludes | ||
const groupId = m.value.content.recps[0] | ||
|
||
if (excludes.includes(ssb.id)) { | ||
keystore.group.exclude(groupId, cb) | ||
} else { | ||
processAuthors(groupId, authors, m.value.author, cb) | ||
cb() | ||
} | ||
}) | ||
} | ||
}), | ||
pull.drain(() => {}, (err) => { | ||
if (err) console.error('Listening for new addMembers errored:', err) | ||
}) | ||
) | ||
|
||
pull( | ||
listen.excludeMember(ssb), | ||
pull.drain((msg) => { | ||
const excludes = msg.value.content.excludes | ||
const groupId = msg.value.content.recps[0] | ||
|
||
if (excludes.includes(ssb.id)) { | ||
keystore.group.exclude(groupId) | ||
} | ||
}, err => { | ||
if (err) console.error('Listening for new excludeMembers errored:', err) | ||
if (err) console.error('Listening for new addMember and excludeMember messages errored:', err) | ||
}) | ||
) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,24 +10,21 @@ const mockSSB = { backlinks: true, query: true } | |
const { isUpdate: isPOBox } = new CRUT(mockSSB, poBoxSpec).spec | ||
|
||
module.exports = { | ||
addMember (ssb) { | ||
return pull( | ||
ssb.messagesByType({ type: 'group/add-member', private: true, live: true }), | ||
// NOTE this will run through all messages on each startup, which will help guarentee | ||
// all messages have been emitted AND processed | ||
// (same not true if we used a dummy flume-view) | ||
pull.filter(m => m.sync !== true), | ||
pull.filter(isAddMember), | ||
pull.unique('key') | ||
// NOTE we DO NOT filter our own messages out | ||
// this is important for rebuilding indexes and keystore state if we have to restore our feed | ||
) | ||
}, | ||
excludeMember (ssb) { | ||
mutateMembers (ssb) { | ||
const query = [{ | ||
$filter: { | ||
value: { | ||
content: { | ||
type: { $in: ['group/add-member', 'group/exclude-member'] } | ||
} | ||
} | ||
} | ||
}] | ||
|
||
return pull( | ||
ssb.messagesByType({ type: 'group/exclude-member', private: true, live: true }), | ||
ssb.query.read({ query, old: true, live: true }), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔥 this will LIKELY scan the whole database. With DB1 the way to check if you have a flume-view index supporting you, or if it's falling back to scan whole db is https://www.npmjs.com/package/ssb-query#queryexplain-query console.log(ssb.query.explain({ query, old: true, live: true })) I think you should stick with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think if you're trying to improve things by reducing the number of pull-streams that are live, then db2 will help with this. It's indexes are a lot more flexible There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i checked pull-merge but it said it removes duplicates, so doing it this way seemed easier There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i didn't want things to break if 2 msgs had the same timestamp |
||
pull.filter(m => m.sync !== true), | ||
pull.filter(isExcludeMember), | ||
pull.filter(msg => isAddMember(msg) || isExcludeMember(msg)), | ||
pull.unique('key') | ||
) | ||
}, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -129,7 +129,6 @@ module.exports = function GroupMethods (ssb, keystore, state) { | |
), | ||
pull.map(msg => msg.value.content.recps.slice(1)), | ||
pull.flatten(), | ||
pull.unique(), | ||
pull.collect((err, addedMembers) => { | ||
if (err) return cb(err) | ||
|
||
|
@@ -151,13 +150,34 @@ module.exports = function GroupMethods (ssb, keystore, state) { | |
), | ||
pull.map(msg => msg.value.content.excludes), | ||
pull.flatten(), | ||
pull.unique(), | ||
pull.collect((err, excludedMembers) => { | ||
if (err) return cb(err) | ||
|
||
// NOTE: this currently prevents people who've been removed from being re-added | ||
// https://github.com/ssbc/ssb-tribes/issues/79 | ||
const members = addedMembers.filter(addedMember => !excludedMembers.includes(addedMember)) | ||
// calculate if the person has been added more times than they've been removed | ||
// this is kind of basic but works. although lol people can add themselves back | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔥 this crude version won't work sorry D: The problem is if I add you to a Batts Group at the same time as Staltz adds you, then you've technically been added "twice", even though that addition was idempotent. Then I remove you ... then you've been added twice and removed once... so according to this you're in the group, even though you may have honoured the exclusion. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. mm ok i based this solution on a discussion we had at some point. a simple solution could be to check this algorithm also whenever we receive something in the mutateMembers stream? to have the 2 systems match up, avoiding mismatches. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's try the tangle stuff in a separate pr instead #95 |
||
// a fancier version would check the members tangle and maybe the author of the additions/exclusions | ||
const numAdded = {} | ||
|
||
addedMembers.forEach(addedMember => { | ||
if (numAdded[addedMember] === undefined) { | ||
numAdded[addedMember] = 0 | ||
} | ||
numAdded[addedMember]++ | ||
}) | ||
|
||
excludedMembers.forEach(excludedMember => { | ||
if (numAdded[excludedMember] !== undefined) { | ||
numAdded[excludedMember]-- | ||
} | ||
}) | ||
|
||
Object.keys(numAdded).forEach(member => { | ||
if (numAdded[member] < 1) { | ||
delete numAdded[member] | ||
} | ||
}) | ||
|
||
const members = Object.keys(numAdded) | ||
|
||
return cb(null, members) | ||
}) | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ const listen = require('../listen') | |
// TODO this is... not listen any more | ||
// we may need to rename this | ||
|
||
test('listen.addMember', t => { | ||
test.skip('listen.addMember', t => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO (undo skip) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the addMember listener is removed though. so just remove the test too? although we'll see after i've rewritten stuff again |
||
const alice = Server() | ||
const bob = Server() | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comments need tidyup