Await for an object creation - rust

In Rust I need to multiple times await till an object is created or return object immediately if it is already created.
If I use plain future, it does not work, because a future can be awaited only once.
Fused future is also not an option, because Fuse returns pending at the second call.
So, what to use?

Related

If I use `.push();` to crate a new empty Firebase realtime DB datum, do I have to resolve the promise before writing to it?

I inherited some NodeJs code which repeatedly uses .push(); to create a new empty array (node/leaf/whatever the FB terminology is - but, it's an array/list).
Immediately afterwards the code loops and starts writing entries to it.
On the one had I am nervous because it looks like a code smell and the quality of the code is noticeably amateurish even to me - and I am primarily an embedded C++ guy.
The code properly treats reads as async and waits for the promise to resolve:
admin
.database()
.ref(url)
.once("value", (snapshot) => { ...
but, the pushes do not wait.
My big fear is that the request to write an array member could arrive at FB before the array has been created, and timing bugs like that are the absolute worst to debug.
On the other hand, this is done so consistently that the original coder may know something that I do not.
Does the code have a problem?
Seeing the actual code that you're asking about would be useful, but my guess is that you have something like:
newRef = rootRef.push();
newRef.set('some value');
That first line does not actually write anything to the database yet. In fact, it is a purely client-side operation that just creates a new unique ID and returns a reference to that. So there's no need to await the call in that first line as it is synchronous.
The second line does perform a write operation to the database, is asynchronous, and thus you'll need to await it if you want the next operation to start after the write completes.
The two lines could be combined into:
rootRef.push('some value');
Now the push() operation does perform the write to the database and if you want to perform another operation after the write, you would have to await it.

C++ std::async - Is it just syntactic sugar for launching threads?

std::future, std::promise and std::threads
I am trying to get my head around a few of the newer C++ concepts such as std::future, std::promise and std::async.
I think I understand pretty well how futures and promises work. They are a apir of classes/objects which can be used to pass data to and from threads in a convenient manner. In summary they work like this:
Create a promise defining the type of data to be returned
Create a future for the created promise using promise.get_future()
Launch a thread, moving the promise into the thread function
Parent thread continues to do other work until result from launched thread function is required, at which point parent waits for result by calling future.get().
If result has already been "set", parent thread continues, else it goes to sleep for an indefinite/infinite/unlimited (?) time
If result has not been "set", child thread continues working
Child thread sets the promise value using promise.set_value()
This prompts parent thread to wake up if it was sleeping
Typically child thread would then exit, parent thread would call thread.join() and continue working
(One of my favorite examples can be found here: https://www.modernescpp.com/index.php/promise-and-future)
Therefore the promise future construct provides a way to launch a thread and return a result while keeping the parent and child threads synchronized at the points in program execution when this is required.
std::async
Here is where I get confused. I have read several documentation pages regarding std::async. What confuses me is that I usually associate future with promise. But when using std::async there is no mention of a promise at any point. Is it hidden by the implementation?
Here's a selection of documentation pages:
https://en.cppreference.com/w/cpp/thread/async
https://www.cplusplus.com/reference/future/async/
https://thispointer.com/c11-multithreading-part-9-stdasync-tutorial-example/
Why should I use std::async?
https://riptutorial.com/cplusplus/example/30411/std--future-and-std--async
https://solarianprogrammer.com/2012/10/17/cpp-11-async-tutorial/
As far as I can tell, std::async does the following:
Launches a thread, returning a std::future object
(Has different launch modes, can be "deferred" meaning the thread does not start work until the result is requested, and "async" meaning the thread starts work immediatly)
When the result is required, future.get() is called.
Since there is no promise involved in this process, I would have assumed that it is not possible to return a value from a promise using future.get()...
However, some examples indicated that the return type is defined by the function to be called with async. The value then is returned by future.get(). So it is possible to return a value, but no std::promise in sight?
Edit: Here's another article which gives details of futures, promises, async and also packaged tasks. It provides some explanations as to why you might use different options, but at the end states the difference between async and launching a thread with future/promise is that the returned value can be set anywhere within the thread function execution rather than just at the end by a return statement.
https://ncona.com/2018/02/futures-async-packaged_tasks-and-promises-in-c/
Questions
Why use async instead of a future promise pair?
Is async just syntactic sugar for launching a thread while hiding the promise from view of the programmer?
In other words, my question is what is the difference between using async to launch a seperate thread and doing it by explicitly using std::thread with promise and future.
Are they functionally, the same?
Why use async instead of a future promise pair?
Because it is one thing, instead of three + orchestration. Or because your implementation does it with a thread pool, rather than a new thread each time. Or because you want deferred or implementation-defined launch policy.
Is async just syntactic sugar for launching a thread while hiding the promise from view of the programmer?
On some implementations, yes. On others it can run the function on a thread-pool thread. It just has to ensure that reachable thread_local data is fresh for each invocation.
Are they functionally, the same?
In the sense that
template <typename F, typename... Args>
std::future<std::invoke_result_t<F, Args...>> async(F f, Args... args) {
std::promise<std::invoke_result_t<F, Args...>> prom;
auto fut = prom.get_future();
std::thread([p = std::move(prom)](F f, Args... args) { p.set_value_at_thread_exit(f(args...)); }, f, args...).detach();
return fut;
}
is approximately what std::async does?

NodeJS: Reading and writing to a shared object from multiple promises

I'm trying to find out if there could be an issue when accessing an object from multiple promises, eg:
let obj = {test: 0}
let promisesArr = []
for (let n = 0; n < 10; n++) {
promisesArr.push(promiseFunc(obj))
}
Promise.all(promisesArr)
// Then the promise would be something like this
function promiseFunc(obj) {
return new Promise(async (resolve, reject) => {
// read from the shared object
let read = obj.test
// write/modify the shared object
obj.test++
// Do some async op with the read data
await asyncFunc(read)
// resolves and gets called again later
})
}
From what I can see/tested there would not be an issue, it would seem like even though processing is asynchronous, there is no race condition. But maybe I could be missing something.
The only issue that I can see is writing to the object and then doing some I/O op and then read expecting what was written before to still be there
I'm not modifying the object after other async operations only at the start, but there are several promises doing the same. Once they resolve they get called again and the cycle starts over.
Race conditions in Javascript with multiple asynchronous operations depend entirely upon the application logic of what exactly your doing.
Since you don't show any real code in that regard, we can't really say whether you have a race condition liability here or not.
There is no generic answer to your question.
Yes, there can be race conditions among multiple asynchronous operations accessing the same data.
OR
The code can be written appropriately such that no race condition occurs.
It all depends upon the exact and real code and what it is doing. There is no generic answer. I can show you code with two promise-based asynchronous operations that absolutely causes a race condition and I can show you code with two promise-based asynchronous operations that does not cause a race condition. So, susceptibility to race conditions depends on the precise code and what it is doing and precisely how it is written.
Pure and simple access to a value in a shared object does not by itself cause a race condition because the main thread in Javascript is single threaded and non-interruptible so any single synchronous Javascript statement is thread-safe by itself. What matters is what you do with that data and how that code is written.
Here's an example of something that is susceptible to race conditions if there are other operations that can also change shareObj.someProperty:
let localValue = shareObj.someProperty;
let data = await doSomeAsyncOperation();
shareObj.someProperty = localValue + data.someProperty;
Whereas, this not cause a race condition:
let data = await doSomeAsyncOperation();
shareObj.someProperty = shareObj.someProperty += data.someProperty;
The second is not causing its own race condition because it is atomically updating the shared data. Whereas the first was getting it, storing it locally, then waiting for an asynchronous operation to complete which is an opportunity for other code to modify the shared variable without this local function knowing about it.
FYI, this is very similar to classic database issues. If you get a value from a database (which is always an asynchronous operation in nodejs), then increment it, then write the value back, that's subject to race conditions because others can be trying to read/modify the value at the same time and you can stomp on each other's changes. So, instead, you have to use an atomic operation built into the database to update the variable in one atomic operation.
For your own variables in Javascript, the problem is a little bit simpler than the generic database issue because reading and writing to a Javascript variable is atomic. You just make to make sure you don't hold onto a value that you will later modify and write back across an asynchronous operation.

Mongoose eachAsync with async function = memory leak?

I am not sure if it's a bug in mongoose or if I am doing something wrong. Once I start using async functions when iterating on a cursor with eachAsync I experience memory leaks (quickly goes up to 4gb and then crashes). After trying some things I noticed that this wouldn't happen if I don't use an async function as callback.
No Memory leak:
const playerCursor: QueryCursor<IPlayerProfileModel> = PlayerProfile.find({}, projection).lean().cursor();
await playerCursor.eachAsync(
(profile: IPlayerProfileModel) => {
return;
},
{ parallel: 50 }
);
Memory leak:
const playerCursor: QueryCursor<IPlayerProfileModel> = PlayerProfile.find({}, projection).lean().cursor();
await playerCursor.eachAsync(
async (profile: IPlayerProfileModel) => {
return;
},
{ parallel: 50 }
);
Obviously above code doesn't make any sense but I need to perform an asynchronous operation within the function.
Question:
What is causing the memory leak / how can I avoid it?
It has to do with how async functions work.
Quoting the documentation:
When the async function returns a value, the Promise will be resolved
with the returned value.
Meaning, values returned by async functions will be automatically wrapped into a Promise.
In your first code sample, your code returns undefined whereas in the second code sample your code returns Promise.resolve(undefined).
What is causing the memory leak?
I didn't take a look at mongoose code but the documentation states:
If fn returns a promise, will wait for the promise to resolve before iterating on to the next one.
Since your first example does not return a Promise, I am thinking your callback is executed on each result all at once rather than sequentially.
How can I avoid it?
I'd recommend using async/wait as you used it on your second code sample.
After taking a look at the code (looking for an answer myself), if provided with a callback that doesn't return a promise eachAsync will run the callback as many times as fast as possible as it can.
This line is where your callback is executed. The next line checks whether it's a Promise and if it's not then execute right away callback which effectively calls your eachAsync callback on the next result. If your callback has any sort of async operation but returns right away then you end up with thousands and thousands of async operations running all at once.
On top of that, you set the option parallel to 100 so it executes eachAsync callback one hundred times in parallel.
This isn't a bug on mongoose because there are cases where this behavior is wanted and it does provide with a sequential processing using Promise. The documentation should mention the caveat of using a callback which doesn't return a Promise.
To go a little further, express uses next on middleware callbacks for the purpose of sequencing them.

NodeJS -- cost of promise chains in recurssion

I am trying to implement a couple of state handler funcitons in my javascript code, in order to perform 2 different distinct actions in each state. This is similar to a state design pattern of Java (https://sourcemaking.com/design_patterns/state).
Conceptually, my program need to remain connected to an elasticsearch instance (or any other server for that matter), and then parse and POST some incoming data to el. If there is no connection available to elasticsearch, my program would keep tring to connect to el endlessly with some retry period.
In a nutshell,
When not connected, keep trying to connect
When connected, start POSTing the data
The main run loop is calling itself recurssively,
function run(ctx) {
logger.info("run: running...");
// initially starts with disconnected state...
return ctx.curState.run(ctx)
.then(function(result) {
if (result) ctx.curState = connectedSt;
// else it remains in old state.
return run(ctx);
});
}
This is not a truly recursive fn in the sense that each invocation is calling itself in a tight loop. But I suspect it ends up with many promises in the chain, and in the long run it will consume more n more memory and hence eventually hang.
Is my assumption / understanding right? Or is it OK to write this kinda code?
If not, should I consider calling setImmediate / process.nextTick etc?
Or should I consider using TCO (Tail Cost Optimization), ofcourse I am yet to fully understand this concept.
Yes, by returning a new promise (the result of the recursive call to run()), you effectively chain in another promise.
Neither setImmediate() nor process.nextTick() are going to solve this directly.
When you call run() again, simply don't return it and you should be fine.

Resources