Hello World Codelab 4
Welcome to part 4 of the codelab.
What we've covered so far:
Hello World Part 1 We created the Hello World Workflow.
Hello World Part 2 We created V2 of Hello World (Versioning) and added an HTTP Task.
Hello World Part 3 We created V3 of Hello World and introduced the concept of FORK and JOIN tasks.
Part 4
In Part 4 of the codelab, we'll add an Inline task to perform some basic logic operations (using JavaScript). Inline tasks are great because they allow for computations on the Conductor server as a part of the workflow, without having to stand up another task & microservice to complete the computation.
Where we stand
In part 3 of this codelab, our workflow was split into 2 forks, one that creates the "Hello World!" message, and the other fork that grabs the users' IP address and extracts their location:
Let's add a second task to the "right fork" (at least in the diagram) that extracts the user's time, and spits out the local time. There are two parameters in the Get_IP
output that allow us to do this: The date header (giving the time in GMT) and the body parameter offset
. offset
is the time (in seconds from GMT at the user's location.
To do this calculation, we will utilize the Inline Task.
Inline task
Inline tasks run basic JavaScript calculations. Since the Get_IP
task outputs both the time in GMT and the offset from GMT at the local location, we can write a script to calculate the users' current time. In JavaScript, the code to convert the time from GMT to the current time looks like this:
Note: Several members of the Orkes team live in India, where the timezone is 30 minutes offset from traditional timezones. This code accounts for time zones that have hour fractions in them.
The JavaScript will have two inputs $.date
and $.offset
. The rest is just logic and math:
function e() {
var offsetSeconds = $.offsetSeconds;
var today = new Date($.date);
var GMTHours = today.getHours();
var GMTMinutes = today.getMinutes();
var localHour = 0;
var hoursSum = 0;
var extraHour =0;
var offsetHours=0;
var localMinute = 0;
if($.offsetSeconds%3600 == 0){
//simple time zone
offsetHours = offsetSeconds/3600;
hoursSum = GMTHours + offsetHours + extraHour;
localMinute = GMTMinutes;
}
else{
//complex time zone
//figure out number of minutes, and if need be - add an extra hour.
var minutesSum = (offsetSeconds%3600)/60 + GMTMinutes;
extraHour = 0;
if(minutesSum >=60){
localMinute = minutesSum-60;
extraHour = 1;
}else{
localMinute = minutesSum;
}
offsetHours=(offsetSeconds - offsetSeconds%3600)/3600;
hoursSum = GMTHours + offsetHours + extraHour;
}
if(hoursSum>23){
localHour = hoursSum- 24;
}else if( hoursSum <0){
localHour = hoursSum+ 24;
}else{
localHour = hoursSum;
}
var minuteString = ("0" + localMinute).slice(-2);
return {"hour": localHour, "minute": minuteString};
}
e();
The function returns the hour and the minute at the location of the IP address.
Adding the task to the workflow
An Inline Task has inputParameters
for all the values needed in the computation and for the expression
to be evaluated. To add our JavaScript expression, we need to minify the JS using an online JS minifier.
Version 4 of the workflow
Changes to this version of the workflow:
- Version updated to 4.
- Added the Inline task to the Fork array (after the
Get_IP
task). - Added 2 parameters as input to the inline task:
"date":"${get_IP.output.response.headers.Date[0]",
"offsetSeconds" : "${get_IP.output.response.body.offset}",
- Updated the Join to
joinOn
the inline taskcalculate_local_time_ref
(instead of the get_IP task). - Added a new
outputParameter
calledhw_time
to announce the local time.
{
"name": "hello_world_<uniqueId>",
"description": "hello world Workflow",
"version": 4,
"tasks": [
{"name":"hello_world_fork",
"taskReferenceName":"hw_fork_ref",
"type":"FORK_JOIN",
"forkTasks":[
[
{
"name": "hello_world_<uniqueid>",
"taskReferenceName": "hello_world_ref",
"inputParameters": {},
"type": "SIMPLE",
"decisionCases": {},
"defaultCase": [],
"forkTasks": [],
"startDelay": 0,
"joinOn": [],
"optional": false,
"defaultExclusiveJoinTask": [],
"asyncComplete": false,
"loopOver": []
}
],[
{
"name": "Get_IP",
"taskReferenceName": "get_IP",
"inputParameters": {
"http_request": {
"uri": "http://ip-api.com/json/${workflow.input.ipaddress}?fields=status,message,country,countryCode,region,regionName,city,zip,lat,lon,timezone,offset,isp,org,as,query",
"method": "GET"
}
},
"type": "HTTP"
},
{
"name": "calculate_local_time",
"taskReferenceName":"calculate_local_time_ref",
"type":"INLINE",
"inputParameters":{
"date":"${get_IP.output.response.headers.Date[0]}",
"offsetSeconds" : "${get_IP.output.response.body.offset}",
"evaluatorType": "javascript",
"expression":<minified JS>
}
}
]
]},
{
"name": "hello_world_join",
"taskReferenceName": "hw_join_ref",
"type": "JOIN",
"joinOn": [
"calculate_local_time_ref",
"hello_world_ref"
]
}
],
"outputParameters": {
"hw_response": "${hello_world_ref.output.hw_response}",
"hw_location": "We hope the weather is nice near ${get_IP.output.response.body.city}",
"hw_time": "The Local time is ${calculate_local_time_ref.output.result.hour}:${calculate_local_time_ref.output.result.minute}"
},
"schemaVersion": 2,
"restartable": true,
"workflowStatusListenerEnabled": true,
"ownerEmail": "devrel@orkes.io",
"timeoutPolicy": "ALERT_ONLY",
"timeoutSeconds": 0,
"variables": {},
"inputTemplate": {}
}
With these changes to the workflow, version 4 of hello_world
now appears as follows:
When we run version 4 of the workflow (there are no changes to the input), the workflow output is now:
{
"hw_location":"We hope the weather is nice near Kennebunk"
"hw_time":"The Local time is 11:02"
"hw_response":"Hello World!"
}
Next Steps
This completes part 4 of the Hello World Codelab. To review what we've done:
In Part 1, we created a workflow using the Netflix Conductor in the Orkes Playground.
In Part 2, we extended the workflow using versioning and added an HTTP Task.
In Part 3, we created parallel workflows using the FORK task.
In Part 4, we created an Inline task and used JavaScript to complete a simple calculation on the Conductor server and return the results.
Part 5 will be our last section, and we will use a Switch task and the Set Variable task to complete our Hello World code lab. Ready to go? On to Part 5!