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

Fawn Dropping out of task without hitting catch. #14

Closed
thedanielfactor opened this issue Aug 4, 2017 · 11 comments
Closed

Fawn Dropping out of task without hitting catch. #14

thedanielfactor opened this issue Aug 4, 2017 · 11 comments

Comments

@thedanielfactor
Copy link

thedanielfactor commented Aug 4, 2017

I have a schema that works under normal mongoose CRUD. This schema and session_friend.js work with Fawn when I use it under a simple Express project setup. But when I am moving this code to a larger API it seems to be falling down. I assume it is related to where the require happens but here is a simple version of what I am doing.

Structure Snippet:

server.js  - Main node js file.
      '------- /config/config.js
      '------- /custom_modules/util.js - Main anchor for include objects (mongoose, fawn, twilio, etc...)
      '------- /api/** - Custom api routes:
      '------- /api/session/model/Session.js - Session Schema - Contains fawn tasks
      '------- /api/session/session.js - Route code.

util.js

NOTE: Promise is a global for BlueBird promises.

...
var mongoose = require('mongoose');
var uri = Config.get("SESSION.mongodburi");

mongoose.Promise = Promise;
mongoose.connect(uri);
var Fawn = require('fawn');
Fawn.init(mongoose, "fawn_task_cache", {promiseLibrary: Promise});
...
module.exports = {
    ...
    mongoose: mongoose,
    fawn: Fawn
}

/api/session/session_friend.js

var build = require('../presence/build_functions');

util.mongoose.Promise = Promise;

// Model Objects
var UserPresence = require('../presence/model/UserPresence');
var GroupSession = require('./model/GroupSession');

// ROUTE '/session/friend/:friendId'
module.exports = {
    post: function (req, res) {
        var userPrincipal = build.getUserPrincipal(req.headers['x-access-token']);

        console.log("*** UserPrincipal " + userPrincipal.userId);
        console.log("*** req.params.friendId : " + req.params.friendId);

        if (userPrincipal.userId && req.params.friendId) {
            UserPresence.findById(req.params.friendId).then(function (friendPresence) {
                if (friendPresence && friendPresence.sessionId) {
                    console.log("**** We Got Presence! ****");
                    var task = util.fawn.Task();
                    console.log("*** Lets use some tasks time...");
                    // Add the session to the user and add the user to the session.  Do it in a "transaction".
                    task.update("UserPresence", {_id: userPrincipal.userId}, {sessionId: friendPresence.sessionId})
                        .update("GroupSession", {_id: friendPresence.sessionId}, {$push: {userList: userPrincipal.userId}})
                        .run({useMongoose: true})
                        .then(function () {
                            GroupSession.findById(friendPresence.sessionId)
                                        .then(function (session) {
                                            session.userList = [];
                                            res.send(session);
                                        });
                        }).catch(function (err) {
                            res.send(err);
                        });
                } else if (!friendPresence.sessionId) {
                    console.log("**** We Not Gottem! ****");

                    var groupSession = new GroupSession();

                    groupSession.userList = [req.params.friendId, userPrincipal.userId];
                    groupSession.hosted = false;

                    console.log("**** Group Session: " + JSON.stringify(groupSession));
                    var task = util.fawn.Task();
                    // Create the session, add both users get updated.
                    task.save(GroupSession, groupSession)
                        .update("UserPresence", {_id: userPrincipal.userId}, {sessionId: {$ojFuture: "0._id"}})
                        .update("UserPresence", {_id: req.params.friendId}, {sessionId: {$ojFuture: "0._id"}})
                        .run({useMongoose: true})
                        .then(function (results) {
                            console.log("**** After Save Group Session: " + JSON.stringify(results[0]));
                            // Update of users sessions complete.
                            var gsess = results[0];
                            console.log("Saved Group Session " + gsess.userList);
                            gsess.userlist = [];
                            res.send(gsess);
                        })
                        .catch(function (err) {
                            console.log("****** " + err);
                            res.send(err);
                        });
                }
            });
        }
    }
}

When I get to this code all three steps are created in the fawn cache table but then the api hangs because nothing is returned. On the console I get the following warning.

(node:2996) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html```
and the state of step 1 is set to "1", the others are still "0".  I do not get any error.  It just appears to exit the process abruptly.```

