Cbq
Collection of skills for the ColdBox Platform and Claude Plugin
npx -y skills add ColdBox/skills --skill cbqAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use this skill when implementing asynchronous background job processing in ColdBox/BoxLang with cbq. Covers job class creation, queue configuration (database, Redis, SQS), dispatching jobs, delayed dispatch, queue routing, retry handling, worker pool management, and monitoring patterns.
SKILL.md
6.1 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it
CBQ Skill
When to Use This Skill
Load this skill when:
- Offloading slow tasks (email, PDF, API calls) to background workers
- Implementing retry logic for unreliable external integrations
- Routing different job types to different queue backends
- Scheduling delayed job execution
- Building worker consumers for database or Redis queues
Installation
box install cbq
Configuration
config/modules/cbq.cfc
function configure() {
return {
// Default queue connection
defaultConnection : "database",
connections : {
database : {
driver : "CBQDatabase",
dsn : "myDatasource",
tableName : "cbq_jobs",
queue : "default",
timeout : 60
},
redis : {
driver : "CBQRedis",
host : getSystemSetting( "REDIS_HOST", "127.0.0.1" ),
port : getSystemSetting( "REDIS_PORT", "6379" ),
queue : "default",
timeout: 60
}
},
// Worker configuration
workers : {
numThreads : 5,
sleep : 1, // seconds between polls
maxAttempts : 3 // global default
}
}
}
Create Database Table (cfmigrations)
function up( schema ) {
schema.create( "cbq_jobs", ( table ) => {
table.increments( "id" )
table.string( "queue" ).default( "default" )
table.string( "connection" ).default( "database" )
table.longText( "payload" )
table.unsignedTinyInteger( "attempts" ).default( 0 )
table.boolean( "reserved" ).default( false )
table.dateTime( "reserved_at" ).nullable()
table.dateTime( "available_at" )
table.dateTime( "created_at" )
} )
schema.create( "cbq_failed_jobs", ( table ) => {
table.increments( "id" )
table.string( "connection" )
table.string( "queue" )
table.longText( "payload" )
table.longText( "exception" )
table.dateTime( "failed_at" )
} )
}
Creating Jobs
// jobs/SendWelcomeEmailJob.bx
class extends="cbq.models.AbstractJob" {
// Inject services the job needs
property name="mailService" inject="MailService@myApp";
// Job payload properties
property name="userId" type="numeric";
property name="email" type="string";
// Optional — override defaults from config
this.queue = "emails"
this.connection = "default"
this.maxAttempts = 3
this.timeout = 30
function handle() {
var user = userService.get( userId )
mailService
.newMail(
to = email,
subject = "Welcome to the platform!",
type = "html"
)
.setBodyTemplate( "email/templates/welcome" )
.setBodyTokens( { name: user.getName() } )
.send()
}
// Called when all retries exhausted
function failed( exception ) {
log.error( "Failed to send welcome email to #email# after #this.maxAttempts# attempts: #exception.message#" )
}
}
Dispatching Jobs
property name="sendWelcomeEmailJob" inject="SendWelcomeEmailJob";
// Dispatch immediately
sendWelcomeEmailJob
.setUserId( newUser.getId() )
.setEmail( newUser.getEmail() )
.dispatch()
// Delay execution (seconds)
sendWelcomeEmailJob
.setUserId( rc.id )
.setEmail( rc.email )
.delay( 30 )
.dispatch()
// Specify queue and connection
sendWelcomeEmailJob
.setUserId( rc.id )
.setEmail( rc.email )
.onQueue( "high-priority" )
.onConnection( "redis" )
.dispatch()
Production Patterns
Handler — Dispatch on User Registration
function register( event, rc, prc ) {
var user = userService.create( rc )
// Dispatch async background jobs
sendWelcomeEmailJob.setUserId( user.getId() ).setEmail( user.getEmail() ).dispatch()
setupDefaultPreferencesJob.setUserId( user.getId() ).dispatch()
// Respond immediately — do not wait for jobs
messagebox.success( "Registration successful! Check your email." )
relocate( "dashboard" )
}
Chaining Jobs
// Job A dispatches Job B upon completion
class extends="cbq.models.AbstractJob" {
property name="generateReportJob" inject="GenerateReportJob";
function handle() {
// ... do work ...
// Dispatch next job in the chain
generateReportJob
.setReportId( reportId )
.delay( 5 )
.dispatch()
}
}
Idempotent Job
class extends="cbq.models.AbstractJob" {
property name="cache" inject="cachebox:default";
function handle() {
var lockKey = "job_processed_#orderId#"
if ( cache.get( lockKey ) ) {
return // Already processed — skip
}
// Process order...
processOrder( orderId )
// Mark as done (TTL: 1 hour)
cache.set( lockKey, true, 60 )
}
}
Best Practices
- Keep jobs small and focused — one job should do one thing
- Make jobs idempotent — safe to run multiple times in case of retries
- Never trust job payload without validation — validate properties in
handle()before use - Use the
failed()hook to log failures and optionally alert via monitoring - Set appropriate
timeoutper job type — short for emails, longer for PDF generation - Route by priority — use
highandlownamed queues with different worker counts - Avoid large payloads — store IDs in the job, not entire entity serializations
- Test job logic in unit tests — call
handle()directly without dispatching
Documentation
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.