Scheduling tasks the human way - Brad Wood - ITB2021

Ortus Solutions, Corp
Ortus Solutions, CorpOrtus Solutions, Corp
Scheduling Tasks
The Human Way!
Brad Wood
@bdw429s
Scheduled Tasks
Scheduled Task Options Today
● Adobe Scheduled Tasks
(Uses Quartz engine)
● Lucee Scheduled Tasks
(Uses custom scheduler thread)
● Cron jobs/Jenkins jobs that hit URL
Completely external to the JVM
Scheduled Task Pain Points
● Limited scheduling capabilities
● LImited error handling
● Hard to cluster
● Each CF engine has different config
● External scheduling isn’t portable
● Can ‘t contribute run-time additions to scheduled tasks
● Usually based around public facing CFMs
● Not OO, not functional
What does the JDK Offer?
● The java.util.concurrent package!
● “Utility classes commonly useful in concurrent programming…
includes a few small standardized extensible frameworks… that
provide useful functionality and are otherwise tedious or difficult
to implement. “
● TimeUnit class for tracking seconds, minutes, hours, etc
● ThreadPoolExecutor and ScheduledThreadPoolExecutor
provide tunable, flexible thread pools.
ColdBox Scheduled Tasks
● NOT ACTUALLY COLDBOX SPECIFIC!! Also available in standalone
WireBox, LogBox, and CacheBox via the AsyncManager
● Define robust schedules via fluent DSL
● Uses Configuration as Code so no CF engine config and all contained in the
app
● Runs the same on all CF engines
● No external scheduling mechanism
● Built-in lifecycle methods and exception handling
● Built in clustering support to only run some tasks on one server
● Composable module-specific schedulers for drop-in HMVC functionality
ColdBox Scheduled Tasks
ColdBox Scheduled Tasks
Getting Started
ColdBox 6.2.0+
ColdBox Scheduler Convention
● Located in /config/Scheduler.cfc
● Our app templates are already updated to include it
● Works similar to Router.cfc-- automatic inheritance and
fluent DSL to call to configure the scheduler
ColdBox Scheduler Examples
component {
function configure() {
task( "my-task" )
.call( ()=log.info( 'Time keeps on ticking...' ) )
.everyMinute();
}
}
ColdBox Scheduler Examples
component {
function configure() {
task( "Clear Unregistered Users" )
.call( () => getInstance( "UserService" ).clearRecentUsers() )
.everyDayAt( "09:00" );
}
}
ColdBox Scheduler Examples
component {
function configure() {
task( "Hearbeat" )
.call( () => runEvent( "main.heartbeat" ) )
.every( 5, "minutes" )
.onFailure( ( task, exception ) => {
getInstance( "System" ).sendBadHeartbeat( exception );
} );
}
}
Scheduler Life-Cycle Methods
Scheduler Life-Cycle Methods
● onStartup() - Called after the scheduler has registered all schedules
● onShutdown() - Called before the scheduler is going to be shutdown
● onAnyTaskError(task,exception) - Called whenever ANY task fails
● onAnyTaskSuccess(task,result) - Called whenever ANY task succeeds
● beforeAnyTask(task) - Called before ANY task runs
● afterAnyTask(task,result) - Called after ANY task runs
Scheduler Life-Cycle Methods
component {
function configure() {
// Tasks here
}
function onStartup(){
log.info( 'Scheduler ready to rock and roll!' );
}
function onAnyTaskError( required task, required e ){
log.error( 'Task #task.getName()# has bombed!', e );
}
}
/config/Scheduler.cfc
Scheduler Configuration Methods
Scheduler Configuration Methods
● setCacheName( cacheName ) - Set the cachename to use for all
registered tasks
● setServerFixation( boolean ) - Set the server fixation to use for all
registered tasks
● setTimezone( timezone ) - Set the timezone to use for all registered tasks
● setExecutor( executor ) - Override the executor generated for the
scheduler
Scheduler Configuration Methods
component {
function configure() {
setCacheName( "Redis" );
setServerFixation( true );
setTimezone( "America/Chicago" );
}
}
/config/Scheduler.cfc
Scheduler Additional Methods
● getSetting()
● getInstance()
● runEvent()
● runRoute()
● view()
● layout()
● announce()
Task call() method
Task call() method
component {
function configure() {
// Lambda Syntax
task( "my-task" )
.call( () => getInstance( "myService" ).runcleanup() )
.everyHour();
}
}
/config/Scheduler.cfc
Task call() method
component {
function configure() {
// Closure Syntax
task( "my-task" )
.call( function(){
getInstance( "myService" ).runcleanup()
} )
.everyHourAt( 45 );
}
}
/config/Scheduler.cfc
Task call() method
component {
function configure() {
// Object with run() method
task( "my-task" )
.call( getInstance( "MyTask" ) )
.everyDay();
}
}
/config/Scheduler.cfc
Task call() method
component {
function configure() {
// Object with a custom method
task( "my-task" )
.call( getInstance( "CacheService" ), "reapCache" )
.everydayAt( "13:00" );
}
}
/config/Scheduler.cfc
Task Schedule Times
Scheduler TimeUnit
.every( period, timeunit )
.spacedDelay( spacedDelay, timeunit )
● days
● hours
● minutes
● seconds
● milliseconds (default)
● microseconds
● nanoseconds
Scheduler everyXXX() methods
.everydayAt( "13:00" )
.everyMinute()
.everyHour()
.everyHourAt( minutes )
.everyDay()
.everyDayAt( time )
.everyWeek()
.everyWeekOn( day, time )
.everyMonth()
.everyMonthOn( day, time )
Scheduler everyXXX() methods
.onFirstBusinessDayOfTheMonth( time )
.onLastBusinessDayOfTheMonth( time )
.everyYear()
.everyYearOn( month, day, time )
Scheduler everyXXX() methods
.onWeekends( time )
.onWeekdays( time )
.onMondays( time )
.onTuesdays( time )
.onWednesdays( time )
.onThursdays( time )
.onFridays( time )
.onSaturdays( time )
.onSundays( time )
Scheduler one-off tasks
component {
function configure() {
// Warm up caches 1 minute after app comes online
task( "build-up-cache" )
.call( () => getInstance( "DataServices" ).buildCache() )
.delay( 1, "minutes" );
}
}
/config/Scheduler.cfc
Task Life-Cycle Methods
Task Life-Cycle Methods
● after( target ) - Store the closure to execute after the task executes
● before( target ) - Store the closure to execute before the task executes
● onFailure( target ) - Store the closure to execute if there is a failure running
the task
● onSuccess( target ) - Store the closure to execute if the task completes
successfully
Task Life-Cycle Methods
task( "cool-task" )
.call( ()=>{} )
.before( function( task ) {
log.info( '#task.getName()# about to run!' );
} )
.after( function( task, results ){
log.info( '#task.getName()# has completed!' );
} )
.onFailure( function( task, exception ){
log.error( '#task.getName()# blew up!', exception );
} )
.onSuccess( function( task, results ){
log.info( '#task.getName()# has completed!' );
} );
/config/Scheduler.cfc
Task Constraints
Task Constraints - when()
component {
property name='drinkService' inject;
function configure() {
task( "remove-thirst" )
.call( () => drinkService.orderDrinks() )
.hourly()
.when( () => drinkService.isHappyHour() );
}
}
/config/Scheduler.cfc
Task Constraints - server fixation
component {
function configure() {
task( "my-task" )
.call( () => getInstance( "securityService" ).cleanOldUsers() )
.daily()
.onOneServer();
}
}
/config/Scheduler.cfc
Task Constraints - environment
component {
function configure() {
task( "my-task" )
.call( () => getInstance( "securityService" ).cleanOldUsers() )
.daily()
.onEnvironment( "staging,production" );
}
}
/config/Scheduler.cfc
Task Stats
Task Stats
● created - The timestamp of when the task was created in memory
● lastRun - The last time the task ran
● nextRun - When the task will run next
● totalFailures - How many times the task has failed execution
● totalRuns - How many times the task has run
● totalSuccess - How many times the task has run and succeeded
Task Stats
getInstance( 'appScheduler@coldbox' )
.getTaskRecord( 'testharness-Heartbeat' )
.task
.getStats()
Schedulers For Modules
Schedulers For Modules
● Every module can have its own scheduler!
● Injectable as cbScheduler@{moduleName}
● Lifecycle is tied to module load/unload
● Provides portable, drop in tasks
Schedulers For Modules - Example
task( "unleashsdk-refresh-features" )
.call( getInstance( "UnleashSDK@unleashsdk" ), "refreshFeatures" )
.every( variables.refreshInterval, "seconds" )
.before( function() {
if ( log.canDebug() ) {
log.debug( "Starting to fetch new features from Unleash" );
}
} )
.onSuccess( function( task, results ) {
if ( log.canInfo() ) {
log.info( "Successfully refreshed features", results );
}
} )
.onFailure( function( task, exception ) {
if ( log.canError() ) {
log.error( "Exception when running task [unleashsdk-refresh-features]:", exception );
}
} );
https://github.com/coldbox-modules/unleashsdk/blob/main/config/Scheduler.cfc
The End (Q & A)
https://coldbox.ortusbooks.com/digging-deeper/scheduled-tasks
Brad Wood
@bdw429s
brad@bradwood.com
1 de 45

