From b39f3b7d5080ee4f196c5a72c4119e2c75c32c5b Mon Sep 17 00:00:00 2001
From: Sagar Sane
Date: Tue, 5 Apr 2016 16:40:11 -0600
Subject: [PATCH] Issue #6 : Adds feature that provides a way to delete
JcrJobRepository that is older than X hours from "now"
* New API added : POST /grabbit/jobrepository/clean --data hours=X
* All JobInstances, JobExecutions, StepExecutions and ExecutionContexts that either FAILED or COMPLETED X hours from "now", i.e., when the API was called -- will be deleted
---
.../CleanJobRepositoryResource.groovy | 44 +++++++
.../grabbit/resources/ContentResource.groovy | 16 +--
.../resources/GrabbitResourceProvider.groovy | 3 +
.../resources/TransactionResource.groovy | 18 +--
.../GrabbitExecutionContextDao.groovy | 40 ++++++
.../repository/GrabbitJobExecution.groovy | 2 +-
.../repository/GrabbitJobExecutionDao.groovy | 39 ++++++
.../repository/GrabbitJobInstanceDao.groovy | 34 ++++++
.../repository/GrabbitStepExecutionDao.groovy | 33 +++++
...y => JcrGrabbitExecutionContextDao.groovy} | 65 ++++++++--
...roovy => JcrGrabbitJobExecutionDao.groovy} | 52 +++++++-
...groovy => JcrGrabbitJobInstanceDao.groovy} | 29 ++++-
...oovy => JcrGrabbitStepExecutionDao.groovy} | 36 +++++-
.../JcrJobRepositoryFactoryBean.groovy | 24 ++--
.../services/CleanJobRepository.groovy | 28 +++++
.../impl/DefaultCleanJobRepository.groovy | 115 ++++++++++++++++++
.../GrabbitCleanJobRepositoryServlet.groovy | 60 +++++++++
.../spring/client-batch-job-context.xml | 2 +-
... JcrGrabbitExecutionContextDaoSpec.groovy} | 41 +++++--
...y => JcrGrabbitJobExecutionDaoSpec.groovy} | 71 +++++++----
...vy => JcrGrabbitJobInstanceDaoSpec.groovy} | 77 ++++++++----
... => JcrGrabbitStepExecutionDaoSpec.groovy} | 39 +++---
...rabbitCleanJobRepositoryServletSpec.groovy | 62 ++++++++++
23 files changed, 800 insertions(+), 130 deletions(-)
create mode 100644 grabbit/src/main/groovy/com/twcable/grabbit/resources/CleanJobRepositoryResource.groovy
create mode 100644 grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitExecutionContextDao.groovy
create mode 100644 grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitJobExecutionDao.groovy
create mode 100644 grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitJobInstanceDao.groovy
create mode 100644 grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitStepExecutionDao.groovy
rename grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/{JcrExecutionContextDao.groovy => JcrGrabbitExecutionContextDao.groovy} (80%)
rename grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/{JcrJobExecutionDao.groovy => JcrGrabbitJobExecutionDao.groovy} (86%)
rename grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/{JcrJobInstanceDao.groovy => JcrGrabbitJobInstanceDao.groovy} (89%)
rename grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/{JcrStepExecutionDao.groovy => JcrGrabbitStepExecutionDao.groovy} (87%)
create mode 100644 grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/services/CleanJobRepository.groovy
create mode 100644 grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/services/impl/DefaultCleanJobRepository.groovy
create mode 100644 grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/servlets/GrabbitCleanJobRepositoryServlet.groovy
rename grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/{JcrExecutionContextDaoSpec.groovy => JcrGrabbitExecutionContextDaoSpec.groovy} (69%)
rename grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/{JcrJobExecutionDaoSpec.groovy => JcrGrabbitJobExecutionDaoSpec.groovy} (72%)
rename grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/{JcrJobInstanceDaoSpec.groovy => JcrGrabbitJobInstanceDaoSpec.groovy} (53%)
rename grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/{JcrStepExecutionDaoSpec.groovy => JcrGrabbitStepExecutionDaoSpec.groovy} (76%)
create mode 100644 grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/servlets/GrabbitCleanJobRepositoryServletSpec.groovy
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/resources/CleanJobRepositoryResource.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/resources/CleanJobRepositoryResource.groovy
new file mode 100644
index 0000000..95595ed
--- /dev/null
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/resources/CleanJobRepositoryResource.groovy
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2015 Time Warner Cable, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.twcable.grabbit.resources
+
+import groovy.transform.CompileStatic
+import org.apache.sling.api.resource.ResourceResolver
+import org.apache.sling.api.resource.SyntheticResource
+
+import javax.annotation.Nonnull
+
+/**
+ * A resource representing what needs to be deleted from Grabbit's JobRepository.
+ * provided by {@link GrabbitResourceProvider}.
+ * Queried from {@link com.twcable.grabbit.spring.batch.repository.servlets.GrabbitCleanJobRepositoryServlet}.
+ */
+@CompileStatic
+class CleanJobRepositoryResource extends SyntheticResource {
+
+ public static final String CLEAN_JOBREPOSITORY_RESOURCE_TYPE = "twcable:grabbit/jobrepository/clean"
+
+ CleanJobRepositoryResource(@Nonnull final ResourceResolver resourceResolver, @Nonnull final String resolutionPath) {
+ super(resourceResolver, resolutionPath, CLEAN_JOBREPOSITORY_RESOURCE_TYPE)
+ }
+
+
+ @Override
+ String getResourceType() {
+ return CLEAN_JOBREPOSITORY_RESOURCE_TYPE
+ }
+}
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/resources/ContentResource.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/resources/ContentResource.groovy
index 67d6366..fe855fa 100644
--- a/grabbit/src/main/groovy/com/twcable/grabbit/resources/ContentResource.groovy
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/resources/ContentResource.groovy
@@ -1,11 +1,3 @@
-package com.twcable.grabbit.resources
-
-import groovy.transform.CompileStatic
-import org.apache.sling.api.resource.ResourceResolver
-import org.apache.sling.api.resource.SyntheticResource
-
-import javax.annotation.Nonnull
-
/*
* Copyright 2015 Time Warner Cable, Inc.
*
@@ -22,6 +14,14 @@ import javax.annotation.Nonnull
* limitations under the License.
*/
+package com.twcable.grabbit.resources
+
+import groovy.transform.CompileStatic
+import org.apache.sling.api.resource.ResourceResolver
+import org.apache.sling.api.resource.SyntheticResource
+
+import javax.annotation.Nonnull
+
/**
* A resource representing some content to be streamed from a Grabbit instance.
* provided by {@link GrabbitResourceProvider}.
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/resources/GrabbitResourceProvider.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/resources/GrabbitResourceProvider.groovy
index 26c9aa3..e6f1d4e 100644
--- a/grabbit/src/main/groovy/com/twcable/grabbit/resources/GrabbitResourceProvider.groovy
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/resources/GrabbitResourceProvider.groovy
@@ -79,6 +79,9 @@ class GrabbitResourceProvider implements ResourceProvider {
case ~/^\/grabbit\/content(\/)?$/:
log.debug "Resolving ${path} to ContentResource"
return new ContentResource(resolver, path)
+ case ~/^\/grabbit\/jobrepository\/clean(\/)?$/:
+ log.debug "Resolving ${path} to CleanJobRepositoryResource"
+ return new CleanJobRepositoryResource(resolver, path)
default:
//Should provide a root resource for /grabbit, along with HATEOS style for this link, and other links. https://github.com/TWCable/grabbit/issues/22
return null
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/resources/TransactionResource.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/resources/TransactionResource.groovy
index 1be1404..ecf5923 100644
--- a/grabbit/src/main/groovy/com/twcable/grabbit/resources/TransactionResource.groovy
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/resources/TransactionResource.groovy
@@ -1,12 +1,3 @@
-package com.twcable.grabbit.resources
-
-import groovy.transform.CompileStatic
-import org.apache.sling.api.resource.ResourceResolver
-import org.apache.sling.api.resource.SyntheticResource
-
-import javax.annotation.Nonnull
-import java.util.regex.Matcher
-
/*
* Copyright 2015 Time Warner Cable, Inc.
*
@@ -23,6 +14,15 @@ import java.util.regex.Matcher
* limitations under the License.
*/
+package com.twcable.grabbit.resources
+
+import groovy.transform.CompileStatic
+import org.apache.sling.api.resource.ResourceResolver
+import org.apache.sling.api.resource.SyntheticResource
+
+import javax.annotation.Nonnull
+import java.util.regex.Matcher
+
/**
* {@link TransactionResource} represents a a logical group of jobs by configuration run.
*
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitExecutionContextDao.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitExecutionContextDao.groovy
new file mode 100644
index 0000000..9939e6e
--- /dev/null
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitExecutionContextDao.groovy
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2015 Time Warner Cable, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.twcable.grabbit.spring.batch.repository
+
+import org.springframework.batch.core.repository.dao.ExecutionContextDao
+import org.springframework.batch.item.ExecutionContext;
+
+
+/**
+ * Modified DAO Interface for persisting and retrieving {@link ExecutionContext}
+ * @see ExecutionContextDao for more details
+ */
+interface GrabbitExecutionContextDao extends ExecutionContextDao {
+
+ /**
+ * Returns job execution context paths by comparing "executionId" property on "executionContext/job/" with
+ * "executionId" property on JobExecutions for the @param jobExecutionResourcePaths
+ */
+ public Collection getJobExecutionContextPaths(Collection jobExecutionResourcePaths)
+
+ /**
+ * Returns step execution context paths by comparing "executionId" property on "executionContext/job/" with
+ * "id" property on StepExecutions for the @param stepExecutionResourcePaths
+ */
+ public Collection getStepExecutionContextPaths(Collection stepExecutionResourcePaths)
+}
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitJobExecution.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitJobExecution.groovy
index 927d0d9..c0fa820 100644
--- a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitJobExecution.groovy
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitJobExecution.groovy
@@ -30,7 +30,7 @@ import org.springframework.batch.core.JobExecution
* be grouped/referenced by their common transactionID.
*
*
- * @see {@link com.twcable.grabbit.spring.batch.repository.JcrJobExecutionDao} for a good handle on how we
+ * @see {@link JcrGrabbitJobExecutionDao} for a good handle on how we
* serve up this JobExecution during the Spring Batch lifecycle.
*/
@CompileStatic
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitJobExecutionDao.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitJobExecutionDao.groovy
new file mode 100644
index 0000000..349ed31
--- /dev/null
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitJobExecutionDao.groovy
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 Time Warner Cable, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.twcable.grabbit.spring.batch.repository
+
+import org.springframework.batch.core.BatchStatus
+import org.springframework.batch.core.JobExecution
+import org.springframework.batch.core.repository.dao.JobExecutionDao
+
+/**
+ * Modified DAO Interface for persisting and retrieving {@link JobExecution}
+ * @see JobExecutionDao for more details
+ */
+interface GrabbitJobExecutionDao extends JobExecutionDao{
+
+ /**
+ * Returns job execution paths for given BatchStatuses
+ */
+ public Collection getJobExecutions(Collection batchStatuses)
+
+ /**
+ * Returns job execution paths which ended @param hours ago from "Now"
+ */
+ public Collection getJobExecutions(int hours, Collection jobExecutionPaths)
+
+}
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitJobInstanceDao.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitJobInstanceDao.groovy
new file mode 100644
index 0000000..032044e
--- /dev/null
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitJobInstanceDao.groovy
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015 Time Warner Cable, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.twcable.grabbit.spring.batch.repository
+
+import org.springframework.batch.core.JobInstance
+import org.springframework.batch.core.repository.dao.JobInstanceDao
+
+/**
+ * Modified DAO Interface for persisting and retrieving {@link JobInstance}
+ * @see JobInstanceDao for more details
+ */
+interface GrabbitJobInstanceDao extends JobInstanceDao {
+
+ /**
+ * Returns job instance paths by comparing "id" property on "jobInstances" with
+ * "instanceId" property on JobExecutions for the @param jobExecutionResourcePaths
+ */
+ public Collection getJobInstancePaths(Collection jobExecutionResourcePaths)
+
+}
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitStepExecutionDao.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitStepExecutionDao.groovy
new file mode 100644
index 0000000..7a1d42d
--- /dev/null
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/GrabbitStepExecutionDao.groovy
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2015 Time Warner Cable, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.twcable.grabbit.spring.batch.repository
+
+import org.springframework.batch.core.StepExecution
+import org.springframework.batch.core.repository.dao.StepExecutionDao
+
+/**
+ * Modified DAO Interface for persisting and retrieving {@link StepExecution}
+ * @see StepExecutionDao for more details
+ */
+interface GrabbitStepExecutionDao extends StepExecutionDao {
+
+ /**
+ * Returns step execution paths by comparing "jobExecutionId" property on "stepExecutions with
+ * "executionId" property on JobExecutions for the @param jobExecutionResourcePaths
+ */
+ public Collection getStepExecutionPaths(Collection jobExecutionResourcePaths)
+}
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrExecutionContextDao.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitExecutionContextDao.groovy
similarity index 80%
rename from grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrExecutionContextDao.groovy
rename to grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitExecutionContextDao.groovy
index cd1116b..f12e06a 100644
--- a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrExecutionContextDao.groovy
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitExecutionContextDao.groovy
@@ -20,11 +20,8 @@ import com.twcable.grabbit.jcr.JcrUtil
import com.twcable.grabbit.util.CryptoUtil
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
-import org.apache.sling.api.resource.ModifiableValueMap
-import org.apache.sling.api.resource.Resource
-import org.apache.sling.api.resource.ResourceResolver
-import org.apache.sling.api.resource.ResourceResolverFactory
-import org.apache.sling.api.resource.ValueMap
+import org.apache.sling.api.SlingException
+import org.apache.sling.api.resource.*
import org.springframework.batch.core.JobExecution
import org.springframework.batch.core.StepExecution
import org.springframework.batch.core.repository.ExecutionContextSerializer
@@ -33,6 +30,7 @@ import org.springframework.batch.item.ExecutionContext
import javax.annotation.Nonnull
+import static JcrGrabbitStepExecutionDao.ID
import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED
import static org.apache.sling.api.resource.ResourceUtil.getOrCreateResource
@@ -42,7 +40,7 @@ import static org.apache.sling.api.resource.ResourceUtil.getOrCreateResource
*/
@CompileStatic
@Slf4j
-class JcrExecutionContextDao extends AbstractJcrDao implements ExecutionContextDao {
+class JcrGrabbitExecutionContextDao extends AbstractJcrDao implements GrabbitExecutionContextDao {
public static final String EXECUTION_CONTEXT_ROOT = "${ROOT_RESOURCE_NAME}/executionContexts"
public static final String JOB_EXECUTION_CONTEXT_ROOT = "${EXECUTION_CONTEXT_ROOT}/job"
@@ -55,7 +53,7 @@ class JcrExecutionContextDao extends AbstractJcrDao implements ExecutionContextD
private ExecutionContextSerializer contextSerializer
- JcrExecutionContextDao(
+ JcrGrabbitExecutionContextDao(
@Nonnull final ResourceResolverFactory rrf, @Nonnull final ExecutionContextSerializer serializer) {
this.resourceResolverFactory = rrf
this.contextSerializer = serializer
@@ -156,7 +154,7 @@ class JcrExecutionContextDao extends AbstractJcrDao implements ExecutionContextD
}
/**
- * Must be called when a new instance of JcrExecutionContextDao is created.
+ * Must be called when a new instance of JcrGrabbitExecutionContextDao is created.
* Ensures that {@link #STEP_EXECUTION_CONTEXT_ROOT} and {@link #JOB_EXECUTION_CONTEXT_ROOT} exist on initialization
*/
@Override
@@ -306,4 +304,55 @@ class JcrExecutionContextDao extends AbstractJcrDao implements ExecutionContextD
contextAsMap.each { key, value -> context.put(key, value) }
context
}
+
+ @Override
+ Collection getJobExecutionContextPaths(Collection jobExecutionResourcePaths) {
+ JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+ Collection jobExecutionContextPathsToRemove = []
+ jobExecutionResourcePaths.each { String jobExecutionResourcePath ->
+ Resource jobExecutionResource = resolver.getResource(jobExecutionResourcePath)
+ ValueMap props = jobExecutionResource.adaptTo(ValueMap)
+ Long jobExecutionId = props[JcrGrabbitJobExecutionDao.EXECUTION_ID] as Long
+ String query = "select * from [nt:unstructured] as s " +
+ "where ISDESCENDANTNODE(s,'${JOB_EXECUTION_CONTEXT_ROOT}') AND ( s.${EXECUTION_ID} = ${jobExecutionId})"
+ try {
+ List jobExecutionContextPaths = resolver.findResources(query, "JCR-SQL2").toList().collect { it.path }
+ jobExecutionContextPathsToRemove.addAll(jobExecutionContextPaths)
+ }
+ catch(SlingException | IllegalStateException e) {
+ log.error "Exception when executing Query: ${query}. \nException - ", e
+ }
+ }
+ //There are 2 versions of Resources returned back by findResources
+ //One for JcrNodeResource and one for SocialResourceWrapper
+ //Hence, duplicates need to be removed
+ return jobExecutionContextPathsToRemove.unique() as Collection
+ }
+ }
+
+ @Override
+ Collection getStepExecutionContextPaths(Collection stepExecutionResourcePaths) {
+ JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+ Collection stepExecutionContextPathsToRemove = []
+ stepExecutionResourcePaths.each { String stepExecutionResourcePath ->
+ Resource stepExecutionResource = resolver.getResource(stepExecutionResourcePath)
+ ValueMap props = stepExecutionResource.adaptTo(ValueMap)
+ Long stepExecutionId = props[ID] as Long
+ String query = "select * from [nt:unstructured] as s " +
+ "where ISDESCENDANTNODE(s,'${STEP_EXECUTION_CONTEXT_ROOT}') AND ( s.${EXECUTION_ID} = ${stepExecutionId})"
+ try {
+ List stepExecutionContextPaths = resolver.findResources(query, "JCR-SQL2").toList().collect { it.path }
+ stepExecutionContextPathsToRemove.addAll(stepExecutionContextPaths)
+ } catch (SlingException | IllegalStateException e) {
+ log.error "Exception when executing Query: ${query}. \nException - ", e
+ }
+ }
+ //There are 2 versions of Resources returned back by findResources
+ //One for JcrNodeResource and one for SocialResourceWrapper
+ //Hence, duplicates need to be removed
+ return stepExecutionContextPathsToRemove.unique() as Collection
+
+ }
+
+ }
}
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobExecutionDao.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobExecutionDao.groovy
similarity index 86%
rename from grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobExecutionDao.groovy
rename to grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobExecutionDao.groovy
index 3ca201f..a0d4be8 100644
--- a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobExecutionDao.groovy
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobExecutionDao.groovy
@@ -29,7 +29,7 @@ import org.springframework.batch.core.repository.dao.JobExecutionDao
import javax.annotation.Nonnull
-import static JcrJobInstanceDao.JOB_INSTANCE_ROOT
+import static JcrGrabbitJobInstanceDao.JOB_INSTANCE_ROOT
import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED
import static org.apache.sling.api.resource.ResourceUtil.getOrCreateResource
@@ -39,7 +39,7 @@ import static org.apache.sling.api.resource.ResourceUtil.getOrCreateResource
*/
@CompileStatic
@Slf4j
-class JcrJobExecutionDao extends AbstractJcrDao implements JobExecutionDao {
+class JcrGrabbitJobExecutionDao extends AbstractJcrDao implements GrabbitJobExecutionDao {
public static final String JOB_EXECUTION_ROOT = "${ROOT_RESOURCE_NAME}/jobExecutions"
@@ -59,7 +59,7 @@ class JcrJobExecutionDao extends AbstractJcrDao implements JobExecutionDao {
private ResourceResolverFactory resourceResolverFactory
- JcrJobExecutionDao(ResourceResolverFactory rrf) {
+ JcrGrabbitJobExecutionDao(ResourceResolverFactory rrf) {
this.resourceResolverFactory = rrf
}
@@ -184,7 +184,7 @@ class JcrJobExecutionDao extends AbstractJcrDao implements JobExecutionDao {
}
/**
- * Returns JobParameters using the given instanceId from {@link JcrJobInstanceDao#JOB_INSTANCE_ROOT}
+ * Returns JobParameters using the given instanceId from {@link JcrGrabbitJobInstanceDao#JOB_INSTANCE_ROOT}
*
* @see #mapJobExecution(ResourceResolver, ValueMap, JobInstance)
*/
@@ -193,7 +193,7 @@ class JcrJobExecutionDao extends AbstractJcrDao implements JobExecutionDao {
final instanceResource = resolver.getResource(jobInstanceRoot, "${instanceId}")
final properties = instanceResource.adaptTo(ValueMap)
- final params = properties[JcrJobInstanceDao.PARAMETERS] as String[]
+ final params = properties[JcrGrabbitJobInstanceDao.PARAMETERS] as String[]
final paramsMap = params?.collectEntries { String entry ->
final pair = entry.split("=")
@@ -365,7 +365,7 @@ class JcrJobExecutionDao extends AbstractJcrDao implements JobExecutionDao {
}
/**
- * Must be called when a new instance of JcrJobExecutionDao is created.
+ * Must be called when a new instance of JcrGrabbitJobExecutionDao is created.
* Ensures that {@link #JOB_EXECUTION_ROOT} exists on initialization
*/
@Override
@@ -381,4 +381,44 @@ class JcrJobExecutionDao extends AbstractJcrDao implements JobExecutionDao {
}
}
}
+
+ @Override
+ Collection getJobExecutions(Collection batchStatuses) {
+ String statusPredicate = batchStatuses.collect { "s.status = '${it}'" }.join(' or ')
+ JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+ String jobExecutionsQuery = "select * from [nt:unstructured] as s where " +
+ "ISDESCENDANTNODE(s,'${JOB_EXECUTION_ROOT}') AND ( ${statusPredicate} )"
+ Collection jobExecutions = resolver.findResources(jobExecutionsQuery, "JCR-SQL2")
+ .toList()
+ .collect { it.path }
+ .unique() as Collection
+ log.debug "JobExecutions: $jobExecutions, size: ${jobExecutions.size()}"
+ return jobExecutions
+ }
+
+ }
+
+ @Override
+ Collection getJobExecutions(int hours, Collection jobExecutions) {
+ JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+ //Create a Date object that is "hours" ago from now
+ Calendar olderThanHours = Calendar.getInstance()
+ log.info "Current time: ${olderThanHours.time}"
+ olderThanHours.add(Calendar.HOUR, -hours)
+ log.info "Hours ${hours} .. OlderThanHours Time: ${olderThanHours.time}"
+
+ //Find all resources that are older than "olderThanHours" Date
+ Collection olderResourcePaths = jobExecutions.findAll { String resourcePath ->
+ Resource resource = resolver.getResource(resourcePath)
+ ValueMap props = resource.adaptTo(ValueMap)
+ String dateInIsoString = props[END_TIME] as String
+ Date endTimeDate = DateUtil.getDateFromISOString(dateInIsoString)
+ olderThanHours.time.compareTo(endTimeDate) > 0
+ } as Collection
+ log.debug "JobExecutionsOlder than ${hours} hours: $olderResourcePaths , length: ${olderResourcePaths.size()}"
+ return olderResourcePaths
+
+ }
+
+ }
}
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobInstanceDao.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobInstanceDao.groovy
similarity index 89%
rename from grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobInstanceDao.groovy
rename to grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobInstanceDao.groovy
index e5f5ca5..97c49a4 100644
--- a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobInstanceDao.groovy
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobInstanceDao.groovy
@@ -41,7 +41,7 @@ import static org.apache.sling.api.resource.ResourceUtil.getOrCreateResource
*/
@CompileStatic
@Slf4j
-class JcrJobInstanceDao extends AbstractJcrDao implements JobInstanceDao {
+class JcrGrabbitJobInstanceDao extends AbstractJcrDao implements GrabbitJobInstanceDao {
public static final String JOB_INSTANCE_ROOT = "${ROOT_RESOURCE_NAME}/jobInstances"
@@ -54,7 +54,7 @@ class JcrJobInstanceDao extends AbstractJcrDao implements JobInstanceDao {
private ResourceResolverFactory resourceResolverFactory
- JcrJobInstanceDao(ResourceResolverFactory rrf) {
+ JcrGrabbitJobInstanceDao(ResourceResolverFactory rrf) {
this.resourceResolverFactory = rrf
}
@@ -235,7 +235,7 @@ class JcrJobInstanceDao extends AbstractJcrDao implements JobInstanceDao {
}
/**
- * Must be called when a new instance of JcrJobInstanceDao is created.
+ * Must be called when a new instance of JcrGrabbitJobInstanceDao is created.
* Ensures that {@link #JOB_INSTANCE_ROOT} exists on initialization
*/
@Override
@@ -262,4 +262,27 @@ class JcrJobInstanceDao extends AbstractJcrDao implements JobInstanceDao {
nextId
}
+
+ @Override
+ Collection getJobInstancePaths(Collection jobExecutionResourcePaths) {
+ JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+ Collection jobInstancesToRemove = []
+ jobExecutionResourcePaths.each { String jobExecutionResourcePath ->
+ Resource jobExecutionResource = resolver.getResource(jobExecutionResourcePath)
+ ValueMap props = jobExecutionResource.adaptTo(ValueMap)
+ Long instanceId = props[JcrGrabbitJobExecutionDao.INSTANCE_ID] as Long
+ String jobInstanceToRemoveResourcePath = "${JOB_INSTANCE_ROOT}/${instanceId}".toString()
+ Resource jobInstanceToRemove = resolver.getResource(jobInstanceToRemoveResourcePath)
+ if (!jobInstanceToRemove) {
+ log.info "JobInstance with id : ${instanceId} is already removed"
+ } else {
+ jobInstancesToRemove.add(jobInstanceToRemoveResourcePath)
+ }
+ }
+ return jobInstancesToRemove
+
+
+ }
+
+ }
}
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrStepExecutionDao.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitStepExecutionDao.groovy
similarity index 87%
rename from grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrStepExecutionDao.groovy
rename to grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitStepExecutionDao.groovy
index 0ecd769..d8b56e7 100644
--- a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrStepExecutionDao.groovy
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitStepExecutionDao.groovy
@@ -21,6 +21,7 @@ import com.twcable.grabbit.jcr.JcrUtil
import com.twcable.grabbit.util.CryptoUtil
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
+import org.apache.sling.api.SlingException
import org.apache.sling.api.resource.ModifiableValueMap
import org.apache.sling.api.resource.Resource
import org.apache.sling.api.resource.ResourceResolver
@@ -34,6 +35,7 @@ import org.springframework.batch.core.repository.dao.StepExecutionDao
import javax.annotation.Nonnull
+import static JcrGrabbitJobExecutionDao.EXECUTION_ID
import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED
import static org.apache.sling.api.resource.ResourceUtil.getOrCreateResource
@@ -43,7 +45,7 @@ import static org.apache.sling.api.resource.ResourceUtil.getOrCreateResource
*/
@CompileStatic
@Slf4j
-public class JcrStepExecutionDao extends AbstractJcrDao implements StepExecutionDao {
+public class JcrGrabbitStepExecutionDao extends AbstractJcrDao implements GrabbitStepExecutionDao {
public static final String STEP_EXECUTION_ROOT = "${ROOT_RESOURCE_NAME}/stepExecutions"
@@ -69,7 +71,7 @@ public class JcrStepExecutionDao extends AbstractJcrDao implements StepExecution
private ResourceResolverFactory resourceResolverFactory
- JcrStepExecutionDao(ResourceResolverFactory rrf) {
+ JcrGrabbitStepExecutionDao(ResourceResolverFactory rrf) {
this.resourceResolverFactory = rrf
}
@@ -279,7 +281,7 @@ public class JcrStepExecutionDao extends AbstractJcrDao implements StepExecution
}
/**
- * Must be called when a new instance of JcrStepExecutionDao is created.
+ * Must be called when a new instance of JcrGrabbitStepExecutionDao is created.
* Ensures that {@link #STEP_EXECUTION_ROOT} exists on initialization
*/
@Override
@@ -290,10 +292,34 @@ public class JcrStepExecutionDao extends AbstractJcrDao implements StepExecution
//create the Root Resource
throw new IllegalStateException("Cannot get or create RootResource for : ${STEP_EXECUTION_ROOT}")
}
- if (!getOrCreateResource(resolver, JcrJobExecutionDao.JOB_EXECUTION_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)) {
+ if (!getOrCreateResource(resolver, JcrGrabbitJobExecutionDao.JOB_EXECUTION_ROOT, NT_UNSTRUCTURED, NT_UNSTRUCTURED, true)) {
//create the Root Resource
- throw new IllegalStateException("Cannot get or create RootResource for : ${JcrJobExecutionDao.JOB_EXECUTION_ROOT}")
+ throw new IllegalStateException("Cannot get or create RootResource for : ${JcrGrabbitJobExecutionDao.JOB_EXECUTION_ROOT}")
}
}
}
+
+ @Override
+ Collection getStepExecutionPaths(Collection jobExecutionResourcePaths) {
+ JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+ Collection stepExecutionsToRemove = []
+ jobExecutionResourcePaths.each { String jobExecutionResourcePath ->
+ Resource jobExecutionResource = resolver.getResource(jobExecutionResourcePath)
+ ValueMap props = jobExecutionResource.adaptTo(ValueMap)
+ Long jobExecutionId = props[EXECUTION_ID] as Long
+ String query = "select * from [nt:unstructured] as s " +
+ "where ISDESCENDANTNODE(s,'${STEP_EXECUTION_ROOT}') AND ( s.${JOB_EXECUTION_ID} = ${jobExecutionId})"
+ try {
+ List stepExecutions = resolver.findResources(query, "JCR-SQL2").toList().collect { it.path }
+ stepExecutionsToRemove.addAll(stepExecutions)
+ } catch (SlingException | IllegalStateException e) {
+ log.error "Exception when executing Query: ${query}. \nException - ", e
+ }
+ }
+ //There are 2 versions of Resources returned back by findResources
+ //One for JcrNodeResource and one for SocialResourceWrapper
+ //Hence, duplicates need to be removed
+ return stepExecutionsToRemove.unique() as Collection
+ }
+ }
}
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobRepositoryFactoryBean.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobRepositoryFactoryBean.groovy
index 4f7f743..fada65d 100644
--- a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobRepositoryFactoryBean.groovy
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobRepositoryFactoryBean.groovy
@@ -39,13 +39,13 @@ import org.springframework.transaction.PlatformTransactionManager
@Slf4j
class JcrJobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean {
- private JcrJobExecutionDao jobExecutionDao
+ private JcrGrabbitJobExecutionDao jobExecutionDao
- private JcrJobInstanceDao jobInstanceDao
+ private JcrGrabbitJobInstanceDao jobInstanceDao
- private JcrStepExecutionDao stepExecutionDao
+ private JcrGrabbitStepExecutionDao stepExecutionDao
- private JcrExecutionContextDao executionContextDao
+ private JcrGrabbitExecutionContextDao executionContextDao
private ResourceResolverFactory resourceResolverFactory
@@ -76,22 +76,22 @@ class JcrJobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean {
}
- JobExecutionDao getJobExecutionDao() {
+ GrabbitJobExecutionDao getJobExecutionDao() {
jobExecutionDao
}
- JobInstanceDao getJobInstanceDao() {
+ GrabbitJobInstanceDao getJobInstanceDao() {
jobInstanceDao
}
- StepExecutionDao getStepExecutionDao() {
+ GrabbitStepExecutionDao getStepExecutionDao() {
stepExecutionDao
}
- ExecutionContextDao getExecutionContextDao() {
+ GrabbitExecutionContextDao getExecutionContextDao() {
executionContextDao
}
@@ -99,7 +99,7 @@ class JcrJobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean {
@Override
protected JobInstanceDao createJobInstanceDao() throws Exception {
log.info "Create JobInstance"
- jobInstanceDao = new JcrJobInstanceDao(resourceResolverFactory)
+ jobInstanceDao = new JcrGrabbitJobInstanceDao(resourceResolverFactory)
jobInstanceDao.ensureRootResource()
jobInstanceDao
}
@@ -108,7 +108,7 @@ class JcrJobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean {
@Override
protected JobExecutionDao createJobExecutionDao() throws Exception {
log.info "Create JobExecution"
- jobExecutionDao = new JcrJobExecutionDao(resourceResolverFactory)
+ jobExecutionDao = new JcrGrabbitJobExecutionDao(resourceResolverFactory)
jobExecutionDao.ensureRootResource()
jobExecutionDao
}
@@ -117,7 +117,7 @@ class JcrJobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean {
@Override
protected StepExecutionDao createStepExecutionDao() throws Exception {
log.info "Create StepExecution"
- stepExecutionDao = new JcrStepExecutionDao(resourceResolverFactory)
+ stepExecutionDao = new JcrGrabbitStepExecutionDao(resourceResolverFactory)
stepExecutionDao.ensureRootResource()
stepExecutionDao
}
@@ -126,7 +126,7 @@ class JcrJobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean {
@Override
protected ExecutionContextDao createExecutionContextDao() throws Exception {
log.info "Create ExecutionContext"
- executionContextDao = new JcrExecutionContextDao(resourceResolverFactory, executionContextSerializer)
+ executionContextDao = new JcrGrabbitExecutionContextDao(resourceResolverFactory, executionContextSerializer)
executionContextDao.ensureRootResource()
executionContextDao
}
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/services/CleanJobRepository.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/services/CleanJobRepository.groovy
new file mode 100644
index 0000000..859c83b
--- /dev/null
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/services/CleanJobRepository.groovy
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2015 Time Warner Cable, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.twcable.grabbit.spring.batch.repository.services
+
+interface CleanJobRepository {
+
+ /**
+ * This API is used to clean Grabbit's JCR Job Repository. It removes all job executions and all associated
+ * job instances etc. that are @param hours older than NOW (time when this API is called)
+ * @return Collection of JobExecutionIds that were removed
+ */
+ public Collection cleanJobRepository(int hours)
+
+}
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/services/impl/DefaultCleanJobRepository.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/services/impl/DefaultCleanJobRepository.groovy
new file mode 100644
index 0000000..1de38ae
--- /dev/null
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/services/impl/DefaultCleanJobRepository.groovy
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2015 Time Warner Cable, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.twcable.grabbit.spring.batch.repository.services.impl
+
+import com.twcable.grabbit.jcr.JcrUtil
+import com.twcable.grabbit.spring.batch.repository.JcrJobRepositoryFactoryBean
+import com.twcable.grabbit.spring.batch.repository.services.CleanJobRepository
+import groovy.transform.CompileStatic
+import groovy.util.logging.Slf4j
+import org.apache.felix.scr.annotations.Activate
+import org.apache.felix.scr.annotations.Component
+import org.apache.felix.scr.annotations.Reference
+import org.apache.felix.scr.annotations.Service
+import org.apache.sling.api.resource.PersistenceException
+import org.apache.sling.api.resource.Resource
+import org.apache.sling.api.resource.ResourceResolver
+import org.apache.sling.api.resource.ResourceResolverFactory
+import org.springframework.batch.core.BatchStatus
+import org.springframework.context.ConfigurableApplicationContext
+
+@Slf4j
+@CompileStatic
+@Component(label = "Grabbit Clean Job Repository Service", description = "Grabbit Clean Job Repository Service", immediate = true, metatype = true, enabled = true)
+@Service(CleanJobRepository)
+@SuppressWarnings(['GroovyUnusedDeclaration', 'GrMethodMayBeStatic'])
+class DefaultCleanJobRepository implements CleanJobRepository {
+
+ @Reference
+ ResourceResolverFactory resourceResolverFactory
+
+ @Reference
+ ConfigurableApplicationContext configurableApplicationContext
+
+ @Activate
+ void activate() {
+ log.info "CleanJobRepository Service activated"
+ }
+
+ @Override
+ Collection cleanJobRepository(int hours) {
+ JcrJobRepositoryFactoryBean jobRepositoryFactoryBean = configurableApplicationContext.getBean(JcrJobRepositoryFactoryBean)
+
+ if(!jobRepositoryFactoryBean) {
+ log.error "Cannot get an instance of JcrJobRepositoryFactoryBean. Will not clean up Grabbit Jcr Job Repository"
+ return []
+ }
+
+ Collection jobExecutionPaths = jobRepositoryFactoryBean.jobExecutionDao.getJobExecutions([BatchStatus.FAILED, BatchStatus.COMPLETED])
+ Collection olderThanHoursJobExecutions = jobRepositoryFactoryBean.jobExecutionDao.getJobExecutions(hours, jobExecutionPaths)
+ Collection jobInstancesToRemove = jobRepositoryFactoryBean.jobInstanceDao.getJobInstancePaths(olderThanHoursJobExecutions)
+ Collection stepExecutionsToRemove = jobRepositoryFactoryBean.stepExecutionDao.getStepExecutionPaths(olderThanHoursJobExecutions)
+ Collection jobExecutionContextsToRemove = jobRepositoryFactoryBean.executionContextDao.getJobExecutionContextPaths(olderThanHoursJobExecutions)
+ Collection stepExecutionContextsToRemove = jobRepositoryFactoryBean.executionContextDao.getStepExecutionContextPaths(stepExecutionsToRemove)
+
+ JcrUtil.manageResourceResolver(resourceResolverFactory) { ResourceResolver resolver ->
+
+ log.debug "jobInstancesToRemove: $jobInstancesToRemove, size: ${jobInstancesToRemove.size()}"
+ log.debug "jobExecutionsToRemove: $olderThanHoursJobExecutions, size: ${olderThanHoursJobExecutions.size()}"
+ log.debug "stepExecutionsToRemove: $stepExecutionsToRemove, size: ${stepExecutionsToRemove.size()}"
+ log.debug "jobExecutionContextsToRemove: $jobExecutionContextsToRemove, size: ${jobExecutionContextsToRemove.size()}"
+ log.debug "stepExecutionContextsToResource: $stepExecutionContextsToRemove, size: ${stepExecutionContextsToRemove.size()}"
+
+ log.info "Removing ${jobInstancesToRemove.size()} JobInstances"
+ removeResources(jobInstancesToRemove, resolver)
+ log.info "Removing ${olderThanHoursJobExecutions.size()} JobExecutions"
+ removeResources(olderThanHoursJobExecutions, resolver)
+ log.info "Removing ${stepExecutionsToRemove.size()} StepExecutions"
+ removeResources(stepExecutionsToRemove, resolver)
+ log.info "Removing ${jobExecutionContextsToRemove.size()} JobExecutionContexts"
+ removeResources(jobExecutionContextsToRemove, resolver)
+ log.info "Removing ${stepExecutionContextsToRemove.size()} StepExecutionContexts"
+ removeResources(stepExecutionContextsToRemove, resolver)
+ }
+
+ Collection removedJobExecutionIds = olderThanHoursJobExecutions.collect { it.split("/").last() }
+ return removedJobExecutionIds
+ }
+
+ private void removeResources(Collection resourcePathsToRemove, ResourceResolver resolver) {
+ try {
+ resourcePathsToRemove.each {
+ Resource resourceToDelete = resolver.getResource(it)
+ if(resourceToDelete) {
+ resolver.delete(resourceToDelete)
+ log.debug "Resource ${it} will be removed"
+ }
+ else {
+ log.warn "Resource ${it} doesn't exist. So cannot remove it"
+ }
+ }
+ resolver.commit()
+ resolver.refresh()
+ }
+ catch(PersistenceException e) {
+ log.error "Exception while removing resources :", e
+ if(resolver.hasChanges()) {
+ resolver.revert()
+ }
+ }
+ }
+}
diff --git a/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/servlets/GrabbitCleanJobRepositoryServlet.groovy b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/servlets/GrabbitCleanJobRepositoryServlet.groovy
new file mode 100644
index 0000000..53f515e
--- /dev/null
+++ b/grabbit/src/main/groovy/com/twcable/grabbit/spring/batch/repository/servlets/GrabbitCleanJobRepositoryServlet.groovy
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2015 Time Warner Cable, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.twcable.grabbit.spring.batch.repository.servlets
+
+import com.twcable.grabbit.spring.batch.repository.services.CleanJobRepository
+import groovy.transform.CompileStatic
+import groovy.util.logging.Slf4j
+import org.apache.felix.scr.annotations.Reference
+import org.apache.felix.scr.annotations.sling.SlingServlet
+import org.apache.sling.api.SlingHttpServletRequest
+import org.apache.sling.api.SlingHttpServletResponse
+import org.apache.sling.api.servlets.SlingAllMethodsServlet
+import org.apache.sling.api.servlets.SlingSafeMethodsServlet
+
+import javax.annotation.Nonnull
+import javax.servlet.http.HttpServletResponse
+
+/**
+ * This servlet is used for cleanup of the Grabbit's JobRepository stored under /var/grabbit/job.
+ *
+ * It is a handler for the {@link com.twcable.grabbit.resources.CleanJobRepositoryResource} resource.
+ */
+@Slf4j
+@CompileStatic
+@SlingServlet(methods = ['POST'], resourceTypes = ['twcable:grabbit/jobrepository/clean'])
+class GrabbitCleanJobRepositoryServlet extends SlingAllMethodsServlet {
+
+ @Reference
+ CleanJobRepository cleanJobRepository
+
+ @Override
+ protected void doPost( @Nonnull SlingHttpServletRequest request, @Nonnull SlingHttpServletResponse response) {
+ String hoursParam = request.getParameter("hours") ?: ""
+ if(!hoursParam.isInteger()) {
+ log.warn "Parameter 'hours' must be an integer"
+ response.status = HttpServletResponse.SC_BAD_REQUEST
+ response.writer.write("Parameter 'hours' must be an integer")
+ return
+ }
+ int hours = hoursParam.toInteger()
+ Collection removedJobExecutions = cleanJobRepository.cleanJobRepository(hours)
+ response.status = HttpServletResponse.SC_OK
+ response.writer.write ("JobExecutions and the corresponding JobInstances, StepExecutions and ExecutionContexts " +
+ "were removed. JobExecutionsIds that were removed: ${removedJobExecutions}")
+ }
+}
diff --git a/grabbit/src/main/resources/META-INF/spring/client-batch-job-context.xml b/grabbit/src/main/resources/META-INF/spring/client-batch-job-context.xml
index 5656c54..fbf72d0 100644
--- a/grabbit/src/main/resources/META-INF/spring/client-batch-job-context.xml
+++ b/grabbit/src/main/resources/META-INF/spring/client-batch-job-context.xml
@@ -69,7 +69,7 @@
-
+
diff --git a/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrExecutionContextDaoSpec.groovy b/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitExecutionContextDaoSpec.groovy
similarity index 69%
rename from grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrExecutionContextDaoSpec.groovy
rename to grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitExecutionContextDaoSpec.groovy
index f9dff2b..e0a9bdb 100644
--- a/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrExecutionContextDaoSpec.groovy
+++ b/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitExecutionContextDaoSpec.groovy
@@ -21,18 +21,17 @@ import org.apache.sling.api.resource.ResourceResolverFactory
import org.springframework.batch.core.JobExecution
import org.springframework.batch.core.StepExecution
import org.springframework.batch.core.repository.ExecutionContextSerializer
+import spock.lang.Ignore
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Subject
-import static com.twcable.grabbit.spring.batch.repository.JcrExecutionContextDao.EXECUTION_CONTEXT
-import static com.twcable.grabbit.spring.batch.repository.JcrExecutionContextDao.EXECUTION_ID
-import static com.twcable.jackalope.JCRBuilder.node
-import static com.twcable.jackalope.JCRBuilder.property
-import static com.twcable.jackalope.JCRBuilder.repository
+import static JcrGrabbitExecutionContextDao.EXECUTION_CONTEXT
+import static JcrGrabbitExecutionContextDao.EXECUTION_ID
+import static com.twcable.jackalope.JCRBuilder.*
-@Subject(JcrExecutionContextDao)
-class JcrExecutionContextDaoSpec extends Specification {
+@Subject(JcrGrabbitExecutionContextDao)
+class JcrGrabbitExecutionContextDaoSpec extends Specification {
@Shared
ResourceResolverFactory mockFactory
@@ -70,9 +69,9 @@ class JcrExecutionContextDaoSpec extends Specification {
}
- def "EnsureRootResource for JcrExecutionContextDao"() {
+ def "EnsureRootResource for JcrGrabbitExecutionContextDao"() {
when:
- final executionContextDao = new JcrExecutionContextDao(mockFactory, stubSerializer)
+ final executionContextDao = new JcrGrabbitExecutionContextDao(mockFactory, stubSerializer)
executionContextDao.ensureRootResource()
then:
@@ -83,7 +82,7 @@ class JcrExecutionContextDaoSpec extends Specification {
def "GetExecutionContext for a JobExecution"() {
when:
- final executionContextDao = new JcrExecutionContextDao(mockFactory, stubSerializer)
+ final executionContextDao = new JcrGrabbitExecutionContextDao(mockFactory, stubSerializer)
final result = executionContextDao.getExecutionContext(new JobExecution(1))
then:
@@ -94,7 +93,7 @@ class JcrExecutionContextDaoSpec extends Specification {
def "GetExecutionContext for a StepExecution"() {
when:
- final executionContextDao = new JcrExecutionContextDao(mockFactory, stubSerializer)
+ final executionContextDao = new JcrGrabbitExecutionContextDao(mockFactory, stubSerializer)
final result = executionContextDao.getExecutionContext(new StepExecution("someStep", new JobExecution(1), 1))
then:
@@ -102,6 +101,26 @@ class JcrExecutionContextDaoSpec extends Specification {
result.containsKey("deserialized")
}
+ @Ignore('TODO: Implement this test when Jackalope implements resourceResolver.findResources() API')
+ def "GetJobExecutionContextPaths for JobExecutionPaths"() {
+ when:
+ final executionContextDao = new JcrGrabbitExecutionContextDao(mockFactory, stubSerializer)
+ final result = executionContextDao.getJobExecutionContextPaths([])
+
+ then:
+ 1 == 1
+ }
+
+ @Ignore('TODO: Implement this test when Jackalope implements resourceResolver.findResources() API')
+ def "GetStepExecutionContextPaths for JobExecutionPaths"() {
+ when:
+ final executionContextDao = new JcrGrabbitExecutionContextDao(mockFactory, stubSerializer)
+ final result = executionContextDao.getStepExecutionContextPaths([])
+
+ then:
+ 1 == 1
+
+ }
class StubExecutionContextSerializer implements ExecutionContextSerializer {
diff --git a/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobExecutionDaoSpec.groovy b/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobExecutionDaoSpec.groovy
similarity index 72%
rename from grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobExecutionDaoSpec.groovy
rename to grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobExecutionDaoSpec.groovy
index 9095368..3751ccc 100644
--- a/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobExecutionDaoSpec.groovy
+++ b/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobExecutionDaoSpec.groovy
@@ -25,22 +25,11 @@ import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Subject
-import static com.twcable.grabbit.spring.batch.repository.JcrJobExecutionDao.CREATE_TIME
-import static com.twcable.grabbit.spring.batch.repository.JcrJobExecutionDao.END_TIME
-import static com.twcable.grabbit.spring.batch.repository.JcrJobExecutionDao.EXECUTION_ID
-import static com.twcable.grabbit.spring.batch.repository.JcrJobExecutionDao.EXIT_CODE
-import static com.twcable.grabbit.spring.batch.repository.JcrJobExecutionDao.EXIT_MESSAGE
-import static com.twcable.grabbit.spring.batch.repository.JcrJobExecutionDao.INSTANCE_ID
-import static com.twcable.grabbit.spring.batch.repository.JcrJobExecutionDao.JOB_NAME
-import static com.twcable.grabbit.spring.batch.repository.JcrJobExecutionDao.STATUS
-import static com.twcable.grabbit.spring.batch.repository.JcrJobExecutionDao.TRANSACTION_ID
-import static com.twcable.grabbit.spring.batch.repository.JcrJobExecutionDao.VERSION
-import static com.twcable.jackalope.JCRBuilder.node
-import static com.twcable.jackalope.JCRBuilder.property
-import static com.twcable.jackalope.JCRBuilder.repository
-
-@Subject(JcrJobExecutionDao)
-class JcrJobExecutionDaoSpec extends Specification {
+import static JcrGrabbitJobExecutionDao.*
+import static com.twcable.jackalope.JCRBuilder.*
+
+@Subject(JcrGrabbitJobExecutionDao)
+class JcrGrabbitJobExecutionDaoSpec extends Specification {
@Shared
ResourceResolverFactory mockFactory
@@ -86,7 +75,20 @@ class JcrJobExecutionDaoSpec extends Specification {
property(CREATE_TIME, "2014-12-29T16:59:18.669-05:00"),
property(END_TIME, "NULL"),
property(JOB_NAME, "someOtherJob")
- )
+ ),
+ node("4",
+ property(INSTANCE_ID, 1),
+ property(EXECUTION_ID, 1),
+ property(TRANSACTION_ID, 5),
+ property(STATUS, "FAILED"),
+ property(EXIT_CODE, "code"),
+ property(EXIT_MESSAGE, "message"),
+ property(CREATE_TIME, "2014-12-27T16:59:18.669-05:00"),
+ property(END_TIME, "2015-12-29T16:59:18.669-05:00"),
+ property(JOB_NAME, "someJob"),
+ property(VERSION, 1)
+
+ ),
),
node("jobInstances",
node("1"))
@@ -98,9 +100,9 @@ class JcrJobExecutionDaoSpec extends Specification {
}
- def "EnsureRootResource for JcrJobExecutionDao"() {
+ def "EnsureRootResource for JcrGrabbitJobExecutionDao"() {
when:
- final jobExecutionDao = new JcrJobExecutionDao(mockFactory)
+ final jobExecutionDao = new JcrGrabbitJobExecutionDao(mockFactory)
jobExecutionDao.ensureRootResource()
then:
@@ -111,19 +113,19 @@ class JcrJobExecutionDaoSpec extends Specification {
def "FindJobExecutions for given JobInstance"() {
when:
- final jobExecutionDao = new JcrJobExecutionDao(mockFactory)
+ final jobExecutionDao = new JcrGrabbitJobExecutionDao(mockFactory)
final result = jobExecutionDao.findJobExecutions(new JobInstance(1, "someJob"))
then:
result != null
- result.size() == 2
+ result.size() == 3
result.first().id == 2
}
def "GetLastJobExecution for given JobInstance"() {
when:
- final jobExecutionDao = new JcrJobExecutionDao(mockFactory)
+ final jobExecutionDao = new JcrGrabbitJobExecutionDao(mockFactory)
final result = jobExecutionDao.getLastJobExecution(new JobInstance(1, "someJob"))
then:
@@ -135,7 +137,7 @@ class JcrJobExecutionDaoSpec extends Specification {
def "FindRunningJobExecutions for given Job Name"() {
when:
- final jobExecutionDao = new JcrJobExecutionDao(mockFactory)
+ final jobExecutionDao = new JcrGrabbitJobExecutionDao(mockFactory)
final result = jobExecutionDao.findRunningJobExecutions("someJob")
then:
@@ -147,7 +149,7 @@ class JcrJobExecutionDaoSpec extends Specification {
def "GetJobExecution for given JobExecution id"() {
when:
- final jobExecutionDao = new JcrJobExecutionDao(mockFactory)
+ final jobExecutionDao = new JcrGrabbitJobExecutionDao(mockFactory)
final result = jobExecutionDao.getJobExecution(2)
then:
@@ -160,7 +162,7 @@ class JcrJobExecutionDaoSpec extends Specification {
def "Get a transaction ID for a given job execution"() {
when:
- final jobExecutionDao = new JcrJobExecutionDao(mockFactory)
+ final jobExecutionDao = new JcrGrabbitJobExecutionDao(mockFactory)
final jobExecution = jobExecutionDao.getJobExecution(2) as GrabbitJobExecution
then:
@@ -170,7 +172,7 @@ class JcrJobExecutionDaoSpec extends Specification {
def "SynchronizeStatus for a given JobExecution"() {
when:
- final jobExecutionDao = new JcrJobExecutionDao(mockFactory)
+ final jobExecutionDao = new JcrGrabbitJobExecutionDao(mockFactory)
def unsyncronized = new JobExecution(1)
unsyncronized.setVersion(0)
unsyncronized.setStatus(BatchStatus.STARTED)
@@ -178,6 +180,21 @@ class JcrJobExecutionDaoSpec extends Specification {
then:
unsyncronized.version == 1
- unsyncronized.status == BatchStatus.COMPLETED
+ unsyncronized.status == BatchStatus.FAILED
+ }
+
+ def "GetJobExecutions for hours and jobExecutions"() {
+ when:
+ final jobExecutionDao = new JcrGrabbitJobExecutionDao(mockFactory)
+ final jobExecutionPaths = [
+ "/var/grabbit/job/repository/jobExecutions/1",
+ "/var/grabbit/job/repository/jobExecutions/4"
+ ]
+ final result = jobExecutionDao.getJobExecutions(1, jobExecutionPaths)
+
+ then:
+ result != null
+ result.size() == 2
}
+
}
diff --git a/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobInstanceDaoSpec.groovy b/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobInstanceDaoSpec.groovy
similarity index 53%
rename from grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobInstanceDaoSpec.groovy
rename to grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobInstanceDaoSpec.groovy
index f7e5b9a..48e91fe 100644
--- a/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrJobInstanceDaoSpec.groovy
+++ b/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitJobInstanceDaoSpec.groovy
@@ -18,25 +18,17 @@ package com.twcable.grabbit.spring.batch.repository
import com.twcable.jackalope.impl.sling.SimpleResourceResolverFactory
import org.apache.sling.api.resource.ResourceResolverFactory
-import org.springframework.batch.core.DefaultJobKeyGenerator
-import org.springframework.batch.core.JobExecution
-import org.springframework.batch.core.JobInstance
-import org.springframework.batch.core.JobParameter
-import org.springframework.batch.core.JobParameters
+import org.springframework.batch.core.*
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Subject
import spock.lang.Unroll
-import static com.twcable.grabbit.spring.batch.repository.JcrJobInstanceDao.INSTANCE_ID
-import static com.twcable.grabbit.spring.batch.repository.JcrJobInstanceDao.KEY
-import static com.twcable.grabbit.spring.batch.repository.JcrJobInstanceDao.NAME
-import static com.twcable.jackalope.JCRBuilder.node
-import static com.twcable.jackalope.JCRBuilder.property
-import static com.twcable.jackalope.JCRBuilder.repository
+import static JcrGrabbitJobInstanceDao.*
+import static com.twcable.jackalope.JCRBuilder.*
-@Subject(JcrJobInstanceDao)
-class JcrJobInstanceDaoSpec extends Specification {
+@Subject(JcrGrabbitJobInstanceDao)
+class JcrGrabbitJobInstanceDaoSpec extends Specification {
@Shared
ResourceResolverFactory mockFactory
@@ -66,7 +58,34 @@ class JcrJobInstanceDaoSpec extends Specification {
property(INSTANCE_ID, 4),
property(NAME, "someOtherJob"),
)
- )
+ ),
+ node("jobExecutions",
+ node("1",
+ property(JcrGrabbitJobExecutionDao.INSTANCE_ID, 1),
+ property(JcrGrabbitJobExecutionDao.EXECUTION_ID, 1),
+ property(JcrGrabbitJobExecutionDao.TRANSACTION_ID, 5),
+ property(JcrGrabbitJobExecutionDao.STATUS, "COMPLETED"),
+ property(JcrGrabbitJobExecutionDao.EXIT_CODE, "code"),
+ property(JcrGrabbitJobExecutionDao.EXIT_MESSAGE, "message"),
+ property(JcrGrabbitJobExecutionDao.CREATE_TIME, "2014-12-27T16:59:18.669-05:00"),
+ property(JcrGrabbitJobExecutionDao.END_TIME, "2014-12-29T16:59:18.669-05:00"),
+ property(JcrGrabbitJobExecutionDao.JOB_NAME, "someJob"),
+ property(JcrGrabbitJobExecutionDao.VERSION, 1)
+ ),
+ node("4",
+ property(JcrGrabbitJobExecutionDao.INSTANCE_ID, 4),
+ property(JcrGrabbitJobExecutionDao.EXECUTION_ID, 1),
+ property(JcrGrabbitJobExecutionDao.TRANSACTION_ID, 5),
+ property(JcrGrabbitJobExecutionDao.STATUS, "FAILED"),
+ property(JcrGrabbitJobExecutionDao.EXIT_CODE, "code"),
+ property(JcrGrabbitJobExecutionDao.EXIT_MESSAGE, "message"),
+ property(JcrGrabbitJobExecutionDao.CREATE_TIME, "2014-12-27T16:59:18.669-05:00"),
+ property(JcrGrabbitJobExecutionDao.END_TIME, "2015-12-29T16:59:18.669-05:00"),
+ property(JcrGrabbitJobExecutionDao.JOB_NAME, "someJob"),
+ property(JcrGrabbitJobExecutionDao.VERSION, 1)
+
+ ),
+ ),
)
)
)
@@ -75,9 +94,9 @@ class JcrJobInstanceDaoSpec extends Specification {
}
- def "EnsureRootResource for JcrJobInstanceDao"() {
+ def "EnsureRootResource for JcrGrabbitJobInstanceDao"() {
when:
- final jobInstanceDao = new JcrJobInstanceDao(mockFactory)
+ final jobInstanceDao = new JcrGrabbitJobInstanceDao(mockFactory)
jobInstanceDao.ensureRootResource()
then:
@@ -87,7 +106,7 @@ class JcrJobInstanceDaoSpec extends Specification {
def "GetJobInstance for given JobExecution"() {
when:
- final jobInstanceDao = new JcrJobInstanceDao(mockFactory)
+ final jobInstanceDao = new JcrGrabbitJobInstanceDao(mockFactory)
final result = jobInstanceDao.getJobInstance(new JobExecution(new JobInstance(1, "someJob"), new JobParameters()))
then:
@@ -99,7 +118,7 @@ class JcrJobInstanceDaoSpec extends Specification {
def "GetJobInstance for given InstanceId"() {
when:
- final jobInstanceDao = new JcrJobInstanceDao(mockFactory)
+ final jobInstanceDao = new JcrGrabbitJobInstanceDao(mockFactory)
final result = jobInstanceDao.getJobInstance(1)
then:
@@ -111,7 +130,7 @@ class JcrJobInstanceDaoSpec extends Specification {
def "GetJobInstance for given Job Name and Job parameters"() {
when:
- final jobInstanceDao = new JcrJobInstanceDao(mockFactory)
+ final jobInstanceDao = new JcrGrabbitJobInstanceDao(mockFactory)
final result = jobInstanceDao.getJobInstance("someJob", new JobParameters([someKey: new JobParameter("someValue")]))
then:
@@ -123,7 +142,7 @@ class JcrJobInstanceDaoSpec extends Specification {
@Unroll
def "GetJobInstances for given Job Name #jobName, a start index and count"() {
when:
- final jobInstanceDao = new JcrJobInstanceDao(mockFactory)
+ final jobInstanceDao = new JcrGrabbitJobInstanceDao(mockFactory)
final result = jobInstanceDao.getJobInstances(jobName, 0, Integer.MAX_VALUE)
then:
@@ -140,10 +159,26 @@ class JcrJobInstanceDaoSpec extends Specification {
def "GetJobNames for Job Instances"() {
when:
- final jobInstanceDao = new JcrJobInstanceDao(mockFactory)
+ final jobInstanceDao = new JcrGrabbitJobInstanceDao(mockFactory)
final result = jobInstanceDao.jobNames
then:
result.containsAll(["someJob", "someOtherJob"])
}
+
+ def "GetJobInstancePaths for jobExecutions"() {
+ when:
+ final jobInstanceDao = new JcrGrabbitJobInstanceDao(mockFactory)
+ final jobExecutionPaths = [
+ "/var/grabbit/job/repository/jobExecutions/1",
+ "/var/grabbit/job/repository/jobExecutions/4"
+ ]
+
+ final result = jobInstanceDao.getJobInstancePaths(jobExecutionPaths)
+
+ then:
+ result != null
+ result.size() == 2
+ }
+
}
diff --git a/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrStepExecutionDaoSpec.groovy b/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitStepExecutionDaoSpec.groovy
similarity index 76%
rename from grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrStepExecutionDaoSpec.groovy
rename to grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitStepExecutionDaoSpec.groovy
index 03d12da..76cef19 100644
--- a/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrStepExecutionDaoSpec.groovy
+++ b/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/JcrGrabbitStepExecutionDaoSpec.groovy
@@ -22,21 +22,13 @@ import org.springframework.batch.core.BatchStatus
import org.springframework.batch.core.JobExecution
import org.springframework.batch.core.JobInstance
import org.springframework.batch.core.JobParameters
-import spock.lang.Shared
-import spock.lang.Specification
-import spock.lang.Subject
-import spock.lang.Unroll
-
-import static com.twcable.grabbit.spring.batch.repository.JcrStepExecutionDao.ID
-import static com.twcable.grabbit.spring.batch.repository.JcrStepExecutionDao.JOB_EXECUTION_ID
-import static com.twcable.grabbit.spring.batch.repository.JcrStepExecutionDao.NAME
-import static com.twcable.grabbit.spring.batch.repository.JcrStepExecutionDao.STATUS
-import static com.twcable.jackalope.JCRBuilder.node
-import static com.twcable.jackalope.JCRBuilder.property
-import static com.twcable.jackalope.JCRBuilder.repository
-
-@Subject(JcrStepExecutionDao)
-class JcrStepExecutionDaoSpec extends Specification {
+import spock.lang.*
+
+import static JcrGrabbitStepExecutionDao.*
+import static com.twcable.jackalope.JCRBuilder.*
+
+@Subject(JcrGrabbitStepExecutionDao)
+class JcrGrabbitStepExecutionDaoSpec extends Specification {
@Shared
ResourceResolverFactory mockFactory
@@ -71,9 +63,9 @@ class JcrStepExecutionDaoSpec extends Specification {
}
- def "EnsureRootResource for JcrStepExecutionDao"() {
+ def "EnsureRootResource for JcrGrabbitStepExecutionDao"() {
when:
- final stepExecutionDao = new JcrStepExecutionDao(mockFactory)
+ final stepExecutionDao = new JcrGrabbitStepExecutionDao(mockFactory)
stepExecutionDao.ensureRootResource()
then:
@@ -84,7 +76,7 @@ class JcrStepExecutionDaoSpec extends Specification {
@Unroll
def "GetStepExecution for a given JobExecution and a StepExecution id #stepExecutionId"() {
when:
- final stepExecutionDao = new JcrStepExecutionDao(mockFactory)
+ final stepExecutionDao = new JcrGrabbitStepExecutionDao(mockFactory)
final result = stepExecutionDao.getStepExecution(new JobExecution(new JobInstance(1, "someJob"), jobExecutionId, new JobParameters()), stepExecutionId)
then:
@@ -98,4 +90,15 @@ class JcrStepExecutionDaoSpec extends Specification {
5 | 3 | BatchStatus.STARTED
}
+
+ @Ignore('TODO: Implement this test when Jackalope implements resourceResolver.findResources() API')
+ def "GetStepExecutionPaths for jobResourcePaths"() {
+ when:
+ final stepExecutionDao = new JcrGrabbitStepExecutionDao(mockFactory)
+ final result = stepExecutionDao.getStepExecutionPaths([])
+
+ then:
+ 1 == 1
+
+ }
}
diff --git a/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/servlets/GrabbitCleanJobRepositoryServletSpec.groovy b/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/servlets/GrabbitCleanJobRepositoryServletSpec.groovy
new file mode 100644
index 0000000..1342757
--- /dev/null
+++ b/grabbit/src/test/groovy/com/twcable/grabbit/spring/batch/repository/servlets/GrabbitCleanJobRepositoryServletSpec.groovy
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2015 Time Warner Cable, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.twcable.grabbit.spring.batch.repository.servlets
+
+import com.twcable.grabbit.spring.batch.repository.services.CleanJobRepository
+import org.apache.sling.api.SlingHttpServletRequest
+import org.apache.sling.api.SlingHttpServletResponse
+import spock.lang.Specification
+import spock.lang.Subject
+
+@Subject(GrabbitCleanJobRepositoryServlet)
+class GrabbitCleanJobRepositoryServletSpec extends Specification {
+
+ def "Servlet handles the case when hours parameter is not passed"() {
+ given:
+ def servlet = new GrabbitCleanJobRepositoryServlet(cleanJobRepository: Mock(CleanJobRepository))
+ def request = Mock(SlingHttpServletRequest)
+ request.getParameter("hours") >> null
+ def response = Mock(SlingHttpServletResponse)
+ def writer = new StringWriter()
+ response.getWriter() >> new PrintWriter(writer)
+ when:
+ servlet.doPost(request, response)
+
+ then:
+ writer != null
+ writer.toString() == "Parameter 'hours' must be an integer"
+ }
+
+ def "Servlet handles the case when hours parameter is correctly passed"() {
+ given:
+ def clientJobRepository = Mock(CleanJobRepository)
+ clientJobRepository.cleanJobRepository(_) >> (["id1","id2","id3"] as List)
+ def servlet = new GrabbitCleanJobRepositoryServlet(cleanJobRepository: clientJobRepository)
+ def request = Mock(SlingHttpServletRequest)
+ request.getParameter("hours") >> 5
+ def response = Mock(SlingHttpServletResponse)
+ def writer = new StringWriter()
+ response.getWriter() >> new PrintWriter(writer)
+ when:
+ servlet.doPost(request, response)
+
+ then:
+ writer != null
+ writer.toString().contains("JobExecutionsIds that were removed")
+ writer.toString().contains("[id1, id2, id3]")
+ }
+}