SlideShare a Scribd company logo
cbq - Jobs and Tasks in the Background by Ortus
cbq - Jobs and Tasks in the Background by Ortus
cbq - Jobs and Tasks in the Background by Ortus
https://slides.com/elpete/itb2024-cbq
What this talk is
An overview of cbq
Examples of problems that queues
and jobs can solve
Overview of how to create new cbq
protocols
What this talk isn't
How to use the ColdBox Async
Manager
Overview of ColdBox Scheduled Tasks
cbq - Jobs and Tasks in the Background by Ortus
What is cbq?
A protocol-based queueing
system for ColdBox
A protocol-based queueing
system for ColdBox
Can interact with different providers, like
the ColdBox Async Engine, a database,
Redis, or Rabbit MQ
A protocol-based queueing
system for ColdBox
A protocol-based queueing
system for ColdBox
Sends a message to be consumed later.
It can be consumed by the same
application or a completely different
application, language, or service.
A protocol-based queueing
system for ColdBox
Defines a Job as the unit of work on a queue
Push a Job onto a queue connection to be worked later
Define multiple queues or named piles of work
Register worker pools to work the jobs passed to queues
Ability to switch between Queue Providers easily
What does cbq give me?
Why not just use...?
cfthread, runAsync, AsyncManager
Redis, Rabbit MQ, etc.
Homegrown queue framework
Backend processing using message queues is a paradigm shift, and CBQ is a game
changer. Asynchronous FIFO processing dynamically split across an unlimited
number of servers allows one to break up any large processing load seamlessly.
Batching, chains, and one-off jobs with built-in logging, automated intelligent
retries, and the ability to use anything from databases to cloud-based services such
as AWS SQS to manage the job queue allows me to build incredibly powerful,
scalable, and resilient systems for my financial services clients. Highly
recommended!
John Wilson
Synaptrix
Why would I use cbq?
Sending
Email
Preparing Large
Spreadsheets
Video
Processing
Background
Uploads
Sequenced
Jobs
Scheduled SMS
Messages
Email
Verification
Processing
Payments
Cancelling
Abandoned Orders
Send Monthly
Invoices
Other reasons
Easier testing making sure the right jobs were
queued
Sync in development, Rabbit in production
Adjust the worker pool scale dynamically
Retry, timeout, and backoff built in.
Definitions
Job
Does its work in the `handle` method
Serializes and deserializes itself to the queue protocol
Set instance data in the `properties`
Exist in the context of your application
Job
Queue
A named stack of jobs or messages to be delivered
A queue connection must have at least one queue which is
usually `default`
A queue connection can have as many queues as desired
Queue
Queue Provider
How a queue connection connects to a backend like Redis,
RabbitMQ, or a database
Can be used multiple times in a single application to define
multiple queue connections with different configuration
options
Queue Provider
Queue Connection
A named combination of Queue Provider and properties
Allows you to connect with multiple Database providers or
multiple Redis providers
Queue Connection
Worker Pool
A group of workers for a Queue Connection
Can optionally work a subset of queues
Can optionally work queues in a specific order
Can be scaled up or down as needed
Worker Pool
Installation
box install cbq
component {
this.javaSettings = {
loadPaths : [ expandPath( "./modules/cbq/lib" ) ],
loadColdFusionClassPath : true,
reloadOnChange : false
};
}
1
2
3
4
5
6
7
8
9
10
Batch-specific
Setup
component {
this.javaSettings = {
loadPaths : [ expandPath( "./modules/cbq/lib" ) ],
loadColdFusionClassPath : true,
reloadOnChange : false
};
}
1
2
3
4
5
6
7
8
9
10
this.javaSettings = {
component {
1
2
3
4
loadPaths : [ expandPath( "./modules/cbq/lib" ) ],
5
loadColdFusionClassPath : true,
6
reloadOnChange : false
7
};
8
9
}
10
Batch-specific
Setup
component {
this.javaSettings = {
loadPaths : [ expandPath( "./modules/cbq/lib" ) ],
loadColdFusionClassPath : true,
reloadOnChange : false
};
}
1
2
3
4
5
6
7
8
9
10
this.javaSettings = {
component {
1
2
3
4
loadPaths : [ expandPath( "./modules/cbq/lib" ) ],
5
loadColdFusionClassPath : true,
6
reloadOnChange : false
7
};
8
9
}
10
loadColdFusionClassPath : true,
reloadOnChange : false
};
component {
1
2
3
this.javaSettings = {
4
loadPaths : [ expandPath( "./modules/cbq/lib" ) ],
5
6
7
8
9
}
10
Batch-specific
Setup
component {
this.javaSettings = {
loadPaths : [ expandPath( "./modules/cbq/lib" ) ],
loadColdFusionClassPath : true,
reloadOnChange : false
};
}
1
2
3
4
5
6
7
8
9
10
this.javaSettings = {
component {
1
2
3
4
loadPaths : [ expandPath( "./modules/cbq/lib" ) ],
5
loadColdFusionClassPath : true,
6
reloadOnChange : false
7
};
8
9
}
10
loadColdFusionClassPath : true,
reloadOnChange : false
};
component {
1
2
3
this.javaSettings = {
4
loadPaths : [ expandPath( "./modules/cbq/lib" ) ],
5
6
7
8
9
}
10 }
component {
1
2
3
this.javaSettings = {
4
loadPaths : [ expandPath( "./modules/cbq/lib" ) ],
5
loadColdFusionClassPath : true,
6
reloadOnChange : false
7
};
8
9
10
Batch-specific
Setup
Configuration
Module Settings
moduleSettings = {
"cbq" : {
// The path the custom config file to
// register connections and worker pools
"configPath" : "config.cbq",
// Flag if workers should be registered.
// If your application only pushes to the queues,
// you can set this to false.
"registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ),
// The interval to poll for changes to the worker pool scaling.
// Defaults to 0 which turns off the scheduled scaling feature.
"scaleInterval" : 0,
// continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
moduleSettings = {
"cbq" : {
// The path the custom config file to
// register connections and worker pools
"configPath" : "config.cbq",
// Flag if workers should be registered.
// If your application only pushes to the queues,
// you can set this to false.
"registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ),
// The interval to poll for changes to the worker pool scaling.
// Defaults to 0 which turns off the scheduled scaling feature.
"scaleInterval" : 0,
// continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// The path the custom config file to
// register connections and worker pools
"configPath" : "config.cbq",
moduleSettings = {
1
"cbq" : {
2
3
4
5
6
// Flag if workers should be registered.
7
// If your application only pushes to the queues,
8
// you can set this to false.
9
"registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ),
10
11
// The interval to poll for changes to the worker pool scaling.
12
// Defaults to 0 which turns off the scheduled scaling feature.
13
"scaleInterval" : 0,
14
15
// continued...
16
}
17
};
18
moduleSettings = {
"cbq" : {
// The path the custom config file to
// register connections and worker pools
"configPath" : "config.cbq",
// Flag if workers should be registered.
// If your application only pushes to the queues,
// you can set this to false.
"registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ),
// The interval to poll for changes to the worker pool scaling.
// Defaults to 0 which turns off the scheduled scaling feature.
"scaleInterval" : 0,
// continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// The path the custom config file to
// register connections and worker pools
"configPath" : "config.cbq",
moduleSettings = {
1
"cbq" : {
2
3
4
5
6
// Flag if workers should be registered.
7
// If your application only pushes to the queues,
8
// you can set this to false.
9
"registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ),
10
11
// The interval to poll for changes to the worker pool scaling.
12
// Defaults to 0 which turns off the scheduled scaling feature.
13
"scaleInterval" : 0,
14
15
// continued...
16
}
17
};
18
// Flag if workers should be registered.
// If your application only pushes to the queues,
// you can set this to false.
"registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ),
moduleSettings = {
1
"cbq" : {
2
// The path the custom config file to
3
// register connections and worker pools
4
"configPath" : "config.cbq",
5
6
7
8
9
10
11
// The interval to poll for changes to the worker pool scaling.
12
// Defaults to 0 which turns off the scheduled scaling feature.
13
"scaleInterval" : 0,
14
15
// continued...
16
}
17
};
18
moduleSettings = {
"cbq" : {
// The path the custom config file to
// register connections and worker pools
"configPath" : "config.cbq",
// Flag if workers should be registered.
// If your application only pushes to the queues,
// you can set this to false.
"registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ),
// The interval to poll for changes to the worker pool scaling.
// Defaults to 0 which turns off the scheduled scaling feature.
"scaleInterval" : 0,
// continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// The path the custom config file to
// register connections and worker pools
"configPath" : "config.cbq",
moduleSettings = {
1
"cbq" : {
2
3
4
5
6
// Flag if workers should be registered.
7
// If your application only pushes to the queues,
8
// you can set this to false.
9
"registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ),
10
11
// The interval to poll for changes to the worker pool scaling.
12
// Defaults to 0 which turns off the scheduled scaling feature.
13
"scaleInterval" : 0,
14
15
// continued...
16
}
17
};
18
// Flag if workers should be registered.
// If your application only pushes to the queues,
// you can set this to false.
"registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ),
moduleSettings = {
1
"cbq" : {
2
// The path the custom config file to
3
// register connections and worker pools
4
"configPath" : "config.cbq",
5
6
7
8
9
10
11
// The interval to poll for changes to the worker pool scaling.
12
// Defaults to 0 which turns off the scheduled scaling feature.
13
"scaleInterval" : 0,
14
15
// continued...
16
}
17
};
18
// The interval to poll for changes to the worker pool scaling.
// Defaults to 0 which turns off the scheduled scaling feature.
"scaleInterval" : 0,
moduleSettings = {
1
"cbq" : {
2
// The path the custom config file to
3
// register connections and worker pools
4
"configPath" : "config.cbq",
5
6
// Flag if workers should be registered.
7
// If your application only pushes to the queues,
8
// you can set this to false.
9
"registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ),
10
11
12
13
14
15
// continued...
16
}
17
};
18
moduleSettings = {
"cbq" : {
// The default amount of time, in seconds, to delay a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerBackoff" : 0,
// The default amount of time, in seconds, to wait before timing out a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerTimeout" : 60,
// The default amount of time, in seconds,
// to wait for tasks to complete before killing them when requesting a shutdown.
"defaultWorkerShutdownTimeout" : 60,
// The default amount of attempts to try before failing a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerMaxAttempts" : 1,
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
"registerJobInterceptorRestrictionAspect" : false
// continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
moduleSettings = {
"cbq" : {
// The default amount of time, in seconds, to delay a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerBackoff" : 0,
// The default amount of time, in seconds, to wait before timing out a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerTimeout" : 60,
// The default amount of time, in seconds,
// to wait for tasks to complete before killing them when requesting a shutdown.
"defaultWorkerShutdownTimeout" : 60,
// The default amount of attempts to try before failing a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerMaxAttempts" : 1,
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
"registerJobInterceptorRestrictionAspect" : false
// continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// The default amount of time, in seconds, to delay a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerBackoff" : 0,
moduleSettings = {
1
"cbq" : {
2
3
4
5
6
// The default amount of time, in seconds, to wait before timing out a job.
7
// Used if the connection and job doesn't define their own.
8
"defaultWorkerTimeout" : 60,
9
10
// The default amount of time, in seconds,
11
// to wait for tasks to complete before killing them when requesting a shutdown.
12
"defaultWorkerShutdownTimeout" : 60,
13
14
// The default amount of attempts to try before failing a job.
15
// Used if the connection and job doesn't define their own.
16
"defaultWorkerMaxAttempts" : 1,
17
18
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
19
"registerJobInterceptorRestrictionAspect" : false
20
21
// continued...
22
}
23
};
24
moduleSettings = {
"cbq" : {
// The default amount of time, in seconds, to delay a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerBackoff" : 0,
// The default amount of time, in seconds, to wait before timing out a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerTimeout" : 60,
// The default amount of time, in seconds,
// to wait for tasks to complete before killing them when requesting a shutdown.
"defaultWorkerShutdownTimeout" : 60,
// The default amount of attempts to try before failing a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerMaxAttempts" : 1,
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
"registerJobInterceptorRestrictionAspect" : false
// continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// The default amount of time, in seconds, to delay a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerBackoff" : 0,
moduleSettings = {
1
"cbq" : {
2
3
4
5
6
// The default amount of time, in seconds, to wait before timing out a job.
7
// Used if the connection and job doesn't define their own.
8
"defaultWorkerTimeout" : 60,
9
10
// The default amount of time, in seconds,
11
// to wait for tasks to complete before killing them when requesting a shutdown.
12
"defaultWorkerShutdownTimeout" : 60,
13
14
// The default amount of attempts to try before failing a job.
15
// Used if the connection and job doesn't define their own.
16
"defaultWorkerMaxAttempts" : 1,
17
18
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
19
"registerJobInterceptorRestrictionAspect" : false
20
21
// continued...
22
}
23
};
24
// The default amount of time, in seconds, to wait before timing out a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerTimeout" : 60,
moduleSettings = {
1
"cbq" : {
2
// The default amount of time, in seconds, to delay a job.
3
// Used if the connection and job doesn't define their own.
4
"defaultWorkerBackoff" : 0,
5
6
7
8
9
10
// The default amount of time, in seconds,
11
// to wait for tasks to complete before killing them when requesting a shutdown.
12
"defaultWorkerShutdownTimeout" : 60,
13
14
// The default amount of attempts to try before failing a job.
15
// Used if the connection and job doesn't define their own.
16
"defaultWorkerMaxAttempts" : 1,
17
18
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
19
"registerJobInterceptorRestrictionAspect" : false
20
21
// continued...
22
}
23
};
24
moduleSettings = {
"cbq" : {
// The default amount of time, in seconds, to delay a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerBackoff" : 0,
// The default amount of time, in seconds, to wait before timing out a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerTimeout" : 60,
// The default amount of time, in seconds,
// to wait for tasks to complete before killing them when requesting a shutdown.
"defaultWorkerShutdownTimeout" : 60,
// The default amount of attempts to try before failing a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerMaxAttempts" : 1,
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
"registerJobInterceptorRestrictionAspect" : false
// continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// The default amount of time, in seconds, to delay a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerBackoff" : 0,
moduleSettings = {
1
"cbq" : {
2
3
4
5
6
// The default amount of time, in seconds, to wait before timing out a job.
7
// Used if the connection and job doesn't define their own.
8
"defaultWorkerTimeout" : 60,
9
10
// The default amount of time, in seconds,
11
// to wait for tasks to complete before killing them when requesting a shutdown.
12
"defaultWorkerShutdownTimeout" : 60,
13
14
// The default amount of attempts to try before failing a job.
15
// Used if the connection and job doesn't define their own.
16
"defaultWorkerMaxAttempts" : 1,
17
18
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
19
"registerJobInterceptorRestrictionAspect" : false
20
21
// continued...
22
}
23
};
24
// The default amount of time, in seconds, to wait before timing out a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerTimeout" : 60,
moduleSettings = {
1
"cbq" : {
2
// The default amount of time, in seconds, to delay a job.
3
// Used if the connection and job doesn't define their own.
4
"defaultWorkerBackoff" : 0,
5
6
7
8
9
10
// The default amount of time, in seconds,
11
// to wait for tasks to complete before killing them when requesting a shutdown.
12
"defaultWorkerShutdownTimeout" : 60,
13
14
// The default amount of attempts to try before failing a job.
15
// Used if the connection and job doesn't define their own.
16
"defaultWorkerMaxAttempts" : 1,
17
18
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
19
"registerJobInterceptorRestrictionAspect" : false
20
21
// continued...
22
}
23
};
24
// to wait for tasks to complete before killing them when requesting a shutdown.
"defaultWorkerShutdownTimeout" : 60,
moduleSettings = {
1
"cbq" : {
2
// The default amount of time, in seconds, to delay a job.
3
// Used if the connection and job doesn't define their own.
4
"defaultWorkerBackoff" : 0,
5
6
// The default amount of time, in seconds, to wait before timing out a job.
7
// Used if the connection and job doesn't define their own.
8
"defaultWorkerTimeout" : 60,
9
10
// The default amount of time, in seconds,
11
12
13
14
// The default amount of attempts to try before failing a job.
15
// Used if the connection and job doesn't define their own.
16
"defaultWorkerMaxAttempts" : 1,
17
18
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
19
"registerJobInterceptorRestrictionAspect" : false
20
21
// continued...
22
}
23
};
24
moduleSettings = {
"cbq" : {
// The default amount of time, in seconds, to delay a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerBackoff" : 0,
// The default amount of time, in seconds, to wait before timing out a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerTimeout" : 60,
// The default amount of time, in seconds,
// to wait for tasks to complete before killing them when requesting a shutdown.
"defaultWorkerShutdownTimeout" : 60,
// The default amount of attempts to try before failing a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerMaxAttempts" : 1,
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
"registerJobInterceptorRestrictionAspect" : false
// continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// The default amount of time, in seconds, to delay a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerBackoff" : 0,
moduleSettings = {
1
"cbq" : {
2
3
4
5
6
// The default amount of time, in seconds, to wait before timing out a job.
7
// Used if the connection and job doesn't define their own.
8
"defaultWorkerTimeout" : 60,
9
10
// The default amount of time, in seconds,
11
// to wait for tasks to complete before killing them when requesting a shutdown.
12
"defaultWorkerShutdownTimeout" : 60,
13
14
// The default amount of attempts to try before failing a job.
15
// Used if the connection and job doesn't define their own.
16
"defaultWorkerMaxAttempts" : 1,
17
18
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
19
"registerJobInterceptorRestrictionAspect" : false
20
21
// continued...
22
}
23
};
24
// The default amount of time, in seconds, to wait before timing out a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerTimeout" : 60,
moduleSettings = {
1
"cbq" : {
2
// The default amount of time, in seconds, to delay a job.
3
// Used if the connection and job doesn't define their own.
4
"defaultWorkerBackoff" : 0,
5
6
7
8
9
10
// The default amount of time, in seconds,
11
// to wait for tasks to complete before killing them when requesting a shutdown.
12
"defaultWorkerShutdownTimeout" : 60,
13
14
// The default amount of attempts to try before failing a job.
15
// Used if the connection and job doesn't define their own.
16
"defaultWorkerMaxAttempts" : 1,
17
18
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
19
"registerJobInterceptorRestrictionAspect" : false
20
21
// continued...
22
}
23
};
24
// to wait for tasks to complete before killing them when requesting a shutdown.
"defaultWorkerShutdownTimeout" : 60,
moduleSettings = {
1
"cbq" : {
2
// The default amount of time, in seconds, to delay a job.
3
// Used if the connection and job doesn't define their own.
4
"defaultWorkerBackoff" : 0,
5
6
// The default amount of time, in seconds, to wait before timing out a job.
7
// Used if the connection and job doesn't define their own.
8
"defaultWorkerTimeout" : 60,
9
10
// The default amount of time, in seconds,
11
12
13
14
// The default amount of attempts to try before failing a job.
15
// Used if the connection and job doesn't define their own.
16
"defaultWorkerMaxAttempts" : 1,
17
18
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
19
"registerJobInterceptorRestrictionAspect" : false
20
21
// continued...
22
}
23
};
24
// The default amount of attempts to try before failing a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerMaxAttempts" : 1,
moduleSettings = {
1
"cbq" : {
2
// The default amount of time, in seconds, to delay a job.
3
// Used if the connection and job doesn't define their own.
4
"defaultWorkerBackoff" : 0,
5
6
// The default amount of time, in seconds, to wait before timing out a job.
7
// Used if the connection and job doesn't define their own.
8
"defaultWorkerTimeout" : 60,
9
10
// The default amount of time, in seconds,
11
// to wait for tasks to complete before killing them when requesting a shutdown.
12
"defaultWorkerShutdownTimeout" : 60,
13
14
15
16
17
18
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
19
"registerJobInterceptorRestrictionAspect" : false
20
21
// continued...
22
}
23
};
24
moduleSettings = {
"cbq" : {
// The default amount of time, in seconds, to delay a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerBackoff" : 0,
// The default amount of time, in seconds, to wait before timing out a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerTimeout" : 60,
// The default amount of time, in seconds,
// to wait for tasks to complete before killing them when requesting a shutdown.
"defaultWorkerShutdownTimeout" : 60,
// The default amount of attempts to try before failing a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerMaxAttempts" : 1,
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
"registerJobInterceptorRestrictionAspect" : false
// continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// The default amount of time, in seconds, to delay a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerBackoff" : 0,
moduleSettings = {
1
"cbq" : {
2
3
4
5
6
// The default amount of time, in seconds, to wait before timing out a job.
7
// Used if the connection and job doesn't define their own.
8
"defaultWorkerTimeout" : 60,
9
10
// The default amount of time, in seconds,
11
// to wait for tasks to complete before killing them when requesting a shutdown.
12
"defaultWorkerShutdownTimeout" : 60,
13
14
// The default amount of attempts to try before failing a job.
15
// Used if the connection and job doesn't define their own.
16
"defaultWorkerMaxAttempts" : 1,
17
18
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
19
"registerJobInterceptorRestrictionAspect" : false
20
21
// continued...
22
}
23
};
24
// The default amount of time, in seconds, to wait before timing out a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerTimeout" : 60,
moduleSettings = {
1
"cbq" : {
2
// The default amount of time, in seconds, to delay a job.
3
// Used if the connection and job doesn't define their own.
4
"defaultWorkerBackoff" : 0,
5
6
7
8
9
10
// The default amount of time, in seconds,
11
// to wait for tasks to complete before killing them when requesting a shutdown.
12
"defaultWorkerShutdownTimeout" : 60,
13
14
// The default amount of attempts to try before failing a job.
15
// Used if the connection and job doesn't define their own.
16
"defaultWorkerMaxAttempts" : 1,
17
18
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
19
"registerJobInterceptorRestrictionAspect" : false
20
21
// continued...
22
}
23
};
24
// to wait for tasks to complete before killing them when requesting a shutdown.
"defaultWorkerShutdownTimeout" : 60,
moduleSettings = {
1
"cbq" : {
2
// The default amount of time, in seconds, to delay a job.
3
// Used if the connection and job doesn't define their own.
4
"defaultWorkerBackoff" : 0,
5
6
// The default amount of time, in seconds, to wait before timing out a job.
7
// Used if the connection and job doesn't define their own.
8
"defaultWorkerTimeout" : 60,
9
10
// The default amount of time, in seconds,
11
12
13
14
// The default amount of attempts to try before failing a job.
15
// Used if the connection and job doesn't define their own.
16
"defaultWorkerMaxAttempts" : 1,
17
18
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
19
"registerJobInterceptorRestrictionAspect" : false
20
21
// continued...
22
}
23
};
24
// The default amount of attempts to try before failing a job.
// Used if the connection and job doesn't define their own.
"defaultWorkerMaxAttempts" : 1,
moduleSettings = {
1
"cbq" : {
2
// The default amount of time, in seconds, to delay a job.
3
// Used if the connection and job doesn't define their own.
4
"defaultWorkerBackoff" : 0,
5
6
// The default amount of time, in seconds, to wait before timing out a job.
7
// Used if the connection and job doesn't define their own.
8
"defaultWorkerTimeout" : 60,
9
10
// The default amount of time, in seconds,
11
// to wait for tasks to complete before killing them when requesting a shutdown.
12
"defaultWorkerShutdownTimeout" : 60,
13
14
15
16
17
18
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
19
"registerJobInterceptorRestrictionAspect" : false
20
21
// continued...
22
}
23
};
24
// Flag to allow restricting Job interceptor execution using a `jobPattern` annotation.
"registerJobInterceptorRestrictionAspect" : false
moduleSettings = {
1
"cbq" : {
2
// The default amount of time, in seconds, to delay a job.
3
// Used if the connection and job doesn't define their own.
4
"defaultWorkerBackoff" : 0,
5
6
// The default amount of time, in seconds, to wait before timing out a job.
7
// Used if the connection and job doesn't define their own.
8
"defaultWorkerTimeout" : 60,
9
10
// The default amount of time, in seconds,
11
// to wait for tasks to complete before killing them when requesting a shutdown.
12
"defaultWorkerShutdownTimeout" : 60,
13
14
// The default amount of attempts to try before failing a job.
15
// Used if the connection and job doesn't define their own.
16
"defaultWorkerMaxAttempts" : 1,
17
18
19
20
21
// continued...
22
}
23
};
24
moduleSettings = {
"cbq" : {
// Datasource information for tracking batches.
"batchRepositoryProperties" : {
"tableName" : "cbq_batches",
// `datasource` can also be a struct
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in queryOptions.
"queryOptions" : {},
// Cleanup options for the batch table
"cleanup" : {
"enabled" : false,
// A callback to configure the ColdBox Scheduled Task
"frequency" : ( task ) => { task.everyDay(); },
// A QueryBuilder instance to configure what batches to delete.
// Only completed or cancelled batches can be deleted.
"criteria" : ( qb, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
qb.where( ( q ) => {
q.where( "cancelledDate", "<=", thirtyDaysAgo );
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
} );
}
}
}, // continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
moduleSettings = {
"cbq" : {
// Datasource information for tracking batches.
"batchRepositoryProperties" : {
"tableName" : "cbq_batches",
// `datasource` can also be a struct
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in queryOptions.
"queryOptions" : {},
// Cleanup options for the batch table
"cleanup" : {
"enabled" : false,
// A callback to configure the ColdBox Scheduled Task
"frequency" : ( task ) => { task.everyDay(); },
// A QueryBuilder instance to configure what batches to delete.
// Only completed or cancelled batches can be deleted.
"criteria" : ( qb, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
qb.where( ( q ) => {
q.where( "cancelledDate", "<=", thirtyDaysAgo );
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
} );
}
}
}, // continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
"tableName" : "cbq_batches",
moduleSettings = {
1
"cbq" : {
2
// Datasource information for tracking batches.
3
"batchRepositoryProperties" : {
4
5
// `datasource` can also be a struct
6
"datasource" : "",
7
// The sibling `datasource` property overrides any defined datasource in queryOptions.
8
"queryOptions" : {},
9
// Cleanup options for the batch table
10
"cleanup" : {
11
"enabled" : false,
12
// A callback to configure the ColdBox Scheduled Task
13
"frequency" : ( task ) => { task.everyDay(); },
14
// A QueryBuilder instance to configure what batches to delete.
15
// Only completed or cancelled batches can be deleted.
16
"criteria" : ( qb, currentUnixTimestamp ) => {
17
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
18
qb.where( ( q ) => {
19
q.where( "cancelledDate", "<=", thirtyDaysAgo );
20
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
21
} );
22
}
23
}
24
}, // continued...
25
}
26
};
27
moduleSettings = {
"cbq" : {
// Datasource information for tracking batches.
"batchRepositoryProperties" : {
"tableName" : "cbq_batches",
// `datasource` can also be a struct
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in queryOptions.
"queryOptions" : {},
// Cleanup options for the batch table
"cleanup" : {
"enabled" : false,
// A callback to configure the ColdBox Scheduled Task
"frequency" : ( task ) => { task.everyDay(); },
// A QueryBuilder instance to configure what batches to delete.
// Only completed or cancelled batches can be deleted.
"criteria" : ( qb, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
qb.where( ( q ) => {
q.where( "cancelledDate", "<=", thirtyDaysAgo );
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
} );
}
}
}, // continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
"tableName" : "cbq_batches",
moduleSettings = {
1
"cbq" : {
2
// Datasource information for tracking batches.
3
"batchRepositoryProperties" : {
4
5
// `datasource` can also be a struct
6
"datasource" : "",
7
// The sibling `datasource` property overrides any defined datasource in queryOptions.
8
"queryOptions" : {},
9
// Cleanup options for the batch table
10
"cleanup" : {
11
"enabled" : false,
12
// A callback to configure the ColdBox Scheduled Task
13
"frequency" : ( task ) => { task.everyDay(); },
14
// A QueryBuilder instance to configure what batches to delete.
15
// Only completed or cancelled batches can be deleted.
16
"criteria" : ( qb, currentUnixTimestamp ) => {
17
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
18
qb.where( ( q ) => {
19
q.where( "cancelledDate", "<=", thirtyDaysAgo );
20
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
21
} );
22
}
23
}
24
}, // continued...
25
}
26
};
27
// `datasource` can also be a struct
"datasource" : "",
moduleSettings = {
1
"cbq" : {
2
// Datasource information for tracking batches.
3
"batchRepositoryProperties" : {
4
"tableName" : "cbq_batches",
5
6
7
// The sibling `datasource` property overrides any defined datasource in queryOptions.
8
"queryOptions" : {},
9
// Cleanup options for the batch table
10
"cleanup" : {
11
"enabled" : false,
12
// A callback to configure the ColdBox Scheduled Task
13
"frequency" : ( task ) => { task.everyDay(); },
14
// A QueryBuilder instance to configure what batches to delete.
15
// Only completed or cancelled batches can be deleted.
16
"criteria" : ( qb, currentUnixTimestamp ) => {
17
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
18
qb.where( ( q ) => {
19
q.where( "cancelledDate", "<=", thirtyDaysAgo );
20
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
21
} );
22
}
23
}
24
}, // continued...
25
}
26
};
27
moduleSettings = {
"cbq" : {
// Datasource information for tracking batches.
"batchRepositoryProperties" : {
"tableName" : "cbq_batches",
// `datasource` can also be a struct
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in queryOptions.
"queryOptions" : {},
// Cleanup options for the batch table
"cleanup" : {
"enabled" : false,
// A callback to configure the ColdBox Scheduled Task
"frequency" : ( task ) => { task.everyDay(); },
// A QueryBuilder instance to configure what batches to delete.
// Only completed or cancelled batches can be deleted.
"criteria" : ( qb, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
qb.where( ( q ) => {
q.where( "cancelledDate", "<=", thirtyDaysAgo );
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
} );
}
}
}, // continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
"tableName" : "cbq_batches",
moduleSettings = {
1
"cbq" : {
2
// Datasource information for tracking batches.
3
"batchRepositoryProperties" : {
4
5
// `datasource` can also be a struct
6
"datasource" : "",
7
// The sibling `datasource` property overrides any defined datasource in queryOptions.
8
"queryOptions" : {},
9
// Cleanup options for the batch table
10
"cleanup" : {
11
"enabled" : false,
12
// A callback to configure the ColdBox Scheduled Task
13
"frequency" : ( task ) => { task.everyDay(); },
14
// A QueryBuilder instance to configure what batches to delete.
15
// Only completed or cancelled batches can be deleted.
16
"criteria" : ( qb, currentUnixTimestamp ) => {
17
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
18
qb.where( ( q ) => {
19
q.where( "cancelledDate", "<=", thirtyDaysAgo );
20
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
21
} );
22
}
23
}
24
}, // continued...
25
}
26
};
27
// `datasource` can also be a struct
"datasource" : "",
moduleSettings = {
1
"cbq" : {
2
// Datasource information for tracking batches.
3
"batchRepositoryProperties" : {
4
"tableName" : "cbq_batches",
5
6
7
// The sibling `datasource` property overrides any defined datasource in queryOptions.
8
"queryOptions" : {},
9
// Cleanup options for the batch table
10
"cleanup" : {
11
"enabled" : false,
12
// A callback to configure the ColdBox Scheduled Task
13
"frequency" : ( task ) => { task.everyDay(); },
14
// A QueryBuilder instance to configure what batches to delete.
15
// Only completed or cancelled batches can be deleted.
16
"criteria" : ( qb, currentUnixTimestamp ) => {
17
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
18
qb.where( ( q ) => {
19
q.where( "cancelledDate", "<=", thirtyDaysAgo );
20
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
21
} );
22
}
23
}
24
}, // continued...
25
}
26
};
27
// The sibling `datasource` property overrides any defined datasource in queryOptions.
"queryOptions" : {},
moduleSettings = {
1
"cbq" : {
2
// Datasource information for tracking batches.
3
"batchRepositoryProperties" : {
4
"tableName" : "cbq_batches",
5
// `datasource` can also be a struct
6
"datasource" : "",
7
8
9
// Cleanup options for the batch table
10
"cleanup" : {
11
"enabled" : false,
12
// A callback to configure the ColdBox Scheduled Task
13
"frequency" : ( task ) => { task.everyDay(); },
14
// A QueryBuilder instance to configure what batches to delete.
15
// Only completed or cancelled batches can be deleted.
16
"criteria" : ( qb, currentUnixTimestamp ) => {
17
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
18
qb.where( ( q ) => {
19
q.where( "cancelledDate", "<=", thirtyDaysAgo );
20
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
21
} );
22
}
23
}
24
}, // continued...
25
}
26
};
27
moduleSettings = {
"cbq" : {
// Datasource information for tracking batches.
"batchRepositoryProperties" : {
"tableName" : "cbq_batches",
// `datasource` can also be a struct
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in queryOptions.
"queryOptions" : {},
// Cleanup options for the batch table
"cleanup" : {
"enabled" : false,
// A callback to configure the ColdBox Scheduled Task
"frequency" : ( task ) => { task.everyDay(); },
// A QueryBuilder instance to configure what batches to delete.
// Only completed or cancelled batches can be deleted.
"criteria" : ( qb, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
qb.where( ( q ) => {
q.where( "cancelledDate", "<=", thirtyDaysAgo );
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
} );
}
}
}, // continued...
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
"tableName" : "cbq_batches",
moduleSettings = {
1
"cbq" : {
2
// Datasource information for tracking batches.
3
"batchRepositoryProperties" : {
4
5
// `datasource` can also be a struct
6
"datasource" : "",
7
// The sibling `datasource` property overrides any defined datasource in queryOptions.
8
"queryOptions" : {},
9
// Cleanup options for the batch table
10
"cleanup" : {
11
"enabled" : false,
12
// A callback to configure the ColdBox Scheduled Task
13
"frequency" : ( task ) => { task.everyDay(); },
14
// A QueryBuilder instance to configure what batches to delete.
15
// Only completed or cancelled batches can be deleted.
16
"criteria" : ( qb, currentUnixTimestamp ) => {
17
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
18
qb.where( ( q ) => {
19
q.where( "cancelledDate", "<=", thirtyDaysAgo );
20
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
21
} );
22
}
23
}
24
}, // continued...
25
}
26
};
27
// `datasource` can also be a struct
"datasource" : "",
moduleSettings = {
1
"cbq" : {
2
// Datasource information for tracking batches.
3
"batchRepositoryProperties" : {
4
"tableName" : "cbq_batches",
5
6
7
// The sibling `datasource` property overrides any defined datasource in queryOptions.
8
"queryOptions" : {},
9
// Cleanup options for the batch table
10
"cleanup" : {
11
"enabled" : false,
12
// A callback to configure the ColdBox Scheduled Task
13
"frequency" : ( task ) => { task.everyDay(); },
14
// A QueryBuilder instance to configure what batches to delete.
15
// Only completed or cancelled batches can be deleted.
16
"criteria" : ( qb, currentUnixTimestamp ) => {
17
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
18
qb.where( ( q ) => {
19
q.where( "cancelledDate", "<=", thirtyDaysAgo );
20
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
21
} );
22
}
23
}
24
}, // continued...
25
}
26
};
27
// The sibling `datasource` property overrides any defined datasource in queryOptions.
"queryOptions" : {},
moduleSettings = {
1
"cbq" : {
2
// Datasource information for tracking batches.
3
"batchRepositoryProperties" : {
4
"tableName" : "cbq_batches",
5
// `datasource` can also be a struct
6
"datasource" : "",
7
8
9
// Cleanup options for the batch table
10
"cleanup" : {
11
"enabled" : false,
12
// A callback to configure the ColdBox Scheduled Task
13
"frequency" : ( task ) => { task.everyDay(); },
14
// A QueryBuilder instance to configure what batches to delete.
15
// Only completed or cancelled batches can be deleted.
16
"criteria" : ( qb, currentUnixTimestamp ) => {
17
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
18
qb.where( ( q ) => {
19
q.where( "cancelledDate", "<=", thirtyDaysAgo );
20
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
21
} );
22
}
23
}
24
}, // continued...
25
}
26
};
27
// Cleanup options for the batch table
"cleanup" : {
"enabled" : false,
// A callback to configure the ColdBox Scheduled Task
"frequency" : ( task ) => { task.everyDay(); },
// A QueryBuilder instance to configure what batches to delete.
// Only completed or cancelled batches can be deleted.
"criteria" : ( qb, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
qb.where( ( q ) => {
q.where( "cancelledDate", "<=", thirtyDaysAgo );
q.orWhere( "completedDate", "<=", thirtyDaysAgo );
} );
}
}
moduleSettings = {
1
"cbq" : {
2
// Datasource information for tracking batches.
3
"batchRepositoryProperties" : {
4
"tableName" : "cbq_batches",
5
// `datasource` can also be a struct
6
"datasource" : "",
7
// The sibling `datasource` property overrides any defined datasource in queryOptions.
8
"queryOptions" : {},
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
}, // continued...
25
}
26
};
27
moduleSettings = {
"cbq" : {
// Flag to turn on logging failed jobs to a database table.
"logFailedJobs" : false,
// Configuration information for logging failed jobs.
"logFailedJobsProperties" : {
"tableName" : "cbq_failed_jobs",
// `datasource` can also be a struct.
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
"queryOptions" : {},
"cleanup" : {
"enabled" : false,
"frequency" : ( task ) => { task.everyDay(); },
"criteria" : ( q, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
q.where( "failedDate", "<=", thirtyDaysAgo );
}
}
}
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
moduleSettings = {
"cbq" : {
// Flag to turn on logging failed jobs to a database table.
"logFailedJobs" : false,
// Configuration information for logging failed jobs.
"logFailedJobsProperties" : {
"tableName" : "cbq_failed_jobs",
// `datasource` can also be a struct.
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
"queryOptions" : {},
"cleanup" : {
"enabled" : false,
"frequency" : ( task ) => { task.everyDay(); },
"criteria" : ( q, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
q.where( "failedDate", "<=", thirtyDaysAgo );
}
}
}
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Flag to turn on logging failed jobs to a database table.
"logFailedJobs" : false,
// Configuration information for logging failed jobs.
moduleSettings = {
1
"cbq" : {
2
3
4
5
"logFailedJobsProperties" : {
6
"tableName" : "cbq_failed_jobs",
7
// `datasource` can also be a struct.
8
"datasource" : "",
9
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
10
"queryOptions" : {},
11
"cleanup" : {
12
"enabled" : false,
13
"frequency" : ( task ) => { task.everyDay(); },
14
"criteria" : ( q, currentUnixTimestamp ) => {
15
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
16
q.where( "failedDate", "<=", thirtyDaysAgo );
17
}
18
}
19
}
20
}
21
};
22
moduleSettings = {
"cbq" : {
// Flag to turn on logging failed jobs to a database table.
"logFailedJobs" : false,
// Configuration information for logging failed jobs.
"logFailedJobsProperties" : {
"tableName" : "cbq_failed_jobs",
// `datasource` can also be a struct.
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
"queryOptions" : {},
"cleanup" : {
"enabled" : false,
"frequency" : ( task ) => { task.everyDay(); },
"criteria" : ( q, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
q.where( "failedDate", "<=", thirtyDaysAgo );
}
}
}
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Flag to turn on logging failed jobs to a database table.
"logFailedJobs" : false,
// Configuration information for logging failed jobs.
moduleSettings = {
1
"cbq" : {
2
3
4
5
"logFailedJobsProperties" : {
6
"tableName" : "cbq_failed_jobs",
7
// `datasource` can also be a struct.
8
"datasource" : "",
9
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
10
"queryOptions" : {},
11
"cleanup" : {
12
"enabled" : false,
13
"frequency" : ( task ) => { task.everyDay(); },
14
"criteria" : ( q, currentUnixTimestamp ) => {
15
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
16
q.where( "failedDate", "<=", thirtyDaysAgo );
17
}
18
}
19
}
20
}
21
};
22
// Configuration information for logging failed jobs.
"logFailedJobsProperties" : {
"tableName" : "cbq_failed_jobs",
// `datasource` can also be a struct.
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
"queryOptions" : {},
"cleanup" : {
"enabled" : false,
"frequency" : ( task ) => { task.everyDay(); },
"criteria" : ( q, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
q.where( "failedDate", "<=", thirtyDaysAgo );
}
}
}
moduleSettings = {
1
"cbq" : {
2
// Flag to turn on logging failed jobs to a database table.
3
"logFailedJobs" : false,
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
}
21
};
22
moduleSettings = {
"cbq" : {
// Flag to turn on logging failed jobs to a database table.
"logFailedJobs" : false,
// Configuration information for logging failed jobs.
"logFailedJobsProperties" : {
"tableName" : "cbq_failed_jobs",
// `datasource` can also be a struct.
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
"queryOptions" : {},
"cleanup" : {
"enabled" : false,
"frequency" : ( task ) => { task.everyDay(); },
"criteria" : ( q, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
q.where( "failedDate", "<=", thirtyDaysAgo );
}
}
}
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Flag to turn on logging failed jobs to a database table.
"logFailedJobs" : false,
// Configuration information for logging failed jobs.
moduleSettings = {
1
"cbq" : {
2
3
4
5
"logFailedJobsProperties" : {
6
"tableName" : "cbq_failed_jobs",
7
// `datasource` can also be a struct.
8
"datasource" : "",
9
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
10
"queryOptions" : {},
11
"cleanup" : {
12
"enabled" : false,
13
"frequency" : ( task ) => { task.everyDay(); },
14
"criteria" : ( q, currentUnixTimestamp ) => {
15
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
16
q.where( "failedDate", "<=", thirtyDaysAgo );
17
}
18
}
19
}
20
}
21
};
22
// Configuration information for logging failed jobs.
"logFailedJobsProperties" : {
"tableName" : "cbq_failed_jobs",
// `datasource` can also be a struct.
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
"queryOptions" : {},
"cleanup" : {
"enabled" : false,
"frequency" : ( task ) => { task.everyDay(); },
"criteria" : ( q, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
q.where( "failedDate", "<=", thirtyDaysAgo );
}
}
}
moduleSettings = {
1
"cbq" : {
2
// Flag to turn on logging failed jobs to a database table.
3
"logFailedJobs" : false,
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
}
21
};
22
"tableName" : "cbq_failed_jobs",
// `datasource` can also be a struct.
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
"queryOptions" : {},
moduleSettings = {
1
"cbq" : {
2
// Flag to turn on logging failed jobs to a database table.
3
"logFailedJobs" : false,
4
// Configuration information for logging failed jobs.
5
"logFailedJobsProperties" : {
6
7
8
9
10
11
"cleanup" : {
12
"enabled" : false,
13
"frequency" : ( task ) => { task.everyDay(); },
14
"criteria" : ( q, currentUnixTimestamp ) => {
15
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
16
q.where( "failedDate", "<=", thirtyDaysAgo );
17
}
18
}
19
}
20
}
21
};
22
moduleSettings = {
"cbq" : {
// Flag to turn on logging failed jobs to a database table.
"logFailedJobs" : false,
// Configuration information for logging failed jobs.
"logFailedJobsProperties" : {
"tableName" : "cbq_failed_jobs",
// `datasource` can also be a struct.
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
"queryOptions" : {},
"cleanup" : {
"enabled" : false,
"frequency" : ( task ) => { task.everyDay(); },
"criteria" : ( q, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
q.where( "failedDate", "<=", thirtyDaysAgo );
}
}
}
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Flag to turn on logging failed jobs to a database table.
"logFailedJobs" : false,
// Configuration information for logging failed jobs.
moduleSettings = {
1
"cbq" : {
2
3
4
5
"logFailedJobsProperties" : {
6
"tableName" : "cbq_failed_jobs",
7
// `datasource` can also be a struct.
8
"datasource" : "",
9
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
10
"queryOptions" : {},
11
"cleanup" : {
12
"enabled" : false,
13
"frequency" : ( task ) => { task.everyDay(); },
14
"criteria" : ( q, currentUnixTimestamp ) => {
15
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
16
q.where( "failedDate", "<=", thirtyDaysAgo );
17
}
18
}
19
}
20
}
21
};
22
// Configuration information for logging failed jobs.
"logFailedJobsProperties" : {
"tableName" : "cbq_failed_jobs",
// `datasource` can also be a struct.
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
"queryOptions" : {},
"cleanup" : {
"enabled" : false,
"frequency" : ( task ) => { task.everyDay(); },
"criteria" : ( q, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
q.where( "failedDate", "<=", thirtyDaysAgo );
}
}
}
moduleSettings = {
1
"cbq" : {
2
// Flag to turn on logging failed jobs to a database table.
3
"logFailedJobs" : false,
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
}
21
};
22
"tableName" : "cbq_failed_jobs",
// `datasource` can also be a struct.
"datasource" : "",
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
"queryOptions" : {},
moduleSettings = {
1
"cbq" : {
2
// Flag to turn on logging failed jobs to a database table.
3
"logFailedJobs" : false,
4
// Configuration information for logging failed jobs.
5
"logFailedJobsProperties" : {
6
7
8
9
10
11
"cleanup" : {
12
"enabled" : false,
13
"frequency" : ( task ) => { task.everyDay(); },
14
"criteria" : ( q, currentUnixTimestamp ) => {
15
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
16
q.where( "failedDate", "<=", thirtyDaysAgo );
17
}
18
}
19
}
20
}
21
};
22
"cleanup" : {
"enabled" : false,
"frequency" : ( task ) => { task.everyDay(); },
"criteria" : ( q, currentUnixTimestamp ) => {
var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 );
q.where( "failedDate", "<=", thirtyDaysAgo );
}
}
moduleSettings = {
1
"cbq" : {
2
// Flag to turn on logging failed jobs to a database table.
3
"logFailedJobs" : false,
4
// Configuration information for logging failed jobs.
5
"logFailedJobsProperties" : {
6
"tableName" : "cbq_failed_jobs",
7
// `datasource` can also be a struct.
8
"datasource" : "",
9
// The sibling `datasource` property overrides any defined datasource in `queryOptions`.
10
"queryOptions" : {},
11
12
13
14
15
16
17
18
19
}
20
}
21
};
22
cbq Config File
component {
function configure() {
newConnection( "default" )
.setProvider( "ColdBoxAsyncProvider@cbq" );
newConnection( "database" )
.setProvider( "DBProvider@cbq" )
.setProperties( { "tableName": "custom_jobs_table" } );
newConnection( "external" )
.setProvider( "DBProvider@cbq" )
.setProperties( { "datasource": "external" } );
newWorkerPool( "default" )
.forConnection( "default" )
.setTimeout( 5 )
.setMaxAttempts( 5 );
newWorkerPool( "priority" )
.forConnection( "database" )
.onQueues( [ "priority", "*" ] )
.setQuantity( 3 );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
component {
function configure() {
newConnection( "default" )
.setProvider( "ColdBoxAsyncProvider@cbq" );
newConnection( "database" )
.setProvider( "DBProvider@cbq" )
.setProperties( { "tableName": "custom_jobs_table" } );
newConnection( "external" )
.setProvider( "DBProvider@cbq" )
.setProperties( { "datasource": "external" } );
newWorkerPool( "default" )
.forConnection( "default" )
.setTimeout( 5 )
.setMaxAttempts( 5 );
newWorkerPool( "priority" )
.forConnection( "database" )
.onQueues( [ "priority", "*" ] )
.setQuantity( 3 );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
newConnection( "default" )
.setProvider( "ColdBoxAsyncProvider@cbq" );
newWorkerPool( "default" )
.forConnection( "default" )
.setTimeout( 5 )
.setMaxAttempts( 5 );
component {
1
function configure() {
2
3
4
5
newConnection( "database" )
6
.setProvider( "DBProvider@cbq" )
7
.setProperties( { "tableName": "custom_jobs_table" } );
8
9
newConnection( "external" )
10
.setProvider( "DBProvider@cbq" )
11
.setProperties( { "datasource": "external" } );
12
13
14
15
16
17
18
newWorkerPool( "priority" )
19
.forConnection( "database" )
20
.onQueues( [ "priority", "*" ] )
21
.setQuantity( 3 );
22
}
23
}
24
component {
function configure() {
newConnection( "default" )
.setProvider( "ColdBoxAsyncProvider@cbq" );
newConnection( "database" )
.setProvider( "DBProvider@cbq" )
.setProperties( { "tableName": "custom_jobs_table" } );
newConnection( "external" )
.setProvider( "DBProvider@cbq" )
.setProperties( { "datasource": "external" } );
newWorkerPool( "default" )
.forConnection( "default" )
.setTimeout( 5 )
.setMaxAttempts( 5 );
newWorkerPool( "priority" )
.forConnection( "database" )
.onQueues( [ "priority", "*" ] )
.setQuantity( 3 );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
newConnection( "default" )
.setProvider( "ColdBoxAsyncProvider@cbq" );
newWorkerPool( "default" )
.forConnection( "default" )
.setTimeout( 5 )
.setMaxAttempts( 5 );
component {
1
function configure() {
2
3
4
5
newConnection( "database" )
6
.setProvider( "DBProvider@cbq" )
7
.setProperties( { "tableName": "custom_jobs_table" } );
8
9
newConnection( "external" )
10
.setProvider( "DBProvider@cbq" )
11
.setProperties( { "datasource": "external" } );
12
13
14
15
16
17
18
newWorkerPool( "priority" )
19
.forConnection( "database" )
20
.onQueues( [ "priority", "*" ] )
21
.setQuantity( 3 );
22
}
23
}
24
newConnection( "database" )
.setProvider( "DBProvider@cbq" )
.setProperties( { "tableName": "custom_jobs_table" } );
newWorkerPool( "priority" )
.forConnection( "database" )
.onQueues( [ "priority", "*" ] )
.setQuantity( 3 );
component {
1
function configure() {
2
newConnection( "default" )
3
.setProvider( "ColdBoxAsyncProvider@cbq" );
4
5
6
7
8
9
newConnection( "external" )
10
.setProvider( "DBProvider@cbq" )
11
.setProperties( { "datasource": "external" } );
12
13
newWorkerPool( "default" )
14
.forConnection( "default" )
15
.setTimeout( 5 )
16
.setMaxAttempts( 5 );
17
18
19
20
21
22
}
23
}
24
component {
function configure() {
newConnection( "default" )
.setProvider( "ColdBoxAsyncProvider@cbq" );
newConnection( "database" )
.setProvider( "DBProvider@cbq" )
.setProperties( { "tableName": "custom_jobs_table" } );
newConnection( "external" )
.setProvider( "DBProvider@cbq" )
.setProperties( { "datasource": "external" } );
newWorkerPool( "default" )
.forConnection( "default" )
.setTimeout( 5 )
.setMaxAttempts( 5 );
newWorkerPool( "priority" )
.forConnection( "database" )
.onQueues( [ "priority", "*" ] )
.setQuantity( 3 );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
newConnection( "default" )
.setProvider( "ColdBoxAsyncProvider@cbq" );
newWorkerPool( "default" )
.forConnection( "default" )
.setTimeout( 5 )
.setMaxAttempts( 5 );
component {
1
function configure() {
2
3
4
5
newConnection( "database" )
6
.setProvider( "DBProvider@cbq" )
7
.setProperties( { "tableName": "custom_jobs_table" } );
8
9
newConnection( "external" )
10
.setProvider( "DBProvider@cbq" )
11
.setProperties( { "datasource": "external" } );
12
13
14
15
16
17
18
newWorkerPool( "priority" )
19
.forConnection( "database" )
20
.onQueues( [ "priority", "*" ] )
21
.setQuantity( 3 );
22
}
23
}
24
newConnection( "database" )
.setProvider( "DBProvider@cbq" )
.setProperties( { "tableName": "custom_jobs_table" } );
newWorkerPool( "priority" )
.forConnection( "database" )
.onQueues( [ "priority", "*" ] )
.setQuantity( 3 );
component {
1
function configure() {
2
newConnection( "default" )
3
.setProvider( "ColdBoxAsyncProvider@cbq" );
4
5
6
7
8
9
newConnection( "external" )
10
.setProvider( "DBProvider@cbq" )
11
.setProperties( { "datasource": "external" } );
12
13
newWorkerPool( "default" )
14
.forConnection( "default" )
15
.setTimeout( 5 )
16
.setMaxAttempts( 5 );
17
18
19
20
21
22
}
23
}
24
newConnection( "external" )
.setProvider( "DBProvider@cbq" )
.setProperties( { "datasource": "external" } );
component {
1
function configure() {
2
newConnection( "default" )
3
.setProvider( "ColdBoxAsyncProvider@cbq" );
4
5
newConnection( "database" )
6
.setProvider( "DBProvider@cbq" )
7
.setProperties( { "tableName": "custom_jobs_table" } );
8
9
10
11
12
13
newWorkerPool( "default" )
14
.forConnection( "default" )
15
.setTimeout( 5 )
16
.setMaxAttempts( 5 );
17
18
newWorkerPool( "priority" )
19
.forConnection( "database" )
20
.onQueues( [ "priority", "*" ] )
21
.setQuantity( 3 );
22
}
23
}
24
Usage
Create a
Job
// SendWelcomeEmailJob.cfc
component extends="cbq.models.Jobs.AbstractJob" {
property name="mailService" inject="provider:MailService@cbmailservices";
property name="userId";
function handle() {
var user = getInstance( "User" ).findOrFail( getUserId() );
variables.mailService
.newMail(
from = "no-reply@example.com",
to = user.getEmail(),
subject = "Welcome!",
type = "html"
)
.setView( "/_emails/users/welcome" )
.setBodyTokens( {
"firstName" : user.getFirstName(),
"lastName" : user.getLastName()
} )
.send();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Per-Job
Configuration
// SendWelcomeEmailJob.cfc
component extends="cbq.models.Jobs.AbstractJob" {
variables.connection = "emails";
variables.maxAttempts = 3;
variables.timeout = 10;
function handle() {
// ...
}
}
1
2
3
4
5
6
7
8
9
10
11
12
// SendWelcomeEmailJob.cfc
component extends="cbq.models.Jobs.AbstractJob" {
variables.connection = "emails";
variables.maxAttempts = 3;
variables.timeout = 10;
function handle() {
// ...
}
}
1
2
3
4
5
6
7
8
9
10
11
12
variables.connection = "emails";
variables.maxAttempts = 3;
variables.timeout = 10;
// SendWelcomeEmailJob.cfc
1
component extends="cbq.models.Jobs.AbstractJob" {
2
3
4
5
6
7
function handle() {
8
// ...
9
}
10
11
}
12
Dispatching
Jobs
// handlers/Main.cfc
component {
function create() {
var user = createUser( rc );
getInstance( "SendWelcomeEmailJob" )
.setProperties( { "userId": user.getId() } )
.dispatch();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
// handlers/Main.cfc
component {
function create() {
var user = createUser( rc );
getInstance( "SendWelcomeEmailJob" )
.setProperties( { "userId": user.getId() } )
.dispatch();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
getInstance( "SendWelcomeEmailJob" )
// handlers/Main.cfc
1
component {
2
3
function create() {
4
var user = createUser( rc );
5
6
7
.setProperties( { "userId": user.getId() } )
8
.dispatch();
9
}
10
11
}
12
// handlers/Main.cfc
component {
function create() {
var user = createUser( rc );
getInstance( "SendWelcomeEmailJob" )
.setProperties( { "userId": user.getId() } )
.dispatch();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
getInstance( "SendWelcomeEmailJob" )
// handlers/Main.cfc
1
component {
2
3
function create() {
4
var user = createUser( rc );
5
6
7
.setProperties( { "userId": user.getId() } )
8
.dispatch();
9
}
10
11
}
12
getInstance( "SendWelcomeEmailJob" )
.setProperties( { "userId": user.getId() } )
// handlers/Main.cfc
1
component {
2
3
function create() {
4
var user = createUser( rc );
5
6
7
8
.dispatch();
9
}
10
11
}
12
// handlers/Main.cfc
component {
function create() {
var user = createUser( rc );
getInstance( "SendWelcomeEmailJob" )
.setProperties( { "userId": user.getId() } )
.dispatch();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
getInstance( "SendWelcomeEmailJob" )
// handlers/Main.cfc
1
component {
2
3
function create() {
4
var user = createUser( rc );
5
6
7
.setProperties( { "userId": user.getId() } )
8
.dispatch();
9
}
10
11
}
12
getInstance( "SendWelcomeEmailJob" )
.setProperties( { "userId": user.getId() } )
// handlers/Main.cfc
1
component {
2
3
function create() {
4
var user = createUser( rc );
5
6
7
8
.dispatch();
9
}
10
11
}
12
getInstance( "SendWelcomeEmailJob" )
.setProperties( { "userId": user.getId() } )
.dispatch();
// handlers/Main.cfc
1
component {
2
3
function create() {
4
var user = createUser( rc );
5
6
7
8
9
}
10
11
}
12
Setting up
Worker Pools
moduleSettings = {
"cbq" : {
"registerWorkers" : true // this is also the default
}
};
1
2
3
4
5
// config/cbq.cfc
component {
function configure() {
newConnection( "default" ).setProvider( "DBProvider@cbq" );
newWorkerPool( "default" )
.forConnection( "default" )
.setTimeout( 30 )
.setMaxAttempts( 5 )
.setQuantity( 3 );
newWorkerPool( "default" )
.forConnection( "default" )
.onQueues( "emails" )
.setTimeout( 60 )
.setMaxAttempts( 10 )
.setQuantity( 10 );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cbq Model
Helper
// handlers/Main.cfc
component {
property name="cbq" inject="cbq@cbq";
function create() {
var user = createUser( rc );
cbq.job( "SendWelcomeEmailJob", {
"userId": user.getId()
} ).dispatch();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Job Chains
// FulfillOrderJob.cfc
component extends="cbq.models.Jobs.AbstractJob" {
function handle() {
var productId = getProperties().productId;
processPayment( productId );
getInstance( "SendProductLinkEmail" )
.onConnection( "fulfillment" )
.setProperties( {
"productId" : productId,
"userId" : getProperties().userId
} )
.dispatch();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// FulfillOrderJob.cfc
component extends="cbq.models.Jobs.AbstractJob" {
function handle() {
var productId = getProperties().productId;
processPayment( productId );
getInstance( "SendProductLinkEmail" )
.onConnection( "fulfillment" )
.setProperties( {
"productId" : productId,
"userId" : getProperties().userId
} )
.dispatch();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
getInstance( "SendProductLinkEmail" )
.onConnection( "fulfillment" )
.setProperties( {
"productId" : productId,
"userId" : getProperties().userId
} )
.dispatch();
// FulfillOrderJob.cfc
1
component extends="cbq.models.Jobs.AbstractJob" {
2
3
function handle() {
4
var productId = getProperties().productId;
5
6
processPayment( productId );
7
8
9
10
11
12
13
14
15
}
16
17
}
18
// handlers/Main.cfc
component {
function create() {
getInstance( "FulfillOrderJob" )
.setProperties( { "productId": rc.productId } )
.chain( [
getInstance( "SendProductLinkEmail" )
.onConnection( "fulfillment" )
.setProperties( {
"productId" : rc.productId,
"userId" : auth().getUserId()
} )
] )
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// handlers/Main.cfc
component {
property name="cbq" inject="cbq@cbq";
function create() {
cbq.chain( [
cbq.job( "FulfillOrderJob", { "productId": rc.productId } ),
cbq.job( job = "SendProductLinkEmail", properties = {
"productId": rc.productId,
"userId": auth().getUserId()
}, connection = "fulfillment" ),
] ).dispatch();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Job Batches
// handlers/Main.cfc
component {
property name="cbq" inject="cbq@cbq";
function create() {
cbq.batch( [
cbq.job( "ImportCsvJob", { "start": 1, "end": 100 } ),
cbq.job( "ImportCsvJob", { "start": 101, "end": 200 } ),
cbq.job( "ImportCsvJob", { "start": 201, "end": 300 } ),
cbq.job( "ImportCsvJob", { "start": 301, "end": 400 } ),
cbq.job( "ImportCsvJob", { "start": 401, "end": 500 } )
] ).then( cbq.job( "ImportCsvSuccessfulJob" ) )
.catch( cbq.job( "ImportCsvFailedJob" ) )
.finally( cbq.job( "ImportCsvCompletedJob" ) )
.dispatch();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// handlers/Main.cfc
component {
property name="cbq" inject="cbq@cbq";
function create() {
cbq.batch( [
cbq.job( "ImportCsvJob", { "start": 1, "end": 100 } ),
cbq.job( "ImportCsvJob", { "start": 101, "end": 200 } ),
cbq.job( "ImportCsvJob", { "start": 201, "end": 300 } ),
cbq.job( "ImportCsvJob", { "start": 301, "end": 400 } ),
cbq.job( "ImportCsvJob", { "start": 401, "end": 500 } )
] ).then( cbq.job( "ImportCsvSuccessfulJob" ) )
.catch( cbq.job( "ImportCsvFailedJob" ) )
.finally( cbq.job( "ImportCsvCompletedJob" ) )
.dispatch();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cbq.job( "ImportCsvJob", { "start": 1, "end": 100 } ),
cbq.job( "ImportCsvJob", { "start": 101, "end": 200 } ),
cbq.job( "ImportCsvJob", { "start": 201, "end": 300 } ),
cbq.job( "ImportCsvJob", { "start": 301, "end": 400 } ),
cbq.job( "ImportCsvJob", { "start": 401, "end": 500 } )
// handlers/Main.cfc
1
component {
2
3
property name="cbq" inject="cbq@cbq";
4
5
function create() {
6
cbq.batch( [
7
8
9
10
11
12
] ).then( cbq.job( "ImportCsvSuccessfulJob" ) )
13
.catch( cbq.job( "ImportCsvFailedJob" ) )
14
.finally( cbq.job( "ImportCsvCompletedJob" ) )
15
.dispatch();
16
}
17
18
}
19
// handlers/Main.cfc
component {
property name="cbq" inject="cbq@cbq";
function create() {
cbq.batch( [
cbq.job( "ImportCsvJob", { "start": 1, "end": 100 } ),
cbq.job( "ImportCsvJob", { "start": 101, "end": 200 } ),
cbq.job( "ImportCsvJob", { "start": 201, "end": 300 } ),
cbq.job( "ImportCsvJob", { "start": 301, "end": 400 } ),
cbq.job( "ImportCsvJob", { "start": 401, "end": 500 } )
] ).then( cbq.job( "ImportCsvSuccessfulJob" ) )
.catch( cbq.job( "ImportCsvFailedJob" ) )
.finally( cbq.job( "ImportCsvCompletedJob" ) )
.dispatch();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cbq.job( "ImportCsvJob", { "start": 1, "end": 100 } ),
cbq.job( "ImportCsvJob", { "start": 101, "end": 200 } ),
cbq.job( "ImportCsvJob", { "start": 201, "end": 300 } ),
cbq.job( "ImportCsvJob", { "start": 301, "end": 400 } ),
cbq.job( "ImportCsvJob", { "start": 401, "end": 500 } )
// handlers/Main.cfc
1
component {
2
3
property name="cbq" inject="cbq@cbq";
4
5
function create() {
6
cbq.batch( [
7
8
9
10
11
12
] ).then( cbq.job( "ImportCsvSuccessfulJob" ) )
13
.catch( cbq.job( "ImportCsvFailedJob" ) )
14
.finally( cbq.job( "ImportCsvCompletedJob" ) )
15
.dispatch();
16
}
17
18
}
19
] ).then( cbq.job( "ImportCsvSuccessfulJob" ) )
.catch( cbq.job( "ImportCsvFailedJob" ) )
.finally( cbq.job( "ImportCsvCompletedJob" ) )
// handlers/Main.cfc
1
component {
2
3
property name="cbq" inject="cbq@cbq";
4
5
function create() {
6
cbq.batch( [
7
cbq.job( "ImportCsvJob", { "start": 1, "end": 100 } ),
8
cbq.job( "ImportCsvJob", { "start": 101, "end": 200 } ),
9
cbq.job( "ImportCsvJob", { "start": 201, "end": 300 } ),
10
cbq.job( "ImportCsvJob", { "start": 301, "end": 400 } ),
11
cbq.job( "ImportCsvJob", { "start": 401, "end": 500 } )
12
13
14
15
.dispatch();
16
}
17
18
}
19
Demo
Bonus
Delay the
Current Job
// MonitorPendingCartJob.cfc
component extends="cbq.models.Jobs.AbstractJob" {
function handle() {
var cartId = getProperties().cartId;
var cart = getInstance( "Cart" ).findOrFail( cartId );
if ( cart.isConfirmed() || cart.isCancelled() ) {
return;
}
if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) {
cart.cancel();
return;
}
getInstance( "MonitorPendingCartJob" )
.setProperties( { "cartId" : cartId } )
.delay( 15 * 1000 )
.dispatch();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// MonitorPendingCartJob.cfc
component extends="cbq.models.Jobs.AbstractJob" {
function handle() {
var cartId = getProperties().cartId;
var cart = getInstance( "Cart" ).findOrFail( cartId );
if ( cart.isConfirmed() || cart.isCancelled() ) {
return;
}
if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) {
cart.cancel();
return;
}
getInstance( "MonitorPendingCartJob" )
.setProperties( { "cartId" : cartId } )
.delay( 15 * 1000 )
.dispatch();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.setProperties( { "cartId" : cartId } )
.delay( 15 * 1000 )
.dispatch();
}
// MonitorPendingCartJob.cfc
1
component extends="cbq.models.Jobs.AbstractJob" {
2
function handle() {
3
var cartId = getProperties().cartId;
4
var cart = getInstance( "Cart" ).findOrFail( cartId );
5
6
if ( cart.isConfirmed() || cart.isCancelled() ) {
7
return;
8
}
9
10
if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) {
11
cart.cancel();
12
return;
13
}
14
15
getInstance( "MonitorPendingCartJob" )
16
17
18
19
20
}
21
// MonitorPendingCartJob.cfc
component extends="cbq.models.Jobs.AbstractJob" {
function handle() {
var cartId = getProperties().cartId;
var cart = getInstance( "Cart" ).findOrFail( cartId );
if ( cart.isConfirmed() || cart.isCancelled() ) {
return;
}
if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) {
cart.cancel();
return;
}
this.release( 15 * 1000 );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Using `release`
// MonitorPendingCartJob.cfc
component extends="cbq.models.Jobs.AbstractJob" {
function handle() {
var cartId = getProperties().cartId;
var cart = getInstance( "Cart" ).findOrFail( cartId );
if ( cart.isConfirmed() || cart.isCancelled() ) {
return;
}
if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) {
cart.cancel();
return;
}
this.release( 15 * 1000 );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
}
}
// MonitorPendingCartJob.cfc
1
component extends="cbq.models.Jobs.AbstractJob" {
2
function handle() {
3
var cartId = getProperties().cartId;
4
var cart = getInstance( "Cart" ).findOrFail( cartId );
5
6
if ( cart.isConfirmed() || cart.isCancelled() ) {
7
return;
8
}
9
10
if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) {
11
cart.cancel();
12
return;
13
}
14
15
this.release( 15 * 1000 );
16
17
18
Using `release`
// MonitorPendingCartJob.cfc
component extends="cbq.models.Jobs.AbstractJob" {
function handle() {
var cartId = getProperties().cartId;
var cart = getInstance( "Cart" ).findOrFail( cartId );
if ( cart.isConfirmed() || cart.isCancelled() ) {
return;
}
if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) {
cart.cancel();
return;
}
var delay = 2 ^ this.getCurrentAttempt() * 1000;
this.release( delay );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Exponential Backoff
// MonitorPendingCartJob.cfc
component extends="cbq.models.Jobs.AbstractJob" {
function handle() {
var cartId = getProperties().cartId;
var cart = getInstance( "Cart" ).findOrFail( cartId );
if ( cart.isConfirmed() || cart.isCancelled() ) {
return;
}
if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) {
cart.cancel();
return;
}
var delay = 2 ^ this.getCurrentAttempt() * 1000;
this.release( delay );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var delay = 2 ^ this.getCurrentAttempt() * 1000;
this.release( delay );
// MonitorPendingCartJob.cfc
1
component extends="cbq.models.Jobs.AbstractJob" {
2
function handle() {
3
var cartId = getProperties().cartId;
4
var cart = getInstance( "Cart" ).findOrFail( cartId );
5
6
if ( cart.isConfirmed() || cart.isCancelled() ) {
7
return;
8
}
9
10
if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) {
11
cart.cancel();
12
return;
13
}
14
15
16
17
18
}
19
}
20
Exponential Backoff
cbq - Jobs and Tasks in the Background by Ortus

More Related Content

Similar to cbq - Jobs and Tasks in the Background by Ortus

Docker Java App with MariaDB – Deployment in Less than a Minute
Docker Java App with MariaDB – Deployment in Less than a MinuteDocker Java App with MariaDB – Deployment in Less than a Minute
Docker Java App with MariaDB – Deployment in Less than a Minute
dchq
 
Microservice bus tutorial
Microservice bus tutorialMicroservice bus tutorial
Microservice bus tutorial
Huabing Zhao
 
2016 W3C Conference #4 : ANGULAR + ES6
2016 W3C Conference #4 : ANGULAR + ES62016 W3C Conference #4 : ANGULAR + ES6
2016 W3C Conference #4 : ANGULAR + ES6
양재동 코드랩
 
[W3C HTML5 2016] Angular + ES6
[W3C HTML5 2016] Angular + ES6[W3C HTML5 2016] Angular + ES6
[W3C HTML5 2016] Angular + ES6
양재동 코드랩
 
AWS Presents: Infrastructure as Code on AWS - ChefConf 2015
AWS Presents: Infrastructure as Code on AWS - ChefConf 2015AWS Presents: Infrastructure as Code on AWS - ChefConf 2015
AWS Presents: Infrastructure as Code on AWS - ChefConf 2015
Chef
 
Into The Box | Alexa and ColdBox Api's
Into The Box | Alexa and ColdBox Api'sInto The Box | Alexa and ColdBox Api's
Into The Box | Alexa and ColdBox Api's
Ortus Solutions, Corp
 
using Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API'susing Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API's
Antônio Roberto Silva
 
Liferay (DXP) 7 Tech Meetup for Developers
Liferay (DXP) 7 Tech Meetup for DevelopersLiferay (DXP) 7 Tech Meetup for Developers
Liferay (DXP) 7 Tech Meetup for Developers
Azilen Technologies Pvt. Ltd.
 
How To Configure Nginx Load Balancer on CentOS 7
How To Configure Nginx Load Balancer on CentOS 7How To Configure Nginx Load Balancer on CentOS 7
How To Configure Nginx Load Balancer on CentOS 7
VCP Muthukrishna
 
ECS & ECR Deep Dive - 김기완 솔루션즈 아키텍트 :: AWS Container Day
ECS & ECR Deep Dive - 김기완 솔루션즈 아키텍트 :: AWS Container DayECS & ECR Deep Dive - 김기완 솔루션즈 아키텍트 :: AWS Container Day
ECS & ECR Deep Dive - 김기완 솔루션즈 아키텍트 :: AWS Container Day
Amazon Web Services Korea
 
Container orchestration from theory to practice
Container orchestration from theory to practiceContainer orchestration from theory to practice
Container orchestration from theory to practice
Docker, Inc.
 
AWS Serverless Workshop
AWS Serverless WorkshopAWS Serverless Workshop
AWS Serverless Workshop
Mikael Puittinen
 
Spring cloud config
Spring cloud configSpring cloud config
Spring cloud config
Shubhani Jain
 
DB proxy server test: run tests on tens of virtual machines with Jenkins, Vag...
DB proxy server test: run tests on tens of virtual machines with Jenkins, Vag...DB proxy server test: run tests on tens of virtual machines with Jenkins, Vag...
DB proxy server test: run tests on tens of virtual machines with Jenkins, Vag...
Timofey Turenko
 
Practical solutions for connections administrators
Practical solutions for connections administratorsPractical solutions for connections administrators
Practical solutions for connections administrators
Sharon James
 
Spring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenSpring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in Heaven
Joshua Long
 
AWS CloudFormation Automation, TrafficScript, and Serverless architecture wit...
AWS CloudFormation Automation, TrafficScript, and Serverless architecture wit...AWS CloudFormation Automation, TrafficScript, and Serverless architecture wit...
AWS CloudFormation Automation, TrafficScript, and Serverless architecture wit...
PolarSeven Pty Ltd
 
Camunda BPM 7.2: Tasklist and Javascript Forms SDK (English)
Camunda BPM 7.2: Tasklist and Javascript Forms SDK (English)Camunda BPM 7.2: Tasklist and Javascript Forms SDK (English)
Camunda BPM 7.2: Tasklist and Javascript Forms SDK (English)
camunda services GmbH
 
Serve Meals, Not Ingredients - ChefConf 2015
Serve Meals, Not Ingredients - ChefConf 2015Serve Meals, Not Ingredients - ChefConf 2015
Serve Meals, Not Ingredients - ChefConf 2015
Chef
 
Serve Meals, Not Ingredients (ChefConf 2015)
Serve Meals, Not Ingredients (ChefConf 2015)Serve Meals, Not Ingredients (ChefConf 2015)
Serve Meals, Not Ingredients (ChefConf 2015)
ThirdWaveInsights
 

Similar to cbq - Jobs and Tasks in the Background by Ortus (20)

Docker Java App with MariaDB – Deployment in Less than a Minute
Docker Java App with MariaDB – Deployment in Less than a MinuteDocker Java App with MariaDB – Deployment in Less than a Minute
Docker Java App with MariaDB – Deployment in Less than a Minute
 
Microservice bus tutorial
Microservice bus tutorialMicroservice bus tutorial
Microservice bus tutorial
 
2016 W3C Conference #4 : ANGULAR + ES6
2016 W3C Conference #4 : ANGULAR + ES62016 W3C Conference #4 : ANGULAR + ES6
2016 W3C Conference #4 : ANGULAR + ES6
 
[W3C HTML5 2016] Angular + ES6
[W3C HTML5 2016] Angular + ES6[W3C HTML5 2016] Angular + ES6
[W3C HTML5 2016] Angular + ES6
 
AWS Presents: Infrastructure as Code on AWS - ChefConf 2015
AWS Presents: Infrastructure as Code on AWS - ChefConf 2015AWS Presents: Infrastructure as Code on AWS - ChefConf 2015
AWS Presents: Infrastructure as Code on AWS - ChefConf 2015
 
Into The Box | Alexa and ColdBox Api's
Into The Box | Alexa and ColdBox Api'sInto The Box | Alexa and ColdBox Api's
Into The Box | Alexa and ColdBox Api's
 
using Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API'susing Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API's
 
Liferay (DXP) 7 Tech Meetup for Developers
Liferay (DXP) 7 Tech Meetup for DevelopersLiferay (DXP) 7 Tech Meetup for Developers
Liferay (DXP) 7 Tech Meetup for Developers
 
How To Configure Nginx Load Balancer on CentOS 7
How To Configure Nginx Load Balancer on CentOS 7How To Configure Nginx Load Balancer on CentOS 7
How To Configure Nginx Load Balancer on CentOS 7
 
ECS & ECR Deep Dive - 김기완 솔루션즈 아키텍트 :: AWS Container Day
ECS & ECR Deep Dive - 김기완 솔루션즈 아키텍트 :: AWS Container DayECS & ECR Deep Dive - 김기완 솔루션즈 아키텍트 :: AWS Container Day
ECS & ECR Deep Dive - 김기완 솔루션즈 아키텍트 :: AWS Container Day
 
Container orchestration from theory to practice
Container orchestration from theory to practiceContainer orchestration from theory to practice
Container orchestration from theory to practice
 
AWS Serverless Workshop
AWS Serverless WorkshopAWS Serverless Workshop
AWS Serverless Workshop
 
Spring cloud config
Spring cloud configSpring cloud config
Spring cloud config
 
DB proxy server test: run tests on tens of virtual machines with Jenkins, Vag...
DB proxy server test: run tests on tens of virtual machines with Jenkins, Vag...DB proxy server test: run tests on tens of virtual machines with Jenkins, Vag...
DB proxy server test: run tests on tens of virtual machines with Jenkins, Vag...
 
Practical solutions for connections administrators
Practical solutions for connections administratorsPractical solutions for connections administrators
Practical solutions for connections administrators
 
Spring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenSpring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in Heaven
 
AWS CloudFormation Automation, TrafficScript, and Serverless architecture wit...
AWS CloudFormation Automation, TrafficScript, and Serverless architecture wit...AWS CloudFormation Automation, TrafficScript, and Serverless architecture wit...
AWS CloudFormation Automation, TrafficScript, and Serverless architecture wit...
 
Camunda BPM 7.2: Tasklist and Javascript Forms SDK (English)
Camunda BPM 7.2: Tasklist and Javascript Forms SDK (English)Camunda BPM 7.2: Tasklist and Javascript Forms SDK (English)
Camunda BPM 7.2: Tasklist and Javascript Forms SDK (English)
 
Serve Meals, Not Ingredients - ChefConf 2015
Serve Meals, Not Ingredients - ChefConf 2015Serve Meals, Not Ingredients - ChefConf 2015
Serve Meals, Not Ingredients - ChefConf 2015
 
Serve Meals, Not Ingredients (ChefConf 2015)
Serve Meals, Not Ingredients (ChefConf 2015)Serve Meals, Not Ingredients (ChefConf 2015)
Serve Meals, Not Ingredients (ChefConf 2015)
 

More from Ortus Solutions, Corp

Intro to Amazon Web Services (AWS) and Gen AI
Intro to Amazon Web Services (AWS) and Gen AIIntro to Amazon Web Services (AWS) and Gen AI
Intro to Amazon Web Services (AWS) and Gen AI
Ortus Solutions, Corp
 
How we built TryBoxLang in under 48 hours
How we built TryBoxLang in under 48 hoursHow we built TryBoxLang in under 48 hours
How we built TryBoxLang in under 48 hours
Ortus Solutions, Corp
 
Migrate your Infrastructure to the AWS Cloud
Migrate your Infrastructure to the AWS CloudMigrate your Infrastructure to the AWS Cloud
Migrate your Infrastructure to the AWS Cloud
Ortus Solutions, Corp
 
BoxLang Developer Tooling: VSCode Extension and Debugger
BoxLang Developer Tooling: VSCode Extension and DebuggerBoxLang Developer Tooling: VSCode Extension and Debugger
BoxLang Developer Tooling: VSCode Extension and Debugger
Ortus Solutions, Corp
 
How to debug ColdFusion Applications using “ColdFusion Builder extension for ...
How to debug ColdFusion Applications using “ColdFusion Builder extension for ...How to debug ColdFusion Applications using “ColdFusion Builder extension for ...
How to debug ColdFusion Applications using “ColdFusion Builder extension for ...
Ortus Solutions, Corp
 
Web Hosting with CommandBox and CommandBox Pro
Web Hosting with CommandBox and CommandBox ProWeb Hosting with CommandBox and CommandBox Pro
Web Hosting with CommandBox and CommandBox Pro
Ortus Solutions, Corp
 
Revolutionizing Task Scheduling in ColdBox
Revolutionizing Task Scheduling in ColdBoxRevolutionizing Task Scheduling in ColdBox
Revolutionizing Task Scheduling in ColdBox
Ortus Solutions, Corp
 
Disk to Cloud: Abstract your File Operations with CBFS
Disk to Cloud: Abstract your File Operations with CBFSDisk to Cloud: Abstract your File Operations with CBFS
Disk to Cloud: Abstract your File Operations with CBFS
Ortus Solutions, Corp
 
How to Break Your App with Playwright Tests
How to Break Your App with Playwright TestsHow to Break Your App with Playwright Tests
How to Break Your App with Playwright Tests
Ortus Solutions, Corp
 
Securing Your Application with Passkeys and cbSecurity
Securing Your Application with Passkeys and cbSecuritySecuring Your Application with Passkeys and cbSecurity
Securing Your Application with Passkeys and cbSecurity
Ortus Solutions, Corp
 
Schrodinger’s Backup: Is Your Backup Really a Backup?
Schrodinger’s Backup: Is Your Backup Really a Backup?Schrodinger’s Backup: Is Your Backup Really a Backup?
Schrodinger’s Backup: Is Your Backup Really a Backup?
Ortus Solutions, Corp
 
Design system: The basis for a consistent design
Design system: The basis for a consistent designDesign system: The basis for a consistent design
Design system: The basis for a consistent design
Ortus Solutions, Corp
 
ColdBox Debugger v4.2.0: Unveiling Advanced Debugging Techniques for ColdBox ...
ColdBox Debugger v4.2.0: Unveiling Advanced Debugging Techniques for ColdBox ...ColdBox Debugger v4.2.0: Unveiling Advanced Debugging Techniques for ColdBox ...
ColdBox Debugger v4.2.0: Unveiling Advanced Debugging Techniques for ColdBox ...
Ortus Solutions, Corp
 
How to Make a Living as a (ColdFusion) Freelancer?
How to Make a Living as a (ColdFusion) Freelancer?How to Make a Living as a (ColdFusion) Freelancer?
How to Make a Living as a (ColdFusion) Freelancer?
Ortus Solutions, Corp
 
What’s New in ContentBox 6 by Ortus Solutions.pdf
What’s New in ContentBox 6 by Ortus Solutions.pdfWhat’s New in ContentBox 6 by Ortus Solutions.pdf
What’s New in ContentBox 6 by Ortus Solutions.pdf
Ortus Solutions, Corp
 
Demonstrating Monitoring Solutions for CF and Lucee
Demonstrating Monitoring Solutions for CF and LuceeDemonstrating Monitoring Solutions for CF and Lucee
Demonstrating Monitoring Solutions for CF and Lucee
Ortus Solutions, Corp
 
Ortus Solutions - Headless Content for the Win!
Ortus Solutions - Headless Content for the Win!Ortus Solutions - Headless Content for the Win!
Ortus Solutions - Headless Content for the Win!
Ortus Solutions, Corp
 
Build a Complex Web Form with RuleBox and TestBox
Build a Complex Web Form with RuleBox and TestBoxBuild a Complex Web Form with RuleBox and TestBox
Build a Complex Web Form with RuleBox and TestBox
Ortus Solutions, Corp
 
Reactive CFML with CBWIRE v4 by Ortus Solutions
Reactive CFML with CBWIRE v4 by Ortus SolutionsReactive CFML with CBWIRE v4 by Ortus Solutions
Reactive CFML with CBWIRE v4 by Ortus Solutions
Ortus Solutions, Corp
 
Building Scaleable Serverless Event-Driven Computing with AWS Lambda powered ...
Building Scaleable Serverless Event-Driven Computing with AWS Lambda powered ...Building Scaleable Serverless Event-Driven Computing with AWS Lambda powered ...
Building Scaleable Serverless Event-Driven Computing with AWS Lambda powered ...
Ortus Solutions, Corp
 

More from Ortus Solutions, Corp (20)

Intro to Amazon Web Services (AWS) and Gen AI
Intro to Amazon Web Services (AWS) and Gen AIIntro to Amazon Web Services (AWS) and Gen AI
Intro to Amazon Web Services (AWS) and Gen AI
 
How we built TryBoxLang in under 48 hours
How we built TryBoxLang in under 48 hoursHow we built TryBoxLang in under 48 hours
How we built TryBoxLang in under 48 hours
 
Migrate your Infrastructure to the AWS Cloud
Migrate your Infrastructure to the AWS CloudMigrate your Infrastructure to the AWS Cloud
Migrate your Infrastructure to the AWS Cloud
 
BoxLang Developer Tooling: VSCode Extension and Debugger
BoxLang Developer Tooling: VSCode Extension and DebuggerBoxLang Developer Tooling: VSCode Extension and Debugger
BoxLang Developer Tooling: VSCode Extension and Debugger
 
How to debug ColdFusion Applications using “ColdFusion Builder extension for ...
How to debug ColdFusion Applications using “ColdFusion Builder extension for ...How to debug ColdFusion Applications using “ColdFusion Builder extension for ...
How to debug ColdFusion Applications using “ColdFusion Builder extension for ...
 
Web Hosting with CommandBox and CommandBox Pro
Web Hosting with CommandBox and CommandBox ProWeb Hosting with CommandBox and CommandBox Pro
Web Hosting with CommandBox and CommandBox Pro
 
Revolutionizing Task Scheduling in ColdBox
Revolutionizing Task Scheduling in ColdBoxRevolutionizing Task Scheduling in ColdBox
Revolutionizing Task Scheduling in ColdBox
 
Disk to Cloud: Abstract your File Operations with CBFS
Disk to Cloud: Abstract your File Operations with CBFSDisk to Cloud: Abstract your File Operations with CBFS
Disk to Cloud: Abstract your File Operations with CBFS
 
How to Break Your App with Playwright Tests
How to Break Your App with Playwright TestsHow to Break Your App with Playwright Tests
How to Break Your App with Playwright Tests
 
Securing Your Application with Passkeys and cbSecurity
Securing Your Application with Passkeys and cbSecuritySecuring Your Application with Passkeys and cbSecurity
Securing Your Application with Passkeys and cbSecurity
 
Schrodinger’s Backup: Is Your Backup Really a Backup?
Schrodinger’s Backup: Is Your Backup Really a Backup?Schrodinger’s Backup: Is Your Backup Really a Backup?
Schrodinger’s Backup: Is Your Backup Really a Backup?
 
Design system: The basis for a consistent design
Design system: The basis for a consistent designDesign system: The basis for a consistent design
Design system: The basis for a consistent design
 
ColdBox Debugger v4.2.0: Unveiling Advanced Debugging Techniques for ColdBox ...
ColdBox Debugger v4.2.0: Unveiling Advanced Debugging Techniques for ColdBox ...ColdBox Debugger v4.2.0: Unveiling Advanced Debugging Techniques for ColdBox ...
ColdBox Debugger v4.2.0: Unveiling Advanced Debugging Techniques for ColdBox ...
 
How to Make a Living as a (ColdFusion) Freelancer?
How to Make a Living as a (ColdFusion) Freelancer?How to Make a Living as a (ColdFusion) Freelancer?
How to Make a Living as a (ColdFusion) Freelancer?
 
What’s New in ContentBox 6 by Ortus Solutions.pdf
What’s New in ContentBox 6 by Ortus Solutions.pdfWhat’s New in ContentBox 6 by Ortus Solutions.pdf
What’s New in ContentBox 6 by Ortus Solutions.pdf
 
Demonstrating Monitoring Solutions for CF and Lucee
Demonstrating Monitoring Solutions for CF and LuceeDemonstrating Monitoring Solutions for CF and Lucee
Demonstrating Monitoring Solutions for CF and Lucee
 
Ortus Solutions - Headless Content for the Win!
Ortus Solutions - Headless Content for the Win!Ortus Solutions - Headless Content for the Win!
Ortus Solutions - Headless Content for the Win!
 
Build a Complex Web Form with RuleBox and TestBox
Build a Complex Web Form with RuleBox and TestBoxBuild a Complex Web Form with RuleBox and TestBox
Build a Complex Web Form with RuleBox and TestBox
 
Reactive CFML with CBWIRE v4 by Ortus Solutions
Reactive CFML with CBWIRE v4 by Ortus SolutionsReactive CFML with CBWIRE v4 by Ortus Solutions
Reactive CFML with CBWIRE v4 by Ortus Solutions
 
Building Scaleable Serverless Event-Driven Computing with AWS Lambda powered ...
Building Scaleable Serverless Event-Driven Computing with AWS Lambda powered ...Building Scaleable Serverless Event-Driven Computing with AWS Lambda powered ...
Building Scaleable Serverless Event-Driven Computing with AWS Lambda powered ...
 

Recently uploaded

introduction of Ansys software and basic and advance knowledge of modelling s...
introduction of Ansys software and basic and advance knowledge of modelling s...introduction of Ansys software and basic and advance knowledge of modelling s...
introduction of Ansys software and basic and advance knowledge of modelling s...
sachin chaurasia
 
CViewSurvey Digitech Pvt Ltd that works on a proven C.A.A.G. model.
CViewSurvey Digitech Pvt Ltd that  works on a proven C.A.A.G. model.CViewSurvey Digitech Pvt Ltd that  works on a proven C.A.A.G. model.
CViewSurvey Digitech Pvt Ltd that works on a proven C.A.A.G. model.
bhatinidhi2001
 
BITCOIN HEIST RANSOMEWARE ATTACK PREDICTION
BITCOIN HEIST RANSOMEWARE ATTACK PREDICTIONBITCOIN HEIST RANSOMEWARE ATTACK PREDICTION
BITCOIN HEIST RANSOMEWARE ATTACK PREDICTION
ssuser2b426d1
 
What is OCR Technology and How to Extract Text from Any Image for Free
What is OCR Technology and How to Extract Text from Any Image for FreeWhat is OCR Technology and How to Extract Text from Any Image for Free
What is OCR Technology and How to Extract Text from Any Image for Free
TwisterTools
 
FAST Channels: Explosive Growth Forecast 2024-2027 (Buckle Up!)
FAST Channels: Explosive Growth Forecast 2024-2027 (Buckle Up!)FAST Channels: Explosive Growth Forecast 2024-2027 (Buckle Up!)
FAST Channels: Explosive Growth Forecast 2024-2027 (Buckle Up!)
Roshan Dwivedi
 
ANSYS Mechanical APDL Introductory Tutorials.pdf
ANSYS Mechanical APDL Introductory Tutorials.pdfANSYS Mechanical APDL Introductory Tutorials.pdf
ANSYS Mechanical APDL Introductory Tutorials.pdf
sachin chaurasia
 
Top 10 Tips To Get Google AdSense For Your Website
Top 10 Tips To Get Google AdSense For Your WebsiteTop 10 Tips To Get Google AdSense For Your Website
Top 10 Tips To Get Google AdSense For Your Website
e-Definers Technology
 
Overview of ERP - Mechlin Technologies.pptx
Overview of ERP - Mechlin Technologies.pptxOverview of ERP - Mechlin Technologies.pptx
Overview of ERP - Mechlin Technologies.pptx
Mitchell Marsh
 
ThaiPy meetup - Indexes and Django
ThaiPy meetup - Indexes and DjangoThaiPy meetup - Indexes and Django
ThaiPy meetup - Indexes and Django
akshesh doshi
 
dachnug51 - HCL Sametime 12 as a Software Appliance.pdf
dachnug51 - HCL Sametime 12 as a Software Appliance.pdfdachnug51 - HCL Sametime 12 as a Software Appliance.pdf
dachnug51 - HCL Sametime 12 as a Software Appliance.pdf
DNUG e.V.
 
Responsibilities of Fleet Managers and How TrackoBit Can Assist.pdf
Responsibilities of Fleet Managers and How TrackoBit Can Assist.pdfResponsibilities of Fleet Managers and How TrackoBit Can Assist.pdf
Responsibilities of Fleet Managers and How TrackoBit Can Assist.pdf
Trackobit
 
Seamless PostgreSQL to Snowflake Data Transfer in 8 Simple Steps
Seamless PostgreSQL to Snowflake Data Transfer in 8 Simple StepsSeamless PostgreSQL to Snowflake Data Transfer in 8 Simple Steps
Seamless PostgreSQL to Snowflake Data Transfer in 8 Simple Steps
Estuary Flow
 
MVP Mobile Application - Codearrest.pptx
MVP Mobile Application - Codearrest.pptxMVP Mobile Application - Codearrest.pptx
MVP Mobile Application - Codearrest.pptx
Mitchell Marsh
 
AWS Cloud Practitioner Essentials (Second Edition) (Arabic) Course Introducti...
AWS Cloud Practitioner Essentials (Second Edition) (Arabic) Course Introducti...AWS Cloud Practitioner Essentials (Second Edition) (Arabic) Course Introducti...
AWS Cloud Practitioner Essentials (Second Edition) (Arabic) Course Introducti...
karim wahed
 
React Native vs Flutter - SSTech System
React Native vs Flutter  - SSTech SystemReact Native vs Flutter  - SSTech System
React Native vs Flutter - SSTech System
SSTech System
 
WEBINAR SLIDES: CCX for Cloud Service Providers
WEBINAR SLIDES: CCX for Cloud Service ProvidersWEBINAR SLIDES: CCX for Cloud Service Providers
WEBINAR SLIDES: CCX for Cloud Service Providers
Severalnines
 
Abortion pills in Fujairah *((+971588192166*)☎️)¥) **Effective Abortion Pills...
Abortion pills in Fujairah *((+971588192166*)☎️)¥) **Effective Abortion Pills...Abortion pills in Fujairah *((+971588192166*)☎️)¥) **Effective Abortion Pills...
Abortion pills in Fujairah *((+971588192166*)☎️)¥) **Effective Abortion Pills...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
NYC 26-Jun-2024 Combined Presentations.pdf
NYC 26-Jun-2024 Combined Presentations.pdfNYC 26-Jun-2024 Combined Presentations.pdf
NYC 26-Jun-2024 Combined Presentations.pdf
AUGNYC
 
Break data silos with real-time connectivity using Confluent Cloud Connectors
Break data silos with real-time connectivity using Confluent Cloud ConnectorsBreak data silos with real-time connectivity using Confluent Cloud Connectors
Break data silos with real-time connectivity using Confluent Cloud Connectors
confluent
 
ENISA Threat Landscape 2023 documentation
ENISA Threat Landscape 2023 documentationENISA Threat Landscape 2023 documentation
ENISA Threat Landscape 2023 documentation
sofiafernandezon
 

Recently uploaded (20)

introduction of Ansys software and basic and advance knowledge of modelling s...
introduction of Ansys software and basic and advance knowledge of modelling s...introduction of Ansys software and basic and advance knowledge of modelling s...
introduction of Ansys software and basic and advance knowledge of modelling s...
 
CViewSurvey Digitech Pvt Ltd that works on a proven C.A.A.G. model.
CViewSurvey Digitech Pvt Ltd that  works on a proven C.A.A.G. model.CViewSurvey Digitech Pvt Ltd that  works on a proven C.A.A.G. model.
CViewSurvey Digitech Pvt Ltd that works on a proven C.A.A.G. model.
 
BITCOIN HEIST RANSOMEWARE ATTACK PREDICTION
BITCOIN HEIST RANSOMEWARE ATTACK PREDICTIONBITCOIN HEIST RANSOMEWARE ATTACK PREDICTION
BITCOIN HEIST RANSOMEWARE ATTACK PREDICTION
 
What is OCR Technology and How to Extract Text from Any Image for Free
What is OCR Technology and How to Extract Text from Any Image for FreeWhat is OCR Technology and How to Extract Text from Any Image for Free
What is OCR Technology and How to Extract Text from Any Image for Free
 
FAST Channels: Explosive Growth Forecast 2024-2027 (Buckle Up!)
FAST Channels: Explosive Growth Forecast 2024-2027 (Buckle Up!)FAST Channels: Explosive Growth Forecast 2024-2027 (Buckle Up!)
FAST Channels: Explosive Growth Forecast 2024-2027 (Buckle Up!)
 
ANSYS Mechanical APDL Introductory Tutorials.pdf
ANSYS Mechanical APDL Introductory Tutorials.pdfANSYS Mechanical APDL Introductory Tutorials.pdf
ANSYS Mechanical APDL Introductory Tutorials.pdf
 
Top 10 Tips To Get Google AdSense For Your Website
Top 10 Tips To Get Google AdSense For Your WebsiteTop 10 Tips To Get Google AdSense For Your Website
Top 10 Tips To Get Google AdSense For Your Website
 
Overview of ERP - Mechlin Technologies.pptx
Overview of ERP - Mechlin Technologies.pptxOverview of ERP - Mechlin Technologies.pptx
Overview of ERP - Mechlin Technologies.pptx
 
ThaiPy meetup - Indexes and Django
ThaiPy meetup - Indexes and DjangoThaiPy meetup - Indexes and Django
ThaiPy meetup - Indexes and Django
 
dachnug51 - HCL Sametime 12 as a Software Appliance.pdf
dachnug51 - HCL Sametime 12 as a Software Appliance.pdfdachnug51 - HCL Sametime 12 as a Software Appliance.pdf
dachnug51 - HCL Sametime 12 as a Software Appliance.pdf
 
Responsibilities of Fleet Managers and How TrackoBit Can Assist.pdf
Responsibilities of Fleet Managers and How TrackoBit Can Assist.pdfResponsibilities of Fleet Managers and How TrackoBit Can Assist.pdf
Responsibilities of Fleet Managers and How TrackoBit Can Assist.pdf
 
Seamless PostgreSQL to Snowflake Data Transfer in 8 Simple Steps
Seamless PostgreSQL to Snowflake Data Transfer in 8 Simple StepsSeamless PostgreSQL to Snowflake Data Transfer in 8 Simple Steps
Seamless PostgreSQL to Snowflake Data Transfer in 8 Simple Steps
 
MVP Mobile Application - Codearrest.pptx
MVP Mobile Application - Codearrest.pptxMVP Mobile Application - Codearrest.pptx
MVP Mobile Application - Codearrest.pptx
 
AWS Cloud Practitioner Essentials (Second Edition) (Arabic) Course Introducti...
AWS Cloud Practitioner Essentials (Second Edition) (Arabic) Course Introducti...AWS Cloud Practitioner Essentials (Second Edition) (Arabic) Course Introducti...
AWS Cloud Practitioner Essentials (Second Edition) (Arabic) Course Introducti...
 
React Native vs Flutter - SSTech System
React Native vs Flutter  - SSTech SystemReact Native vs Flutter  - SSTech System
React Native vs Flutter - SSTech System
 
WEBINAR SLIDES: CCX for Cloud Service Providers
WEBINAR SLIDES: CCX for Cloud Service ProvidersWEBINAR SLIDES: CCX for Cloud Service Providers
WEBINAR SLIDES: CCX for Cloud Service Providers
 
Abortion pills in Fujairah *((+971588192166*)☎️)¥) **Effective Abortion Pills...
Abortion pills in Fujairah *((+971588192166*)☎️)¥) **Effective Abortion Pills...Abortion pills in Fujairah *((+971588192166*)☎️)¥) **Effective Abortion Pills...
Abortion pills in Fujairah *((+971588192166*)☎️)¥) **Effective Abortion Pills...
 
NYC 26-Jun-2024 Combined Presentations.pdf
NYC 26-Jun-2024 Combined Presentations.pdfNYC 26-Jun-2024 Combined Presentations.pdf
NYC 26-Jun-2024 Combined Presentations.pdf
 
Break data silos with real-time connectivity using Confluent Cloud Connectors
Break data silos with real-time connectivity using Confluent Cloud ConnectorsBreak data silos with real-time connectivity using Confluent Cloud Connectors
Break data silos with real-time connectivity using Confluent Cloud Connectors
 
ENISA Threat Landscape 2023 documentation
ENISA Threat Landscape 2023 documentationENISA Threat Landscape 2023 documentation
ENISA Threat Landscape 2023 documentation
 

cbq - Jobs and Tasks in the Background by Ortus

  • 5. What this talk is An overview of cbq Examples of problems that queues and jobs can solve Overview of how to create new cbq protocols
  • 6. What this talk isn't How to use the ColdBox Async Manager Overview of ColdBox Scheduled Tasks
  • 10. A protocol-based queueing system for ColdBox Can interact with different providers, like the ColdBox Async Engine, a database, Redis, or Rabbit MQ A protocol-based queueing system for ColdBox
  • 11. A protocol-based queueing system for ColdBox Sends a message to be consumed later. It can be consumed by the same application or a completely different application, language, or service. A protocol-based queueing system for ColdBox
  • 12. Defines a Job as the unit of work on a queue Push a Job onto a queue connection to be worked later Define multiple queues or named piles of work Register worker pools to work the jobs passed to queues Ability to switch between Queue Providers easily What does cbq give me?
  • 13. Why not just use...? cfthread, runAsync, AsyncManager Redis, Rabbit MQ, etc. Homegrown queue framework
  • 14. Backend processing using message queues is a paradigm shift, and CBQ is a game changer. Asynchronous FIFO processing dynamically split across an unlimited number of servers allows one to break up any large processing load seamlessly. Batching, chains, and one-off jobs with built-in logging, automated intelligent retries, and the ability to use anything from databases to cloud-based services such as AWS SQS to manage the job queue allows me to build incredibly powerful, scalable, and resilient systems for my financial services clients. Highly recommended! John Wilson Synaptrix
  • 15. Why would I use cbq?
  • 17. Other reasons Easier testing making sure the right jobs were queued Sync in development, Rabbit in production Adjust the worker pool scale dynamically Retry, timeout, and backoff built in.
  • 19. Job
  • 20. Does its work in the `handle` method Serializes and deserializes itself to the queue protocol Set instance data in the `properties` Exist in the context of your application Job
  • 21. Queue
  • 22. A named stack of jobs or messages to be delivered A queue connection must have at least one queue which is usually `default` A queue connection can have as many queues as desired Queue
  • 24. How a queue connection connects to a backend like Redis, RabbitMQ, or a database Can be used multiple times in a single application to define multiple queue connections with different configuration options Queue Provider
  • 26. A named combination of Queue Provider and properties Allows you to connect with multiple Database providers or multiple Redis providers Queue Connection
  • 28. A group of workers for a Queue Connection Can optionally work a subset of queues Can optionally work queues in a specific order Can be scaled up or down as needed Worker Pool
  • 31. component { this.javaSettings = { loadPaths : [ expandPath( "./modules/cbq/lib" ) ], loadColdFusionClassPath : true, reloadOnChange : false }; } 1 2 3 4 5 6 7 8 9 10 Batch-specific Setup
  • 32. component { this.javaSettings = { loadPaths : [ expandPath( "./modules/cbq/lib" ) ], loadColdFusionClassPath : true, reloadOnChange : false }; } 1 2 3 4 5 6 7 8 9 10 this.javaSettings = { component { 1 2 3 4 loadPaths : [ expandPath( "./modules/cbq/lib" ) ], 5 loadColdFusionClassPath : true, 6 reloadOnChange : false 7 }; 8 9 } 10 Batch-specific Setup
  • 33. component { this.javaSettings = { loadPaths : [ expandPath( "./modules/cbq/lib" ) ], loadColdFusionClassPath : true, reloadOnChange : false }; } 1 2 3 4 5 6 7 8 9 10 this.javaSettings = { component { 1 2 3 4 loadPaths : [ expandPath( "./modules/cbq/lib" ) ], 5 loadColdFusionClassPath : true, 6 reloadOnChange : false 7 }; 8 9 } 10 loadColdFusionClassPath : true, reloadOnChange : false }; component { 1 2 3 this.javaSettings = { 4 loadPaths : [ expandPath( "./modules/cbq/lib" ) ], 5 6 7 8 9 } 10 Batch-specific Setup
  • 34. component { this.javaSettings = { loadPaths : [ expandPath( "./modules/cbq/lib" ) ], loadColdFusionClassPath : true, reloadOnChange : false }; } 1 2 3 4 5 6 7 8 9 10 this.javaSettings = { component { 1 2 3 4 loadPaths : [ expandPath( "./modules/cbq/lib" ) ], 5 loadColdFusionClassPath : true, 6 reloadOnChange : false 7 }; 8 9 } 10 loadColdFusionClassPath : true, reloadOnChange : false }; component { 1 2 3 this.javaSettings = { 4 loadPaths : [ expandPath( "./modules/cbq/lib" ) ], 5 6 7 8 9 } 10 } component { 1 2 3 this.javaSettings = { 4 loadPaths : [ expandPath( "./modules/cbq/lib" ) ], 5 loadColdFusionClassPath : true, 6 reloadOnChange : false 7 }; 8 9 10 Batch-specific Setup
  • 37. moduleSettings = { "cbq" : { // The path the custom config file to // register connections and worker pools "configPath" : "config.cbq", // Flag if workers should be registered. // If your application only pushes to the queues, // you can set this to false. "registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ), // The interval to poll for changes to the worker pool scaling. // Defaults to 0 which turns off the scheduled scaling feature. "scaleInterval" : 0, // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  • 38. moduleSettings = { "cbq" : { // The path the custom config file to // register connections and worker pools "configPath" : "config.cbq", // Flag if workers should be registered. // If your application only pushes to the queues, // you can set this to false. "registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ), // The interval to poll for changes to the worker pool scaling. // Defaults to 0 which turns off the scheduled scaling feature. "scaleInterval" : 0, // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // The path the custom config file to // register connections and worker pools "configPath" : "config.cbq", moduleSettings = { 1 "cbq" : { 2 3 4 5 6 // Flag if workers should be registered. 7 // If your application only pushes to the queues, 8 // you can set this to false. 9 "registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ), 10 11 // The interval to poll for changes to the worker pool scaling. 12 // Defaults to 0 which turns off the scheduled scaling feature. 13 "scaleInterval" : 0, 14 15 // continued... 16 } 17 }; 18
  • 39. moduleSettings = { "cbq" : { // The path the custom config file to // register connections and worker pools "configPath" : "config.cbq", // Flag if workers should be registered. // If your application only pushes to the queues, // you can set this to false. "registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ), // The interval to poll for changes to the worker pool scaling. // Defaults to 0 which turns off the scheduled scaling feature. "scaleInterval" : 0, // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // The path the custom config file to // register connections and worker pools "configPath" : "config.cbq", moduleSettings = { 1 "cbq" : { 2 3 4 5 6 // Flag if workers should be registered. 7 // If your application only pushes to the queues, 8 // you can set this to false. 9 "registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ), 10 11 // The interval to poll for changes to the worker pool scaling. 12 // Defaults to 0 which turns off the scheduled scaling feature. 13 "scaleInterval" : 0, 14 15 // continued... 16 } 17 }; 18 // Flag if workers should be registered. // If your application only pushes to the queues, // you can set this to false. "registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ), moduleSettings = { 1 "cbq" : { 2 // The path the custom config file to 3 // register connections and worker pools 4 "configPath" : "config.cbq", 5 6 7 8 9 10 11 // The interval to poll for changes to the worker pool scaling. 12 // Defaults to 0 which turns off the scheduled scaling feature. 13 "scaleInterval" : 0, 14 15 // continued... 16 } 17 }; 18
  • 40. moduleSettings = { "cbq" : { // The path the custom config file to // register connections and worker pools "configPath" : "config.cbq", // Flag if workers should be registered. // If your application only pushes to the queues, // you can set this to false. "registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ), // The interval to poll for changes to the worker pool scaling. // Defaults to 0 which turns off the scheduled scaling feature. "scaleInterval" : 0, // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // The path the custom config file to // register connections and worker pools "configPath" : "config.cbq", moduleSettings = { 1 "cbq" : { 2 3 4 5 6 // Flag if workers should be registered. 7 // If your application only pushes to the queues, 8 // you can set this to false. 9 "registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ), 10 11 // The interval to poll for changes to the worker pool scaling. 12 // Defaults to 0 which turns off the scheduled scaling feature. 13 "scaleInterval" : 0, 14 15 // continued... 16 } 17 }; 18 // Flag if workers should be registered. // If your application only pushes to the queues, // you can set this to false. "registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ), moduleSettings = { 1 "cbq" : { 2 // The path the custom config file to 3 // register connections and worker pools 4 "configPath" : "config.cbq", 5 6 7 8 9 10 11 // The interval to poll for changes to the worker pool scaling. 12 // Defaults to 0 which turns off the scheduled scaling feature. 13 "scaleInterval" : 0, 14 15 // continued... 16 } 17 }; 18 // The interval to poll for changes to the worker pool scaling. // Defaults to 0 which turns off the scheduled scaling feature. "scaleInterval" : 0, moduleSettings = { 1 "cbq" : { 2 // The path the custom config file to 3 // register connections and worker pools 4 "configPath" : "config.cbq", 5 6 // Flag if workers should be registered. 7 // If your application only pushes to the queues, 8 // you can set this to false. 9 "registerWorkers" : getSystemSetting( "CBQ_REGISTER_WORKERS", true ), 10 11 12 13 14 15 // continued... 16 } 17 }; 18
  • 41. moduleSettings = { "cbq" : { // The default amount of time, in seconds, to delay a job. // Used if the connection and job doesn't define their own. "defaultWorkerBackoff" : 0, // The default amount of time, in seconds, to wait before timing out a job. // Used if the connection and job doesn't define their own. "defaultWorkerTimeout" : 60, // The default amount of time, in seconds, // to wait for tasks to complete before killing them when requesting a shutdown. "defaultWorkerShutdownTimeout" : 60, // The default amount of attempts to try before failing a job. // Used if the connection and job doesn't define their own. "defaultWorkerMaxAttempts" : 1, // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. "registerJobInterceptorRestrictionAspect" : false // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  • 42. moduleSettings = { "cbq" : { // The default amount of time, in seconds, to delay a job. // Used if the connection and job doesn't define their own. "defaultWorkerBackoff" : 0, // The default amount of time, in seconds, to wait before timing out a job. // Used if the connection and job doesn't define their own. "defaultWorkerTimeout" : 60, // The default amount of time, in seconds, // to wait for tasks to complete before killing them when requesting a shutdown. "defaultWorkerShutdownTimeout" : 60, // The default amount of attempts to try before failing a job. // Used if the connection and job doesn't define their own. "defaultWorkerMaxAttempts" : 1, // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. "registerJobInterceptorRestrictionAspect" : false // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // The default amount of time, in seconds, to delay a job. // Used if the connection and job doesn't define their own. "defaultWorkerBackoff" : 0, moduleSettings = { 1 "cbq" : { 2 3 4 5 6 // The default amount of time, in seconds, to wait before timing out a job. 7 // Used if the connection and job doesn't define their own. 8 "defaultWorkerTimeout" : 60, 9 10 // The default amount of time, in seconds, 11 // to wait for tasks to complete before killing them when requesting a shutdown. 12 "defaultWorkerShutdownTimeout" : 60, 13 14 // The default amount of attempts to try before failing a job. 15 // Used if the connection and job doesn't define their own. 16 "defaultWorkerMaxAttempts" : 1, 17 18 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. 19 "registerJobInterceptorRestrictionAspect" : false 20 21 // continued... 22 } 23 }; 24
  • 43. moduleSettings = { "cbq" : { // The default amount of time, in seconds, to delay a job. // Used if the connection and job doesn't define their own. "defaultWorkerBackoff" : 0, // The default amount of time, in seconds, to wait before timing out a job. // Used if the connection and job doesn't define their own. "defaultWorkerTimeout" : 60, // The default amount of time, in seconds, // to wait for tasks to complete before killing them when requesting a shutdown. "defaultWorkerShutdownTimeout" : 60, // The default amount of attempts to try before failing a job. // Used if the connection and job doesn't define their own. "defaultWorkerMaxAttempts" : 1, // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. "registerJobInterceptorRestrictionAspect" : false // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // The default amount of time, in seconds, to delay a job. // Used if the connection and job doesn't define their own. "defaultWorkerBackoff" : 0, moduleSettings = { 1 "cbq" : { 2 3 4 5 6 // The default amount of time, in seconds, to wait before timing out a job. 7 // Used if the connection and job doesn't define their own. 8 "defaultWorkerTimeout" : 60, 9 10 // The default amount of time, in seconds, 11 // to wait for tasks to complete before killing them when requesting a shutdown. 12 "defaultWorkerShutdownTimeout" : 60, 13 14 // The default amount of attempts to try before failing a job. 15 // Used if the connection and job doesn't define their own. 16 "defaultWorkerMaxAttempts" : 1, 17 18 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. 19 "registerJobInterceptorRestrictionAspect" : false 20 21 // continued... 22 } 23 }; 24 // The default amount of time, in seconds, to wait before timing out a job. // Used if the connection and job doesn't define their own. "defaultWorkerTimeout" : 60, moduleSettings = { 1 "cbq" : { 2 // The default amount of time, in seconds, to delay a job. 3 // Used if the connection and job doesn't define their own. 4 "defaultWorkerBackoff" : 0, 5 6 7 8 9 10 // The default amount of time, in seconds, 11 // to wait for tasks to complete before killing them when requesting a shutdown. 12 "defaultWorkerShutdownTimeout" : 60, 13 14 // The default amount of attempts to try before failing a job. 15 // Used if the connection and job doesn't define their own. 16 "defaultWorkerMaxAttempts" : 1, 17 18 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. 19 "registerJobInterceptorRestrictionAspect" : false 20 21 // continued... 22 } 23 }; 24
  • 44. moduleSettings = { "cbq" : { // The default amount of time, in seconds, to delay a job. // Used if the connection and job doesn't define their own. "defaultWorkerBackoff" : 0, // The default amount of time, in seconds, to wait before timing out a job. // Used if the connection and job doesn't define their own. "defaultWorkerTimeout" : 60, // The default amount of time, in seconds, // to wait for tasks to complete before killing them when requesting a shutdown. "defaultWorkerShutdownTimeout" : 60, // The default amount of attempts to try before failing a job. // Used if the connection and job doesn't define their own. "defaultWorkerMaxAttempts" : 1, // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. "registerJobInterceptorRestrictionAspect" : false // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // The default amount of time, in seconds, to delay a job. // Used if the connection and job doesn't define their own. "defaultWorkerBackoff" : 0, moduleSettings = { 1 "cbq" : { 2 3 4 5 6 // The default amount of time, in seconds, to wait before timing out a job. 7 // Used if the connection and job doesn't define their own. 8 "defaultWorkerTimeout" : 60, 9 10 // The default amount of time, in seconds, 11 // to wait for tasks to complete before killing them when requesting a shutdown. 12 "defaultWorkerShutdownTimeout" : 60, 13 14 // The default amount of attempts to try before failing a job. 15 // Used if the connection and job doesn't define their own. 16 "defaultWorkerMaxAttempts" : 1, 17 18 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. 19 "registerJobInterceptorRestrictionAspect" : false 20 21 // continued... 22 } 23 }; 24 // The default amount of time, in seconds, to wait before timing out a job. // Used if the connection and job doesn't define their own. "defaultWorkerTimeout" : 60, moduleSettings = { 1 "cbq" : { 2 // The default amount of time, in seconds, to delay a job. 3 // Used if the connection and job doesn't define their own. 4 "defaultWorkerBackoff" : 0, 5 6 7 8 9 10 // The default amount of time, in seconds, 11 // to wait for tasks to complete before killing them when requesting a shutdown. 12 "defaultWorkerShutdownTimeout" : 60, 13 14 // The default amount of attempts to try before failing a job. 15 // Used if the connection and job doesn't define their own. 16 "defaultWorkerMaxAttempts" : 1, 17 18 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. 19 "registerJobInterceptorRestrictionAspect" : false 20 21 // continued... 22 } 23 }; 24 // to wait for tasks to complete before killing them when requesting a shutdown. "defaultWorkerShutdownTimeout" : 60, moduleSettings = { 1 "cbq" : { 2 // The default amount of time, in seconds, to delay a job. 3 // Used if the connection and job doesn't define their own. 4 "defaultWorkerBackoff" : 0, 5 6 // The default amount of time, in seconds, to wait before timing out a job. 7 // Used if the connection and job doesn't define their own. 8 "defaultWorkerTimeout" : 60, 9 10 // The default amount of time, in seconds, 11 12 13 14 // The default amount of attempts to try before failing a job. 15 // Used if the connection and job doesn't define their own. 16 "defaultWorkerMaxAttempts" : 1, 17 18 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. 19 "registerJobInterceptorRestrictionAspect" : false 20 21 // continued... 22 } 23 }; 24
  • 45. moduleSettings = { "cbq" : { // The default amount of time, in seconds, to delay a job. // Used if the connection and job doesn't define their own. "defaultWorkerBackoff" : 0, // The default amount of time, in seconds, to wait before timing out a job. // Used if the connection and job doesn't define their own. "defaultWorkerTimeout" : 60, // The default amount of time, in seconds, // to wait for tasks to complete before killing them when requesting a shutdown. "defaultWorkerShutdownTimeout" : 60, // The default amount of attempts to try before failing a job. // Used if the connection and job doesn't define their own. "defaultWorkerMaxAttempts" : 1, // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. "registerJobInterceptorRestrictionAspect" : false // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // The default amount of time, in seconds, to delay a job. // Used if the connection and job doesn't define their own. "defaultWorkerBackoff" : 0, moduleSettings = { 1 "cbq" : { 2 3 4 5 6 // The default amount of time, in seconds, to wait before timing out a job. 7 // Used if the connection and job doesn't define their own. 8 "defaultWorkerTimeout" : 60, 9 10 // The default amount of time, in seconds, 11 // to wait for tasks to complete before killing them when requesting a shutdown. 12 "defaultWorkerShutdownTimeout" : 60, 13 14 // The default amount of attempts to try before failing a job. 15 // Used if the connection and job doesn't define their own. 16 "defaultWorkerMaxAttempts" : 1, 17 18 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. 19 "registerJobInterceptorRestrictionAspect" : false 20 21 // continued... 22 } 23 }; 24 // The default amount of time, in seconds, to wait before timing out a job. // Used if the connection and job doesn't define their own. "defaultWorkerTimeout" : 60, moduleSettings = { 1 "cbq" : { 2 // The default amount of time, in seconds, to delay a job. 3 // Used if the connection and job doesn't define their own. 4 "defaultWorkerBackoff" : 0, 5 6 7 8 9 10 // The default amount of time, in seconds, 11 // to wait for tasks to complete before killing them when requesting a shutdown. 12 "defaultWorkerShutdownTimeout" : 60, 13 14 // The default amount of attempts to try before failing a job. 15 // Used if the connection and job doesn't define their own. 16 "defaultWorkerMaxAttempts" : 1, 17 18 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. 19 "registerJobInterceptorRestrictionAspect" : false 20 21 // continued... 22 } 23 }; 24 // to wait for tasks to complete before killing them when requesting a shutdown. "defaultWorkerShutdownTimeout" : 60, moduleSettings = { 1 "cbq" : { 2 // The default amount of time, in seconds, to delay a job. 3 // Used if the connection and job doesn't define their own. 4 "defaultWorkerBackoff" : 0, 5 6 // The default amount of time, in seconds, to wait before timing out a job. 7 // Used if the connection and job doesn't define their own. 8 "defaultWorkerTimeout" : 60, 9 10 // The default amount of time, in seconds, 11 12 13 14 // The default amount of attempts to try before failing a job. 15 // Used if the connection and job doesn't define their own. 16 "defaultWorkerMaxAttempts" : 1, 17 18 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. 19 "registerJobInterceptorRestrictionAspect" : false 20 21 // continued... 22 } 23 }; 24 // The default amount of attempts to try before failing a job. // Used if the connection and job doesn't define their own. "defaultWorkerMaxAttempts" : 1, moduleSettings = { 1 "cbq" : { 2 // The default amount of time, in seconds, to delay a job. 3 // Used if the connection and job doesn't define their own. 4 "defaultWorkerBackoff" : 0, 5 6 // The default amount of time, in seconds, to wait before timing out a job. 7 // Used if the connection and job doesn't define their own. 8 "defaultWorkerTimeout" : 60, 9 10 // The default amount of time, in seconds, 11 // to wait for tasks to complete before killing them when requesting a shutdown. 12 "defaultWorkerShutdownTimeout" : 60, 13 14 15 16 17 18 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. 19 "registerJobInterceptorRestrictionAspect" : false 20 21 // continued... 22 } 23 }; 24
  • 46. moduleSettings = { "cbq" : { // The default amount of time, in seconds, to delay a job. // Used if the connection and job doesn't define their own. "defaultWorkerBackoff" : 0, // The default amount of time, in seconds, to wait before timing out a job. // Used if the connection and job doesn't define their own. "defaultWorkerTimeout" : 60, // The default amount of time, in seconds, // to wait for tasks to complete before killing them when requesting a shutdown. "defaultWorkerShutdownTimeout" : 60, // The default amount of attempts to try before failing a job. // Used if the connection and job doesn't define their own. "defaultWorkerMaxAttempts" : 1, // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. "registerJobInterceptorRestrictionAspect" : false // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // The default amount of time, in seconds, to delay a job. // Used if the connection and job doesn't define their own. "defaultWorkerBackoff" : 0, moduleSettings = { 1 "cbq" : { 2 3 4 5 6 // The default amount of time, in seconds, to wait before timing out a job. 7 // Used if the connection and job doesn't define their own. 8 "defaultWorkerTimeout" : 60, 9 10 // The default amount of time, in seconds, 11 // to wait for tasks to complete before killing them when requesting a shutdown. 12 "defaultWorkerShutdownTimeout" : 60, 13 14 // The default amount of attempts to try before failing a job. 15 // Used if the connection and job doesn't define their own. 16 "defaultWorkerMaxAttempts" : 1, 17 18 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. 19 "registerJobInterceptorRestrictionAspect" : false 20 21 // continued... 22 } 23 }; 24 // The default amount of time, in seconds, to wait before timing out a job. // Used if the connection and job doesn't define their own. "defaultWorkerTimeout" : 60, moduleSettings = { 1 "cbq" : { 2 // The default amount of time, in seconds, to delay a job. 3 // Used if the connection and job doesn't define their own. 4 "defaultWorkerBackoff" : 0, 5 6 7 8 9 10 // The default amount of time, in seconds, 11 // to wait for tasks to complete before killing them when requesting a shutdown. 12 "defaultWorkerShutdownTimeout" : 60, 13 14 // The default amount of attempts to try before failing a job. 15 // Used if the connection and job doesn't define their own. 16 "defaultWorkerMaxAttempts" : 1, 17 18 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. 19 "registerJobInterceptorRestrictionAspect" : false 20 21 // continued... 22 } 23 }; 24 // to wait for tasks to complete before killing them when requesting a shutdown. "defaultWorkerShutdownTimeout" : 60, moduleSettings = { 1 "cbq" : { 2 // The default amount of time, in seconds, to delay a job. 3 // Used if the connection and job doesn't define their own. 4 "defaultWorkerBackoff" : 0, 5 6 // The default amount of time, in seconds, to wait before timing out a job. 7 // Used if the connection and job doesn't define their own. 8 "defaultWorkerTimeout" : 60, 9 10 // The default amount of time, in seconds, 11 12 13 14 // The default amount of attempts to try before failing a job. 15 // Used if the connection and job doesn't define their own. 16 "defaultWorkerMaxAttempts" : 1, 17 18 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. 19 "registerJobInterceptorRestrictionAspect" : false 20 21 // continued... 22 } 23 }; 24 // The default amount of attempts to try before failing a job. // Used if the connection and job doesn't define their own. "defaultWorkerMaxAttempts" : 1, moduleSettings = { 1 "cbq" : { 2 // The default amount of time, in seconds, to delay a job. 3 // Used if the connection and job doesn't define their own. 4 "defaultWorkerBackoff" : 0, 5 6 // The default amount of time, in seconds, to wait before timing out a job. 7 // Used if the connection and job doesn't define their own. 8 "defaultWorkerTimeout" : 60, 9 10 // The default amount of time, in seconds, 11 // to wait for tasks to complete before killing them when requesting a shutdown. 12 "defaultWorkerShutdownTimeout" : 60, 13 14 15 16 17 18 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. 19 "registerJobInterceptorRestrictionAspect" : false 20 21 // continued... 22 } 23 }; 24 // Flag to allow restricting Job interceptor execution using a `jobPattern` annotation. "registerJobInterceptorRestrictionAspect" : false moduleSettings = { 1 "cbq" : { 2 // The default amount of time, in seconds, to delay a job. 3 // Used if the connection and job doesn't define their own. 4 "defaultWorkerBackoff" : 0, 5 6 // The default amount of time, in seconds, to wait before timing out a job. 7 // Used if the connection and job doesn't define their own. 8 "defaultWorkerTimeout" : 60, 9 10 // The default amount of time, in seconds, 11 // to wait for tasks to complete before killing them when requesting a shutdown. 12 "defaultWorkerShutdownTimeout" : 60, 13 14 // The default amount of attempts to try before failing a job. 15 // Used if the connection and job doesn't define their own. 16 "defaultWorkerMaxAttempts" : 1, 17 18 19 20 21 // continued... 22 } 23 }; 24
  • 47. moduleSettings = { "cbq" : { // Datasource information for tracking batches. "batchRepositoryProperties" : { "tableName" : "cbq_batches", // `datasource` can also be a struct "datasource" : "", // The sibling `datasource` property overrides any defined datasource in queryOptions. "queryOptions" : {}, // Cleanup options for the batch table "cleanup" : { "enabled" : false, // A callback to configure the ColdBox Scheduled Task "frequency" : ( task ) => { task.everyDay(); }, // A QueryBuilder instance to configure what batches to delete. // Only completed or cancelled batches can be deleted. "criteria" : ( qb, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); qb.where( ( q ) => { q.where( "cancelledDate", "<=", thirtyDaysAgo ); q.orWhere( "completedDate", "<=", thirtyDaysAgo ); } ); } } }, // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
  • 48. moduleSettings = { "cbq" : { // Datasource information for tracking batches. "batchRepositoryProperties" : { "tableName" : "cbq_batches", // `datasource` can also be a struct "datasource" : "", // The sibling `datasource` property overrides any defined datasource in queryOptions. "queryOptions" : {}, // Cleanup options for the batch table "cleanup" : { "enabled" : false, // A callback to configure the ColdBox Scheduled Task "frequency" : ( task ) => { task.everyDay(); }, // A QueryBuilder instance to configure what batches to delete. // Only completed or cancelled batches can be deleted. "criteria" : ( qb, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); qb.where( ( q ) => { q.where( "cancelledDate", "<=", thirtyDaysAgo ); q.orWhere( "completedDate", "<=", thirtyDaysAgo ); } ); } } }, // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 "tableName" : "cbq_batches", moduleSettings = { 1 "cbq" : { 2 // Datasource information for tracking batches. 3 "batchRepositoryProperties" : { 4 5 // `datasource` can also be a struct 6 "datasource" : "", 7 // The sibling `datasource` property overrides any defined datasource in queryOptions. 8 "queryOptions" : {}, 9 // Cleanup options for the batch table 10 "cleanup" : { 11 "enabled" : false, 12 // A callback to configure the ColdBox Scheduled Task 13 "frequency" : ( task ) => { task.everyDay(); }, 14 // A QueryBuilder instance to configure what batches to delete. 15 // Only completed or cancelled batches can be deleted. 16 "criteria" : ( qb, currentUnixTimestamp ) => { 17 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 18 qb.where( ( q ) => { 19 q.where( "cancelledDate", "<=", thirtyDaysAgo ); 20 q.orWhere( "completedDate", "<=", thirtyDaysAgo ); 21 } ); 22 } 23 } 24 }, // continued... 25 } 26 }; 27
  • 49. moduleSettings = { "cbq" : { // Datasource information for tracking batches. "batchRepositoryProperties" : { "tableName" : "cbq_batches", // `datasource` can also be a struct "datasource" : "", // The sibling `datasource` property overrides any defined datasource in queryOptions. "queryOptions" : {}, // Cleanup options for the batch table "cleanup" : { "enabled" : false, // A callback to configure the ColdBox Scheduled Task "frequency" : ( task ) => { task.everyDay(); }, // A QueryBuilder instance to configure what batches to delete. // Only completed or cancelled batches can be deleted. "criteria" : ( qb, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); qb.where( ( q ) => { q.where( "cancelledDate", "<=", thirtyDaysAgo ); q.orWhere( "completedDate", "<=", thirtyDaysAgo ); } ); } } }, // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 "tableName" : "cbq_batches", moduleSettings = { 1 "cbq" : { 2 // Datasource information for tracking batches. 3 "batchRepositoryProperties" : { 4 5 // `datasource` can also be a struct 6 "datasource" : "", 7 // The sibling `datasource` property overrides any defined datasource in queryOptions. 8 "queryOptions" : {}, 9 // Cleanup options for the batch table 10 "cleanup" : { 11 "enabled" : false, 12 // A callback to configure the ColdBox Scheduled Task 13 "frequency" : ( task ) => { task.everyDay(); }, 14 // A QueryBuilder instance to configure what batches to delete. 15 // Only completed or cancelled batches can be deleted. 16 "criteria" : ( qb, currentUnixTimestamp ) => { 17 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 18 qb.where( ( q ) => { 19 q.where( "cancelledDate", "<=", thirtyDaysAgo ); 20 q.orWhere( "completedDate", "<=", thirtyDaysAgo ); 21 } ); 22 } 23 } 24 }, // continued... 25 } 26 }; 27 // `datasource` can also be a struct "datasource" : "", moduleSettings = { 1 "cbq" : { 2 // Datasource information for tracking batches. 3 "batchRepositoryProperties" : { 4 "tableName" : "cbq_batches", 5 6 7 // The sibling `datasource` property overrides any defined datasource in queryOptions. 8 "queryOptions" : {}, 9 // Cleanup options for the batch table 10 "cleanup" : { 11 "enabled" : false, 12 // A callback to configure the ColdBox Scheduled Task 13 "frequency" : ( task ) => { task.everyDay(); }, 14 // A QueryBuilder instance to configure what batches to delete. 15 // Only completed or cancelled batches can be deleted. 16 "criteria" : ( qb, currentUnixTimestamp ) => { 17 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 18 qb.where( ( q ) => { 19 q.where( "cancelledDate", "<=", thirtyDaysAgo ); 20 q.orWhere( "completedDate", "<=", thirtyDaysAgo ); 21 } ); 22 } 23 } 24 }, // continued... 25 } 26 }; 27
  • 50. moduleSettings = { "cbq" : { // Datasource information for tracking batches. "batchRepositoryProperties" : { "tableName" : "cbq_batches", // `datasource` can also be a struct "datasource" : "", // The sibling `datasource` property overrides any defined datasource in queryOptions. "queryOptions" : {}, // Cleanup options for the batch table "cleanup" : { "enabled" : false, // A callback to configure the ColdBox Scheduled Task "frequency" : ( task ) => { task.everyDay(); }, // A QueryBuilder instance to configure what batches to delete. // Only completed or cancelled batches can be deleted. "criteria" : ( qb, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); qb.where( ( q ) => { q.where( "cancelledDate", "<=", thirtyDaysAgo ); q.orWhere( "completedDate", "<=", thirtyDaysAgo ); } ); } } }, // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 "tableName" : "cbq_batches", moduleSettings = { 1 "cbq" : { 2 // Datasource information for tracking batches. 3 "batchRepositoryProperties" : { 4 5 // `datasource` can also be a struct 6 "datasource" : "", 7 // The sibling `datasource` property overrides any defined datasource in queryOptions. 8 "queryOptions" : {}, 9 // Cleanup options for the batch table 10 "cleanup" : { 11 "enabled" : false, 12 // A callback to configure the ColdBox Scheduled Task 13 "frequency" : ( task ) => { task.everyDay(); }, 14 // A QueryBuilder instance to configure what batches to delete. 15 // Only completed or cancelled batches can be deleted. 16 "criteria" : ( qb, currentUnixTimestamp ) => { 17 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 18 qb.where( ( q ) => { 19 q.where( "cancelledDate", "<=", thirtyDaysAgo ); 20 q.orWhere( "completedDate", "<=", thirtyDaysAgo ); 21 } ); 22 } 23 } 24 }, // continued... 25 } 26 }; 27 // `datasource` can also be a struct "datasource" : "", moduleSettings = { 1 "cbq" : { 2 // Datasource information for tracking batches. 3 "batchRepositoryProperties" : { 4 "tableName" : "cbq_batches", 5 6 7 // The sibling `datasource` property overrides any defined datasource in queryOptions. 8 "queryOptions" : {}, 9 // Cleanup options for the batch table 10 "cleanup" : { 11 "enabled" : false, 12 // A callback to configure the ColdBox Scheduled Task 13 "frequency" : ( task ) => { task.everyDay(); }, 14 // A QueryBuilder instance to configure what batches to delete. 15 // Only completed or cancelled batches can be deleted. 16 "criteria" : ( qb, currentUnixTimestamp ) => { 17 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 18 qb.where( ( q ) => { 19 q.where( "cancelledDate", "<=", thirtyDaysAgo ); 20 q.orWhere( "completedDate", "<=", thirtyDaysAgo ); 21 } ); 22 } 23 } 24 }, // continued... 25 } 26 }; 27 // The sibling `datasource` property overrides any defined datasource in queryOptions. "queryOptions" : {}, moduleSettings = { 1 "cbq" : { 2 // Datasource information for tracking batches. 3 "batchRepositoryProperties" : { 4 "tableName" : "cbq_batches", 5 // `datasource` can also be a struct 6 "datasource" : "", 7 8 9 // Cleanup options for the batch table 10 "cleanup" : { 11 "enabled" : false, 12 // A callback to configure the ColdBox Scheduled Task 13 "frequency" : ( task ) => { task.everyDay(); }, 14 // A QueryBuilder instance to configure what batches to delete. 15 // Only completed or cancelled batches can be deleted. 16 "criteria" : ( qb, currentUnixTimestamp ) => { 17 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 18 qb.where( ( q ) => { 19 q.where( "cancelledDate", "<=", thirtyDaysAgo ); 20 q.orWhere( "completedDate", "<=", thirtyDaysAgo ); 21 } ); 22 } 23 } 24 }, // continued... 25 } 26 }; 27
  • 51. moduleSettings = { "cbq" : { // Datasource information for tracking batches. "batchRepositoryProperties" : { "tableName" : "cbq_batches", // `datasource` can also be a struct "datasource" : "", // The sibling `datasource` property overrides any defined datasource in queryOptions. "queryOptions" : {}, // Cleanup options for the batch table "cleanup" : { "enabled" : false, // A callback to configure the ColdBox Scheduled Task "frequency" : ( task ) => { task.everyDay(); }, // A QueryBuilder instance to configure what batches to delete. // Only completed or cancelled batches can be deleted. "criteria" : ( qb, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); qb.where( ( q ) => { q.where( "cancelledDate", "<=", thirtyDaysAgo ); q.orWhere( "completedDate", "<=", thirtyDaysAgo ); } ); } } }, // continued... } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 "tableName" : "cbq_batches", moduleSettings = { 1 "cbq" : { 2 // Datasource information for tracking batches. 3 "batchRepositoryProperties" : { 4 5 // `datasource` can also be a struct 6 "datasource" : "", 7 // The sibling `datasource` property overrides any defined datasource in queryOptions. 8 "queryOptions" : {}, 9 // Cleanup options for the batch table 10 "cleanup" : { 11 "enabled" : false, 12 // A callback to configure the ColdBox Scheduled Task 13 "frequency" : ( task ) => { task.everyDay(); }, 14 // A QueryBuilder instance to configure what batches to delete. 15 // Only completed or cancelled batches can be deleted. 16 "criteria" : ( qb, currentUnixTimestamp ) => { 17 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 18 qb.where( ( q ) => { 19 q.where( "cancelledDate", "<=", thirtyDaysAgo ); 20 q.orWhere( "completedDate", "<=", thirtyDaysAgo ); 21 } ); 22 } 23 } 24 }, // continued... 25 } 26 }; 27 // `datasource` can also be a struct "datasource" : "", moduleSettings = { 1 "cbq" : { 2 // Datasource information for tracking batches. 3 "batchRepositoryProperties" : { 4 "tableName" : "cbq_batches", 5 6 7 // The sibling `datasource` property overrides any defined datasource in queryOptions. 8 "queryOptions" : {}, 9 // Cleanup options for the batch table 10 "cleanup" : { 11 "enabled" : false, 12 // A callback to configure the ColdBox Scheduled Task 13 "frequency" : ( task ) => { task.everyDay(); }, 14 // A QueryBuilder instance to configure what batches to delete. 15 // Only completed or cancelled batches can be deleted. 16 "criteria" : ( qb, currentUnixTimestamp ) => { 17 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 18 qb.where( ( q ) => { 19 q.where( "cancelledDate", "<=", thirtyDaysAgo ); 20 q.orWhere( "completedDate", "<=", thirtyDaysAgo ); 21 } ); 22 } 23 } 24 }, // continued... 25 } 26 }; 27 // The sibling `datasource` property overrides any defined datasource in queryOptions. "queryOptions" : {}, moduleSettings = { 1 "cbq" : { 2 // Datasource information for tracking batches. 3 "batchRepositoryProperties" : { 4 "tableName" : "cbq_batches", 5 // `datasource` can also be a struct 6 "datasource" : "", 7 8 9 // Cleanup options for the batch table 10 "cleanup" : { 11 "enabled" : false, 12 // A callback to configure the ColdBox Scheduled Task 13 "frequency" : ( task ) => { task.everyDay(); }, 14 // A QueryBuilder instance to configure what batches to delete. 15 // Only completed or cancelled batches can be deleted. 16 "criteria" : ( qb, currentUnixTimestamp ) => { 17 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 18 qb.where( ( q ) => { 19 q.where( "cancelledDate", "<=", thirtyDaysAgo ); 20 q.orWhere( "completedDate", "<=", thirtyDaysAgo ); 21 } ); 22 } 23 } 24 }, // continued... 25 } 26 }; 27 // Cleanup options for the batch table "cleanup" : { "enabled" : false, // A callback to configure the ColdBox Scheduled Task "frequency" : ( task ) => { task.everyDay(); }, // A QueryBuilder instance to configure what batches to delete. // Only completed or cancelled batches can be deleted. "criteria" : ( qb, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); qb.where( ( q ) => { q.where( "cancelledDate", "<=", thirtyDaysAgo ); q.orWhere( "completedDate", "<=", thirtyDaysAgo ); } ); } } moduleSettings = { 1 "cbq" : { 2 // Datasource information for tracking batches. 3 "batchRepositoryProperties" : { 4 "tableName" : "cbq_batches", 5 // `datasource` can also be a struct 6 "datasource" : "", 7 // The sibling `datasource` property overrides any defined datasource in queryOptions. 8 "queryOptions" : {}, 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 }, // continued... 25 } 26 }; 27
  • 52. moduleSettings = { "cbq" : { // Flag to turn on logging failed jobs to a database table. "logFailedJobs" : false, // Configuration information for logging failed jobs. "logFailedJobsProperties" : { "tableName" : "cbq_failed_jobs", // `datasource` can also be a struct. "datasource" : "", // The sibling `datasource` property overrides any defined datasource in `queryOptions`. "queryOptions" : {}, "cleanup" : { "enabled" : false, "frequency" : ( task ) => { task.everyDay(); }, "criteria" : ( q, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); q.where( "failedDate", "<=", thirtyDaysAgo ); } } } } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
  • 53. moduleSettings = { "cbq" : { // Flag to turn on logging failed jobs to a database table. "logFailedJobs" : false, // Configuration information for logging failed jobs. "logFailedJobsProperties" : { "tableName" : "cbq_failed_jobs", // `datasource` can also be a struct. "datasource" : "", // The sibling `datasource` property overrides any defined datasource in `queryOptions`. "queryOptions" : {}, "cleanup" : { "enabled" : false, "frequency" : ( task ) => { task.everyDay(); }, "criteria" : ( q, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); q.where( "failedDate", "<=", thirtyDaysAgo ); } } } } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // Flag to turn on logging failed jobs to a database table. "logFailedJobs" : false, // Configuration information for logging failed jobs. moduleSettings = { 1 "cbq" : { 2 3 4 5 "logFailedJobsProperties" : { 6 "tableName" : "cbq_failed_jobs", 7 // `datasource` can also be a struct. 8 "datasource" : "", 9 // The sibling `datasource` property overrides any defined datasource in `queryOptions`. 10 "queryOptions" : {}, 11 "cleanup" : { 12 "enabled" : false, 13 "frequency" : ( task ) => { task.everyDay(); }, 14 "criteria" : ( q, currentUnixTimestamp ) => { 15 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 16 q.where( "failedDate", "<=", thirtyDaysAgo ); 17 } 18 } 19 } 20 } 21 }; 22
  • 54. moduleSettings = { "cbq" : { // Flag to turn on logging failed jobs to a database table. "logFailedJobs" : false, // Configuration information for logging failed jobs. "logFailedJobsProperties" : { "tableName" : "cbq_failed_jobs", // `datasource` can also be a struct. "datasource" : "", // The sibling `datasource` property overrides any defined datasource in `queryOptions`. "queryOptions" : {}, "cleanup" : { "enabled" : false, "frequency" : ( task ) => { task.everyDay(); }, "criteria" : ( q, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); q.where( "failedDate", "<=", thirtyDaysAgo ); } } } } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // Flag to turn on logging failed jobs to a database table. "logFailedJobs" : false, // Configuration information for logging failed jobs. moduleSettings = { 1 "cbq" : { 2 3 4 5 "logFailedJobsProperties" : { 6 "tableName" : "cbq_failed_jobs", 7 // `datasource` can also be a struct. 8 "datasource" : "", 9 // The sibling `datasource` property overrides any defined datasource in `queryOptions`. 10 "queryOptions" : {}, 11 "cleanup" : { 12 "enabled" : false, 13 "frequency" : ( task ) => { task.everyDay(); }, 14 "criteria" : ( q, currentUnixTimestamp ) => { 15 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 16 q.where( "failedDate", "<=", thirtyDaysAgo ); 17 } 18 } 19 } 20 } 21 }; 22 // Configuration information for logging failed jobs. "logFailedJobsProperties" : { "tableName" : "cbq_failed_jobs", // `datasource` can also be a struct. "datasource" : "", // The sibling `datasource` property overrides any defined datasource in `queryOptions`. "queryOptions" : {}, "cleanup" : { "enabled" : false, "frequency" : ( task ) => { task.everyDay(); }, "criteria" : ( q, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); q.where( "failedDate", "<=", thirtyDaysAgo ); } } } moduleSettings = { 1 "cbq" : { 2 // Flag to turn on logging failed jobs to a database table. 3 "logFailedJobs" : false, 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 } 21 }; 22
  • 55. moduleSettings = { "cbq" : { // Flag to turn on logging failed jobs to a database table. "logFailedJobs" : false, // Configuration information for logging failed jobs. "logFailedJobsProperties" : { "tableName" : "cbq_failed_jobs", // `datasource` can also be a struct. "datasource" : "", // The sibling `datasource` property overrides any defined datasource in `queryOptions`. "queryOptions" : {}, "cleanup" : { "enabled" : false, "frequency" : ( task ) => { task.everyDay(); }, "criteria" : ( q, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); q.where( "failedDate", "<=", thirtyDaysAgo ); } } } } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // Flag to turn on logging failed jobs to a database table. "logFailedJobs" : false, // Configuration information for logging failed jobs. moduleSettings = { 1 "cbq" : { 2 3 4 5 "logFailedJobsProperties" : { 6 "tableName" : "cbq_failed_jobs", 7 // `datasource` can also be a struct. 8 "datasource" : "", 9 // The sibling `datasource` property overrides any defined datasource in `queryOptions`. 10 "queryOptions" : {}, 11 "cleanup" : { 12 "enabled" : false, 13 "frequency" : ( task ) => { task.everyDay(); }, 14 "criteria" : ( q, currentUnixTimestamp ) => { 15 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 16 q.where( "failedDate", "<=", thirtyDaysAgo ); 17 } 18 } 19 } 20 } 21 }; 22 // Configuration information for logging failed jobs. "logFailedJobsProperties" : { "tableName" : "cbq_failed_jobs", // `datasource` can also be a struct. "datasource" : "", // The sibling `datasource` property overrides any defined datasource in `queryOptions`. "queryOptions" : {}, "cleanup" : { "enabled" : false, "frequency" : ( task ) => { task.everyDay(); }, "criteria" : ( q, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); q.where( "failedDate", "<=", thirtyDaysAgo ); } } } moduleSettings = { 1 "cbq" : { 2 // Flag to turn on logging failed jobs to a database table. 3 "logFailedJobs" : false, 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 } 21 }; 22 "tableName" : "cbq_failed_jobs", // `datasource` can also be a struct. "datasource" : "", // The sibling `datasource` property overrides any defined datasource in `queryOptions`. "queryOptions" : {}, moduleSettings = { 1 "cbq" : { 2 // Flag to turn on logging failed jobs to a database table. 3 "logFailedJobs" : false, 4 // Configuration information for logging failed jobs. 5 "logFailedJobsProperties" : { 6 7 8 9 10 11 "cleanup" : { 12 "enabled" : false, 13 "frequency" : ( task ) => { task.everyDay(); }, 14 "criteria" : ( q, currentUnixTimestamp ) => { 15 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 16 q.where( "failedDate", "<=", thirtyDaysAgo ); 17 } 18 } 19 } 20 } 21 }; 22
  • 56. moduleSettings = { "cbq" : { // Flag to turn on logging failed jobs to a database table. "logFailedJobs" : false, // Configuration information for logging failed jobs. "logFailedJobsProperties" : { "tableName" : "cbq_failed_jobs", // `datasource` can also be a struct. "datasource" : "", // The sibling `datasource` property overrides any defined datasource in `queryOptions`. "queryOptions" : {}, "cleanup" : { "enabled" : false, "frequency" : ( task ) => { task.everyDay(); }, "criteria" : ( q, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); q.where( "failedDate", "<=", thirtyDaysAgo ); } } } } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // Flag to turn on logging failed jobs to a database table. "logFailedJobs" : false, // Configuration information for logging failed jobs. moduleSettings = { 1 "cbq" : { 2 3 4 5 "logFailedJobsProperties" : { 6 "tableName" : "cbq_failed_jobs", 7 // `datasource` can also be a struct. 8 "datasource" : "", 9 // The sibling `datasource` property overrides any defined datasource in `queryOptions`. 10 "queryOptions" : {}, 11 "cleanup" : { 12 "enabled" : false, 13 "frequency" : ( task ) => { task.everyDay(); }, 14 "criteria" : ( q, currentUnixTimestamp ) => { 15 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 16 q.where( "failedDate", "<=", thirtyDaysAgo ); 17 } 18 } 19 } 20 } 21 }; 22 // Configuration information for logging failed jobs. "logFailedJobsProperties" : { "tableName" : "cbq_failed_jobs", // `datasource` can also be a struct. "datasource" : "", // The sibling `datasource` property overrides any defined datasource in `queryOptions`. "queryOptions" : {}, "cleanup" : { "enabled" : false, "frequency" : ( task ) => { task.everyDay(); }, "criteria" : ( q, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); q.where( "failedDate", "<=", thirtyDaysAgo ); } } } moduleSettings = { 1 "cbq" : { 2 // Flag to turn on logging failed jobs to a database table. 3 "logFailedJobs" : false, 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 } 21 }; 22 "tableName" : "cbq_failed_jobs", // `datasource` can also be a struct. "datasource" : "", // The sibling `datasource` property overrides any defined datasource in `queryOptions`. "queryOptions" : {}, moduleSettings = { 1 "cbq" : { 2 // Flag to turn on logging failed jobs to a database table. 3 "logFailedJobs" : false, 4 // Configuration information for logging failed jobs. 5 "logFailedJobsProperties" : { 6 7 8 9 10 11 "cleanup" : { 12 "enabled" : false, 13 "frequency" : ( task ) => { task.everyDay(); }, 14 "criteria" : ( q, currentUnixTimestamp ) => { 15 var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); 16 q.where( "failedDate", "<=", thirtyDaysAgo ); 17 } 18 } 19 } 20 } 21 }; 22 "cleanup" : { "enabled" : false, "frequency" : ( task ) => { task.everyDay(); }, "criteria" : ( q, currentUnixTimestamp ) => { var thirtyDaysAgo = currentUnixTimestamp - ( 60 * 60 * 24 * 30 ); q.where( "failedDate", "<=", thirtyDaysAgo ); } } moduleSettings = { 1 "cbq" : { 2 // Flag to turn on logging failed jobs to a database table. 3 "logFailedJobs" : false, 4 // Configuration information for logging failed jobs. 5 "logFailedJobsProperties" : { 6 "tableName" : "cbq_failed_jobs", 7 // `datasource` can also be a struct. 8 "datasource" : "", 9 // The sibling `datasource` property overrides any defined datasource in `queryOptions`. 10 "queryOptions" : {}, 11 12 13 14 15 16 17 18 19 } 20 } 21 }; 22
  • 58. component { function configure() { newConnection( "default" ) .setProvider( "ColdBoxAsyncProvider@cbq" ); newConnection( "database" ) .setProvider( "DBProvider@cbq" ) .setProperties( { "tableName": "custom_jobs_table" } ); newConnection( "external" ) .setProvider( "DBProvider@cbq" ) .setProperties( { "datasource": "external" } ); newWorkerPool( "default" ) .forConnection( "default" ) .setTimeout( 5 ) .setMaxAttempts( 5 ); newWorkerPool( "priority" ) .forConnection( "database" ) .onQueues( [ "priority", "*" ] ) .setQuantity( 3 ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  • 59. component { function configure() { newConnection( "default" ) .setProvider( "ColdBoxAsyncProvider@cbq" ); newConnection( "database" ) .setProvider( "DBProvider@cbq" ) .setProperties( { "tableName": "custom_jobs_table" } ); newConnection( "external" ) .setProvider( "DBProvider@cbq" ) .setProperties( { "datasource": "external" } ); newWorkerPool( "default" ) .forConnection( "default" ) .setTimeout( 5 ) .setMaxAttempts( 5 ); newWorkerPool( "priority" ) .forConnection( "database" ) .onQueues( [ "priority", "*" ] ) .setQuantity( 3 ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 newConnection( "default" ) .setProvider( "ColdBoxAsyncProvider@cbq" ); newWorkerPool( "default" ) .forConnection( "default" ) .setTimeout( 5 ) .setMaxAttempts( 5 ); component { 1 function configure() { 2 3 4 5 newConnection( "database" ) 6 .setProvider( "DBProvider@cbq" ) 7 .setProperties( { "tableName": "custom_jobs_table" } ); 8 9 newConnection( "external" ) 10 .setProvider( "DBProvider@cbq" ) 11 .setProperties( { "datasource": "external" } ); 12 13 14 15 16 17 18 newWorkerPool( "priority" ) 19 .forConnection( "database" ) 20 .onQueues( [ "priority", "*" ] ) 21 .setQuantity( 3 ); 22 } 23 } 24
  • 60. component { function configure() { newConnection( "default" ) .setProvider( "ColdBoxAsyncProvider@cbq" ); newConnection( "database" ) .setProvider( "DBProvider@cbq" ) .setProperties( { "tableName": "custom_jobs_table" } ); newConnection( "external" ) .setProvider( "DBProvider@cbq" ) .setProperties( { "datasource": "external" } ); newWorkerPool( "default" ) .forConnection( "default" ) .setTimeout( 5 ) .setMaxAttempts( 5 ); newWorkerPool( "priority" ) .forConnection( "database" ) .onQueues( [ "priority", "*" ] ) .setQuantity( 3 ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 newConnection( "default" ) .setProvider( "ColdBoxAsyncProvider@cbq" ); newWorkerPool( "default" ) .forConnection( "default" ) .setTimeout( 5 ) .setMaxAttempts( 5 ); component { 1 function configure() { 2 3 4 5 newConnection( "database" ) 6 .setProvider( "DBProvider@cbq" ) 7 .setProperties( { "tableName": "custom_jobs_table" } ); 8 9 newConnection( "external" ) 10 .setProvider( "DBProvider@cbq" ) 11 .setProperties( { "datasource": "external" } ); 12 13 14 15 16 17 18 newWorkerPool( "priority" ) 19 .forConnection( "database" ) 20 .onQueues( [ "priority", "*" ] ) 21 .setQuantity( 3 ); 22 } 23 } 24 newConnection( "database" ) .setProvider( "DBProvider@cbq" ) .setProperties( { "tableName": "custom_jobs_table" } ); newWorkerPool( "priority" ) .forConnection( "database" ) .onQueues( [ "priority", "*" ] ) .setQuantity( 3 ); component { 1 function configure() { 2 newConnection( "default" ) 3 .setProvider( "ColdBoxAsyncProvider@cbq" ); 4 5 6 7 8 9 newConnection( "external" ) 10 .setProvider( "DBProvider@cbq" ) 11 .setProperties( { "datasource": "external" } ); 12 13 newWorkerPool( "default" ) 14 .forConnection( "default" ) 15 .setTimeout( 5 ) 16 .setMaxAttempts( 5 ); 17 18 19 20 21 22 } 23 } 24
  • 61. component { function configure() { newConnection( "default" ) .setProvider( "ColdBoxAsyncProvider@cbq" ); newConnection( "database" ) .setProvider( "DBProvider@cbq" ) .setProperties( { "tableName": "custom_jobs_table" } ); newConnection( "external" ) .setProvider( "DBProvider@cbq" ) .setProperties( { "datasource": "external" } ); newWorkerPool( "default" ) .forConnection( "default" ) .setTimeout( 5 ) .setMaxAttempts( 5 ); newWorkerPool( "priority" ) .forConnection( "database" ) .onQueues( [ "priority", "*" ] ) .setQuantity( 3 ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 newConnection( "default" ) .setProvider( "ColdBoxAsyncProvider@cbq" ); newWorkerPool( "default" ) .forConnection( "default" ) .setTimeout( 5 ) .setMaxAttempts( 5 ); component { 1 function configure() { 2 3 4 5 newConnection( "database" ) 6 .setProvider( "DBProvider@cbq" ) 7 .setProperties( { "tableName": "custom_jobs_table" } ); 8 9 newConnection( "external" ) 10 .setProvider( "DBProvider@cbq" ) 11 .setProperties( { "datasource": "external" } ); 12 13 14 15 16 17 18 newWorkerPool( "priority" ) 19 .forConnection( "database" ) 20 .onQueues( [ "priority", "*" ] ) 21 .setQuantity( 3 ); 22 } 23 } 24 newConnection( "database" ) .setProvider( "DBProvider@cbq" ) .setProperties( { "tableName": "custom_jobs_table" } ); newWorkerPool( "priority" ) .forConnection( "database" ) .onQueues( [ "priority", "*" ] ) .setQuantity( 3 ); component { 1 function configure() { 2 newConnection( "default" ) 3 .setProvider( "ColdBoxAsyncProvider@cbq" ); 4 5 6 7 8 9 newConnection( "external" ) 10 .setProvider( "DBProvider@cbq" ) 11 .setProperties( { "datasource": "external" } ); 12 13 newWorkerPool( "default" ) 14 .forConnection( "default" ) 15 .setTimeout( 5 ) 16 .setMaxAttempts( 5 ); 17 18 19 20 21 22 } 23 } 24 newConnection( "external" ) .setProvider( "DBProvider@cbq" ) .setProperties( { "datasource": "external" } ); component { 1 function configure() { 2 newConnection( "default" ) 3 .setProvider( "ColdBoxAsyncProvider@cbq" ); 4 5 newConnection( "database" ) 6 .setProvider( "DBProvider@cbq" ) 7 .setProperties( { "tableName": "custom_jobs_table" } ); 8 9 10 11 12 13 newWorkerPool( "default" ) 14 .forConnection( "default" ) 15 .setTimeout( 5 ) 16 .setMaxAttempts( 5 ); 17 18 newWorkerPool( "priority" ) 19 .forConnection( "database" ) 20 .onQueues( [ "priority", "*" ] ) 21 .setQuantity( 3 ); 22 } 23 } 24
  • 62. Usage
  • 64. // SendWelcomeEmailJob.cfc component extends="cbq.models.Jobs.AbstractJob" { property name="mailService" inject="provider:MailService@cbmailservices"; property name="userId"; function handle() { var user = getInstance( "User" ).findOrFail( getUserId() ); variables.mailService .newMail( from = "no-reply@example.com", to = user.getEmail(), subject = "Welcome!", type = "html" ) .setView( "/_emails/users/welcome" ) .setBodyTokens( { "firstName" : user.getFirstName(), "lastName" : user.getLastName() } ) .send(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
  • 66. // SendWelcomeEmailJob.cfc component extends="cbq.models.Jobs.AbstractJob" { variables.connection = "emails"; variables.maxAttempts = 3; variables.timeout = 10; function handle() { // ... } } 1 2 3 4 5 6 7 8 9 10 11 12
  • 67. // SendWelcomeEmailJob.cfc component extends="cbq.models.Jobs.AbstractJob" { variables.connection = "emails"; variables.maxAttempts = 3; variables.timeout = 10; function handle() { // ... } } 1 2 3 4 5 6 7 8 9 10 11 12 variables.connection = "emails"; variables.maxAttempts = 3; variables.timeout = 10; // SendWelcomeEmailJob.cfc 1 component extends="cbq.models.Jobs.AbstractJob" { 2 3 4 5 6 7 function handle() { 8 // ... 9 } 10 11 } 12
  • 69. // handlers/Main.cfc component { function create() { var user = createUser( rc ); getInstance( "SendWelcomeEmailJob" ) .setProperties( { "userId": user.getId() } ) .dispatch(); } } 1 2 3 4 5 6 7 8 9 10 11 12
  • 70. // handlers/Main.cfc component { function create() { var user = createUser( rc ); getInstance( "SendWelcomeEmailJob" ) .setProperties( { "userId": user.getId() } ) .dispatch(); } } 1 2 3 4 5 6 7 8 9 10 11 12 getInstance( "SendWelcomeEmailJob" ) // handlers/Main.cfc 1 component { 2 3 function create() { 4 var user = createUser( rc ); 5 6 7 .setProperties( { "userId": user.getId() } ) 8 .dispatch(); 9 } 10 11 } 12
  • 71. // handlers/Main.cfc component { function create() { var user = createUser( rc ); getInstance( "SendWelcomeEmailJob" ) .setProperties( { "userId": user.getId() } ) .dispatch(); } } 1 2 3 4 5 6 7 8 9 10 11 12 getInstance( "SendWelcomeEmailJob" ) // handlers/Main.cfc 1 component { 2 3 function create() { 4 var user = createUser( rc ); 5 6 7 .setProperties( { "userId": user.getId() } ) 8 .dispatch(); 9 } 10 11 } 12 getInstance( "SendWelcomeEmailJob" ) .setProperties( { "userId": user.getId() } ) // handlers/Main.cfc 1 component { 2 3 function create() { 4 var user = createUser( rc ); 5 6 7 8 .dispatch(); 9 } 10 11 } 12
  • 72. // handlers/Main.cfc component { function create() { var user = createUser( rc ); getInstance( "SendWelcomeEmailJob" ) .setProperties( { "userId": user.getId() } ) .dispatch(); } } 1 2 3 4 5 6 7 8 9 10 11 12 getInstance( "SendWelcomeEmailJob" ) // handlers/Main.cfc 1 component { 2 3 function create() { 4 var user = createUser( rc ); 5 6 7 .setProperties( { "userId": user.getId() } ) 8 .dispatch(); 9 } 10 11 } 12 getInstance( "SendWelcomeEmailJob" ) .setProperties( { "userId": user.getId() } ) // handlers/Main.cfc 1 component { 2 3 function create() { 4 var user = createUser( rc ); 5 6 7 8 .dispatch(); 9 } 10 11 } 12 getInstance( "SendWelcomeEmailJob" ) .setProperties( { "userId": user.getId() } ) .dispatch(); // handlers/Main.cfc 1 component { 2 3 function create() { 4 var user = createUser( rc ); 5 6 7 8 9 } 10 11 } 12
  • 74. moduleSettings = { "cbq" : { "registerWorkers" : true // this is also the default } }; 1 2 3 4 5
  • 75. // config/cbq.cfc component { function configure() { newConnection( "default" ).setProvider( "DBProvider@cbq" ); newWorkerPool( "default" ) .forConnection( "default" ) .setTimeout( 30 ) .setMaxAttempts( 5 ) .setQuantity( 3 ); newWorkerPool( "default" ) .forConnection( "default" ) .onQueues( "emails" ) .setTimeout( 60 ) .setMaxAttempts( 10 ) .setQuantity( 10 ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  • 77. // handlers/Main.cfc component { property name="cbq" inject="cbq@cbq"; function create() { var user = createUser( rc ); cbq.job( "SendWelcomeEmailJob", { "userId": user.getId() } ).dispatch(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  • 79. // FulfillOrderJob.cfc component extends="cbq.models.Jobs.AbstractJob" { function handle() { var productId = getProperties().productId; processPayment( productId ); getInstance( "SendProductLinkEmail" ) .onConnection( "fulfillment" ) .setProperties( { "productId" : productId, "userId" : getProperties().userId } ) .dispatch(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  • 80. // FulfillOrderJob.cfc component extends="cbq.models.Jobs.AbstractJob" { function handle() { var productId = getProperties().productId; processPayment( productId ); getInstance( "SendProductLinkEmail" ) .onConnection( "fulfillment" ) .setProperties( { "productId" : productId, "userId" : getProperties().userId } ) .dispatch(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 getInstance( "SendProductLinkEmail" ) .onConnection( "fulfillment" ) .setProperties( { "productId" : productId, "userId" : getProperties().userId } ) .dispatch(); // FulfillOrderJob.cfc 1 component extends="cbq.models.Jobs.AbstractJob" { 2 3 function handle() { 4 var productId = getProperties().productId; 5 6 processPayment( productId ); 7 8 9 10 11 12 13 14 15 } 16 17 } 18
  • 81. // handlers/Main.cfc component { function create() { getInstance( "FulfillOrderJob" ) .setProperties( { "productId": rc.productId } ) .chain( [ getInstance( "SendProductLinkEmail" ) .onConnection( "fulfillment" ) .setProperties( { "productId" : rc.productId, "userId" : auth().getUserId() } ) ] ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  • 82. // handlers/Main.cfc component { property name="cbq" inject="cbq@cbq"; function create() { cbq.chain( [ cbq.job( "FulfillOrderJob", { "productId": rc.productId } ), cbq.job( job = "SendProductLinkEmail", properties = { "productId": rc.productId, "userId": auth().getUserId() }, connection = "fulfillment" ), ] ).dispatch(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  • 84. // handlers/Main.cfc component { property name="cbq" inject="cbq@cbq"; function create() { cbq.batch( [ cbq.job( "ImportCsvJob", { "start": 1, "end": 100 } ), cbq.job( "ImportCsvJob", { "start": 101, "end": 200 } ), cbq.job( "ImportCsvJob", { "start": 201, "end": 300 } ), cbq.job( "ImportCsvJob", { "start": 301, "end": 400 } ), cbq.job( "ImportCsvJob", { "start": 401, "end": 500 } ) ] ).then( cbq.job( "ImportCsvSuccessfulJob" ) ) .catch( cbq.job( "ImportCsvFailedJob" ) ) .finally( cbq.job( "ImportCsvCompletedJob" ) ) .dispatch(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  • 85. // handlers/Main.cfc component { property name="cbq" inject="cbq@cbq"; function create() { cbq.batch( [ cbq.job( "ImportCsvJob", { "start": 1, "end": 100 } ), cbq.job( "ImportCsvJob", { "start": 101, "end": 200 } ), cbq.job( "ImportCsvJob", { "start": 201, "end": 300 } ), cbq.job( "ImportCsvJob", { "start": 301, "end": 400 } ), cbq.job( "ImportCsvJob", { "start": 401, "end": 500 } ) ] ).then( cbq.job( "ImportCsvSuccessfulJob" ) ) .catch( cbq.job( "ImportCsvFailedJob" ) ) .finally( cbq.job( "ImportCsvCompletedJob" ) ) .dispatch(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 cbq.job( "ImportCsvJob", { "start": 1, "end": 100 } ), cbq.job( "ImportCsvJob", { "start": 101, "end": 200 } ), cbq.job( "ImportCsvJob", { "start": 201, "end": 300 } ), cbq.job( "ImportCsvJob", { "start": 301, "end": 400 } ), cbq.job( "ImportCsvJob", { "start": 401, "end": 500 } ) // handlers/Main.cfc 1 component { 2 3 property name="cbq" inject="cbq@cbq"; 4 5 function create() { 6 cbq.batch( [ 7 8 9 10 11 12 ] ).then( cbq.job( "ImportCsvSuccessfulJob" ) ) 13 .catch( cbq.job( "ImportCsvFailedJob" ) ) 14 .finally( cbq.job( "ImportCsvCompletedJob" ) ) 15 .dispatch(); 16 } 17 18 } 19
  • 86. // handlers/Main.cfc component { property name="cbq" inject="cbq@cbq"; function create() { cbq.batch( [ cbq.job( "ImportCsvJob", { "start": 1, "end": 100 } ), cbq.job( "ImportCsvJob", { "start": 101, "end": 200 } ), cbq.job( "ImportCsvJob", { "start": 201, "end": 300 } ), cbq.job( "ImportCsvJob", { "start": 301, "end": 400 } ), cbq.job( "ImportCsvJob", { "start": 401, "end": 500 } ) ] ).then( cbq.job( "ImportCsvSuccessfulJob" ) ) .catch( cbq.job( "ImportCsvFailedJob" ) ) .finally( cbq.job( "ImportCsvCompletedJob" ) ) .dispatch(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 cbq.job( "ImportCsvJob", { "start": 1, "end": 100 } ), cbq.job( "ImportCsvJob", { "start": 101, "end": 200 } ), cbq.job( "ImportCsvJob", { "start": 201, "end": 300 } ), cbq.job( "ImportCsvJob", { "start": 301, "end": 400 } ), cbq.job( "ImportCsvJob", { "start": 401, "end": 500 } ) // handlers/Main.cfc 1 component { 2 3 property name="cbq" inject="cbq@cbq"; 4 5 function create() { 6 cbq.batch( [ 7 8 9 10 11 12 ] ).then( cbq.job( "ImportCsvSuccessfulJob" ) ) 13 .catch( cbq.job( "ImportCsvFailedJob" ) ) 14 .finally( cbq.job( "ImportCsvCompletedJob" ) ) 15 .dispatch(); 16 } 17 18 } 19 ] ).then( cbq.job( "ImportCsvSuccessfulJob" ) ) .catch( cbq.job( "ImportCsvFailedJob" ) ) .finally( cbq.job( "ImportCsvCompletedJob" ) ) // handlers/Main.cfc 1 component { 2 3 property name="cbq" inject="cbq@cbq"; 4 5 function create() { 6 cbq.batch( [ 7 cbq.job( "ImportCsvJob", { "start": 1, "end": 100 } ), 8 cbq.job( "ImportCsvJob", { "start": 101, "end": 200 } ), 9 cbq.job( "ImportCsvJob", { "start": 201, "end": 300 } ), 10 cbq.job( "ImportCsvJob", { "start": 301, "end": 400 } ), 11 cbq.job( "ImportCsvJob", { "start": 401, "end": 500 } ) 12 13 14 15 .dispatch(); 16 } 17 18 } 19
  • 87. Demo
  • 88. Bonus
  • 90. // MonitorPendingCartJob.cfc component extends="cbq.models.Jobs.AbstractJob" { function handle() { var cartId = getProperties().cartId; var cart = getInstance( "Cart" ).findOrFail( cartId ); if ( cart.isConfirmed() || cart.isCancelled() ) { return; } if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) { cart.cancel(); return; } getInstance( "MonitorPendingCartJob" ) .setProperties( { "cartId" : cartId } ) .delay( 15 * 1000 ) .dispatch(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
  • 91. // MonitorPendingCartJob.cfc component extends="cbq.models.Jobs.AbstractJob" { function handle() { var cartId = getProperties().cartId; var cart = getInstance( "Cart" ).findOrFail( cartId ); if ( cart.isConfirmed() || cart.isCancelled() ) { return; } if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) { cart.cancel(); return; } getInstance( "MonitorPendingCartJob" ) .setProperties( { "cartId" : cartId } ) .delay( 15 * 1000 ) .dispatch(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 .setProperties( { "cartId" : cartId } ) .delay( 15 * 1000 ) .dispatch(); } // MonitorPendingCartJob.cfc 1 component extends="cbq.models.Jobs.AbstractJob" { 2 function handle() { 3 var cartId = getProperties().cartId; 4 var cart = getInstance( "Cart" ).findOrFail( cartId ); 5 6 if ( cart.isConfirmed() || cart.isCancelled() ) { 7 return; 8 } 9 10 if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) { 11 cart.cancel(); 12 return; 13 } 14 15 getInstance( "MonitorPendingCartJob" ) 16 17 18 19 20 } 21
  • 92. // MonitorPendingCartJob.cfc component extends="cbq.models.Jobs.AbstractJob" { function handle() { var cartId = getProperties().cartId; var cart = getInstance( "Cart" ).findOrFail( cartId ); if ( cart.isConfirmed() || cart.isCancelled() ) { return; } if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) { cart.cancel(); return; } this.release( 15 * 1000 ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Using `release`
  • 93. // MonitorPendingCartJob.cfc component extends="cbq.models.Jobs.AbstractJob" { function handle() { var cartId = getProperties().cartId; var cart = getInstance( "Cart" ).findOrFail( cartId ); if ( cart.isConfirmed() || cart.isCancelled() ) { return; } if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) { cart.cancel(); return; } this.release( 15 * 1000 ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 } } // MonitorPendingCartJob.cfc 1 component extends="cbq.models.Jobs.AbstractJob" { 2 function handle() { 3 var cartId = getProperties().cartId; 4 var cart = getInstance( "Cart" ).findOrFail( cartId ); 5 6 if ( cart.isConfirmed() || cart.isCancelled() ) { 7 return; 8 } 9 10 if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) { 11 cart.cancel(); 12 return; 13 } 14 15 this.release( 15 * 1000 ); 16 17 18 Using `release`
  • 94. // MonitorPendingCartJob.cfc component extends="cbq.models.Jobs.AbstractJob" { function handle() { var cartId = getProperties().cartId; var cart = getInstance( "Cart" ).findOrFail( cartId ); if ( cart.isConfirmed() || cart.isCancelled() ) { return; } if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) { cart.cancel(); return; } var delay = 2 ^ this.getCurrentAttempt() * 1000; this.release( delay ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Exponential Backoff
  • 95. // MonitorPendingCartJob.cfc component extends="cbq.models.Jobs.AbstractJob" { function handle() { var cartId = getProperties().cartId; var cart = getInstance( "Cart" ).findOrFail( cartId ); if ( cart.isConfirmed() || cart.isCancelled() ) { return; } if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) { cart.cancel(); return; } var delay = 2 ^ this.getCurrentAttempt() * 1000; this.release( delay ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var delay = 2 ^ this.getCurrentAttempt() * 1000; this.release( delay ); // MonitorPendingCartJob.cfc 1 component extends="cbq.models.Jobs.AbstractJob" { 2 function handle() { 3 var cartId = getProperties().cartId; 4 var cart = getInstance( "Cart" ).findOrFail( cartId ); 5 6 if ( cart.isConfirmed() || cart.isCancelled() ) { 7 return; 8 } 9 10 if ( abs( dateDiff( "n", cart.getModifiedDate(), now() ) ) > 60 ) { 11 cart.cancel(); 12 return; 13 } 14 15 16 17 18 } 19 } 20 Exponential Backoff