Mais conteúdo relacionado

Mais procurados

About Node.jsAbout Node.js
About Node.jsArtemisa Yescas Engler
2.3K visualizações107 slides
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to productionFDConf
8.8K visualizações51 slides
Express JSExpress JS
Express JSAlok Guha
2.5K visualizações17 slides
Cli jbugCli jbug
Cli jbugmaeste
722 visualizações24 slides

Mais procurados(20)

About Node.jsAbout Node.js
About Node.js
Artemisa Yescas Engler2.3K visualizações
Serverless Java on KubernetesServerless Java on Kubernetes
Serverless Java on Kubernetes
Krzysztof Sobkowiak134 visualizações
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to production
FDConf8.8K visualizações
Express JSExpress JS
Express JS
Alok Guha2.5K visualizações
Cli jbugCli jbug
Cli jbug
maeste722 visualizações
Intro to node.js - Ran Mizrahi (28/8/14)Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)
Ran Mizrahi564 visualizações
Building a real life application in node jsBuilding a real life application in node js
Building a real life application in node js
fakedarren20.4K visualizações
Advanced VCL: how to use restartAdvanced VCL: how to use restart
Advanced VCL: how to use restart
Fastly3.8K visualizações
COSchedulerCOScheduler
COScheduler
WO Community553 visualizações
Introduction to Python CeleryIntroduction to Python Celery
Introduction to Python Celery
Mahendra M4.6K visualizações
Scala, docker and testing, oh my! mario camouScala, docker and testing, oh my! mario camou
Scala, docker and testing, oh my! mario camou
J On The Beach2.8K visualizações
Javascript TDD with Jasmine, Karma, and GulpJavascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and Gulp
All Things Open4.6K visualizações
Build RESTful API Using Express JSBuild RESTful API Using Express JS
Build RESTful API Using Express JS
Cakra Danu Sedayu389 visualizações
Intro to NodeIntro to Node
Intro to Node
Aaron Stannard5.2K visualizações
Dropwizard InternalsDropwizard Internals
Dropwizard Internals
carlo-rtr2.9K visualizações
Autoscaling with hashi_corp_nomadAutoscaling with hashi_corp_nomad
Autoscaling with hashi_corp_nomad
Bram Vogelaar219 visualizações
Introduction to Vert.xIntroduction to Vert.x
Introduction to Vert.x
Yiguang Hu3.5K visualizações
Nodejs Explained with ExamplesNodejs Explained with Examples
Nodejs Explained with Examples
Gabriele Lana112.3K visualizações
Angular beansAngular beans
Angular beans
Bessem Hmidi5.1K visualizações
Apache Aries   OverviewApache Aries   Overview
Apache Aries Overview
Ian Robinson3K visualizações

