Freshworks Serverless apps have a variety of features that can be used for different purposes. We are going to see how Product Events, Scheduled Events, and Server Method Invocation (SMI) works.
Clone this application repository to get started with this tutorial,
git clone https://github.com/freshworks-developers/serverless-events-freshdesk.git
start
to begin with the boilerplate application.finish
will have the complete code that can be referred to at the end of the tutorial or when stuck in any of the steps.Product events are getting triggered whenever a specific event occurs in the Freshdesk product. If a specific event is registered with a function to execute when the event occurs, Serverless function will automatically be executed when the specific event occurs in the Freshdesk product. For example, a product event called onTicketCreate is triggered when a ticket is created in your Freshdesk account.
In server.js
file under /server
directory, the events are subscribed with a function that is exported to run upon event occurrence.
The syntax for subscribing for events can be noted on how onTicketCreate
event and its respective function is mentioned in the events
attribute of the export object in server.js
file.
events: [
{ event: 'onTicketCreate', callback: 'onTicketCreateHandler' }
]
Let's check the callback function code which only has a console log statement. We will develop further upon it to schedule a function whenever receiving an onTicketCreate
event.
onTicketCreateHandler: function (args) {
console.log('Hello');
}
This is a special feature available in Freshworks platform to schedule a function execution at a later point in time.
Sometimes, there will be a need to execute a function at a specific time or periodically at the same time. For example, send a reminder email at a specific time or generate an analytical report every day at a specific time. Scheduled events are a right choice for them.
Scheduled events are registered similar to the product events. Add the following object where the events are subscribed in the events
attribute of the exports object.
{ event: "onScheduledEvent", callback: "onScheduledEventHandler" }
Now the events object should look like it. Don't forget to add the comma between two objects in the array.
events: [
{ event: 'onTicketCreate', callback: 'onTicketCreateHandler' },
{ event: "onScheduledEvent", callback: "onScheduledEventHandler" }
]
Let's write a function, onScheduledEventHandler
for this scheduled event to execute the function when triggered. Copy and paste the following function definition within the exports object.
onScheduledEventHandler: function (args) { $request.post(`https://${args.domain}/api/v2/tickets/${args.data.ticket_id}/notes`, {
headers: {
Authorization: "Basic <%= encode(iparam.api_key) %>"
},
json: {
private: false,
notify_emails: [args.iparams.notification_to],
body: "Guess what! You forgot to reply to this ticket",
}
}).then(data => {
console.info('Successfully added private note for reminder');
console.info(data);
}, error => {
console.error('Error: Failed to add private note for reminder');
console.error(JSON.stringify(error));
});
}
What are we doing in this function:
Guess what! You forgot to reply to this ticket
.The function has been defined on what to do upon the execution of the scheduled event. But, this scheduled event has not been created yet.
Let's create the ticket reminder schedule in the onTicketCreateHandler
function. Replace the content of the function with the following snippet. The onTicketCreateHandler
function should enclose this code.
const newDate = new Date();
$schedule.create({
name: "ticket_reminder_" + args.data.ticket.id,
data: { ticket_id: args.data.ticket.id},
schedule_at: new Date(newDate.setMinutes(newDate.getMinutes() + 6)).toISOString(),
}).then(function (data) {
console.log('successfully scheduled the reminder')
console.log(data);
}, function (error) {
console.error('Error: Failed to schedule the event');
console.error(error);
});
What are we doing in this function:
$schedule.create()
syntax.ticket_reminder_123
(In this sample name, 123 is the ticket ID).data
attribute of the options.schedule_at
option is passed with a time in ISO format. This time should be at least 5 minutes away from the schedule creation time. So, let's add 6 minutes to the time when this schedule is created.If you face issues during the simulation, refer to the code in the finish
branch of the repository that has the complete code.
Let's test out the schedule create process with the following steps:
fdk run
command.onTicketCreate
event and verify or modify the parameters data to be passed to the event according to your testing criteria. The id
attribute inside the ticket
object is the only data interesting for us for the schedule name.Simulate
button and the event will be triggered to the app, relevant logs can be found in the Terminal/Command Prompt where the app is run.The schedule has been created now if the logs exposed that the function executed in the positive flow.
Keep the app running. The function registered with the scheduled event will be triggered at the set time.
Note: If the app is published as a Custom App, the events can be triggered by creating a ticket in the Freshdesk portal and referring to the documentation to check the Serverless logs.
localstore
file in the /.fdk
directory in the root directory of the application.When a Freshdesk agent wishes to delete the reminder schedule for a ticket, our app can enable them to do it. It is possible to delete the schedule before it's execution with its name. But there's a flaw to it.
An agent can only use the frontend app to do any actions and the schedule is accessible only from the Serverless application. There's a solution for it.
There's a feature called, Server Method Invocation. It is invoked from the frontend application. Let's see how it can be implemented.
A Serverless function is defined in the regular way. But, it's not registered to any event. This function can be called directly from the frontend application. So, when the frontend application calls this function, the function will be executed in the Serverless environment and response will be sent back to the frontend application. This is the flow of the Server Method Invocation (SMI).
Let's try to understand it better by doing it. There's a scenario where this scheduled reminder may not be needed. In this case, the scheduled event should be deleted before the execution. Let's see how this case can be solved by using SMI.
Add the following function within the export
object so that it can be called from the frontend application.
deleteSchedule: function (args) {
$schedule.delete({
name: "ticket_reminder_" + args.ticket_id,
}).then(function (data) {
console.info('Successfully deleted schedule');
console.info(data);
renderData(null, data)
}, function (error) {
if (error.status === 404) {
console.error('Schedule does not exist for the ticket:', args.data.ticket.id);
} else {
console.error('Error: Failed to delete the schedule');
}
console.error(error);
renderData({ status: error.status, message: error.message });
});
}
What are we doing in this function:
$schedule.delete()
syntax.ticket_id
is expected in the function arguments to find the name of the schedule for the particular ticket.renderData(error, data)
syntax. This is a mandatory callback function for SMI. The error object should have status and message attributes and data is optional for error condition.The defined server method is called from the frontend with the following syntax. It can be found in the app/app.js
file.
client.data.get("ticket").then(
function (data) {
client.request.invoke('deleteSchedule', { ticket_id: data.ticket.id })
}
client.request.invoke()
syntax.Let's test the SMI with the following steps:
fdk run
command if not already running.?dev=true
. Example URL: https://subdomain.freshdesk.com/a/tickets/1?dev=trueDelete Schedule
button to call the server method.localstore
file in the /.fdk
directory in the root directory of the application.Voila! You have learnt a bunch of features in the Serverless environment of Freshworks Developer Platform. Refer to the complete code in the finish
branch of the same code repository.
These are the areas which are covered in this tutorial:
There are some of the Serverless features that are not covered in this tutorial. Go through the documentation and other resources to get your hands dirty with these areas to master the Freshworks Serverless apps.