A callback is Qube's mechanism to allow custom execution of queuing logic depending upon the events which occur during the lifetime of a Qube job or upon pre-defined system events.
The use of callbacks can range from sending email when a job has completed, to designing complex dependency trees or direct integration with an asset tracking system.
When specifying a callback, Qube requires a little information in order to execute it properly. Each callback must include:
- The trigger expression to specify when the callback should be executed.
- The scripting language to use for the callback.
- The action or code the callback will execute each time the trigger condition is met
Callbacks In Detail:
Callbacks are defined as a list of one or more key/value pairs which is appended to the job's callback
list.
Python API Examples - refer to the above pages for more information
JobB waits for the entire jobA to complete
Code Block |
---|
title | Using the "qube" callback language |
---|
linenumbers | true |
---|
language | python |
---|
|
frameRange = '1-10'
jobA = {
'name': 'my ribgen job',
'label': 'ribgenLabel',
'prototype': 'cmdrange',
'package': {
'cmdline': 'my ribgen command...'
},
'agenda': qb.genframes(frameRange),
}
jobB = {
'name': 'my render job',
'label': 'render',
'status': 'blocked',
'prototype': 'cmdrange',
'package': {
'cmdline': 'my render command...'
},
'agenda': qb.genframes(frameRange),
}
callbacks = [
{
'triggers': 'complete-job-ribgenLabel',
'language': 'qube',
'code': 'unblock-self'
}
]
jobB['callbacks'] = callbacks
qb.submit( [jobA, jobB] ) |
Code Block |
---|
title | Using the "python" callback language is identical to the first example, except the callback's "language" and "code" is different |
---|
linenumbers | true |
---|
language | python |
---|
|
jobA = {
.
.
.
}
jobB = {
.
.
.
}
cbCode = 'jobId = qb.jobid()\n'
cbCode += 'qb.unblock(jobId)\n'
callbacks = [
{
'triggers': 'complete-job-ribgenLabel',
'language': 'python',
'code': cbCode
}
jobB['callbacks'] = callbacks
qb.submit( [jobA, jobB] ) |
Each frame in JobB waits for the its corresponding frame in jobA to complete
Code Block |
---|
title | Using the "qube" callback language |
---|
linenumbers | true |
---|
language | python |
---|
|
frameRange = '1-10'
jobA = {
'name': 'my ribgen job',
'label': 'ribgenLabel',
'prototype': 'cmdrange',
'package': {
'cmdline': 'my ribgen command...'
},
'agenda': qb.genframes(frameRange),
}
jobB = {
'name': 'my render job',
'label': 'render',
'status': 'blocked',
'prototype': 'cmdrange',
'package': {
'cmdline': 'my render command...'
},
'agenda': qb.genframes(frameRange),
}
callbacks = []
for work in jobB['agenda']:
work['status'] = 'blocked'
callbacks.append(
{
'triggers': 'complete-work-ribgenLabel-%s' % work['name'],
'language': 'qube',
'code': 'unblock-work-self',
}
)
]
jobB['callbacks'] = callbacks
qb.submit( [jobA, jobB] ) |
Code Block |
---|
title | Using the "python" callback language is identical to the first example, except the callback's "language" and "code" is different |
---|
linenumbers | true |
---|
language | python |
---|
|
jobA = {
.
.
.
}
jobB = {
.
.
.
}
callbacks = []
for work in jobB['agenda']:
work['status'] = 'blocked'
frameNumber = work['name']
# the agenda item's callback should unblock both itself and the job
cbCode = 'jobId = qb.jobid()\n'
cbCode += 'qb.workunblock("%%s:%s" %% jobId)\n' % frameNumber
cbCode += 'qb.unblock(jobId)\n'
callbacks.append(
{
'triggers': 'complete-work-ribgenLabel-%s' % frameNumber,
'language': 'python',
'code': cbCode,
}
)
]
jobB['callbacks'] = callbacks
qb.submit( [jobA, jobB] ) |
JobC waits for jobA and jobB
This can be done using any of the callback languages, the only difference is the triggers value
Code Block |
---|
title | Using the "python" callback language is identical to the first example, except the callback's "language" and "code" is different |
---|
linenumbers | true |
---|
language | python |
---|
|
jobA = {
'label': 'ribGen',
.
.
}
jobB = {
'label': 'render',
.
.
}
jobC = {
'label': 'composite'
.
.
}
callbacks = []
for work in jobC['agenda']:
work['status'] = 'blocked'
frameNumber = work['name']
# the agenda item's callback should unblock both itself and the job
cbCode = 'jobId = qb.jobid()\n'
cbCode += 'qb.workunblock("%%s:%s" %% jobId)\n' % frameNumber
cbCode += 'qb.unblock(jobId)\n'
triggerStr = 'complete-work-ribgen-%s' % frameNumber'
triggerStr += ' AND '
triggerStr += 'complete-work-render-%s' % frameNumber'
callbacks.append(
{
'triggers': triggerStr,
'language': 'python',
'code': cbCode,
}
)
]
jobB['callbacks'] = callbacks
qb.submit( [jobA, jobB, jobC] ) |
JobD waits for either (jobA AND jobB) OR jobC
Code Block |
---|
title | This is identical to the above example, except the 'triggerStr'" is different |
---|
linenumbers | true |
---|
language | python |
---|
|
jobA = {
'label': 'ribGen',
.
.
}
jobB = {
'label': 'render',
.
.
}
jobC = {
'label': 'composite',
.
.
}
jobD = {
'label': 'sendToDailies',
.
.
}
callbacks = []
for work in jobD['agenda']:
work['status'] = 'blocked',
frameNumber = work['name']
# the agenda item's callback should unblock both itself and the job
cbCode = 'jobId = qb.jobid()\n'
cbCode += 'qb.workunblock("%%s:%s" %% jobId)\n' % frameNumber
cbCode += 'qb.unblock(jobId)\n'
triggerSt = '('
triggerStr += 'complete-work-ribgen-%s' % frameNumber'
triggerStr += ' AND '
triggerStr += 'complete-work-render-%s' % frameNumber'
triggerStr += ')'
triggerStr += ' OR '
triggerStr = 'complete-work-composite-%s' % frameNumber'
callbacks.append(
{
'triggers': triggerStr,
'language': 'python',
'code': cbCode,
}
)
]
jobB['callbacks'] = callbacks
qb.submit( [jobA, jobB, jobC, jobD] ) |