1

I have some code as listed:

function write_to_orchestrate(data_to_write) {

    console.log('more testing');

    db.put('musician', '1', '{"test":"test1"}')
        .then(function (result) {
            res.send(result);
        })
        .fail(function (err) {
            res.send(err);
        });

    console.log('something');

}

It appears, that even though I have breakpoints on the res.send() function calls in the .then and .fail of the db.put function call it isn't stopping for any of them. However both console.log('more testing'); and console.log('something'); are reached without error.

I'm using Webstorm, but even when I just execute this code regularly with a terminal and text editor it appears that the code for db.put(...) is just being skipped somehow. Any ideas on additional troubleshooting/debugging?

I've also noted that the data source that this call is issuing a put to is also live and accepting commands. Just to be sure I issued several curl commands and gets to insure that the data is going in and coming out just fine.

Here's a video explaining what is going on: http://youtu.be/CKq69z4ml8o

UPDATE #1: I also tried per the suggestion making '{"test":"test1"}' into {"test":"test1"} which seemed like a good idea, still no go.

UPDATE #2: Per @hafthor I tried another suggestion and implemented the code like this to eliminate possible semi-colon issues.

function write_to_orchestrate(data_to_write) {

    console.log('more testing');

    db.put('musician', '1', {"test":"test1"}).then(function (result){res.send(result);}).fail(function (err) {res.send(err);});

    console.log('something');

}

It still didn't but I did find upon running the code and debugging in WebStorm that the code gets to the db.put, but then I try to step into the code and it just goes straight to the .fail, then skips out and ends up at the console.log('something'); line.

Also, another video for some more attempts at getting this to work: http://www.youtube.com/watch?v=rItBhyfG5AY

Adron
  • 1,698
  • 3
  • 19
  • 40
  • You are sending data to a remote database correct? Is that database working correctly? The then/fail function is only executed once a result is known. Perhaps the remote machine is taking a long time to respond. – diolemo Jan 08 '14 at 00:01
  • Added an update to the question to clarify the remote database's status. Good question. – Adron Jan 08 '14 at 00:05
  • 1
    Is your program exiting before the puts take place? It's hard to tell without more context, but if this module executes straight through and then exits it's possible the event queue never got around to running those async puts. – drhayes Jan 22 '14 at 22:29

7 Answers7

2
  1. You've failed to make explicit the database module you're using. Based on context clues it looks like this orchestrate module, is that correct?
  2. OMG the youtube! Put your code in your question. Including where you initialize db, it's the most important part, and it allows you to hide your token by just changing the text you post here... you'll either want to take down those videos or change your token, you've hopelessly compromised your security in the first video. Yes, it's blurry, but not that blurry.

OK, your first troubleshooting step is to create a simplified script. My guess is that you're somehow using the module incorrectly. Try this:

var db = require('orchestrate')('SUPER SECRET TOKEN THAT SHOULD NOT BE IN A YOUTUBE VIDEO');

console.log('before query');
db.put('musician', '1', {test: 'test1'})
    .then(function (result) {
        console.log('THEN!!!');
        console.log(result);
    })
    .fail(function (err) {
        console.log('FAIL!!!');
        console.log(err);
    });
console.log('after query');

... there's several important things I want you to take note of here:

  • Hide your token (seriously, hide your token)
  • I'm working from the documentation for the module I linked, but if you're using something different or have modified it in any way, all of this advice is suspect
  • Per @nhaa123s comment, and the documentation, the value is an object literal, not a JSON string, so I've made that adjustment
  • According to the linked docs, musician is the collection name, 1 is the key you're trying to set (this seems an odd key name, but whatever), and {test:'test1'} is the data structure you're using for your value. I've never used orchestrate, please make sure you've properly initialized musician if you need to, and please confirm that it will support strictly numeric keys, like 1 (or, better yet, use a more traditional key type like testkey)
  • I used console.log so you can confirm that the callbacks are being executed more simply.

... you might see several different outcomes, depending on where the problem actually lies. If you are using the database module correctly, then you should execute the .then() callback and know that the problem lies in how you're incorporating it into your code. If it fails and you get the fail messages on the console, you'll see the actual error and that might lead you in the right direction. If you never call the .then() or .fail() callback, then the orchestrate module may not be ready for prime time, or you have some incompatibility in your dependency chain.

If you can successfully execute that snippet, your next step is to copy the db.put().then().fail(); chain into your write_to_orchestrate() function without any modification, removing the existing chain. If it still works, then you've solved your db problem, if not, then my first guess is some sort of scope issue, but it's impossible to tell without seeing more code.

Now, I believe you definitely have a scope problem with your response object, hence why you never sent anything.

Add this to your write_to_orchestrate() function, at the top:

function write_to_orchestrate(data_to_write) {
    if (res === undefined) console.log("This is not the response you're looking for");
    else console.log("Just kidding, you're (probably) good");

    // etc.
}

If you find that res is not accessible in your function, you just need to find a way to get it in scope, perhaps by sending it along with data_to_write:

function write_to_orchestrate(data_to_write, res) {
    if (res === undefined) console.log("The problem clearly exists even further up the chain");
    else console.log("Ah, just as we expected");

    // etc.
}

... that should set you on the right path.

Jason
  • 13,606
  • 2
  • 29
  • 40
  • Also this got me headed in the right direction. I also went and started doing some BDD/TDD along these lines and ended up with an easy tests pattern for asynchronous code using done: http://stackoverflow.com/questions/21175123/how-do-i-use-mocha-to-do-asynchronous-tests-using-done – Adron Jan 28 '14 at 18:50
1

Try replacing '{"test":"test1"}' to {"test":"test1"}.

nhaa123
  • 9,570
  • 11
  • 42
  • 63
1

Just a thought, have you tried overloading the db.put function?

var _put = db.put; db.put = function(a,b,c){ console.log('yep'); return _put(a,b,c); }

jeffmayeur
  • 1,008
  • 6
  • 3
1

Upon watching your second video, it appears that you are expecting the functions to get executed as you step over their assignments. (e.g. 47s into the second video). What you are actually doing is assigning db.put the function(a, b, c), not executing it. So, there it makes sense that it skips over the body as you noted in the video.

However, it should eventually execute it. Is it skipping over breakpoints you put in it?

Since I don't know anything about Webstorm, I think the most reliable way to get it to break in your then and fail functions is to put explicit debugger statements like so:

function write_to_orchestrate(data_to_write) {

console.log('more testing');

db.put('musician', '1', '{"test":"test1"}')
    .then(function (result) {
        debugger;
        res.send(result);
    })
    .fail(function (err) {
        debugger;
        res.send(err);
    });

console.log('something');

}

Then run it through native Node debugger:

node debug yourapp.js

In the debugger, type C to continue, then it should stop when it hits a debugger statement.

Jim
  • 1,014
  • 1
  • 11
  • 22
  • Yup. It never seems to capture any of the .then or .fail code. I know the db.put is nonblocking but I'm lost as to why nothing is ever occurring past that. Theoretically one of those two things should eventually execute. Right? – Adron Jan 08 '14 at 01:10
  • Well, I don't know which database module you're using, so I can't say that's true, but that is reasonable. I updated my answer with an alternative debugging test you could try. – Jim Jan 08 '14 at 01:15
1

I'm not sure it's possible to answer the question without more detail on the rest of your program, but it looks like this is a classic "why does my asynchronous code not run synchronously?" question (there are a ton of these on SO - here's the canonical example).

db.put() is almost certainly asynchronous - it looks like it returns a promise, so that when your asynchronous database write is finished, it will execute either the .then() function or the .fail() function. The key thing to understand here is that these functions are not executed in the same stack as the rest of the code - they happen at some unspecified future time, so the execution looks like this:

// initial stack
console.log('more testing');
db.put(...);
console.log('something');

// ... time passes, the call stack is cleared
// ... the database returns a status message
// new stack:
res.send(result);

My best guess is that either:

  1. your program exits before the database returns its status message, or
  2. your program is still running, but res has changed and isn't a usable stream anymore, or
  3. your database write dies silently.

(2) can be ruled out with breakpoints or console.log calls in the callbacks, which it looks like you've tried. (3) is unlikely if the database module is stable. (1) is hard to evaluate without seeing the rest of your code, but seems the most likely.

If you understand all this and were expecting asynchronous callbacks, then never mind.

Community
  • 1
  • 1
nrabinowitz
  • 55,314
  • 10
  • 149
  • 165
1

If this is the orchestrate package you are using, then I see that it uses kew as its promise manager. The documentation for this package suggests using .end() to end chains then and fail calls. From having done a quick test, I can tell that there are certain types of errors you won't be able to catch unless you add this .end() call at the end of your chain. So try something like this:

db.put('musician', '1', '{"test":"test1"}')
    .then(function (result) {
        res.send(result);
    })
    .fail(function (err) {
        res.send(err);
    })
    .end(); /// <<< Add this at the end of your chain.

This may result in an error being reported.

Louis
  • 146,715
  • 28
  • 274
  • 320
1

What's the error when you fail? Which of these is it: https://docs.orchestrate.io/#errors ?

Can you try using a network proxy such as wireshark and watch the network traffic - what are the headers that are sent with the put request? Does it match what you see here: https://docs.orchestrate.io/#key/value/put-(create/update)

Etai
  • 1,483
  • 1
  • 11
  • 15