Meteor docs about methods say:
On the server, this function can be run either synchronously or asynchronously. If the callback is omitted, it runs synchronously and the results are returned once the request completes successfully. If the request was not successful, an error is thrown. This is useful when making server-to-server HTTP API calls from within Meteor methods, as the method can succeed or fail based on the results of the synchronous HTTP call. In this case, consider using this.unblock() to allow other methods on the same connection to run in the mean time. On the client, this function must be used asynchronously by passing a callback.
But I find it pretty ambiguous and unobvious, does it just look sync but runs async using fibers, or does it really become sync?
E.g. if I make a server-to-server DDP method call to a meteor app from a meteor app:
const data = anotherMeteorApp.call(...)
Does the code above run sync, blocking the event loop and slowing things down? If it's in a method, would adding this.unblock() before that line of code make it async? If it's not in a method (e.g. if it's in a collection2 hook) would it block?
Yes! the code above runs synchronously (if no callback mentioned.), this will slow down things until operation is completed. You can yourself check the impact of adding this.unblock() by sleeping the process inside meteor call at server.
You can use below code to create a simulation of process taking too much time to execute and return from a method defined on server (Meteor.method()).
var breakTime = 20000; // 20 secs
var Future = Npm.require('fibers/future');
var fut = new Future();
var pause = new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), breakTime);
});
pause.then((1) => {
fut.return(true);
});
let waitHere = fut.wait();
return true;
Related
I have an http web server that I'm trying to detect long-running requests and abort them. The following code successfully returns to the client upon timeout, but the async zone still continues to run to completion. How can I actually kill the request handler?
var zone = runZoned(() {
var timer = new Timer(new Duration(seconds: Config.longRequestTimeoutSeconds), () {
if (!completer.isCompleted) { // -- not already completed
log.severe('request timed out');
// TODO: This successfully responds to the client early, but it does nothing to abort the zone/handler that is already running.
// Even though the client will never see the result (and won't have to wait for it), the zone/handler will continue to run to completion as normal.
// TODO: Find a way to kill/abort/cancel the zone
completer.complete(new shelf.Response(HttpStatus.SERVICE_UNAVAILABLE, body: 'The server timed out while processing the request'));
}
});
return innerHandler(request) // -- handle request as normal (this may consist of several async futures within)
.then((shelf.Response response) {
timer.cancel(); // -- prevent the timeout intercept
if (!completer.isCompleted) { // -- not already completed (not timed out)
completer.complete(response);
}
})
.catchError(completer.completeError);
});
Nothing can kill running code except itself. If you want code to be interruptible, you need some way to tell it, and the code itself needs to terminate (likely by throwing an error). In this case, the innerHandler needs to be able to interrupt itself when requested. If it's not your code, that might not be possible.
You can write a zone that stops execution of asynchronous events when a flag is set (by modifying Zone.run etc.), but you must be very careful about that - it might never get to an asynchronous finally block and release resources if you start throwing away asynchronous events. So, that's not recommended as a general solution, only for very careful people willing to do manual resource management.
I have a Cloud service ASP.NET application which is consuming document db API (Microsoft.Azure.DocumentDB 1.14.0). Here I need to call asynchronous code from synchronous code. My call to execute results on document db is
If I call it from synchronous method:
var result = Task.Run (() => schemaResults.ExecuteNextAsync ()).Result;
If I call it from asynchronous method:
var result = await schemaResults.ExecuteNextAsync ();
OR
var result = await schemaResults.ExecuteNextAsync ().ConfigureAwait (false);
The code works perfectly fine if I run it on localhost on Azure emulator but when I deploy it on Azure, it gets stuck at the above call. Seems like it has gone into a deadlock.
Any help?
I tried updating Microsoft.Azure.DocumentDB 1.14.0 to Microsoft.Azure.DocumentDB 1.14.1
It contains fixes for the deadlocks that occurs in ASP.NET context
Release Notes: https://learn.microsoft.com/en-us/azure/cosmos-db/documentdb-sdk-dotnet#release-notes
I am using Firebase to monitor machines across the building.
So architecture is multiple front-ends and multiple machines.
At a certain moment I want to be able to trigger some actions on these machines like:
take screenshot and put to ftp
encode a certain video file
analyze a large data-set
I am used to Actionscript, there are NetConnection and
Client objects to whom one could invoke remote methods.
Is there something similar in Firebase ?
How would you implement such a feature easily ?
I thought of having a message box, using an Array, where a message could be a data structure like:
{
'client_id': 'xxx-yyy-zzz',
'name': 'takeScrenshot',
'body': { 'creator': 'my-name' },
'timestamp': 1406214344
}
How it might work
a method call is a message entering this message box Array
listening with value_changed over this message box
pop item from array (this will trigger another value changed)
use the item to perform async operation
when async operation is done, using the client_id, notify the invoker about the operation
But to implement it correctly a lot of work must be done, does anyone know if there is an easy way to achieve this kind of functionality ?
Since Firebase is a powerful backend service, scalable, and has a RESTful API in addition to SDKs (not yet for Python, unfortunately), it generally makes the most sense to just use it directly, rather than fashioning API services on top of it.
One fast and effective way to do this is to utilize a queue approach. Have each client write data into an in/ path, and have the recipient of the event listen for child_added on that path. Then perform the remote invocation, and write data back to an out/ path for the requesting client.
client
// send it
var ref = new Firebase(QUEUE_URL);
var request = ref.child('in').push( requestData );
// wait for a reply and remove after processing
ref.child('out/'+request.name()).on('value', function(snap) {
if( snap.val() !== null ) {
console.log(snap.val());
request.remove();
// stop listening
snap.ref().off();
}
});
remote service
var ref = new Firebase(QUEUE_URL);
// listen for queue events
ref.child('in').on('child_added', function(snap) {
/*
... process queue event ...
*/
doneProcessing(snap, resultData);
});
function doneProcessing(snap, results) {
ref.child('out/'+snap.name()).set(results);
snap.ref().remove();
}
I'm using meteor 0.6.4.
Meteor.methods({
random: function(top){
var random = Math.floor((Math.random()*(top+1)));
return random;
}
});
It returns undefined whenever I execute
Meteor.call('random', 10);
Any ideas how I can get past this?
This is a perfectly normal behavior: server method calls in Meteor are documented to be asynchronous :
On the client, if you do not pass a callback and you are not inside a stub, call will return undefined, and you will have no way to get the return value of the method.
It means that when you ask for a Meteor.call method to execute remotely on the server, the local method call is non blocking and returns undefined immediately.
When the method has been called on the server it will send the result asynchronously to the client, so you should retrieve it using the callback pattern :
Meteor.call("myMethod", arguments..., function(error, result){
if(error){
console.log(error.reason);
return;
}
// do something with result
});
The anonymous callback function will be called on the client as soon as the server method result is sent back to the client.
There is another subtle feature in Meteor invalidating what I just said : latency compensation and methods stubs.
In case the server method call can be SIMULATED properly in the client and thus executed right away without a round-trip to the server, you can define what is called a method stub (or simulation).
A common use case for this behavior is inserting immediately in the local (client side replication subset) database some user content just posted (a comment under a blog article for example) : all the necessary data and logic is available and it makes sense to simulate server side insertion.
What happens next is that the user sees the webpage updated as soon as he submitted his content even if the server hasn't acknowledged these changes yet. (this is an example how latency compensation is implemented in Meteor).
Of course the server has final words on what gets ultimately inserted in the database, this means that when the server side twin method is executed, its actions will take precedence and replace what was inserted in the local database.
To define such method stub, you just have to define the same server method name on client code.
If the method declaration is defined in shared code (shipped both to client and server), you can test if the method call is actually a simulation by checking the isSimulation property :
Meteor.methods({
myMethod: function(arguments...){
if(this.isSimulation){
// called from the client
}
}
});
UPDATE 26/11/2014 : #steph643 commented on how the last part of my previous answer was actually wrong, here is a correction.
Note that on the server method calls can always be invoked using the synchronous syntax because server environment provides adequate blocking mechanism (fibers).
On the client however, if you return something from a method stub, it can be executed synchronously only if you're inside another stub and you can retrieve the result in a synchronous way, ie
Meteor.methods({
intermediateMethod: function(){
return " WORLD";
},
method: function(){
var result = "HELLO";
result += intermediateResult;
var intermediateResult = Meteor.call("intermediateMethod");
return result;
}
});
This behavior is a bit weird considering that Mongo collection operations (insert/update/delete) are implemented as Meteor methods and their client versions are implementing valid stubs (modification of minimongo replicated local database subset) that can be executed synchronously.
I have a web service that can be broken down into two main sections:
[WebMethod]
MyServiceCall()
{
//Do stuff the client cares about
//Do stuff I care about
}
What I'd like to do is run that 2nd part on another thread, so that the client isn't waiting on it: once the user's logic has completed, send them their information immediately, but continue processing the stuff I care about (logging, etc).
From a web service, what is the recommended way of running that 2nd piece asynchronously, to get the user back their information as quickly as possible? BackgroundWorker? QueueUserWorkItem?
You may want to look into Tasks which are new to .NET 4.0.
It lets you kick off an asynchronous operation, but also gives you an easy way to see if it's done or not later.
var task = Task.Factory.StartNew(() => DoSomeWork());
It'll kick off DoSomeWork() and continue without waiting so you can continue doing your other processing. When you get to the point where you don't want to process anymore until your asynchronous task has finished, you can call:
task.Wait();
Which will wait there until the task has completed. If you want to get a result back from the task, you can do this:
var task = Task.Factory.StartNew(() =>
{
Thread.Sleep(3000);
return "dummy value";
});
Console.WriteLine(task.Result);
A call to task.Result blocks until the result is available.
Here's a tutorial that covers Tasks in greater detail: http://www.codethinked.com/net-40-and-systemthreadingtasks
The easiest way to fire off a new thread is probably:
new Thread(() =>
{
/// do whatever you want here
}).Start();
Be careful, though - if the service is hit very frequently, you could wind up creating a lot of threads that block each other.