This is my situation:
Client starts a login operation, has no way of knowing status or getting a response
Login operation has a Cloud Function callback so it saves the login status in the Realtime DB
Client polls a different Cloud Function to check if login status has been written in the Realtime DB to a specific node (key is a UUID)
I've been trying to write the last function with promise intervals but it feels off, and I've started wondering if I can use onUpdate() inside my HTTP endpoint?
Metacode of my idea:
user = ref.child(uuid)
user.onUpdate((update) => res.send(update.status))
From what I've seen in the docs/tutorials onUpdate seems something you use to deploy a function directly (since it returns a CloudFunction), so is there a way to use it as above?
If not, is there a way to do something similar in an HTTP endpoint?
You're trying to make an asynchronous operation synchronous, which is not usually a great idea in Cloud Functions.
I instead would:
Return a unique ID/location in the database to the client in their initial call.
Then have the client wait until a response appears in the database location.
And the Cloud Function responding to the auth completion can then write to that location.
The key difference with your approach is that #2 is watching a database location, instead of polling a Cloud Function. The code this is shown in this gist with code to wait for a value on various platforms.
Related
I have a nodejs application that listens to events on the firebase firestore and performs actions on the whatsapp-web.js client based on the event.
The process is as follows:
Let's say I have a collection "requests" in firestore and every time a document in the collection is created (updated), it generates the following actions:
The function in my nodejs code that listens for events will retrieve the document, read the request and launch an action from the whatsapp-web.js client.
The whatspp-web.js client to perform the action, must launch, initialize a connection, and then perform the request action (the document from the request collection) once the client is connected.
Except that cloud run closes before all these previous functions are performed.
Is there a way to solve this problem with cloud run or should we look for an alternative solution like compute engine?
I'm using Express in Firebase Functions that are on Node 10. My question is: if I have heavy Promises that I need to complete before the function terminates, but I want to do this after I sent the response (res.status(200).send...), how is the best way I could do this?
I have come up with two approaches so far but neither seem great (and I haven't tried the 'finish' approach yet to see if it works):
For every router, add a finally... clause that awaits accumulated promises. This has the major downside that it'd be easy to forget to do this when adding a new router, or might have bugs if the router already needs its own finally clause
Use the Node stream 'finish' event, https://nodejs.org/docs/latest-v10.x/api/stream.html#stream_event_finish ... but I don't know if Firebase Functions allow this to be caught, or if it'll still be caught if my function runs to its end and the event is fired afterwards.
I'm doing this to try to make my functions' responses faster. Thanks for any help.
if I have heavy Promises that I need to complete before the function terminates, but I want to do this after I sent the response (res.status(200).send...), how is the best way I could do this?
With Cloud Functions, it's not possible to send a response before promises are resolved, and have the work from those promises complete normally. When you send the response, Cloud Functions assumes that's the very last thing the function will do. When the response is sent using res.send(), Cloud Functions will terminate the function and shut down the code. Any incomplete asynchronous work might never finish.
If you want to continue work after a response is sent, you will have to first offload that work to some other component or service that is not in the critical path of the function. One option is to send a message to a pubsub function, and let that function finish in the "background" while the first function sends the response and terminates. You could also send messages to other services, such as App Engine or Compute Engine, or even kick off work in other clouds to finish asynchronously.
See also:
Continue execution after sending response (Cloud Functions for Firebase)
How to exec code after res.send() in express server at Firebase cloudFunctions
I have a Node app/script that needs to constantly be running (it's a discord bot, done with discord.js, but I think that's mostly irrelevant), and I'd like to do it on Firebase.
It has its own client.on('event', ()=>{}) events system, so I don't believe that I could use Firebase's cloud functions. There's also what seems to be a website-hosting based way to have a node.js server, but that seems triggered by HTTP requests.
Is there any other way I could do it?
There is no way to run arbitrary node.js code on Firebase. Unless your script can run within Cloud Functions "triggered execution" mode, you'll need your own app server to run it.
You can of course create a service that maps Discord.js events to Firebase events, such as writes to the Realtime Database, Cloud Firestore, even just direct HTTPS calls to a Cloud Functions endpoint. You could even bypass Firebase there and have your mapping service write to Cloud PubSub and use that to trigger Cloud Functions.
One thing that looks promising in the Discord.js documentation is their mention of web hooks, which is just another way of describing HTTP endpoints. But from my quick scan I couldn't figure out if those would allow you to call your HTTP triggered Cloud Function.
Which one is better approach for things this sending Emails ,Sms (for account verification) , notifications bla bla via nodejs application
As per my knowledge there can be two approaches.
Execute a function after save which will do this... one can use mongoose middleware like after save..
Simulate triggers with the help of replica set in mongodb and run it through background jobs
I think second approach is better because it will be executed by some other process in background, But on the other hand node.js is asynchronous may be node.js handles these kind of stuffs in a smart way .. any idea !!!
In short: Sending Sms emails notification after user regestration should be send by nodjs middleware or by background process
and as per my knowledge background process can be executed by binding a listener to oplog
The best approach for triggering an sms/email service request after saving the document in mongoDB would be through some messaging queue.
I would recommend using RabbitMQ. It will segregate the process of sending sms/email from your req/res loop. Invoke it after the success of save function and it will get added in the queue with a completely different process. You can simply return the success result of save function without waiting for the response of message worker.
The messaging queue comes with many more features like delivery acknowledgement, scalability options, apis and guis for managing and monitoring the status of actions performed.
You can either set it up on the same server or deploy on a separate server according to the traffic.
As of MongoDB 3.6, you can do exactly this via Change Streams. They are a new feature API that let you trigger all sorts of actions based on events happening in the database.
I am parse.com user, and now I look for another service.
How can I write back end logic to firebase?
let say I want to validate all the values on server side, or trigger things. I thought about one solution, but I want to know the recommended way.
I think to
create nodejs server, that uses express.
create middlewares to handle the logic.
send rest request from the app, that triggers the middlewares
use the nodejs sdk of firebase to update the values according to the params of the http request.
And implement on the app firebase handler that listen to changes
their something simpler? In parse I used cloud code, I want that the logic will not be on the client side but on a server side.
Update (March 10, 2017): While the architecture I outline below is still valid and can be used to combine Firebase with any existing infrastructure, Firebase just released Cloud Functions for Firebase, which allows you to run JavaScript functions on Google's servers in response to Firebase events (such as database changes, users signing in and much more).
The common architectures of Firebase applications are pretty well-defined in this blog post Where does Firebase fit in your app?.
The architecture you propose is closest to architecture 3, where your client-side code talks both directly to Firebase and to your node.js server directly.
I also highly recommend that you consider option 2, where all interaction between clients and server runs through Firebase. A great example of this type of architecture is the Flashlight search integration. Clients write their search queries into the Firebase database. The server listens for such requests, executes the query and writes the response back to the database. The client waits for that response.
A simple outline for this server could be:
var ref = new Firebase('https://yours.firebaseio.com/searches');
ref.child('requests').on('child_added', function(requestSnapshot) {
// TODO: execute your operation for the request
var responseRef = ref.child('responses').child(requestSnapshot.key());
responseRef.set(result, function(error) {
if (!error) {
// remove the request, since we've handled it
requestSnapshot.ref().remove();
}
});
})
With this last approach the client never directly talks to your server, which removes all kind of potential problems that you have to worry about. For this reason I sometimes refer to them as "bots", instead of servers.
2017
Today Google announced Cloud Functions for Firebase
https://firebase.google.com/features/functions/
This is a great solution for the architectures and back end logic in Firebase.
Here's what I would do:
Validade all the inputs with the ".validate" rules. No server needed for that.
If you have tasks to run, use Firebase Queue, a bot to run the tasks and you are done.
If you don't do the last one, you may have two problems:
If you try use the diagram you posted it will be a little tricky to get the auth object at the server (but not impossible). Go ahead if you don't need to validate the user to allow the request.
If you use just the regular firebase app to listen to changes and respond (editing the object for instance, like Frank van Puffelen's example code), you might have scalability problems. Once your back end scales to two (or more) instances, a firebase edit will trigger the task on all of them. Each instance will notice there was a change, then run the same task once each, add/replace the response object once each and try to remove the request object once each..
Using Firebase Queue avoids both of these problems.
You can combine these two behaviors simultaneously:
Client side communicates directly with the Database
One excelent thing about the Firebase Realtime & Firestore is that you are able to listen in realtime to database changes. But is important to configure the Security Rules so the client can't modify or read data that he is not suppose to.
Client communicates with a Node.js server (or other server)
The node.js server will have adminstrative privilegies by using the Firebase Admin SDK, it can perform any change in the database regardless how the Firebase Security Rules are configured.
The Client Side should use the Firebase Authentication library to obtain the
ID Token, it will inform to the server on each request (e.g. on headers). For each received request, the node.js server verifies if the ID Token is valid by using the Firebase Admin SDK.
I created a documented GitHub project of a Node.js server that uses Firestore Database and Firebase Authentication, check the example here.