Schedule call function from smart contract - cron

I woudlike to run everytime my farm function from my smart contract.
How can I process to run the function every 3 hours ?

There's no native way implemented in the language, because Solidity functions are executed as a result of a transaction. But you can schedule the transaction to be sent every 3 hours.
One of the ways is using a cron initiator of a Chainlink job.
Docs with examples of the job config:
https://docs.chain.link/docs/job-specifications/
https://docs.chain.link/docs/initiators/#cron
Or running a script on your server that sends the transaction directly (without using Chainlink as a mediator).
const Web3 = require('web3');
const web3 = new Web3(providerUrl);
const myContract = new web3.eth.Contract(jsonAbi, contractAddress);
web3.eth.accounts.wallet.add(senderPrivateKey);
async function sendTransaction() {
myContract.methods.myFunction().send({from: senderAddress});
}
setInterval('sendTransaction', 3 * 60 * 60 * 1000); // 3 hours in milliseconds

You can accomplish this type of 'smart contract cron' or 'smart contract scheduler' completely on chain using Chainlink Keepers. I'd recommend following the sample Keepers contract from the Chinalink docs, where you can set a time interval (in your case, every 3 hours). After the 3 hour interval has passed, you can define which smart contract function you want to automate within the performUpkeep function: https://docs.chain.link/docs/chainlink-keepers/compatible-contracts/#example-contract
Once you've written that contract, register it on the Keepers network at keepers.chain.link to begin the automation.

Related

i want to run a function on a future date/time - once | nodejs - backend task?

i have a event web app on react.js | when logged-in user set an event on event page - assume four days later from today and there is another dropdown input filed of setReminder with values 4 hours ago / 3 hours ago and so on and on submit i'm calling or hiting an
route/api/endpoint/postRequest post->api->userSchema->mongoDB->req.body -
json
{ setReminderTime: currentDateTime - req.body.data.setReminderValue } etc. etc.
and saving other more data and so now i want to my code to run a function in there i write some code i want that code to exicute on that event date/time - {minus} that reminder date/time (4 hours or 3 or 2 hours ago ) so in reminder i send a notification or a smg or want to do other things more and i don't want to hit my databse each second and i also don't want to do use setTimeout staf beacuse my server refresh again again due to puch->updates
I'm not sure if i had understand your problem well, but you can try to use a reminder on the server (backend side) and you have to run the reminder every hour by using cron service like that :
const schedulerFactory = function() {
return {
start: function() {
// this action will be executed every day at 12:00 u can choose what you wan't
new CronJob('00 00 12 * * *', function() {
//CronJob('0 */1 * * * *') // this for execute each one minute
console.log('Running Send Notifications Worker for ' + moment().format());
notificationsWorker.run(); // this should be the function to call and it will search for all instance where some condition are true and than execute them
}, null, true, '');
},
};
};
on the database you can stock some informations to know if you have to execute this action or no (for example last connection or something like that to know when to send notification)
Good luck Bro.

How to make automated notifcation Sender using Nodejs

I wanted to make a function which will send the list of users a notification (Email) and want this to continue after every 6 hrs regularly.
Something like this
function(){
if(currentTime==scheduledTime){
//Triger notification sender
sendNotification();
scheduledTime = (scheduledTime + 6 hrs);
}
}
How can I implement this Feature. Also, where can I deploy this website with this kind of functionality for free.
You can use node-cron instead.You can setup the interval using cron syntax and it will run in a scheduled manner.
npm install --save node-cron
Then :
var cron = require('node-cron');
cron.schedule('* */6 * * *', () => {
console.log('running a task every 6 hours');
sendNotification();
});

Avoiding more than one cronjob in parallel in node.js

I would like to do some cronjob using the Node.js package "cron" every 10 minutes.
This cronjob takes between 5 to 15 minutes, and I don't want that in a case that one instance is still running - another will be joining it in parallel. Instead, it will skip the additional running and wait until the next period.
Is it possible to implement it using this package?
Here is the code of the implementation using the cron package :
const CronJob = require("cron").CronJob;
const job = new CronJob(
'0 */10 * * * *',
()=>SomeCronJob(),
null,
true,
'America/Los_Angeles',
);
I thought of implementing it using a combination of simple setInterval() and clearInterval() instead of the package, not sure how though.
I'd appreciate any help!
I would use a flag to check if the job is running. Example:
let isJobRunning = false;
function SomeCronJob() {
if (isJobRunning) {
// Skip
return;
}
isJobRunning = true;
// run stuff
// Once is finished
isJobRunning = false;
}

Run a Cron Job every 30mins after onCreate Firestore event

