Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import org.apache.commons.lang3.StringUtils
import org.springframework.http.HttpStatus

import gorm.tools.job.SyncJobState

import yakworks.rest.client.OkHttpRestTrait
import grails.testing.mixin.integration.Integration
import okhttp3.Response
Expand Down Expand Up @@ -210,4 +209,16 @@ class BulkRestApiSpec extends Specification implements OkHttpRestTrait {
inserted == 1
updated == 3
}

void "bulk export"() {
when:
Response resp = get("/api/rally/org/bulk?q=*&parallel=false&async=false")
Map body = bodyToMap(resp)

then:
body
body.id
body.state == SyncJobState.Queued.name()
body.sourceId
}
}
1 change: 1 addition & 0 deletions examples/testify/grails-app/conf/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ app:
resources:
rootLocation: "${project.rootProjectDir}/examples/resources"
tempDir: "./build/rootLocation/tempDir"
attachments.location: 'attachments'

yakworks:
gorm:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package gorm.tools.repository

import gorm.tools.job.SyncJobArgs
import gorm.tools.job.SyncJobContext
import gorm.tools.job.SyncJobState
import gorm.tools.repository.bulk.BulkExportService
import grails.gorm.transactions.Rollback
import grails.testing.mixin.integration.Integration
import spock.lang.Specification
import yakworks.rally.attachment.model.Attachment
import yakworks.rally.job.SyncJob
import yakworks.rally.orgs.model.Org
import yakworks.testing.gorm.integration.DomainIntTest

import javax.inject.Inject

import static yakworks.json.groovy.JsonEngine.parseJson

@Integration
@Rollback
class BulkExportServiceIntegrationSpec extends Specification implements DomainIntTest {

@Inject BulkExportService bulkExportService

void "test scheduleBulkExportJob"() {
setup:
SyncJobArgs args = setupJobArgs("type": "Company", "inactive":false)

when:
Long jobId = bulkExportService.scheduleBulkExportJob(args)

then:
noExceptionThrown()
jobId

when:
SyncJob job = SyncJob.get(jobId)

then:
job
job.state == SyncJobState.Queued

when:
String payload = job.payloadToString()

then:
payload

when:
def payloadJson = parseJson(payload)

then:
payloadJson
payloadJson.q == ["type": "Company", "inactive":false]
payloadJson.includes == ["id", "num", "name"]
}

void "test buildJobContext and args "() {
setup:
Long jobId = bulkExportService.scheduleBulkExportJob(setupJobArgs("type": "Company", "inactive":false))

when:
SyncJobContext context = bulkExportService.buildJobContext(jobId)
SyncJobArgs args = context.args

then:
noExceptionThrown()
context
context.syncJobService
args
args.queryArgs
args.queryArgs.criteriaMap == ["type": "Company", "inactive":false]
args.includes == ["id", "num", "name"]
args.saveDataAsFile
args.async
args.parallel
}

void "run export"() {
setup:
Long jobId = bulkExportService.scheduleBulkExportJob(setupJobArgs("inactive": false))

when:
bulkExportService.runBulkExportJob(jobId, false)
flushAndClear()

then:
noExceptionThrown()

when:
SyncJob job = SyncJob.repo.getWithTrx(jobId)


then:
job
job.ok
job.dataId //should have attachment
Attachment.repo.exists(job.dataId)

when:
String jsonStr = job.dataToString()
def json = parseJson(jsonStr)

then:
json
json instanceof List
json.size() == Org.findAllWhere(inactive:false).size() / 10
json[0].data instanceof List

when:
List data = json[0].data

then:
//syncjob data format
/*
* {
* data: [
* {id:1, name:"x", num:"y"},
* {id:2, name:"x", num:"y"},
* ]
* }
*/
data.size() == 10 //
data[0].id == 1
data[0].num
data[0].name


cleanup:
if(job && job.dataId) {
Attachment.repo.removeById(job.dataId)
}
}

SyncJobArgs setupJobArgs(Map q) {
SyncJobArgs syncJobArgs = SyncJobArgs.withParams(q:q)
syncJobArgs.includes = ["id", "num", "name"]
syncJobArgs.jobState = SyncJobState.Queued
syncJobArgs.entityClass = Org
return syncJobArgs
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package yakworks.rest.gorm.controller

import java.net.http.HttpRequest
import java.nio.charset.StandardCharsets
import java.util.concurrent.TimeoutException
import java.util.function.Function
import javax.persistence.LockTimeoutException
import javax.servlet.http.HttpServletRequest
Expand Down Expand Up @@ -70,6 +69,7 @@ trait CrudApiController<D> extends RestApiController {
@Autowired
private Function<Class, CrudApi> crudApiFactory


// @Autowired
// Closure<CrudApi> crudApiClosure

Expand Down Expand Up @@ -244,6 +244,19 @@ trait CrudApiController<D> extends RestApiController {
}
}

@Action
def bulkExport() {
try {
Map qParams = getParamsMap()
SyncJobEntity job = getCrudApi().bulkExport(qParams, requestToSourceId(request))
respondWith(job, [status: MULTI_STATUS])
} catch (Exception | AssertionError e) {
respondWith(
BulkExceptionHandler.of(getEntityClass(), problemHandler).handleBulkOperationException(request, e)
)
}
}

void bulkProcess(DataOp dataOp) {
List dataList = bodyAsList() as List<Map>
Map qParams = getParamsMap()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,19 @@ class RepoApiMappingsService {
.httpMethod('PUT').action('bulkUpdate').suffix('/bulk')
.urlMappingBuilder(builderDelegate).build()

//bulk export FIXME @SUD, not working, doesnt get picked up
SimpleUrlMappingBuilder.of(contextPath, nspace, ctrlName)
.httpMethod('GET').action('bulkExport').suffix('/bulk')
.urlMappingBuilder(builderDelegate).build()


//allow POST any action added to the controller
// /api/nspace/controller/$action
// post "/$action(.$format)?"(controller: cName)
SimpleUrlMappingBuilder.of(contextPath, nspace, ctrlName)
.httpMethod('POST').suffix('/(*)').matchParams(['action'])
.urlMappingBuilder(builderDelegate).build()

}
}
}
Expand Down
6 changes: 6 additions & 0 deletions gorm-tools/src/main/groovy/gorm/tools/job/SyncJobArgs.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ class SyncJobArgs {
//reference back to the SyncJobContext built from these args.
SyncJobContext context

/**
* SyncJobState to use when creating new job.
* Default is Running. But Queued can be used for jobs which are scheduled to run later, eg BulkExport.
*/
SyncJobState jobState = SyncJobState.Running

/** helper to return true if op=DataOp.add */
boolean isCreate(){
op == DataOp.add
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class SyncJobContext {

Map data = [
id: args.jobId, source: args.source, sourceId: args.sourceId,
state: SyncJobState.Running, payload: payload
state: args.jobState, payload: payload
] as Map<String,Object>

if(payload instanceof Collection && payload.size() > 1000) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ trait GormRepo<D> implements ApiCrudRepo<D>, BulkableRepo<D>, ResolvableTypeProv

/**
* load without hydrating
*
*x
* @param id required, the id to get
* @return the retrieved entity
*/
Expand Down
Loading