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());
     }
 }
+