Slow response to resolved promise node.js - node.js

I'm brand new to node.js and and I feel I am doing something incorrectly, but I'm having a harder time googling good answers then I have for other languages for some reason. Basically I'm using a node wrapped c++ addon to do some work and then I want to send it over a websocket after I've done some some additional parsing on it. When the additional parsing is done synchronously it is sent immediately (as expected). When I do the work in a promise (which is what a thirdparty module is doing for me) after the resolve is called it takes an excessively long time for the fulfilled callback to be called. Like upwards of 5-10 seconds. Here's the code:
var addon = require('...'); // Node wrapped C++ module
...
var server = http.createServer(){...};
var ios = io.listen(server);
function someFunction(args) {
console.log("Preparing to call some function");
someOtherFunction(args).then(funtction(val) {
console.log("Sending val over websocket....");
ios.sockets.emit('thing', val);
}
}
function someOtherFunction(args) {
return new Promise(function(resolve, reject) {
//logic
resolve(someVal);
console.log("Done with someOtherFunc");
}
}
ios.sockets.on('connection', function(socket){
console.log("Conneced");
// This does some work on a different thread. Eventually reposts to event loop and calls callback
addon.doThing("someVal", someFunc);
socket.on('disconnect', function() {
console.log("Disconnected");
});
});
Output:
Connected
Preparing to call some function...
Done with someOtherFunc;
<variable delay sometimes up to 5-10 seconds>
Sending val over websocket.
Multiple callbacks to someFunction may happen before the first call to someOtherFunction is done. These are all posted events to the the main Event loop, so I don't believe anything is blocking there.
Output:
Connected
Preparing to call some function...
Done with someOtherFunc;
<1 second delay>
Preparing to call some function...
Done with someOtherFunc;
<1 second delay>
Preparing to call some function...
Done with someOtherFunc;
<1 second delay>
<variable delay sometimes up to 5-10 seconds>
Sending val over websocket.
Sending val over websocket.
Sending val over websocket.
So my question original thought was that when resolve was called then the callback was called immediately. But that doesn't look like it's happening. Something is triggering the callback to eventually trigger but I have no idea what and it seems random when it actually does. Any help would be appreciated!
C++ Addon code:
class NodeWrapper {
public:
static NodeWrapper& GetInstance() {
static NodeWrapper mInstance;
return mInstance;
}
~NodeWrapper() {
uv_close((uv_handle_t*) &mNodeAsyncEventLoop, NULL);
};
static void SendToNode(uv_async_t *handle) {
GetInstance().SendToNode();
}
void SendToNode() {
uv_mutex_lock(&mMutex);
swap(pushQueue, popQueue);
uv_mutex_unlock(&mMutex);
while(!popQueue.empty()) {
Data* pData = popQueue.front();
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
const unsigned argc = 1;
Local<Value> argv = { node::Buffer::New(isolate, pData->mData, pData->mLen, DataDeleter, NULL).ToLocalChecked() };
Local<Function> cb = Local<Function>::New(isolate, mNodeCB);
cb->Call(isolate->GetCurrentContext()->Global(), argc, &argv);
popQueue.pop();
}
log << "Done with Callback!" << std::endl;
}
void SendOnData(const void* pData, DWORD dwLen) {
log << "Callback received!" << std::endl;
if(dwLen > 0) {
uv_mutex_lock(&mMutex);
pushQueue.push(new Data(pData, dwLen));
uv_mutex_unlock(&mMutex);
uv_async_send(&GetInstance().mNodeAsyncEventLoop);
}
};
static NodeWrapper mInstance;
UniquePersistent<Function> mNodeCB;
private:
NodeWrapper() {
uv_async_init(uv_default_loop(), &mNodeAsyncEventLoop, &NodeWrapper::SendToNode);
uv_mutex_init(&mMutex);
};
DATA_QUEUE pushQueue;
DATA_QUEUE popQueue;
uv_mutex_t mMutex;
uv_async_t mNodeAsyncEventLoop;
};
void doThing(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
auto f = std::bind(&NodeWrapper::SendOnData, &NodeWrapper::GetInstance());
DoThingAnotherThreadAndCallCallback(f);
NodeWrapper::GetInstance().mNodeCB = UniquePersistent<Function>(isolate, Local<Function>::Cast(args[1]));
}
Output update:
22:01:57.831645 - Callback received
Preparing to call some function....
Done with someOtherFunc
22:01:57.839711 - Done with Callback!
22:01:57.918472 - Callback received
Preparing to call some function....
Done with someOtherFunc
22:01:57.927344 - Done with Callback!
Sending val over websocket....
Sending val over websocket....

Promise .then() callbacks are never called immediately upon resolve(). Instead, they are always called asynchronously. This provides uniform async behavior whether the resolve is called synchronously or asynchronously, thus making life a lot easier for the caller.
Promises wait until other code in the current thread of execution has finished executing and the stack frame has cleared back to only "platform code" as the spec says. Then, the .then() callback is called. If you are doing a lot of other stuff in that thread of execution, then there can be a delay before the .then() handler is called.

I solved it by switching from native v8 Promises to bluebird Promises. Native v8 Promises are handled by a Microtask queue, I'm not sure how c++ addons are handled (I could never get a good stack trace to see) but it looks like the microtask queue was getting starved until it eventually ran after some event must of flushed it (still not sure about it). bluebird uses SetImmediate which and it is processed immediately which solved the issue for me.
Further reading read here: https://github.com/nodejs/node-v0.x-archive/issues/7714
This was "fixed" in v0.12, I'm using actually io.js v3.2.0. I'm not 100% sure if this is the same issue or different. Either way I'll stick with bluebird for now

Related

Glib & Gstreamer: Does a probe callback behave like another thread in glib

I am trying to ask a question with reference to the question Glib: Calling a iterative loop function
I am actually doing GStreamer and trying to use Glib library function in my application as much as possible. The program require some system event/response before performing some action in response to some user input
Design of flow
User input the option and application take it as user_input is asserted to be true
Application need install a callback (called it callback_A) -- which wait out for buffer flowing in that point of application
Callback-A will be called whenever buffer passes through a point.
In callback A, Application to wait for some particular condition (ie a key-frame buffer passing through) at a point. If a key frame buffer pass through, it will then install a second callback at some point downstream, callback-B. An EOS event is send out through the pipeline. Otherwise wait for next time a buffer pass through
In callback B, it will wait for the event (EOS) to arrive and determine further action. If everything is completed, set task_completed to be true
function return to main while loop. The blocking (task_completed) is released and the application will report the task completed to UI
Problem'
Currently I faced a problem of the callback not completing their task (takes a long time) before it went to being blocked by task completed (and being blocked thereafter)
Question
In Glib, is a callback within the same memory space(or thread) as its caller?
In Glib, how do I overcome the problem of being blocked? Is there some methods to ensure that the task are being run before time up and control is returned to the caller
Will a gthread help? Putting the two call-back as a separate thread since they need to wait for some events to happen
This may be too much. Any alternatives, example polling instead of callback in this case.
Code
Here is my pseudocode
gbool user_input;
gbool task_completed = false;
static void
callback_B(GstPad *pad,
GstPadProbeInfo *info,
gpointer udata)
{
//// wait for some events--- call it event B
GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
if (GST_EVENT_TYPE (event) != GST_EVENT_EOS)
return GST_PAD_PROBE_OK;
/// do something
/// ......
task_completed =true;
return GST_PAD_PROBE_REMOVE;
}
static void
callback_A( GstPad *pad,
GstBuffer * buffer,
gpointer udata)
{
//// wait for some event call it event A
if( !GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT))
{
/// install callback-B to determine some condition
gst_pad_add_probe ( pad,
GST_PAD_PROBE_TYPE_BLOCK,
(GSourceFunc)callback_B,
//NULL,
NULL,
NULL);
GstPad* padB = gst_pad_get_peer (pad);
gst_pad_send_event(padB, gst_event_new_eos());
}
else
{
return GST_PAD_PROBE_REMOVE;
}
}
gboolean
check_cmd_session(NULL )
{
if(user_input)
{
// ........ some other actions *****************
/// initialize task_complete to be false
task_completed = false;
//// install callback_A
gst_pad_add_probe(padA,
GST_PAD_PROBE_TYPE_BUFFER,
callback_A,
NULL,
NULL);
while(!task_completed)
g_usleep(10000);
/// notify UI of changes done
notify_UI();
}
}

Begin/EndInvoke not synchronizing with main thread

I'm creating a networked game in Unity using tcp based sockets.
(I'm new to networking and threading stuff).
I'm using System.Net.Sockets async methods like socket.BeginReceive() and socket.EndReceive().
All the client-server connecting and messaging works. But as soon as I try access anything from a Monobehavior (so that I can actually have any effect on the Unity game), like a gameobject's transform, an exception is thrown telling me that I can only access these properties from the main thread.
My question is: why am I not back on the main thread in the callback to foo.beginRecieve(), or at least after I call foo.EndReceive()? How do I return to the main thread using the async socket api? Will I end up having to use the synchronous socket api and just handle the threading myself so I can properly resync with Unity's main thread?
Thanks!
Any help would be much appreciated.
//code which sets up the callbacks which are executed when a client receives a message from the server
void BeginReceive() => _clientSocket.BeginReceive(_messageReceivedBuffer, 0, _messageReceivedBuffer.Length, SocketFlags.None, ReceiveCallback, null);
void ReceiveCallback(IAsyncResult result)
{
_clientSocket.EndReceive(result);
var msg = _serializer.ByteArrayToObject<NetworkMessage>(_messageReceivedBuffer);
//this clientmanipulation manipulates the game grid and the gameobjects' which it references
//it's in this method that an exception gets thrown and the code breaks
msg.ClientManipulation(_gameGrid);
BeginReceive();
}
In general for EndReceive:
Before calling BeginReceive, you need to create a callback method that implements the AsyncCallback delegate. This callback method executes in a separate thread and is called by the system after BeginReceive returns. The callback method must accept the IAsyncResult returned by the BeginReceive method as a parameter.
[...]
The EndReceive method will block until data is available.
Usually you would use a pattern often referred to as Main Thread Dispatcher using a ConcurrentQueue. For Unity this is quite easy since you already have something that is surely always been executed in the main thread: Update
public class Example : MonoBehaviour
{
...
private ConcurrentQueue<Action> _mainThreadActions = new ConcurrentQueue<Action>();
private void Update()
{
// Handle all callbacks in main thread
while(_mainthreadActions.Count > 0 && _mainThreadActions.TryDequeue(out var action))
{
action?.Invoke();
}
}
void BeginReceive()
{
_clientSocket.BeginReceive(_messageReceivedBuffer, 0, _messageReceivedBuffer.Length, SocketFlags.None, ReceiveCallback, null);
}
void ReceiveCallback(IAsyncResult result)
{
_clientSocket.EndReceive(result);
var msg = _serializer.ByteArrayToObject<NetworkMessage>(_messageReceivedBuffer);
// On threads / possibly async code enqueue the action to be invoked in the main thread
_mainThreadActions.Enqueue(()=> {msg.ClientManipulation(_gameGrid)});
BeginReceive();
}
}

Understanding try and catch in node.js

I'm new to coding. Trying to understand why try...catch isn't supposed to work in node.js. I've created an example, but contrary to expectations, try...catch seems to be working. Where am I going wrong in my understanding ? Please help.
function callback(error) { console.log(error); }
function A() {
var errorForCallback;
var y = parseInt("hardnut");
if (!y) {
throw new Error("boycott parsley");
errorForCallback = "boycott parsley for callback";
}
setTimeout(callback(errorForCallback),1000);
}
try {
A();
}
catch (e) {
console.log(e.message);
}
// Output: boycott parsley
// Synchronous behaviour, try...catch works
-----------Example re-framed to reflect my understanding after reading answer below----------
function callback(error) { console.log(error); }
function A() {
var errorForCallback;
setTimeout(function(){
var y = parseInt("hardnut");
if (!y) {
// throw new Error("boycott parsley");
errorForCallback = "boycott parsley for callback";
}
callback(errorForCallback);
}, 1000);
}
try {
A();
}
catch (e) {
console.log(e.message);
}
// Output: boycott parsley for callback
// Asynchronous behaviour
// And if "throw new Error" is uncommented,
// then node.js stops
The try-catch approach is something that works perfectly with synchronous code. Not all the programming that you do in Node.js is asynchronous and so in those pieces of synchronous code that you write you can perfectly use a try-catch approach. Asynchronous code, on the other hand, does not work that way.
For instance, if you had two function executions like this
var x = fooSync();
var y = barSync();
You would expect three things, first that barSync() would be executed only after fooSync() has finished, and you would expect that x would contain whatever value is returned by the execution of fooSync before barSync() is executed. Also you would expect that if fooSync throws an exception, barSync is never executed.
If you would use a try-catch around fooSync() you could guarantee that if fooSync() fails you can catch that exception.
Now, the conditions completely change if you would have a code like this:
var x = fooAsync();
var y = barSync();
Now imagine that when fooAsync() is invoked in this scenario, it is not actually executed. It's just scheduled for execution later on. It is as if node would have a todo list, and at this moment it is too busy running your current module, and when it finds this function invocation, instead of running it, it simply adds it to the end of its todo list.
So, now you cannot guarantee that barSync() will run before fooAsync(), as a matter of fact, it probably won't. Now you don't control the context in which fooAsync() is executed.
So, after scheduling the fooAsync() function, it immediately moves to execution of barSync(). So, what can fooAsync() return? At this point nothing, because it has not run yet. So x above is probably undefined. If you would put try-catch around this piece of code it would be pointless, because the function will not be executed in the context of this code. It will be executed later on, when Node.js checks if there are any pending tasks in its todo list. It will be executed in the context of another routine that is constantly checking this todo list, and this only thread of execution is called an event loop.
If your function fooAsync() gets to fail, it will fail in the context of execution of this thread running the event loop and therefore it would not be caught by your try-catch statement, at that point, that module above may have probably finished execution.
So, that is why in asynchronous programing you cannot either get a return value, neither can you expect to do a try-catch, because you code is evaluated somewhere else, in another context different from the one where you think you invoked it. It is as if you could would have done something like this instead:
scheduleForExecutionLaterWhenYouHaveTime(foo);
var y = barSync();
And that's the reason why asynchronous programming requires other techniques to determine what happened to your code when it finally runs. Typically this is notified through a callback. You define a callback function which is called back with the details of what failed (if anything) or what your function produced and then you can react to that.

How to forcibly keep a Node.js process from terminating?

TL;DR
What is the best way to forcibly keep a Node.js process running, i.e., keep its event loop from running empty and hence keeping the process from terminating? The best solution I could come up with was this:
const SOME_HUGE_INTERVAL = 1 << 30;
setInterval(() => {}, SOME_HUGE_INTERVAL);
Which will keep an interval running without causing too much disturbance if you keep the interval period long enough.
Is there a better way to do it?
Long version of the question
I have a Node.js script using Edge.js to register a callback function so that it can be called from inside a DLL in .NET. This function will be called 1 time per second, sending a simple sequence number that should be printed to the console.
The Edge.js part is fine, everything is working. My only problem is that my Node.js process executes its script and after that it runs out of events to process. With its event loop empty, it just terminates, ignoring the fact that it should've kept running to be able to receive callbacks from the DLL.
My Node.js script:
var
edge = require('edge');
var foo = edge.func({
assemblyFile: 'cs.dll',
typeName: 'cs.MyClass',
methodName: 'Foo'
});
// The callback function that will be called from C# code:
function callback(sequence) {
console.info('Sequence:', sequence);
}
// Register for a callback:
foo({ callback: callback }, true);
// My hack to keep the process alive:
setInterval(function() {}, 60000);
My C# code (the DLL):
public class MyClass
{
Func<object, Task<object>> Callback;
void Bar()
{
int sequence = 1;
while (true)
{
Callback(sequence++);
Thread.Sleep(1000);
}
}
public async Task<object> Foo(dynamic input)
{
// Receives the callback function that will be used:
Callback = (Func<object, Task<object>>)input.callback;
// Starts a new thread that will call back periodically:
(new Thread(Bar)).Start();
return new object { };
}
}
The only solution I could come up with was to register a timer with a long interval to call an empty function just to keep the scheduler busy and avoid getting the event loop empty so that the process keeps running forever.
Is there any way to do this better than I did? I.e., keep the process running without having to use this kind of "hack"?
The simplest, least intrusive solution
I honestly think my approach is the least intrusive one:
setInterval(() => {}, 1 << 30);
This will set a harmless interval that will fire approximately once every 12 days, effectively doing nothing, but keeping the process running.
Originally, my solution used Number.POSITIVE_INFINITY as the period, so the timer would actually never fire, but this behavior was recently changed by the API and now it doesn't accept anything greater than 2147483647 (i.e., 2 ** 31 - 1). See docs here and here.
Comments on other solutions
For reference, here are the other two answers given so far:
Joe's (deleted since then, but perfectly valid):
require('net').createServer().listen();
Will create a "bogus listener", as he called it. A minor downside is that we'd allocate a port just for that.
Jacob's:
process.stdin.resume();
Or the equivalent:
process.stdin.on("data", () => {});
Puts stdin into "old" mode, a deprecated feature that is still present in Node.js for compatibility with scripts written prior to Node.js v0.10 (reference).
I'd advise against it. Not only it's deprecated, it also unnecessarily messes with stdin.
Use "old" Streams mode to listen for a standard input that will never come:
// Start reading from stdin so we don't exit.
process.stdin.resume();
Here is IFFE based on the accepted answer:
(function keepProcessRunning() {
setTimeout(keepProcessRunning, 1 << 30);
})();
and here is conditional exit:
let flag = true;
(function keepProcessRunning() {
setTimeout(() => flag && keepProcessRunning(), 1000);
})();
You could use a setTimeout(function() {""},1000000000000000000); command to keep your script alive without overload.
spin up a nice repl, node would do the same if it didn't receive an exit code anyway:
import("repl").then(repl=>
repl.start({prompt:"\x1b[31m"+process.versions.node+": \x1b[0m"}));
I'll throw another hack into the mix. Here's how to do it with Promise:
new Promise(_ => null);
Throw that at the bottom of your .js file and it should run forever.

Callback function in waveOutOpen() API

I am building an audio player that plays '.wav' files and I have a problem with the callback function called from waveOutOpen() API.
Opening the output audio device for playback:
MMRESULT mRes = waveOutOpen(m_hWO,WAVE_MAPPER,&wFmt,(DWORD)&waveOutProc,(DWORD)this, CALLBACK_FUNCTION);
Implementation of callback function:
void CPlayWave::waveOutProc(HWAVEOUT m_hWO,UINT uMsg,DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
MMRESULT mmRes;
CPlayWave *pPW = (CPlayWave*)dwInstance;
switch(uMsg)
{
case MM_WOM_DONE: //playback finished
mmRes = waveOutUnprepareHeader(m_hWO, &pPW->m_WHdr, sizeof(WAVEHDR));
if(mmRes!=MMSYSERR_NOERROR)
{
//error handling
.....
}
mmRes = waveOutClose(m_hWO);
if(mmRes!=MMSYSERR_NOERROR)
{
//error handling
.....
}
AfxMessageBox("Finished playing the file");
m_bPlay = FALSE; //boolean flag used for pausing
break;
case WIM_DATA:
//for recording completion
break;
}
}
The problem is the MM_WOM_DONE never occurs and the callback function is never called after the playback of the file is completed. If a thread has to be used instead of callback function, can someone give me a simple example on how to use a callback thread(haven't found on net).
Also waveOutReset() documentation suggests that it closes all the buffers and returns to the system, so for handling the Stop-button in my application, I used the waveOutReset() function but, this causing the application to freeze. Why is this happening? Is there any alternative method to stop playing while buffer is still in queue for playback.
Callback function probably can not be a method of your class CPlayWave itself. It must be simple function out of your class with requested prototype.
void CALLBACK waveOutProc(HWAVEOUT m_hWO, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
...
}
It must be, of course, declared/defined before you call waveOutOpen(). In addition, function name is pointer itself and ampersand & is not needed. Thus calling waveOutOpen() should be:
MMRESULT mRes = waveOutOpen(m_hWO, WAVE_MAPPER, &wFmt, (DWORD_PTR) waveOutProc, (DWORD_PTR) this, CALLBACK_FUNCTION | WAVE_ALLOWSYNC);
Also you there are only few system functions you can call from waveOutProc:
"Applications should not call any system-defined functions from inside a callback function, except for EnterCriticalSection, LeaveCriticalSection, midiOutLongMsg, midiOutShortMsg, OutputDebugString, PostMessage, PostThreadMessage, SetEvent, timeGetSystemTime, timeGetTime, timeKillEvent, and timeSetEvent. Calling other wave functions will cause deadlock."
So calling funcitons like AfxMessageBox or waveOutUnprepareHeader might be cause terrible issues.

Resources