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

Browser DDP call promise never resolves #20

Open
hems opened this issue Apr 4, 2020 · 11 comments
Open

Browser DDP call promise never resolves #20

hems opened this issue Apr 4, 2020 · 11 comments

Comments

@hems
Copy link
Contributor

hems commented Apr 4, 2020

Good work on the package and plugins architecture ( :

Currently i tried:

  • login ( worked perfectly )
  • subscriptions ( worked perfectly )

But funny enough, when i tried to do a simple call to some method the returned promise never resolves.

I investigated a bit of the source code ( specifically the apply method ) and turns out:

  • methodId value is 0
  • onMethodResult is never called

Then basically the promise hangs forever and never resolves.

I have some Meteor "native code" using that same Meteor.method and it works normally, so i can confirm it's not a problem on the meteor side.

I'll let you know if I find any other clues about what might be causing that problem.

@hems
Copy link
Contributor Author

hems commented Apr 4, 2020

It seems it has something to do with the way arguments are sent.

I tried

server.call("hello", 5) // never resolved, meteor method code never executed
server.call("hello", [5]) // did resolve, method executed

@hems
Copy link
Contributor Author

hems commented Apr 4, 2020

The other problem i'm seeing is:

This works:

  • Meteor method gets called
  • Meteor return correct values
  • promise resolves with value
Meteor.methods({
  hello (limit = 5) {
    // do some database work
    return [{
      hello: "true"
    }]
  }
})

server.call('hello', [5] )

This does not work:

  • Meteor method gets called
  • Meteor method does some database work and returns an array of objects
  • promise never resolves
  • The method works as expected on the Meteor application, but not on simpleDDP
Meteor.methods({
  hello (limit = 5) {
    // do some database work
    const things = Things.find(myQuery).fetch()
    // actually return an array of items from the database, DONT WORK
    return things
  }
})

server.call('hello', [5] )

@hems
Copy link
Contributor Author

hems commented Apr 4, 2020

I found something that seems to nail what the problem is, although i don't know the solution yet:

This does not work:

  • Meteor method gets called
  • Meteor method does some database work and returns an array of objects
  • promise never resolves
  • My Meteor application works just fine
Meteor.methods({
  hello (limit = 5) {
    // do some database work
    const things = Things.find(myQuery).fetch()
    // actually return an array of items from the database, DONT WORK
    return things
  }
})

server.call('hello', [5] )

This works on both, Meteor Application and simpleDDP.

Meteor.methods({
  hello (limit = 5) {
    // do some database work
    const things = Things.find(myQuery).fetch()
    // actually return an array of items from the database, DONT WORK
    return JSON.parse(JSON.stringify(things))
  }
})

server.call('hello', [5] )

A funny thing is that, debugging ddp.js on simpleddp-core i found out that:

``` socket.on("message:in", function (message) {````

Won't receive a message with msg set to result on simpleDDP, while the Meteor application works anyway.

There is something wrong about the communication that for some reason the result don't get received by simpleDDP unless i do something funny with JSON on the server.

@hems hems changed the title DDP call promise never resolves Browser DDP call promise never resolves Apr 4, 2020
@hems
Copy link
Contributor Author

hems commented Apr 4, 2020

I just tried exactly same code on node.js:

  • the promise resolves to []

if i

JSON.parse(JSON.stringify(response))

Then it works as expected on node.js and on the browser.


The puzzling thing is that my Meteor application works as expected.

I'm using Meteor 1.8.1

Have you experienced anything similar?


I'll give up on debugging it further because I need to carry on with my app, let me know if you have experienced something similar or have an idea on how to fix it.

I can provide you with a sample app privately if you let me know your email.

@Gregivy
Copy link
Owner

Gregivy commented Apr 8, 2020

Really strange issue with call method. If your Meteor method accepts one argument for example, and you pass it as [5], your Meteor method should receive it as [5]. About the second issue it seems a problem with EJSON. Please provide the browser and its version and the version of simpleDDP you are using.

@Gregivy
Copy link
Owner

Gregivy commented Apr 8, 2020

You can create a secret gist of your Meteor method and your simpleDDP code then send me the link here gpoi.mail@gmail.com

@dennishu001
Copy link

I've got the same problem. Fortunately for me, I only got problems when requesting certain documents. Upon comparing the difference with other document, I found the problematic ones got ObjectIDs from workers using mongoose outside of Meteor.

The DDP client seems have trouble parsing non standard data object, hence JSON.stringify/JSON.parse can mitigate the problem. You may want to check if this is the case.

@Gregivy
Copy link
Owner

Gregivy commented Jun 4, 2020

It could be possible. Both Meteor DDP and simpleDDP uses EJSON not JSON (https://docs.meteor.com/api/ejson.html). However Mongo.ObjectID is not included in EJSON by default, so you should do it manually (read more here https://github.com/Gregivy/simpleddp/blob/master/custom_ejson.md):

import EJSON from 'ejson';

class MongoObjectId {
  constructor(value) {
    this.value = value;
  }

  // Convert our type to JSON.
  toJSONValue() {
    return this.value;
  }

  // Unique type name.
  typeName() {
    return 'oid';
  }
}

EJSON.addType('oid', function fromJSONValue(str) {
  return new MongoObjectId(str);
});

Do it before creating simpleDDP instance. If you also want to create MongoId on client and send it on server, the MongoObjectId class would become more complicated (see https://github.com/meteor/meteor/blob/d8042c8fa9dd0cc53604b2729ac33333a2ce5b73/packages/mongo-id/id.js)

@hems
Copy link
Contributor Author

hems commented Jun 10, 2020

Really strange issue with call method. If your Meteor method accepts one argument for example, and you pass it as [5], your Meteor method should receive it as [5].

Turns out this was a bug on my abstraction ( as you could imagine ), so that's solved for me.

@hems
Copy link
Contributor Author

hems commented Jun 10, 2020

It could be possible. Both Meteor DDP and simpleDDP uses EJSON not JSON (https://docs.meteor.com/api/ejson.html). However Mongo.ObjectID is not included in EJSON by default, so you should do it manually (read more here https://github.com/Gregivy/simpleddp/blob/master/custom_ejson.md):

Yes indeed it seems to be something related to this issue.

The funny part tough is that Meteor version of the DDP Client don't have this issue ( as i said, the same subscription that got stuck for me with DDPClient did not get stuck on the Meteor Client), i wonder if there is an easy way to "copy" the solution Meteor DDP uses and implement it on the DDP Client transparently?

@Gregivy
Copy link
Owner

Gregivy commented Jun 14, 2020

@hems I think it will be easier if you publish here the structure with data types of the object because I am not sure about easy copying of all custom ejsons :(

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

3 participants