MultiThreading using SysOperationFrameWork
Requirement
Develop batch job (Sysoperation Framework, with multi threading) to cleanup older or historical transactions.
UI
transaction cleanup
Technical
CleanupScheduler
CleanupTask
Dialog
Messages older than (In Days) = 90
Number of tasks
Scheduler
Finds records from custom table that are older than 90 days and assign to tasks
Tasks will just delete the record
Provide info log on how many records cleaned up
we should create six classes for multithreading by using sysoperation frameworks
1)CleanupSchedulerContract
1)CleanupSchedulerContract
2)CleanupSchedulerController
3)CleanupSchedulerService
4)CleanupTaskContract
5)CleanupTaskController
6)CleanupTaskService
1)CleanupSchedulerContract
[DataContractAttribute]
[SysOperationAlwaysInitializeAttribute]
class CleanupSchedulerContract implements SysOperationInitializable
{
Integer numOfTask,numOfDays;
[DataMemberAttribute,
SysOperationLabel(literalStr("OlderRecords"))]
public Integer parmNumOfDays(Integer _numOfDays = numOfDays)
{
numOfDays = _numOfDays;
return numOfDays;
}
[DataMemberAttribute,
SysOperationLabel(literalStr("NumOfTasks"))]
public Integer parmNumOfTask(Integer _numOfTask = numOfTask)
{
numOfTask = _numOfTask;
return numOfTask;
}
public void initialize()
{
numOfTask = 4;
numOfDays = 90;
}
}
2)CleanupSchedulerController
class CleanupSchedulerController extends SysOperationServiceController
{
public static SysOperationController construct()
{
SysOperationController controller = new CleanupSchedulerController(
classStr(CleanupSchedulerService),
methodStr(CleanupSchedulerService, process));
return controller;
}
public static void main(Args _args)
{
CleanupSchedulerController::construct().startOperation();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public ClassDescription caption()
{
ClassDescription ret;
ret = super();
ret = "SchedulerTransCleanup";
return ret;
}
}
3)CleanupSchedulerService
class CleanupSchedulerService extends SysOperationServiceBase
{
BatchHeader batchHeader;
SysOperationServiceController controller;
PaymentTable paymentsTable; //customTable
CleanupTaskContract taskContract = new CleanupTaskContract();
Counter paymRecIDs;
RefRecId batchInheritedRecId;
Counter totalRecords;
public void addTask(List PaymentTableRecIdsList, str caption = '')
{
// Check if the list of payment record IDs is empty
if (PaymentTableRecIdsList.elements() <= 0)
{
return;
}
ttsbegin;
controller = CleanupTaskController::construct();
taskContract = controller.getDataContractObject();
taskContract.parmRecIds(PaymentTableRecIdsList);
batchHeader.addRuntimeTask(controller,batchInheritedRecId);
ttsCommit;
Info(strFmt("%1-%2", caption, PaymentTableRecIdsList.elements()));
totalRecords += BASOFARECONRetailPaymentTableRecIdsList.elements();
}
public void process(CleanupSchedulerContract _contract)
{
Integer numOfTask,numOfDays,numOfRecords = 0;
TransDateTime transactionDate;
TransDate currentDate;
// List to hold paymentTable record IDs
List recIdsList = new List(Types::Int64);
numOfTask = _contract.parmNumOfTask();
numOfDays = _contract.parmNumOfDays();
currentDate = DateTimeUtil::getSystemDate(DateTimeUtil::getUserPreferredTimeZone());
transactionDate = DateTimeUtil::newDateTime((currentDate-numOfDays),85399);
// Retrieve payment records based on the provided condition
while select RecId from paymentsTable
where paymentsTable.CreatedDateTime < transactionDate
{
recIdsList.addEnd(paymentsTable.RecId);
}
ListIterator recIdsItr = new ListIterator(recIdsList);
numOfRecords = recIdsList.elements();
info(strFmt("%1",numOfRecords ));
if (this.isExecutingInBatch())
{
batchHeader = this.getCurrentBatchHeader();
}
else
{
batchHeader = BatchHeader::construct();
batchHeader.parmCaption("SchedulerTransCleanup");
}
batchInheritedRecId = batchHeader.parmBatchHeaderId();
if (numOfRecords > 0)
{
int recordsPerTask = numOfRecords / numOfTask;
int remainingRecords = numOfRecords - (recordsPerTask * numOfTask);// Calculate remaining records
int taskIndex = 1;
while (taskIndex <= numOfTask)
{
// List to hold record IDs for each task
List taskRecIdsList = new List(Types::Int64);
// Add records to the taskRecIdsList for each task
for (int i = 0; i < recordsPerTask && recIdsItr.more(); i++)
{
taskRecIdsList.addEnd(recIdsItr.value());
recIdsItr.next();
}
// If there are remaining records and more records in the iterator, add one record to the taskRecIdsList
if (remainingRecords > 0 && recIdsItr.more())
{
taskRecIdsList.addEnd(recIdsItr.value());
recIdsItr.next();
remainingRecords--;
}
this.addTask(taskRecIdsList, strFmt("Task %1", taskIndex));
taskIndex++;
}
}
if (batchHeader != null)
{
batchHeader.save();
}
}
}
4)CleanupTaskContract
[DataContractAttribute]
class CleanupTaskContract
{
List recIds;
[DataMemberAttribute('PaymentTableRecIdsList'),
AifCollectionTypeAttribute('_recIds', Types::Int64),
SysOperationControlVisibilityAttribute(false)]
public List parmRecIds(List _recIds = recIds)
{
recIds = _recIds;
return recIds;
}
}
5)CleanupTaskController
class CleanupTaskController extends SysOperationServiceController
{
public static SysOperationController construct()
{
SysOperationController controller = new CleanupTaskController(
classStr(CleanupTaskService),
methodStr(CleanupTaskService, process));
return controller;
}
public static void main(Args _args)
{
CleanupTaskController::construct().startOperation();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public ClassDescription caption()
{
ClassDescription ret;
ret = super();
ret = "SchedulerCleanupTask";
return ret;
}
}
6)CleanupTaskService
class CleanupTaskService extends SysOperationServiceBase
{
public void process(CleanupTaskContract _contract)
{
PaymentTable paymentsTable;//customTable
// Retrieve the RecIds from the contract
List recIds = _contract.parmRecIds();
// Create a ListIterator to iterate over the RecIds
ListIterator itr = new ListIterator(recIds);
try
{
while (itr.more())// Iterate through each RecId in the list
{
int64 recId = itr.value();
ttsbegin;
select forupdate paymentsTable
where paymentsTable.RecId == recId;
//select firstonly paymentsTable
// where paymentsTable.RecId == recId;
if (paymentsTable)// Check if a record was found
{
paymentsTable.delete();
}
ttscommit;
itr.next();// Move to the next RecId in the list
}
}
catch
{
Error("CatchErrorForPayment");
}
}
}
Create a Action Menu Item
Properties : Object = CleanupSchedulerController.
ObjectType = class.
Comments
Post a Comment