-
Notifications
You must be signed in to change notification settings - Fork 24
Introduction to Scheduled Task Endpoints
- Introduction to Endpoints
- The Schedule Task Endpoint
- Scheduled Task Endpoint Configuration
- Setting Up Scheduled Tasks
- Building Tasks
- Special Situations and Controlling Tasks
- Generating endpoint specific URLs
Main Article: Endpoints
In all simplicity, endpoints are simple and lightweight "servlet" like handlers that accept requests and respond to them as required. Since endpoints will be used for non-human interactions (non-GUI), they are purposely designed to be extremely lightweight, and singular in purpose by performing without the need of plugins, filters, subroutines or other Mach-II constructs that the full Mach-II event request lifecycle provides. However, an endpoint does have the ability to invoke the full Mach-II request lifecycle if required. Since endpoints are registered with the framework itself, the deployment of Mach-II applications that leverage other technologies would be simplified.
In the end, endpoints make it simple to expose services such as REST, file serving, etc. that leverage Mach-II's mature application structure. All endpoints have full access to Mach-II's ColdSpring integration (via the depends attribute), which provides hooks into other features like Mach-II's Caching and Logging. We've worked hard to make it as easy as possible for developers to quickly create intuitive, high-performance API "servlets."
An endpoint should respond in a manner that is valid for the type of endpoint it is. In this case, the scheduled task endpoint takes care of routing, security and exception handling for your scheduled tasks. Another feature is all tasks you defined in an endpoint are auto-registered for you in your CFML engine.
- Built-in security via basic HTTP access authenticate which
<cfschedule>
supports - Auto-registration of tasks implemented in your endpoint in your CFML engine
- Exception handling
- Logic to disallow allow concurrent task execution (not allowing two requests to a task at one time)
- Retry on a number of time when a task fails
This endpoint simplifies deployment headache since any task methods are automatically registered as a scheduled task in your CFML engine.
- No more forgetting to register or remove scheduled tasks. Defining a scheduled task endpoint means your tasks move with your code during code deployments.
- Complete integration with you Mach-II application with access to properties and environment information
- Built-in security
- Easy integration with your pre-existing service layer / model via
depends
The file endpoint is setup by adding it to your Mach-II configuration file just like a listener or plugin. Beware that endpoint names must be unique across your application and therefore the name of an endpoint in a module cannot be the same name in another module
Since you defined your tasks in code, the value of the type
attribute with be the dot-path to your CFC that extends MachII.endpoints.task.BaseEndpoint
.
Example Simple Configuration
<endpoints>
<endpoint name="scheduledTasks" type="path.to.your.TaskEndpoint" />
</endpoints>
Example Custom Configuration
<endpoints>
<endpoint name="scheduledTasks" type="path.to.your.TaskEndpoint">
<parameters>
<parameter name="taskEnabled" value="true|false" />
<parameter name="taskEnabled">
<struct>
<key name="group:development" value="false" />
<key name="group:production" value="true" />
</struct>
</parameter>
<parameter name="taskNamePrefix" value="auto-generated" />
<parameter name="server" value="auto-generated(value of cgi.server_name)" />
<parameter name="authUsername" value="auto-generated" />
<parameter name="authPassword" value="auto-generated" />
</parameters>
</endpoint>
</endpoints>
Parameter Name | Required | Default | Description |
---|---|---|---|
taskEnabled | optional | true | The registration of scheduled tasks in the CFML engine if set to false the endpoint will be available, but no tasks will be registered in the CFML engine and any tasks in the CFML engine that start with the taskNamePrefix will be removed. Optionally takes a struct of environment groups or specific environment names to enabled/disable this endpoint. |
taskNamePrefix | optional | {application.applicationName}_{endpointName} | The prefix to use in front of the task name when registering it with cfschedule |
server | optional | The value returned by cgi.server_name
|
The base server and protocol to use for task url. |
authUsername | optional | auto-generated | The basic HTTP access authentication user name. |
authPassword | optional | auto-generated | The basic HTTP access authentication password. |
As we talked about before, scheduled tasks are implemented in code by extending the base scheduled task endpoint CFC. No confusing XML configuration is required since all tasks are implemented using annotations on your cffunction
tags. If you don't know what annotations are, they are just simple attributes added to the your cffuntion
tags that are denote configuration information (metadata) for your tasks.
In our example, we are going to define a few tasks:
<cfcomponent extends="MachII.endpoints.task.BaseEndpoint"
depends="UserService,ReportingService">
<!--- The task:interval indicates to run the task every 30 minutes (using CreateTimespan like syntax) --->
<cffunction name="sendPromotionalEmails" access="public" returntype="void" output="false"
hint="Sends some emails."
task:interval="0,0,30,0">
<cfargument name="event=" type="MachII.framework.Event" required="true" />
<cfset getUserService().sendPromotionalEmails() />
</cffunction>
<!---
The task:startDate indicates when to start the task.
10/10/10 is a Sunday so this task will be run every Sunday
--->
<cffunction name="generateSalesReports" access="public" returntype="void" output="false"
hint="Generates a sales report."
task:interval="weekly"
task:startDate="10/10/10">
<cfargument name="event=" type="MachII.framework.Event" required="true" />
<cfset var weekNumber = Week(Now()) />
<cfset var yearNumber = Year(Now()) />
<cfset getReportingService().generateSalesReport(yearNumber, weekNumber) />
</cffunction>
</cfcomponent>
Scheduled task are configured by providing annotations on your cffunctions
. The only required annotation is task:interval
which will run the task with the start date of 8/1/03
(which is the day of the first release of Mach-II).
Annotation Name | Required | Default | Type | Description |
---|---|---|---|---|
task:interval | true | n/a |
daily , weekly , monthly , 0,0,0,0
|
The interval when to run the scheduled task. Uses CreateTimespan syntax of days,hours,minutes,seconds . |
task:enabled | false | true | boolean or string indicating environments | Whether or not this particular scheduled task should be enabled or disabled. This is useful for development instead of commenting out code. By default, all tasks are enabled. You can indicate environments by using the format of `group:development=false |
task:startDate | false |
8/1/03 (Friday) |
date in mm/dd/yy
|
The date to start the scheduled task. |
task:endDate | false | n/a | date in mm/dd/yy
|
The date to end the scheduled task. By default, all tasks run infinitely if not defined. |
task:timePeriod | false |
00:00 (Midnight) |
hh:mm(-hh:mm) |
The time start/end to run the scheduled task. You can defined just one time 10:00 (10am) to indicated just a start time (useful for daily interval tasks). You can also define a time range in 24 clock. For example 17:30-19:45 is 5:30p start to 7:45p end using the interval you have defined. |
task:requestTimeout | false | 180 | numeric | The length of time for the scheduled task to run before the request times out. |
task:allowConcurrentExecutions | false | false | boolean | Allows concurrent executions of the same task at the same time. This can happen when scheduled tasks run long and the interval between them is short causing overlap. By default, this task endpoint does not allow task executions to overlap unless this flag is set to true. |
task.retryOnFailure | false | 0 | numeric | Indicates the number of times to immediately retry the task if the task encounters an exception. By default, the endpoint does not retry immediately and will wait until the next interval time period to occur. |
Our example above is purposefully simple. This is by design because scheduled task endpoints should be "connective" tissue to your pre-existing service layer / model. Try not to write ad-hoc logic in your tasks. Instead leverage your service layer / model. Scheduled task endpoints should look similar to listeners. The endpoint is the place to catch common exceptions, perform task specific logging and other schedule task specific logic such as sending task failure emails.
You can return a "string" using cfreturn
from your task function to output results to screen. If you return void, the endpoint will output a message similar to this:
Task 'xyz' has completed execution in 300ms.
Concurrent executions of the same task can occur if the task is a long running task and the task interval period is shorter than the time the task takes to complete. In most situations, a scheduled task is not designed to allow concurrent executions at the same time. By default, the endpoint blocks concurrent executions of the same task unless you defined task:allowConcurrentExecutions="true"
on your task.
Sometimes tasks fail because they encounter an un-handled exception. This can be because of a bug in your code, bad data you did not account for or an external dependency such as a database or external service like REST/SOAP service being unavailable. By default, the task endpoint will not retry a task that encountered an un-handled exception. The next time the task will be run is at the next scheduled interval. However in some cases it's nice to retry the task immediately. You can immediately retry a failed task a number of times when you defined task:retryOnFailure="10"
which retries the task 10 times before allowing the task to fail.
Getting URLs that are built specifically to a file endpoint is as simple as calling the buildEndpointUrl()
method in any framework aware component (view, listener, etc.).
Example:
#BuildEndpointUrl("nameOfTaskEndpoint", "task=nameOfTask")#
BuildEndpointUrl()
method URL parameters (the second argument) accepts the following attributes either is a |
(pipe) list or struct:
URL Parameter Name | Required | Description |
---|---|---|
task | true | The name of the task (which is the same of the cffunction name). |