Skip to content
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

Bugs with "map([cb])" and following once / on #1315

Open
pwFoo opened this issue Apr 7, 2023 · 8 comments
Open

Bugs with "map([cb])" and following once / on #1315

pwFoo opened this issue Apr 7, 2023 · 8 comments

Comments

@pwFoo
Copy link

pwFoo commented Apr 7, 2023

Hi,

tested some map() filters as shown in documentation here: https://gun.eco/docs/API#-a-name-map-a-gun-map-callback-

Test data

gun.get("test").get("people").set({name: "Mark"})
gun.get("test").get("people").set({name: "Dex"})
gun.get("test").get("people").set({name: "Bob"})

Filtering "once" without a gun listener seems to work fine with single object of user "Mark".

gun.get("members").once().map(user => user.name === 'Mark'? user : undefined).once((user, id) => console.log(id, user))

Output:

lg6buomqJ9NiZGkjUzXi {_: {…}, name: 'Mark'}

Same with debugging output and return the "user" object in map callback

gun.get("test").get("people").once().map(user => { console.log("MAP DEBUG", user); return user }).once((user, id) => console.log(id, user))

Output:

MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Dex'}
MAP DEBUG {_: {…}, name: 'Dex'}

lg6c5n0e0llD26gR65UV {_: {…}, name: 'Bob'}
lg6c5pm4bszPj4VNFsMl {_: {…}, name: 'Mark'}
lg6c5sgtz6OPlaj9aJ2Q {_: {…}, name: 'Dex'}

Problem 1
If I remove the first once before map([cb]) the second once or also on callback isn't triggered anymore?

gun.get("test").get("people").map(user => { console.log("MAP DEBUG", user); return user }).once((user, id) => console.log(id, user))

Example output

MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Dex'}
Gun {_: {…}}

Expected output

MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Dex'}

lg6c5n0e0llD26gR65UV {_: {…}, name: 'Bob'}
lg6c5pm4bszPj4VNFsMl {_: {…}, name: 'Mark'}
lg6c5sgtz6OPlaj9aJ2Q {_: {…}, name: 'Dex'}

Problem 2:
Execute following code multipe times more and more listeners added!

gun.get("test").get("people").once().map(user => { console.log("MAP DEBUG", user); return user }).once((user, id) => console.log(id, user))

First time result of once is as expected. MAP DEBUG output twice...

MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Dex'}
MAP DEBUG {_: {…}, name: 'Dex'}

lg6c5n0e0llD26gR65UV {_: {…}, name: 'Bob'}
lg6c5pm4bszPj4VNFsMl {_: {…}, name: 'Mark'}
lg6c5sgtz6OPlaj9aJ2Q {_: {…}, name: 'Dex'}

Second time of execution same result of once, but increased MAP DEBUG output?

MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Dex'}
MAP DEBUG {_: {…}, name: 'Dex'}
MAP DEBUG {_: {…}, name: 'Dex'}
MAP DEBUG {_: {…}, name: 'Dex'}

lg6c5n0e0llD26gR65UV {_: {…}, name: 'Bob'}
lg6c5pm4bszPj4VNFsMl {_: {…}, name: 'Mark'}
lg6c5sgtz6OPlaj9aJ2Q {_: {…}, name: 'Dex'}

Third time...

MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Bob'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Mark'}
MAP DEBUG {_: {…}, name: 'Dex'}
MAP DEBUG {_: {…}, name: 'Dex'}
MAP DEBUG {_: {…}, name: 'Dex'}
MAP DEBUG {_: {…}, name: 'Dex'}
MAP DEBUG {_: {…}, name: 'Dex'}
MAP DEBUG {_: {…}, name: 'Dex'}

lg6c5n0e0llD26gR65UV {_: {…}, name: 'Bob'}
lg6c5pm4bszPj4VNFsMl {_: {…}, name: 'Mark'}
lg6c5sgtz6OPlaj9aJ2Q {_: {…}, name: 'Dex'}

And with each execution the MAP CALLBACK is triggered two times more... Looks like map(cb) adds Gun listener for each execution?
Result of once is still the same / ok.

Problem 3:
With once().map([cb]).on(cb) the "on() callback" is triggered twice compared to "once()"?

gun.get("test").get("people").once().map().on((user, id) => console.log(id, user))

Output:

lg6c5n0e0llD26gR65UV {_: {…}, name: 'Bob'}
lg6c5n0e0llD26gR65UV {_: {…}, name: 'Bob'}
lg6c5pm4bszPj4VNFsMl {_: {…}, name: 'Mark'}
lg6c5pm4bszPj4VNFsMl {_: {…}, name: 'Mark'}
lg6c5sgtz6OPlaj9aJ2Q {_: {…}, name: 'Dex'}
lg6c5sgtz6OPlaj9aJ2Q {_: {…}, name: 'Dex'}

