지금은 전체 작업의 레코드, 이미 처리 된 배치 수 및 처리 된 레코드 수를 추적하기 위해 어플리케이션 변수를 사용합니다.
<cfif not structKeyExists(application,"batchNumber") or application.batchNumber
eq 0 or application.batchNumber eq "">
<cfset application.batchNumber = 0>
<cfset application.recordsToDo = 0>
<cfset application.recordsDone = 0>
<cfset application.recordsDoneErrors = 0>
</cfif>
그 후, 나는 쿼리에서 모든 레코드를 설정하고 우리가 필요로하는 쿼리에서 레코드를 결정 : 작업의 시작에서 , 나는이 모든 그래서 같은 변수를 시작 코드의 조각을 가지고 현재 일괄 처리에서 처리합니다. 일괄 처리의 레코드 양은 전체 레코드 크기와 최대 큐 크기에 의해 결정됩니다. 이렇게하면 각 배치는 대기열의 약 절반 이상 차지하지 않습니다. 이렇게하면 작업이 다른 작업이나 작업을 방해하지 않으며 초기 요청이 시간 초과되지 않습니다.
<cfset application.recordsToSync = qryRecords.recordcount>
<cfif not structKeyExists(application,"recordsPerBatch") or application.recordsPerBatch eq "" or application.recordsPerBatch eq 0>
<cfset application.recordsPerBatch = ceiling(application.recordsToDo/(ceiling(application.recordsToDo/gatewayService.getMaxQueueSize())+1))>
</cfif>
<cfset startRow = (application.recordsPerBatch*application.batchNumber)+1>
<cfset endRow = startRow + application.recordsPerBatch-1>
<cfif endRow gt application.recordsToDo>
<cfset endRow = application.recordsToDo>
</cfif>
그런 다음 게이트웨이 이벤트를 시작하기 위해 from/to 루프를 사용하여 쿼리를 반복합니다. 큐가 가득 차서 레코드가 손실되지 않도록 가디언을 지켰습니다.
<cfloop from="#startRow#" to="#endRow#" index="i">
<cfset guardianCount = 0>
<!--- load all values from the record into a struct --->
<cfset stRecordData = structNew()>
<cfloop list="#qryRecords.columnlist#" index="columnlabel">
<cfset stRecordData[columnlabel] = trim(qryRecords[columnlabel][i])>
</cfloop>
<cfset eventData = structNew()>
<cfset eventData.stData = stRecordData>
<cfset eventData.action = "bigJob">
<cfloop condition="#gatewayService.getQueueSize()# GTE #gatewayService.getMaxQueueSize()#">
<cfset guardianCount = guardianCount++>
</cfloop>
<cfset SendGatewayMessage("eventGateway",eventData)>
</cfloop>
레코드가 완료 될 때마다 수행 할 레코드 수와 레코드 수를 확인하는 기능이 있습니다. 그들이 동일 할 때, 나는 끝난다. 그렇지 않으면 새로운 배치를 시작해야 할 수도 있습니다. 완료되었는지 확인하는 것은 cflock이지만 실제 이벤트 게시는 수행되지 않습니다. 왜냐하면 게시 한 이벤트가 자물쇠 내부에서 사용하는 변수를 읽을 수 없으면 교착 상태가 발생할 수 있기 때문입니다.
다른 사람에게 유용하거나 다른 누군가에게 더 나은 아이디어가 있기를 바랍니다.
<cflock timeout="30" name="jobResult">
<cfset application.recordsDone++>
<cfif application.recordsDone eq application.recordsToDo>
<!--- We are done. Set all the application variables we used back to zero, so they do not get in the way when we start the job again --->
<cfset application.batchNumber = 0>
<cfset application.recordsToDo = 0>
<cfset application.recordsDone = 0>
<cfset application.recordsPerBatch = 0>
<cfset application.recordsDoneErrors = 0>
<cfset application.JobStarted = 0>
<!--- If the number of records we have done is the same as the number of records in a batch times the current batchnumber plus one, we are done with the batch. --->
<cfelseif application.recordsDone eq application.recordsPerBatch*(application.batchNumber+1)
and application.recordsDone neq application.recordsToDo>
<cfset application.batchNumber++>
<cfset doEventAnnounce = true>
</cfif>
</cflock>
<cfif doEventAnnounce>
<!--- Fire off the event that starts the job. All the info it needs is in the applicationscope. --->
<cfhttp url="#URURLHERE#/index.cfm" method="post">
<cfhttpparam type="url" name="event" value="startBigJob">
</cfhttp>
</cfif>
나는 처리중인 데이터의 양을 줄이는 방법을 모색합니다. –
@DanBracuk 물론 그것은 최적 일 것입니다. 그러나 처리 할 데이터의 양은 실제로 협상 할 수 없습니다 ... 나는 그것을자를려고 할 수 있지만 가능한 한 짧은 요청으로 가능한 많은 레코드를 프로세스로 처리하려고합니다. – Sander
정말로'gatewayService'를 바꿀 수 없다면, 여기서 할 수있는 일은별로 없습니다. 당신은' '로 바꿀 수 있었지만 그 차이는 상당 할 것이라고 생각합니다. –