Similar a Scheduling tasks the human way - Brad Wood - ITB2021

Google App Engine Developer - Day3Google App Engine Developer - Day3
Google App Engine Developer - Day3Simon Su
1.6K visualizações36 slides
An Introduction to CeleryAn Introduction to Celery
An Introduction to CeleryIdan Gazit
70.3K visualizações46 slides
CeleryCelery
CeleryÒscar Vilaplana
954 visualizações34 slides

Similar a Scheduling tasks the human way - Brad Wood - ITB2021(20)

ITB_2023_CommandBox_Task_Runners_Brad_Wood.pdfITB_2023_CommandBox_Task_Runners_Brad_Wood.pdf
ITB_2023_CommandBox_Task_Runners_Brad_Wood.pdf
Ortus Solutions, Corp6 visualizações
Google App Engine Developer - Day3Google App Engine Developer - Day3
Google App Engine Developer - Day3
Simon Su1.6K visualizações
Brad Wood - CommandBox CLI Brad Wood - CommandBox CLI
Brad Wood - CommandBox CLI
Ortus Solutions, Corp59 visualizações
An Introduction to CeleryAn Introduction to Celery
An Introduction to Celery
Idan Gazit70.3K visualizações
CeleryCelery
Celery
Òscar Vilaplana954 visualizações
[NDC 2019] Enterprise-Grade Serverless[NDC 2019] Enterprise-Grade Serverless
[NDC 2019] Enterprise-Grade Serverless
KatyShimizu118 visualizações
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
Ankit Rastogi3.5K visualizações
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js framework
Ben Lin3.3K visualizações
Matthew Eernisse, NodeJs, .toster {webdev}Matthew Eernisse, NodeJs, .toster {webdev}
Matthew Eernisse, NodeJs, .toster {webdev}
.toster1.4K visualizações
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
Adam L Barrett282 visualizações
Node js lectureNode js lecture
Node js lecture
Darryl Sherman71 visualizações
Grails   transactionsGrails   transactions
Grails transactions
Husain Dalal1.4K visualizações
Dragoncraft Architectural OverviewDragoncraft Architectural Overview
Dragoncraft Architectural Overview
jessesanford653 visualizações
Azure Durable Functions (2019-04-27)Azure Durable Functions (2019-04-27)
Azure Durable Functions (2019-04-27)
Paco de la Cruz741 visualizações