![fawncache](https://user-images.githubusercontent.com/448370/28986618-5879c006-792d-11e7-9de2-c12715e0e856.png)

@e-oj
Copy link
Owner

e-oj commented Aug 5, 2017

Is this happening in other areas of the app? Also, do the updates in the "if" block work? It's strange that there are no errors. Try updating your version of mongoose; that might fix the deprecation warning (Automattic/mongoose#4951 (comment))

@e-oj
Copy link
Owner

e-oj commented Aug 5, 2017

Also, try running the task with {useMongoose: false}

@thedanielfactor
Copy link
Author

thedanielfactor commented Aug 6, 2017

I am using mongoose 4.11.5 and node 6.11.1. This is the only place I use Fawn. All other places work great with Mongoose. Like I mentioned in my original statement. This works great when I am using a very simple setup. The following setup works great.

server.js - Main node js.
    '------ /routes/groupsession.js - Route file.  
    '------ /model/GroupSession.js - Schema file.

server.js

var express = require('express');
var app = express();
var Promise = require('bluebird');
...
// MongoDB
var mongoose = require('mongoose');
var uri = 'mongodb://localhost:27017/vertigo-session';
mongoose.Promise = require('bluebird');
mongoose.connect(uri);
...
app.use('/presence', presenceRouter);
app.use('/groupsession', sessionRouter);
...

groupsession.js

var Promise = require('bluebird');
var mongoose = require('mongoose');
var Fawn = require('fawn');
const uuidv4 = require('uuid/v4');

// Model Objects
var UserPresence = require('../model/UserPresence');
var GroupSession = require('../model/GroupSession');

Fawn.init(mongoose);

var sessionRouter = express.Router();
...
sessionRouter.route('/friend/:friendId')
    .post(function(req, res) {
        logger.debug("Joining friend " + req.params.userId);
        if (req.userPrincipal && req.params.friendId) {
            UserPresence.findById(req.params.friendId).then(function(friendPresence) {
                if (friendPresence && friendPresence.sessionId) {
                    var task = Fawn.Task();
                    // Add the session to the user and add the user to the session.  Do it in a "transaction".
                    task.update("UserPresence", {_id: req.userPrincipal.userId}, {sessionId: friendPresence.sessionId})
                        .update("GroupSession", {_id: friendPresence.sessionId}, {$push: {userList: req.userPrincipal.userId}})
                        .run({useMongoose: true})
                        .then(function () {
                            GroupSession.findById(friendPresence.sessionId).then(function (session) {
                                session.userList = [];
                                res.send(session);
                            });
                        }).catch(function (err) {
                            res.send(err);
                        });
                } else if (!friendPresence.sessionId) {
                    var groupSession = new GroupSession();
                    groupSession.userList = [req.params.friendId, req.userPrincipal.userId];
                    groupSession.hosted = false;

                    var task = Fawn.Task();
                    // Create the session, add both users get updated.
                    task.save(GroupSession, groupSession)
                        .update("UserPresence", {_id: req.userPrincipal.userId}, {sessionId: {$ojFuture: "0._id"}})
                        .update("UserPresence", {_id: req.params.friendId}, {sessionId: {$ojFuture: "0._id"}})
                        .run({useMongoose: true})
                        .then(function (results) {
                            // Update of users sessions complete.
                            var gsess = results[0];
                            console.log("Saved Group Session " + gsess.userList);
                            gsess.userlist = [];
                            res.send(gsess);
                        })
                        .catch(function (err) {
                            debugger;
                            res.send(err);
                        });
                }
            });
        } else {
            res.status(403).send("You do not have rights to visit this page");
        }
    });

module.exports = sessionRouter;

@e-oj
Copy link
Owner

e-oj commented Aug 6, 2017

I've tried to reproduce this locally but I can't.

utils.js

var mongoose = require("mongoose");
var Fawn = require("../index");

mongoose.Promise = require("bluebird");
mongoose.connect("mongodb://127.0.0.1:27017/AnimalDB", {useMongoClient: true});
Fawn.init(mongoose, "_tasks_");

exports.mongoose = mongoose;
exports.Fawn = Fawn;

db.js

var utils = require("./utils");

var Animals = utils.mongoose.model("Animals", new utils.mongoose.Schema({
  name: String
  , color: String
  , bipedal: Boolean
}));

var animal1 = new Animals({
  name: "Bob"
  , color: "magenta"
  , bipedal: true
});

var animal2 = new Animals({
  name: "Giraffe"
  , color: "yellow"
  , bipedal: false
});

animal2.save()
  .then(function(giraffe){
    utils.Fawn.Task()
      .save(Animals, animal1)
      .update("Animals", {_id: giraffe._id}, {color: {$ojFuture: "0.color"}})
      .run({useMongoose: true})
      .then(function(results){
        console.log(results);
      });
  });

This works for me so your setup is good. It's difficult to figure out what the problem is without reproducing it. Does it work if you run the task with {useMongoose: false}?

@thedanielfactor
Copy link
Author

thedanielfactor commented Aug 7, 2017

If I set {useMongoose: false} I get the following error in both versions of my app.
****** Error: No such key exists in result {"n":1,"ok":1} at index0

In the small working version and the large API I have added my work to.

@thedanielfactor
Copy link
Author

I did notice one difference in what you are doing is that my util.js is setup as a global. So i do not require it.

@e-oj
Copy link
Owner

e-oj commented Aug 7, 2017

if you set {useMongoose: false} it returns the node-mongodb-native result. you can access the value with {sessionId: {$ojFuture: "0.ops.0._id"}}

@e-oj
Copy link
Owner

e-oj commented Aug 7, 2017

{"n":1,"ok":1} means the save was successful. So for some reason, saving with mongoose isn't working in your case but using the native driver works. Your setup seems fine; I made my utils global and it still worked. You said it just hangs and gives the promise warning?

@thedanielfactor
Copy link
Author

Well, I figured out that it does not "hang" it just exits the fawn transaction but does not hit the catch. I added res.send({message: "End of the line."}) after the task statement and I got that back. So the "hang" comes from the promise failing somewhere but not hitting the catch.

e-oj pushed a commit that referenced this issue Aug 7, 2017
@e-oj e-oj added the bug label Aug 7, 2017
@e-oj
Copy link
Owner

e-oj commented Aug 7, 2017

@thedanielfactor So I was eventually able to reproduce and fix this issue. Update your Fawn version and it should work fine. Thanks for your patience and help with this and sorry for the inconvenience. Feel free to reopen this issue if the problem persists.

@e-oj e-oj closed this as completed Aug 7, 2017
@thedanielfactor
Copy link
Author

Works Great!!!! Thanks for the fast response and for working through this with me!

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

No branches or pull requests

2 participants