I want to have a cron job/scheduler that will run every 30 minutes after an onCreate event occurs in Firestore. The cron job should trigger a cloud function that picks the documents created in the last 30 minutes-validates them against a json schema-and saves them in another collection.How do I achieve this,programmatically writing such a scheduler?
What would also be fail-safe mechanism and some sort of queuing/tracking the documents created before the cron job runs to push them to another collection.
Building a queue with Firestore is simple and fits perfectly for your use-case. The idea is to write tasks to a queue collection with a due date that will then be processed when being due.
Here's an example.
Whenever your initial onCreate event for your collection occurs, write a document with the following data to a tasks collection:
duedate: new Date() + 30 minutes
type: 'yourjob'
status: 'scheduled'
data: '...' // <-- put whatever data here you need to know when processing the task
Have a worker pick up available work regularly - e.g. every minute depending on your needs
// Define what happens on what task type
const workers: Workers = {
yourjob: (data) => db.collection('xyz').add({ foo: data }),
}
// The following needs to be scheduled
export const checkQueue = functions.https.onRequest(async (req, res) => {
// Consistent timestamp
const now = admin.firestore.Timestamp.now();
// Check which tasks are due
const query = db.collection('tasks').where('duedate', '<=', new Date()).where('status', '==', 'scheduled');
const tasks = await query.get();
// Process tasks and mark it in queue as done
tasks.forEach(snapshot => {
const { type, data } = snapshot.data();
console.info('Executing job for task ' + JSON.stringify(type) + ' with data ' + JSON.stringify(data));
const job = workers[type](data)
// Update task doc with status or error
.then(() => snapshot.ref.update({ status: 'complete' }))
.catch((err) => {
console.error('Error when executing worker', err);
return snapshot.ref.update({ status: 'error' });
});
jobs.push(job);
});
return Promise.all(jobs).then(() => {
res.send('ok');
return true;
}).catch((onError) => {
console.error('Error', onError);
});
});
You have different options to trigger the checking of the queue if there is a task that is due:
Using a http callable function as in the example above. This requires you to perform a http call to this function regularly so it executes and checks if there is a task to be done. Depending on your needs you could do it from an own server or use a service like cron-job.org to perform the calls. Note that the HTTP callable function will be available publicly and potentially, others could also call it. However, if you make your check code idempotent, it shouldn't be an issue.
Use the Firebase "internal" cron option that uses Cloud Scheduler internally. Using that you can directly trigger the queue checking:
export scheduledFunctionCrontab =
functions.pubsub.schedule('* * * * *').onRun((context) => {
console.log('This will be run every minute!');
// Include code from checkQueue here from above
});
Using such a queue also makes your system more robust - if something goes wrong in between, you will not loose tasks that would somehow only exist in memory but as long as they are not marked as processed, a fixed worker will pick them up and reprocess them. This of course depends on your implementation.
You can trigger a cloud function on the Firestore Create event which will schedule the Cloud Task after 30 minutes. This will have queuing and retrying mechanism.
An easy way is that you could add a created field with a timestamp, and then have a scheduled function run at a predefined period (say, once a minute) and execute certain code for all records where created >= NOW - 31 mins AND created <= NOW - 30 mins (pseudocode). If your time precision requirements are not extremely high, that should work for most cases.
If this doesn't suit your needs, you can add a Cloud Task (Google Cloud product). The details are specified in this good article.

Schedule Agenda job to run every day at midnight

I am new to Agenda jobs (https://github.com/rschmukler/agenda) and fail to understand how I can schedule a job to run every day at a given time. I have tried the following:
agenda.every('everyday at 00:01', ...) - runs only one time.
agenda.schedule('at 00:01', ...) and then job.repeatEvery('1 day') but without much effect.
Agenda internally uses Human Interval which is inspired by date. i checked demo of date here and found that everyday at 00:00 is accepted but could not use that very well with Agenda.
Any help will be appreciated. Thank you.
//You can use something like this...
agenda.define('first', (job, done) => {
Somefunction()
job.repeatEvery('24 hours', {
skipImmediate: true
});
job.save()
done()
})
agenda.start()
agenda.on('ready', function () {
agenda.schedule('everyday at 00:00','first')
})
// This worked for me..
I think you can use repeatAt() for this purpose. Like repeatAt('12am')
or you can also use 24 hour format:- repeatAt('00:00')
The solution proposed by others, I think is a bit funky as calling job.repeatEvery() within the job handler feels kind of out of its place.
agenda.every accepts cron format, therefore you can apply it to any defined job and run the handler according to the cron sequence
You have a defined job:
agenda.define('do-something', async (job, done) => {
// Doing some heavy async stuff here
async heavyStuff();
done();
})
After server initialisation you can call it anywhere in your code to setup a repeated job. Just make sure await agenda.start() was already called and agenda has an established mongo connection
await agenda.every("0 1 * * *", "do-something");
This will run the do-something job and call the handler every day at 00:01am

Resources