Let's say I'm making a react application with firebase realtime database.
I'm having a listener that checks for a certain key in the database and updates the state every time it detects a change which causes a re-render.
const getTemperature = () => {
var dbRef = firebase.database().ref('temperature');
dbRef.on('value', (snapshot) => {
setState(snapshot.val());
});
};
I want to make a self sustained script outside of the application that runs every 2 hours and updates the firebase data from an api. I can make a script and execute it manually every 2 hours but that looks tedious.
I know of Heroku but I have no idea how it's done.
This is not a duplicate of this question because I want to update my data outside of my application. On a free server hopefully.
I'd recommend having a look at Cloud Functions for Firebase, which allow you to run code (for example code that updates the database) on Google's servers. While Cloud Functions are likely going to only be available on Firebase's paid plan, they come with a generous free tier on that plan.
Related
I am currently creating a react native + expo application upon which essentially each page makes an API call, which is a lot of API calls. I have this app also connected to firebase for different information. The things is, each of these pages don't update more than once or twice a day for the most part, so I really don't want the End User to be calling the API that much either.
My question is, is there a way to write and host a script that will continuously run that knows to call this API once every hour (or so) and then rewrite to the firebase db from which I can then only need to pull from the database as compared to having each user individually making dozens of API calls.
Please let me know! I have spent days on google and am no closer than I was before. I'm also willing to change my set up from firebase if it is not possible to accomplish that way. Thanks!
You can use a Cloud Functions scheduled trigger to run code periodically that can make changes to your database.
We have a React.js web application for one of our clients. The client has thousands of customers, and each customer makes payments/transactions every couple of months. The web application is developed using React and node, and is deployed using firebase-cli. In order to process transactions, we work with a 3rd party vendor (a credit card processing company) who supplies us with a Transaction Report REST API.
The issue is arising with our cloud function that is deployed to Firebase. This cloud function runs every night at 11:50PM EST, using Google Cloud cron jobs as the automation tool. The function makes a call out to the REST API using axios, and when a payload response is returned, our logic iterates through the response. The logic in this function gathers data from each transaction (e.g. custom Account Number, name, address, payment amount, etc.) and updates the history node within our Realtime Database.
Here's where things get really weird. We have both a DEV and PROD project for our client. When this function is deployed and running in DEV, it works with no issues! But when in PROD, it only works about 70% of the time (that is a rough guess). When I say it "only works sometimes", the function logs are printing out Function execution took 1556ms, finished with status: 'ok' - but the updating does not always occur.
Node version is v12.16.2, npm version is 6.14.4
Is there something specific that we need to set in regards to the timeout or memory usage? It is just bizarre that it works with no issues in one Firebase project but not the other.
Please advise!! Any help is great, as our client processes hundreds of transactions a night. I can show some code if necessary, just would like to protect our client's code if at all possible...
I am looking for a way to schedule Cloud Functions for Firebase or in other words trigger them on a specific time.
Update 2019-04-18
There is now a very simple way to deploy scheduled code on Cloud Functions through Firebase.
You can either use a simple text syntax:
export scheduledFunctionPlainEnglish =
functions.pubsub.schedule('every 5 minutes').onRun((context) => {
console.log('This will be run every 5 minutes!');
})
Or the more flexible cron table format:
export scheduledFunctionCrontab =
functions.pubsub.schedule('5 11 * * *').onRun((context) => {
console.log('This will be run every day at 11:05 AM UTC!');
});
To learn more about this, see:
The Scheduling Cloud Functions for Firebase blog post introducing the feature.
The documentation on scheduled functions.
Note that your project needs to be on a Blaze plan for this to work, so I'm leaving the alternative options below for reference.
If you want to schedule a single invocation of a Cloud Function on a delay from within the execution of another trigger, you can use Cloud Tasks to set that up. Read this article for an extended example of how that can work.
Original answer below...
There is no built-in runat/cron type trigger yet.
For the moment, the best option is to use an external service to trigger a HTTP function periodically. See this sample in the functions-samples repo for more information. Or use the recently introduced Google Cloud Scheduler to trigger Cloud Functions through PubSub or HTTPS:
I also highly recommend reading this post on the Firebase blog: How to Schedule (Cron) Jobs with Cloud Functions for Firebase and this video: Timing Cloud Functions for Firebase using an HTTP Trigger and Cron.
That last link uses cron-job.org to trigger Cloud Functions, and works for projects that are on a free plan. Note that this allows anyone to call your function without authorization, so you may want to include some abuse protection mechanism in the code itself.
What you can do, is spin up an AppEngine instance that is triggered by cron job and emits to PubSub. I wrote a blog post specifically on that, you might want to take a look:
https://mhaligowski.github.io/blog/2017/05/25/scheduled-cloud-function-execution.html
It is important to first note that the default timezone your functions will execute on is America/Los_Angeles according to the documentation. You may find a list of timezones here if you'd like to trigger your function(s) on a different timezone.
NB!!: Here's a useful website to assist with cron table formats (I found it pretty useful)
Here's how you'd go about it:
(Assuming you'd like to use Africa/Johannesburg as your timezone)
export const executeFunction = functions.pubsub.schedule("10 23 * * *")
.timeZone('Africa/Johannesburg').onRun(() => {
console.log("successfully executed at 23:10 Johannesburg Time!!");
});
Otherwise if you'd rather stick to the default:
export const executeFunction = functions.pubsub.schedule("10 23 * * *")
.onRun(() => {
console.log("successfully executed at 23:10 Los Angeles Time!!");
});
I'm facing a challenge on using heroku-connect with Salesforce. I'm inserting a record into a parent object (order) on PG db and I get the PG id when I do the insert, then I have to insert the child (order lines) but heroku-connect hasn't done the insert into Salesforce and I don't have the SFID to be able to insert it.
What would you guys recommend I do? Do I do a requery of the field that tells me if it's synched and refresh the $digest in NG? Or do I do it on the API backend with a interval. I'm a little lost on what route to take.
I'm using streaming API but still can't get the SFID from the callback when I do the insert.
rows: [ { id: 85, sfid: null } ],
EDIT
Got this from Heroku support, works great.
https://devcenter.heroku.com/articles/herokuconnect#relationships-between-objects
We ran into this issue before, when we were evaluating Heroku Connect. We ended up with writing our own sync due several limitations of our data model.
In your case, before saving record into Postgres database, I would suggest to send API REST call to SFDC in order to get SFDC Id - only after that persist a record into Postgres. It will keep data model on SFDC/Postgres side consistent. At the same time API call limit utilization will be relatively low as you will be using API only for record creation.
As you are using Heroku Connect(not stand alone sync app) I would not recommend to put backend scheduler into your web app to control refresh of populated Ids. Logic will be highly coupled and might be painful in future to support you system
I'm currently using angularJS and phonegap to build a test application for Android / iOS.
The app use only text data stored in a Firebase database. I want the app to have its own local database (used when the device is offline) and sometime (when the device is online)
sync with a Firebase database.
The offline mode uses the storage API of phonegap/cordova. Could I just check the device's online state and backup the online database periodically ?
Any clues on how I can achieve this ? Last time a similar question was asked, the answer was "not yet"... (here)... because it focused on a hypothetical Firebase feature.
If Firebase is online at the start and loses its connection temporarily, then reconnects later, it will sync the local data then. So in many cases, once Firebase is online, you can simply keep pushing to Firebase during an outage.
For true offline usage, you will probably want to monitor the device's state, and also watch .info/connected to know when Firebase connects.
new Firebase('URL/.info/connected').on('value', function(ss) {
if( ss.val() === null ) /* firebase disconnected */
else /* firebase reconnected */
});
The way to achieve this with the current Firebase toolset, until it supports true offline storage, would
keep the local data simple and small
when the device comes online, convert the locally stored data to JSON
use set() to save the data into Firebase at the appropriate path
Additionally, if the app loads while the device is offline, for some reason, you can "prime" Firebase by calling set() to "initialize" the data. Then you can use Firebase as normal (just as if it were online) until it comes online at some point in the future (you would also want to store your local copy to handle the case where it never does).
Obviously, the simpler the better. Concurrent modifications, limits of local storage size, and many other factors will quickly accumulate to make any offline storage solution complex and time consuming.
After some time, I would like to add $0.03 to #Kato's answer:
Opt to call snapshot.exists() instead of calling snapshot.val() === null. As the documentation points out, exists() is slightly more efficient than comparing snapshot.val() to null.
And if you want to update data prefer to use the update() method rather then set(), as the last will overwrite your Firebase data. You can read more here.