You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by to...@apache.org on 2015/02/04 17:15:49 UTC
incubator-usergrid git commit: Updated PersistenceException to be a
subclass of RuntimeException
Repository: incubator-usergrid
Updated Branches:
refs/heads/two-dot-o-import c9742c0ef -> ee88ea5ba
Updated PersistenceException to be a subclass of RuntimeException
Updated tests to reflect changes
Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/ee88ea5b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/ee88ea5b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/ee88ea5b
Branch: refs/heads/two-dot-o-import
Commit: ee88ea5bad6df3afe8942f35cc8b6b42eb084976
Parents: c9742c0
Author: Todd Nine <tn...@apigee.com>
Authored: Wed Feb 4 09:15:47 2015 -0700
Committer: Todd Nine <tn...@apigee.com>
Committed: Wed Feb 4 09:15:47 2015 -0700
----------------------------------------------------------------------
.../entities/FailedEntityImport.java | 68 ++++++++++++++++
.../exceptions/PersistenceException.java | 2 +-
.../importer/FileImportStatistics.java | 67 ++++++++++-----
.../importer/FileImportStatisticsTest.java | 85 +++++++++++++++++++-
4 files changed, 200 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ee88ea5b/stack/core/src/main/java/org/apache/usergrid/persistence/entities/FailedEntityImport.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/persistence/entities/FailedEntityImport.java b/stack/core/src/main/java/org/apache/usergrid/persistence/entities/FailedEntityImport.java
new file mode 100644
index 0000000..1d8adf6
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/persistence/entities/FailedEntityImport.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.usergrid.persistence.entities;
+
+
+import java.util.UUID;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+import org.apache.usergrid.persistence.TypedEntity;
+import org.apache.usergrid.persistence.annotations.EntityProperty;
+
+
+/**
+ * Contains state information for an entity within a FileImport the failed to load
+ */
+@XmlRootElement
+public class FailedEntityImport extends TypedEntity {
+
+
+ /**
+ * Error message
+ */
+ @EntityProperty
+ protected String errorMessage;
+
+
+ public FailedEntityImport() {
+ }
+
+
+ /**
+ * Get error message for the job
+ * @return
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * Sets the error message for the job
+ * @param errorMessage error message
+ */
+ public void setErrorMessage(final String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ee88ea5b/stack/core/src/main/java/org/apache/usergrid/persistence/exceptions/PersistenceException.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/persistence/exceptions/PersistenceException.java b/stack/core/src/main/java/org/apache/usergrid/persistence/exceptions/PersistenceException.java
index 604a976..a6f1cf4 100644
--- a/stack/core/src/main/java/org/apache/usergrid/persistence/exceptions/PersistenceException.java
+++ b/stack/core/src/main/java/org/apache/usergrid/persistence/exceptions/PersistenceException.java
@@ -17,7 +17,7 @@
package org.apache.usergrid.persistence.exceptions;
-public class PersistenceException extends Exception {
+public class PersistenceException extends RuntimeException {
/**
*
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ee88ea5b/stack/services/src/main/java/org/apache/usergrid/management/importer/FileImportStatistics.java
----------------------------------------------------------------------
diff --git a/stack/services/src/main/java/org/apache/usergrid/management/importer/FileImportStatistics.java b/stack/services/src/main/java/org/apache/usergrid/management/importer/FileImportStatistics.java
index e455c29..739c709 100644
--- a/stack/services/src/main/java/org/apache/usergrid/management/importer/FileImportStatistics.java
+++ b/stack/services/src/main/java/org/apache/usergrid/management/importer/FileImportStatistics.java
@@ -24,27 +24,33 @@ import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.usergrid.persistence.EntityManager;
+import org.apache.usergrid.persistence.entities.FailedEntityImport;
import org.apache.usergrid.persistence.entities.FileImport;
import org.apache.usergrid.persistence.exceptions.EntityNotFoundException;
+import org.apache.usergrid.persistence.exceptions.PersistenceException;
/**
* Statistics used to track a file import. Only 1 instance of this class should exist per file imported in the cluster.
- * There is a direct 1-1 mapping of the statistics provided here and the file import status
+ * There is a direct 1-1 mapping of the statistics provided here and the file import status.
+ * This class is threadsafe to be used across multiple threads.
*/
public class FileImportStatistics {
+
+ private static final String ERRORS_CONNECTION_NAME = "errors";
+
private final AtomicLong entitiesWritten = new AtomicLong( 0 );
private final AtomicLong entitiesFailed = new AtomicLong( 0 );
- private final UUID fileImportId;
+ private final FileImport fileImport;
private final EntityManager entityManager;
public FileImportStatistics( final UUID fileImportId, final EntityManager entityManager ) {
- this.fileImportId = fileImportId;
this.entityManager = entityManager;
+ this.fileImport = getFileImport( fileImportId);
}
@@ -60,8 +66,20 @@ public class FileImportStatistics {
* Invoke when an entity fails to write correctly
*/
- public void entityFailed( final String message ) {
+ public void entityFailed(final String message ) {
entitiesFailed.incrementAndGet();
+
+
+ FailedEntityImport failedEntityImport = new FailedEntityImport();
+ failedEntityImport.setErrorMessage( message );
+
+ try {
+ failedEntityImport = entityManager.create( failedEntityImport );
+ entityManager.createConnection( fileImport, ERRORS_CONNECTION_NAME, failedEntityImport );
+ }
+ catch(Exception e){
+ throw new PersistenceException( "Unable to save failed entity import message", e );
+ }
}
@@ -95,16 +113,8 @@ public class FileImportStatistics {
final long failed = entitiesFailed.get();
final long written = entitiesWritten.get();
- final FileImport.State state;
- if ( failed > 0 ) {
- state = FileImport.State.FAILED;
- }
- else {
- state = FileImport.State.FINISHED;
- }
-
- updateFileImport( written, failed, state, message );
+ updateFileImport( written, failed, FileImport.State.FAILED, message );
}
@@ -120,12 +130,6 @@ public class FileImportStatistics {
final String message ) {
try {
- FileImport fileImport = entityManager.get( fileImportId, FileImport.class );
-
- if ( fileImport == null ) {
- throw new EntityNotFoundException( "Could not file FileImport with id " + fileImportId );
- }
-
fileImport.setImportedEntityCount( written );
fileImport.setFailedEntityCount( failed );
@@ -141,6 +145,31 @@ public class FileImportStatistics {
/**
+ * Get the FileImport by uuid and return it
+ * @param fileImportId
+ * @return
+ * @throws EntityNotFoundException if we can't find the file import with the given uuid
+ */
+ private FileImport getFileImport( final UUID fileImportId ) {
+
+ final FileImport fileImport;
+
+ try {
+ fileImport = entityManager.get( fileImportId, FileImport.class );
+ }
+ catch ( Exception e ) {
+ throw new RuntimeException( "Unable to load fileImport with id " + fileImportId, e );
+ }
+
+ if ( fileImport == null ) {
+ throw new EntityNotFoundException( "Could not file FileImport with id " + fileImportId );
+ }
+
+ return fileImport;
+ }
+
+
+ /**
* Returns true if we should stop processing. This will use the following logic
*
* We've attempted to import over 1k entities After 1k, we have over a 50% failure rate
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ee88ea5b/stack/services/src/test/java/org/apache/usergrid/management/importer/FileImportStatisticsTest.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/management/importer/FileImportStatisticsTest.java b/stack/services/src/test/java/org/apache/usergrid/management/importer/FileImportStatisticsTest.java
index d4872bc..e2040fd 100644
--- a/stack/services/src/test/java/org/apache/usergrid/management/importer/FileImportStatisticsTest.java
+++ b/stack/services/src/test/java/org/apache/usergrid/management/importer/FileImportStatisticsTest.java
@@ -20,19 +20,27 @@
package org.apache.usergrid.management.importer;
+import java.util.List;
import java.util.UUID;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import org.apache.usergrid.persistence.EntityManager;
+import org.apache.usergrid.persistence.entities.FailedEntityImport;
import org.apache.usergrid.persistence.entities.FileImport;
import org.apache.usergrid.persistence.model.util.UUIDGenerator;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.same;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -93,6 +101,14 @@ public class FileImportStatisticsTest {
when( em.get( importFileId, FileImport.class ) ).thenReturn( fileImport );
+ //mock up returning the FailedEntityImport instance after save is invoked.
+
+ when( em.create( any( FailedEntityImport.class ) ) ).thenAnswer( new Answer<FailedEntityImport>() {
+ @Override
+ public FailedEntityImport answer( final InvocationOnMock invocation ) throws Throwable {
+ return ( FailedEntityImport ) invocation.getArguments()[0];
+ }
+ } );
final FileImportStatistics fileImportStatistics = new FileImportStatistics( importFileId, em );
@@ -102,9 +118,9 @@ public class FileImportStatisticsTest {
fileImportStatistics.entityWritten();
}
- final long expectedFails = 10;
+ final int expectedFails = 10;
- for ( long i = 0; i < expectedFails; i++ ) {
+ for ( int i = 0; i < expectedFails; i++ ) {
fileImportStatistics.entityFailed( "Failed to write entity " + i );
}
@@ -129,5 +145,70 @@ public class FileImportStatisticsTest {
updated.getErrorMessage() );
//TODO get the connections from the file import
+
+ ArgumentCaptor<FailedEntityImport> failedEntities = ArgumentCaptor.forClass( FailedEntityImport.class );
+
+ verify( em, times( expectedFails ) )
+ .createConnection( same( fileImport ), eq( "errors" ), failedEntities.capture() );
+
+ //now check all our arguments
+
+ final List<FailedEntityImport> args = failedEntities.getAllValues();
+
+ assertEquals( "Same number of error connections created", expectedFails, args.size() );
+
+
+ for ( int i = 0; i < expectedFails; i++ ) {
+
+ final FailedEntityImport failedImport = args.get( i );
+
+ assertEquals( "Same message expected", "Failed to write entity " + i, failedImport.getErrorMessage() );
+ }
+ }
+
+
+ @Test
+ public void explicitFail() throws Exception {
+
+ final EntityManager em = mock( EntityManager.class );
+
+ final UUID importFileId = UUIDGenerator.newTimeUUID();
+
+
+ final FileImport fileImport = new FileImport();
+ fileImport.setUuid( importFileId );
+
+ when( em.get( importFileId, FileImport.class ) ).thenReturn( fileImport );
+
+
+ final FileImportStatistics fileImportStatistics = new FileImportStatistics( importFileId, em );
+
+ final long expectedCount = 100;
+
+ for ( long i = 0; i < expectedCount; i++ ) {
+ fileImportStatistics.entityWritten();
+ }
+
+
+ fileImportStatistics.fatal( "Something bad happened" );
+
+
+ ArgumentCaptor<FileImport> savedFileImport = ArgumentCaptor.forClass( FileImport.class );
+
+ verify( em ).update( savedFileImport.capture() );
+
+ final FileImport updated = savedFileImport.getValue();
+
+ assertSame( "Same instance should be updated", fileImport, updated );
+
+
+ assertEquals( "Same count expected", expectedCount, updated.getImportedEntityCount() );
+
+ assertEquals("Fail count is 0", 0, updated.getFailedEntityCount());
+
+ assertEquals("Correct expected message", "Something bad happened", updated.getErrorMessage());
+
+ assertEquals("Expected failed state", FileImport.State.FAILED, updated.getState());
}
}
+