Same with once().map().once(cb) works as expected with one output for each object.
Maybe not related to map(cb) topic and just once / on... I'm not sure

@amark
Copy link
Owner

amark commented May 11, 2023

well detailed! Thank you. You're correct. Interested in adding these to the unit tests? starts around https://github.com/amark/gun/blob/master/test/common.js#L3439 , or better (since its low priority for me) trying to fix? Can do a video call if need.

@pwFoo
Copy link
Author

pwFoo commented May 20, 2023

Hi @amark,
I tried to solve these problems, but unfortunately i didn't understand how Gun map() internally works. I gave it up some time ago...

@amark
Copy link
Owner

amark commented May 21, 2023

@pwFoo thanks for trying tho. Maybe when higher priority items are off the checklist (oof... taking a long time) then can do a screen call on this piece.

@pwFoo
Copy link
Author

pwFoo commented May 30, 2023

I think listeners increasing because of that on()? Also tried to remove listener inside of the callback, but without success
But callback code and used gun parts are not understandable for me :(

gun.map().on(function(data, key, msg, eve){
		var next = (cb||noop).call(this, data, key, msg, eve);
		if(u === next){ return }
		if(data === next){ return chain._.on('in', msg) }
		if(Gun.is(next)){ return chain._.on('in', next._) }
		var tmp = {}; Object.keys(msg.put).forEach(function(k){ tmp[k] = msg.put[k] }, tmp); tmp['='] = next; 
		chain._.on('in', {get: key, put: tmp});
	});

So each time it's called another listener is added?

Or lines like that

(cat.each = chain = gun.chain())._.lex = lex || chain._.lex || cat.lex;

or the map code if called without callback

if(!cb){
		if(chain = cat.each){ return chain }
		(cat.each = chain = gun.chain())._.lex = lex || chain._.lex || cat.lex;
		chain._.nix = gun.back('nix');
		gun.on('in', map, chain._);
		return chain;
	}

I think it would be easier for you to fix the bug instead of explain to me how the code works.

@pwFoo
Copy link
Author

pwFoo commented May 30, 2023

I started my project based on Gun / SEA to have a working base (offline first, encryption, ...).
Countless hours of troubleshooting over weeks have frustrated me. I stopped the project to wait for further development and bugfixes within Gun.

I'm not clear if Gun has reached EOS / EOL or your higher priority projects / tasks are based on Gun?

Despite the bugs. Gun is an impressive project with a lot of potential. I would like to see an active support team and improved documentation / code base with comments to push Gun further.
Gun is awesome project! Great job, @amark !

@draeder
Copy link
Contributor

draeder commented May 30, 2023

@pwFoo This may help.. You can work around duplicate data like so:

let last
gun.get("graph").get("subgraph").on(data => {
  if(data == last) return
  last = data
})

However, if your code is creating multiple listeners for the same thing, it can lead to memory leaks.

@pwFoo
Copy link
Author

pwFoo commented May 30, 2023

@draeder
Increasing count of listener and potential memory leaks should be fixed too, but isn't the show stopper at the moment.
The map(cb) bug stopped me from building my planned app and waiting for bugfixes and stable gun.js.

@gustavcorpas
Copy link

Anybody know what is the status on this?

I just ran some additional tests, that gave curious results....

In some situations the map function will work correctly. It seem to be a timing issue.
The effects of this seem to be that you can use the map(cb) in certain situations, page loading and possibly when mounting components in js-frameworks, but it will not work in a function that runs later (user button press etc.)

Test results

Test1 (Works)

MAP DEBUG {_: {…}, name: 'Mark'}
lo5rg... {_: {…}, name: 'Mark'}

Test2 (Unexpected result)

MAP DEBUG {_: {…}, name: 'Mark'}
// missing response from once call.

Test code

// test1 works
function test1(){
    gun.get("test1").get("people").set({name: "Mark"}) }

    gun.get("test1").get("people").map(user => { 
        console.log("MAP DEBUG 1", user); return user 
    }).once((user, id) => console.log(id, user));
}

// test2 does not work
async function test2(){
    gun.get("test2").get("people").set({name: "Mark"})

    await delay(2); // added this.

    gun.get("test2").get("people").map(user => { 
        console.log("MAP DEBUG 2", user); return user 
    }).once((user, id) => console.log(id, user))};
}

Any insight into this would be greatly appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants