-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
TLDR;
You cannot reliably map data on an authenticated gun.user in the same way you can when using just gun.
Why is this bad. A practical example
Say you have some users. These users have groups. The groups have certain attributes.
You may want to map through the users groups, and do stuff with them. Currently this is not possible to do reliably.
What is going on?
When you do gun.get("groups").map().once(cb)
this will iterate all the groups.
All of the group's attributes will be available in the callback.
When you do user.get("groups").map().once(cb)
this will iterate the groups, if it is in the mood to do so.
Sometimes all the group's attributes will be available, sometimes only a subset of them.
Some numbers and variations
In the code example below we iterate the groups, and await the attributes. If we can await all of them we count that as a success.
I tested a few variations of the code, here are the results:
Testing on gun yields expected results:
This table shows expected results for groups with two and three attributes
number of attributes | iterations | iterations with all attributes present |
---|---|---|
2 | 1 | 1 |
2 | 2 | 2 |
2 | 3 | 3 |
2 | 4 | 4 |
2 | 5 | 5 |
2 | 100 | 100 |
3 | 1 | 1 |
3 | 2 | 2 |
3 | 3 | 3 |
3 | 4 | 4 |
3 | 5 | 5 |
3 | 100 | 100 |
Testing on gun.user yields unexpected results!
This table shows seemingly random behaviour.
Sometimes some values may be present. See images attached below.
number of attributes | iterations | iterations with all attributes present |
---|---|---|
2 | 1 | 1 |
2 | 2 | 2 |
2 | 3 | 3 |
2 | 4 | 4 |
2 | 5 | 5 |
2 | 20 | 11 |
2 | 100 | (4, 11 or 12, ...) |
3 | 1 | 1 |
3 | 2 | 2 |
3 | 3 | 3 |
3 | 4 | 2 |
3 | 5 | 2 |
3 | 20 | 2 |
3 | 100 | 2 |
A code example / test
//
// TEST SETUP
//
const iterations = 10;
// test on gun, test function returns number of correctly mapped items.
console.log("RUNNING GUN TESTS");
console.log(await test_consecutive(gun, iterations));
// test on authenticated gun.user().
console.log("RUNNING USER TESTS");
user.create("alice", "alicepass", () => {
user.auth("alice", "alicepass", async () => {
console.log(await test_consecutive(user, iterations));
});
});
//
// TEST FUNCTION
//
async function test_consecutive(gun_test, iterations) {
let num = 0;
gun_test.get("groups").map().once(async function() {
console.log(await this);
await this.get("one");
await this.get("two");
await this.get("three");
num += 1;
})
for(let i = 0; i < iterations; i++){
const group_pair = await SEA.pair();
const user_group = gun_test.get("groups").get(group_pair.pub);
user_group.get("one").put(Date.now());
user_group.get("two").put(Date.now());
user_group.get("three").put(Date.now()); // removing this line will make gun.user() be slightly less bad.
}
await new Promise(resolve => setTimeout(() => {resolve(true)}, 2000));
return num;
}