Mais de Ortus Solutions, Corp(20)

Luis Majano The Battlefield ORMLuis Majano The Battlefield ORM
Luis Majano The Battlefield ORM
Ortus Solutions, Corp28 visualizações
Secure your Secrets and Settings in ColdFusionSecure your Secrets and Settings in ColdFusion
Secure your Secrets and Settings in ColdFusion
Ortus Solutions, Corp71 visualizações
Daniel Garcia ContentBox: CFSummit 2023Daniel Garcia ContentBox: CFSummit 2023
Daniel Garcia ContentBox: CFSummit 2023
Ortus Solutions, Corp41 visualizações
ITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdfITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdf
ITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdf
Ortus Solutions, Corp14 visualizações
ITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdfITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdf
ITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdf
Ortus Solutions, Corp14 visualizações
ITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdfITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdf
ITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdf
Ortus Solutions, Corp11 visualizações
ITB_2023_CBWire_v3_Grant_Copley.pdfITB_2023_CBWire_v3_Grant_Copley.pdf
ITB_2023_CBWire_v3_Grant_Copley.pdf
Ortus Solutions, Corp7 visualizações
ITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdfITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdf
ITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdf
Ortus Solutions, Corp16 visualizações
ITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdfITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdf
ITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdf
Ortus Solutions, Corp8 visualizações
ITB_2023_Chatgpt_Box_Scott_Steinbeck.pdfITB_2023_Chatgpt_Box_Scott_Steinbeck.pdf
ITB_2023_Chatgpt_Box_Scott_Steinbeck.pdf
Ortus Solutions, Corp19 visualizações
ITB2023 Developing for Performance - Denard Springle.pdfITB2023 Developing for Performance - Denard Springle.pdf
ITB2023 Developing for Performance - Denard Springle.pdf
Ortus Solutions, Corp14 visualizações
Enterprise Messaging with RabbitMQ.pdfEnterprise Messaging with RabbitMQ.pdf
Enterprise Messaging with RabbitMQ.pdf
Ortus Solutions, Corp89 visualizações
Into The Box 2023 Keynote day 2Into The Box 2023 Keynote day 2
Into The Box 2023 Keynote day 2
Ortus Solutions, Corp6 visualizações
Into The Box 2023 Keynote Day 1Into The Box 2023 Keynote Day 1
Into The Box 2023 Keynote Day 1
Ortus Solutions, Corp17 visualizações
Secure all things with CBSecurity 3Secure all things with CBSecurity 3
Secure all things with CBSecurity 3
Ortus Solutions, Corp17 visualizações
CBSecurity 3 - Secure Your ColdBox ApplicationsCBSecurity 3 - Secure Your ColdBox Applications
CBSecurity 3 - Secure Your ColdBox Applications
Ortus Solutions, Corp51 visualizações
Open Source LicensesOpen Source Licenses
Open Source Licenses
Ortus Solutions, Corp5 visualizações
Message Queues with RabbitMQ - Brad Wood.pdfMessage Queues with RabbitMQ - Brad Wood.pdf
Message Queues with RabbitMQ - Brad Wood.pdf
Ortus Solutions, Corp24 visualizações

