Example work queue for updating entities

The following Gosu code is an example of a custom work queue that updates entity data as part of processing a unit of work. It uses the StandardWorkItem entity type for its work queue table. Its unit of work is an activity that has not been viewed for five days or more. The process sends an email to the user assigned to the activity, and then it sets the escalation date on the activity to the current date. The process updates entity data, so the processWorkItemMethod uses the runWithNewBundle API.

uses gw.api.database.Query
uses gw.api.database.Relop
uses gw.api.email.EmailUtil
uses gw.processes.WorkQueueBase
uses gw.transaction.Transaction 
uses java.util.Iterator

/**
 * An example of batch processing implemented as a work queue that sends email
 * to assignees of activities that have not been viewed for five days or more.
 */
class MyActivityEscalationWorkQueue extends WorkQueueBase <Activity, StandardWorkItem> {

   /**
   * Let the base class register this type of custom process by
   * passing the process type, the entity type the work queue item, and
   * the target type for the units of work.
   */
  construct () {
    super (typekey.BatchProcessType.TC_NOTIFYUNVIEWEDACTIVITIES, StandardWorkItem, Activity)
  }

  /**
   * Select the units of work for a batch run: activities that have not been
   * viewed for five days or more.
   */
  override function findTargets (): Iterator  <Activity> {
    // Query the target type and apply conditions: activities not viewed for 5 days or more
    var targetsQuery = Query.make(Activity)
    targetsQuery.compare(Activity#LastViewedDate, Relop.LessThanOrEquals,
      java.util.Date.Today.addBusinessDays(-5))
    return targetsQuery.select().iterator()
  }

  /**
   * Process a unit of work: an activity not viewed for five days or more
   */
  override function processWorkItem (WorkItem : StandardWorkItem) {
    // Extract an object referenct to the unit of work: an Activity instance
    var activity = extractTarget(WorkItem) 

     // Send an email to the user assigned to the activity.
    if (activity.AssignedUser.Contact.EmailAddress1 != null) {
      EmailUtil.sendEmailWithBody(null,
        activity.AssignedUser.Contact,                                                // To:
        null,                                                                         // From:
        "Activity not viewed for five days",                                          // Subject:
        "See activity " + activity.Subject + ", due on " + activity.TargetDate + ".") // Body:
    }

     // Update the escalation date on the assigned activity
    Transaction.runWithNewBundle( \ bundle -> { 
      activity = bundle.add(activity)                    // Add the activity to the new bundle
      activity.EscalationDate = java.util.Date.Today } ) // Update the escalation date
  }
}