Último(20)

ChatGPT and AI for Web DevelopersChatGPT and AI for Web Developers
ChatGPT and AI for Web Developers
Maximiliano Firtman161 visualizações
TE Connectivity: Card Edge InterconnectsTE Connectivity: Card Edge Interconnects
TE Connectivity: Card Edge Interconnects
CXL Forum95 visualizações
METHOD AND SYSTEM FOR PREDICTING OPTIMAL LOAD FOR WHICH THE YIELD IS MAXIMUM ...METHOD AND SYSTEM FOR PREDICTING OPTIMAL LOAD FOR WHICH THE YIELD IS MAXIMUM ...
METHOD AND SYSTEM FOR PREDICTING OPTIMAL LOAD FOR WHICH THE YIELD IS MAXIMUM ...
Prity Khastgir IPR Strategic India Patent Attorney Amplify Innovation24 visualizações
Web Dev - 1 PPT.pdfWeb Dev - 1 PPT.pdf
Web Dev - 1 PPT.pdf
gdsczhcet49 visualizações
MemVerge: Memory Viewer SoftwareMemVerge: Memory Viewer Software
MemVerge: Memory Viewer Software
CXL Forum117 visualizações
Business Analyst Series 2023 -  Week 2 Session 3Business Analyst Series 2023 -  Week 2 Session 3
Business Analyst Series 2023 - Week 2 Session 3
DianaGray10319 visualizações
Five Things You SHOULD Know About PostmanFive Things You SHOULD Know About Postman
Five Things You SHOULD Know About Postman
Postman22 visualizações
Java Platform Approach 1.0 - Picnic MeetupJava Platform Approach 1.0 - Picnic Meetup
Java Platform Approach 1.0 - Picnic Meetup
Rick Ossendrijver24 visualizações
ThroughputThroughput
Throughput
Moisés Armani Ramírez31 visualizações
Green Leaf Consulting: Capabilities DeckGreen Leaf Consulting: Capabilities Deck
Green Leaf Consulting: Capabilities Deck
GreenLeafConsulting177 visualizações
The Research Portal of Catalonia: Growing more (information) & more (services)The Research Portal of Catalonia: Growing more (information) & more (services)
The Research Portal of Catalonia: Growing more (information) & more (services)
CSUC - Consorci de Serveis Universitaris de Catalunya59 visualizações
Spesifikasi Lengkap ASUS Vivobook Go 14Spesifikasi Lengkap ASUS Vivobook Go 14
Spesifikasi Lengkap ASUS Vivobook Go 14
Dot Semarang34 visualizações
Business Analyst Series 2023 -  Week 3 Session 5Business Analyst Series 2023 -  Week 3 Session 5
Business Analyst Series 2023 - Week 3 Session 5
DianaGray1094 visualizações

Scheduling tasks the human way - Brad Wood - ITB2021

  • 1. Scheduling Tasks The Human Way! Brad Wood @bdw429s
  • 3. Scheduled Task Options Today ● Adobe Scheduled Tasks (Uses Quartz engine) ● Lucee Scheduled Tasks (Uses custom scheduler thread) ● Cron jobs/Jenkins jobs that hit URL Completely external to the JVM
  • 4. Scheduled Task Pain Points ● Limited scheduling capabilities ● LImited error handling ● Hard to cluster ● Each CF engine has different config ● External scheduling isn’t portable ● Can ‘t contribute run-time additions to scheduled tasks ● Usually based around public facing CFMs ● Not OO, not functional
  • 5. What does the JDK Offer? ● The java.util.concurrent package! ● “Utility classes commonly useful in concurrent programming… includes a few small standardized extensible frameworks… that provide useful functionality and are otherwise tedious or difficult to implement. “ ● TimeUnit class for tracking seconds, minutes, hours, etc ● ThreadPoolExecutor and ScheduledThreadPoolExecutor provide tunable, flexible thread pools.
  • 6. ColdBox Scheduled Tasks ● NOT ACTUALLY COLDBOX SPECIFIC!! Also available in standalone WireBox, LogBox, and CacheBox via the AsyncManager ● Define robust schedules via fluent DSL ● Uses Configuration as Code so no CF engine config and all contained in the app ● Runs the same on all CF engines ● No external scheduling mechanism ● Built-in lifecycle methods and exception handling ● Built in clustering support to only run some tasks on one server ● Composable module-specific schedulers for drop-in HMVC functionality
  • 10. ColdBox Scheduler Convention ● Located in /config/Scheduler.cfc ● Our app templates are already updated to include it ● Works similar to Router.cfc-- automatic inheritance and fluent DSL to call to configure the scheduler
  • 11. ColdBox Scheduler Examples component { function configure() { task( "my-task" ) .call( ()=log.info( 'Time keeps on ticking...' ) ) .everyMinute(); } }
  • 12. ColdBox Scheduler Examples component { function configure() { task( "Clear Unregistered Users" ) .call( () => getInstance( "UserService" ).clearRecentUsers() ) .everyDayAt( "09:00" ); } }
  • 13. ColdBox Scheduler Examples component { function configure() { task( "Hearbeat" ) .call( () => runEvent( "main.heartbeat" ) ) .every( 5, "minutes" ) .onFailure( ( task, exception ) => { getInstance( "System" ).sendBadHeartbeat( exception ); } ); } }
  • 15. Scheduler Life-Cycle Methods ● onStartup() - Called after the scheduler has registered all schedules ● onShutdown() - Called before the scheduler is going to be shutdown ● onAnyTaskError(task,exception) - Called whenever ANY task fails ● onAnyTaskSuccess(task,result) - Called whenever ANY task succeeds ● beforeAnyTask(task) - Called before ANY task runs ● afterAnyTask(task,result) - Called after ANY task runs
  • 16. Scheduler Life-Cycle Methods component { function configure() { // Tasks here } function onStartup(){ log.info( 'Scheduler ready to rock and roll!' ); } function onAnyTaskError( required task, required e ){ log.error( 'Task #task.getName()# has bombed!', e ); } } /config/Scheduler.cfc
  • 18. Scheduler Configuration Methods ● setCacheName( cacheName ) - Set the cachename to use for all registered tasks ● setServerFixation( boolean ) - Set the server fixation to use for all registered tasks ● setTimezone( timezone ) - Set the timezone to use for all registered tasks ● setExecutor( executor ) - Override the executor generated for the scheduler
  • 19. Scheduler Configuration Methods component { function configure() { setCacheName( "Redis" ); setServerFixation( true ); setTimezone( "America/Chicago" ); } } /config/Scheduler.cfc
  • 20. Scheduler Additional Methods ● getSetting() ● getInstance() ● runEvent() ● runRoute() ● view() ● layout() ● announce()
  • 22. Task call() method component { function configure() { // Lambda Syntax task( "my-task" ) .call( () => getInstance( "myService" ).runcleanup() ) .everyHour(); } } /config/Scheduler.cfc
  • 23. Task call() method component { function configure() { // Closure Syntax task( "my-task" ) .call( function(){ getInstance( "myService" ).runcleanup() } ) .everyHourAt( 45 ); } } /config/Scheduler.cfc
  • 24. Task call() method component { function configure() { // Object with run() method task( "my-task" ) .call( getInstance( "MyTask" ) ) .everyDay(); } } /config/Scheduler.cfc
  • 25. Task call() method component { function configure() { // Object with a custom method task( "my-task" ) .call( getInstance( "CacheService" ), "reapCache" ) .everydayAt( "13:00" ); } } /config/Scheduler.cfc
  • 27. Scheduler TimeUnit .every( period, timeunit ) .spacedDelay( spacedDelay, timeunit ) ● days ● hours ● minutes ● seconds ● milliseconds (default) ● microseconds ● nanoseconds
  • 28. Scheduler everyXXX() methods .everydayAt( "13:00" ) .everyMinute() .everyHour() .everyHourAt( minutes ) .everyDay() .everyDayAt( time ) .everyWeek() .everyWeekOn( day, time ) .everyMonth() .everyMonthOn( day, time )
  • 29. Scheduler everyXXX() methods .onFirstBusinessDayOfTheMonth( time ) .onLastBusinessDayOfTheMonth( time ) .everyYear() .everyYearOn( month, day, time )
  • 30. Scheduler everyXXX() methods .onWeekends( time ) .onWeekdays( time ) .onMondays( time ) .onTuesdays( time ) .onWednesdays( time ) .onThursdays( time ) .onFridays( time ) .onSaturdays( time ) .onSundays( time )
  • 31. Scheduler one-off tasks component { function configure() { // Warm up caches 1 minute after app comes online task( "build-up-cache" ) .call( () => getInstance( "DataServices" ).buildCache() ) .delay( 1, "minutes" ); } } /config/Scheduler.cfc
  • 33. Task Life-Cycle Methods ● after( target ) - Store the closure to execute after the task executes ● before( target ) - Store the closure to execute before the task executes ● onFailure( target ) - Store the closure to execute if there is a failure running the task ● onSuccess( target ) - Store the closure to execute if the task completes successfully
  • 34. Task Life-Cycle Methods task( "cool-task" ) .call( ()=>{} ) .before( function( task ) { log.info( '#task.getName()# about to run!' ); } ) .after( function( task, results ){ log.info( '#task.getName()# has completed!' ); } ) .onFailure( function( task, exception ){ log.error( '#task.getName()# blew up!', exception ); } ) .onSuccess( function( task, results ){ log.info( '#task.getName()# has completed!' ); } ); /config/Scheduler.cfc
  • 36. Task Constraints - when() component { property name='drinkService' inject; function configure() { task( "remove-thirst" ) .call( () => drinkService.orderDrinks() ) .hourly() .when( () => drinkService.isHappyHour() ); } } /config/Scheduler.cfc
  • 37. Task Constraints - server fixation component { function configure() { task( "my-task" ) .call( () => getInstance( "securityService" ).cleanOldUsers() ) .daily() .onOneServer(); } } /config/Scheduler.cfc
  • 38. Task Constraints - environment component { function configure() { task( "my-task" ) .call( () => getInstance( "securityService" ).cleanOldUsers() ) .daily() .onEnvironment( "staging,production" ); } } /config/Scheduler.cfc
  • 40. Task Stats ● created - The timestamp of when the task was created in memory ● lastRun - The last time the task ran ● nextRun - When the task will run next ● totalFailures - How many times the task has failed execution ● totalRuns - How many times the task has run ● totalSuccess - How many times the task has run and succeeded
  • 41. Task Stats getInstance( 'appScheduler@coldbox' ) .getTaskRecord( 'testharness-Heartbeat' ) .task .getStats()
  • 43. Schedulers For Modules ● Every module can have its own scheduler! ● Injectable as cbScheduler@{moduleName} ● Lifecycle is tied to module load/unload ● Provides portable, drop in tasks
  • 44. Schedulers For Modules - Example task( "unleashsdk-refresh-features" ) .call( getInstance( "UnleashSDK@unleashsdk" ), "refreshFeatures" ) .every( variables.refreshInterval, "seconds" ) .before( function() { if ( log.canDebug() ) { log.debug( "Starting to fetch new features from Unleash" ); } } ) .onSuccess( function( task, results ) { if ( log.canInfo() ) { log.info( "Successfully refreshed features", results ); } } ) .onFailure( function( task, exception ) { if ( log.canError() ) { log.error( "Exception when running task [unleashsdk-refresh-features]:", exception ); } } ); https://github.com/coldbox-modules/unleashsdk/blob/main/config/Scheduler.cfc
  • 45. The End (Q & A) https://coldbox.ortusbooks.com/digging-deeper/scheduled-tasks Brad Wood @bdw429s brad@bradwood.com