Alexander Wels has uploaded a new change for review.

Change subject: userportal,webadmin: implement retry in Frontend
......................................................................

userportal,webadmin: implement retry in Frontend

- Implemented retry mechanism in Frontend in case of failures.

Change-Id: I68461d76cbbfa2f1c218f23023ce0e044ba9387e
Signed-off-by: Alexander Wels <aw...@redhat.com>
---
M 
frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/Frontend.java
A 
frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/RetryManager.java
M 
frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/server/gwt/GenericApiGWTServiceImpl.java
3 files changed, 253 insertions(+), 55 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/83/14583/1

diff --git 
a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/Frontend.java
 
b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/Frontend.java
index 3da0e27..9f36783 100644
--- 
a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/Frontend.java
+++ 
b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/Frontend.java
@@ -19,6 +19,7 @@
 import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
 import org.ovirt.engine.core.common.queries.VdcQueryType;
 import org.ovirt.engine.core.common.users.VdcUser;
+import org.ovirt.engine.ui.frontend.RetryManager.RetryCallback;
 import org.ovirt.engine.ui.frontend.gwtservices.GenericApiGWTServiceAsync;
 import org.ovirt.engine.ui.uicompat.ConstantsManager;
 import org.ovirt.engine.ui.uicompat.Event;
@@ -205,24 +206,37 @@
         dumpQueryDetails(queryType, parameters);
         logger.finer("Frontend: Invoking async runQuery."); //$NON-NLS-1$
         raiseQueryStartedEvent(queryType, callback.getContext());
+        final RetryManager retryManager = new RetryManager();
         final GenericApiGWTServiceAsync service = 
GenericApiGWTServiceAsync.Util.getInstance();
         service.RunQuery(queryType, parameters, new 
AsyncCallback<VdcQueryReturnValue>() {
             @Override
             public void onFailure(final Throwable caught) {
-                try {
-                    if (ignoreFailure(caught)) {
-                        return;
-                    }
-                    logger.log(Level.SEVERE, "Failed to execute RunQuery: " + 
caught, caught); //$NON-NLS-1$
-                    getEventsHandler().runQueryFailed(null);
-                    failureEventHandler(caught);
-                    if (callback.isHandleFailure()) {
-                        callback.asyncCallback.onSuccess(callback.getModel(), 
null);
-                    }
-                    raiseQueryCompleteEvent(queryType, callback.getContext());
-                } finally {
-                    if (isHandleSequentialQueries) {
-                        handleSequentialQueries(queryWrapper.getKey());
+                if (retryManager.canRetry()) {
+                    final AsyncCallback<VdcQueryReturnValue> callback = this;
+                    retryManager.retry(new RetryCallback() {
+
+                        @Override
+                        public void executeRetry() {
+                            service.RunQuery(queryType, parameters, callback);
+                        }
+                    });
+                    retryManager.incrementRetry();
+                } else {
+                    try {
+                        if (ignoreFailure(caught)) {
+                            return;
+                        }
+                        logger.log(Level.SEVERE, "Failed to execute RunQuery: 
" + caught, caught); //$NON-NLS-1$
+                        getEventsHandler().runQueryFailed(null);
+                        failureEventHandler(caught);
+                        if (callback.isHandleFailure()) {
+                            
callback.asyncCallback.onSuccess(callback.getModel(), null);
+                        }
+                        raiseQueryCompleteEvent(queryType, 
callback.getContext());
+                    } finally {
+                        if (isHandleSequentialQueries) {
+                            handleSequentialQueries(queryWrapper.getKey());
+                        }
                     }
                 }
             }
@@ -288,19 +302,31 @@
         initQueryParamsFilter(parameters);
         dumpQueryDetails(queryType, parameters);
         logger.finer("Frontend: Invoking async runQuery."); //$NON-NLS-1$
-
-        GenericApiGWTServiceAsync service = 
GenericApiGWTServiceAsync.Util.getInstance();
+        final RetryManager retryManager = new RetryManager();
+        final GenericApiGWTServiceAsync service = 
GenericApiGWTServiceAsync.Util.getInstance();
         service.RunPublicQuery(queryType, parameters, new 
AsyncCallback<VdcQueryReturnValue>() {
             @Override
             public void onFailure(final Throwable caught) {
                 if (ignoreFailure(caught)) {
                     return;
                 }
-                logger.log(Level.SEVERE, "Failed to execute RunQuery: " + 
caught, caught); //$NON-NLS-1$
-                getEventsHandler().runQueryFailed(null);
-                failureEventHandler(caught);
-                if (callback.isHandleFailure()) {
-                    callback.asyncCallback.onSuccess(callback.getModel(), 
null);
+                if (retryManager.canRetry()) {
+                    final AsyncCallback<VdcQueryReturnValue> callback = this;
+                    retryManager.retry(new RetryCallback() {
+
+                        @Override
+                        public void executeRetry() {
+                            service.RunPublicQuery(queryType, parameters, 
callback);
+                        }
+                    });
+                    retryManager.incrementRetry();
+                } else {
+                    logger.log(Level.SEVERE, "Failed to execute RunQuery: " + 
caught, caught); //$NON-NLS-1$
+                    getEventsHandler().runQueryFailed(null);
+                    failureEventHandler(caught);
+                    if (callback.isHandleFailure()) {
+                        callback.asyncCallback.onSuccess(callback.getModel(), 
null);
+                    }
                 }
             }
 
@@ -356,20 +382,33 @@
             initQueryParamsFilter(parameters);
         }
 
-        GenericApiGWTServiceAsync service = 
GenericApiGWTServiceAsync.Util.getInstance();
+        final GenericApiGWTServiceAsync service = 
GenericApiGWTServiceAsync.Util.getInstance();
+        final RetryManager retryManager = new RetryManager();
         service.RunMultipleQueries(queryTypeList, queryParamsList, new 
AsyncCallback<ArrayList<VdcQueryReturnValue>>() {
             @Override
             public void onFailure(final Throwable caught) {
                 if (ignoreFailure(caught)) {
                     return;
                 }
-                logger.log(Level.SEVERE, "Failed to execute RunPublicQuery: " 
+ caught, caught); //$NON-NLS-1$
-                FrontendMultipleQueryAsyncResult f =
-                        new FrontendMultipleQueryAsyncResult(queryTypeList, 
queryParamsList, null);
-                failureEventHandler(caught);
-                callback.executed(f);
+                if (retryManager.canRetry()) {
+                    final AsyncCallback<ArrayList<VdcQueryReturnValue>> 
callback = this;
+                    retryManager.retry(new RetryCallback() {
 
-                raiseQueryCompleteEvent(queryTypeList, context);
+                        @Override
+                        public void executeRetry() {
+                            service.RunMultipleQueries(queryTypeList, 
queryParamsList, callback);
+                        }
+                    });
+                    retryManager.incrementRetry();
+                } else {
+                    logger.log(Level.SEVERE, "Failed to execute 
RunPublicQuery: " + caught, caught); //$NON-NLS-1$
+                    FrontendMultipleQueryAsyncResult f =
+                            new 
FrontendMultipleQueryAsyncResult(queryTypeList, queryParamsList, null);
+                    failureEventHandler(caught);
+                    callback.executed(f);
+
+                    raiseQueryCompleteEvent(queryTypeList, context);
+                }
             }
 
             @Override
@@ -454,7 +493,7 @@
     }
 
     /**
-     * Run an action of the specified action type using the passed in 
parameters, also pass in a state object
+     * Run an action of the specified action type using the passed in 
parameters, also pass in a state object.
      * @param actionType The action type of the action to perform.
      * @param parameters The parameters of the action.
      * @param callback The callback to call when the action is completed.
@@ -481,17 +520,30 @@
         logger.finer("Invoking async runAction."); //$NON-NLS-1$
         dumpActionDetails(actionType, parameters);
 
-        GenericApiGWTServiceAsync service = 
GenericApiGWTServiceAsync.Util.getInstance();
+        final GenericApiGWTServiceAsync service = 
GenericApiGWTServiceAsync.Util.getInstance();
+        final RetryManager retryManager = new RetryManager();
         service.RunAction(actionType, parameters, new 
AsyncCallback<VdcReturnValueBase>() {
             @Override
             public void onFailure(final Throwable caught) {
                 if (ignoreFailure(caught)) {
                     return;
                 }
-                logger.log(Level.SEVERE, "Failed to execute RunAction: " + 
caught, caught); //$NON-NLS-1$
-                failureEventHandler(caught);
-                FrontendActionAsyncResult f = new 
FrontendActionAsyncResult(actionType, parameters, null, state);
-                callback.executed(f);
+                if (retryManager.canRetry()) {
+                    final AsyncCallback<VdcReturnValueBase> callback = this;
+                    retryManager.retry(new RetryCallback() {
+
+                        @Override
+                        public void executeRetry() {
+                            service.RunAction(actionType, parameters, 
callback);
+                        }
+                    });
+                    retryManager.incrementRetry();
+                } else {
+                    logger.log(Level.SEVERE, "Failed to execute RunAction: " + 
caught, caught); //$NON-NLS-1$
+                    failureEventHandler(caught);
+                    FrontendActionAsyncResult f = new 
FrontendActionAsyncResult(actionType, parameters, null, state);
+                    callback.executed(f);
+                }
             }
 
             @Override
@@ -521,8 +573,8 @@
             final boolean isRunOnlyIfAllCanDoPass,
             final IFrontendMultipleActionAsyncCallback callback,
             final Object state) {
-        GenericApiGWTServiceAsync service = 
GenericApiGWTServiceAsync.Util.getInstance();
-
+        final GenericApiGWTServiceAsync service = 
GenericApiGWTServiceAsync.Util.getInstance();
+        final RetryManager retryManager = new RetryManager();
         service.RunMultipleActions(actionType,
                 parameters,
                 isRunOnlyIfAllCanDoPass,
@@ -532,12 +584,25 @@
                         if (ignoreFailure(caught)) {
                             return;
                         }
-                        logger.log(Level.SEVERE, "Failed to execute RunAction: 
" + caught, caught); //$NON-NLS-1$
-                        failureEventHandler(caught);
+                        if (retryManager.canRetry()) {
+                            final AsyncCallback<ArrayList<VdcReturnValueBase>> 
callback = this;
+                            retryManager.retry(new RetryCallback() {
 
-                        if (callback != null) {
-                            callback.executed(new 
FrontendMultipleActionAsyncResult(actionType, parameters, null,
-                                    state));
+                                @Override
+                                public void executeRetry() {
+                                    service.RunMultipleActions(actionType, 
parameters, isRunOnlyIfAllCanDoPass,
+                                            callback);
+                                }
+                            });
+                            retryManager.incrementRetry();
+                        } else {
+                            logger.log(Level.SEVERE, "Failed to execute 
RunAction: " + caught, caught); //$NON-NLS-1$
+                            failureEventHandler(caught);
+
+                            if (callback != null) {
+                                callback.executed(new 
FrontendMultipleActionAsyncResult(actionType, parameters, null,
+                                        state));
+                            }
                         }
                     }
 
@@ -614,7 +679,8 @@
             final AsyncQuery callback) {
         logger.finer("Frontend: Invoking async Login."); //$NON-NLS-1$
 
-        GenericApiGWTServiceAsync service = 
GenericApiGWTServiceAsync.Util.getInstance();
+        final GenericApiGWTServiceAsync service = 
GenericApiGWTServiceAsync.Util.getInstance();
+        final RetryManager retryManager = new RetryManager();
         service.Login(userName, password, domain, new 
AsyncCallback<VdcReturnValueBase>() {
             @Override
             public void onSuccess(final VdcReturnValueBase result) {
@@ -634,21 +700,39 @@
                 if (ignoreFailure(caught)) {
                     return;
                 }
-                logger.log(Level.SEVERE, "Failed to execute RunQuery: " + 
caught, caught); //$NON-NLS-1$
-                getEventsHandler().runQueryFailed(null);
-                failureEventHandler(caught);
-                if (callback.isHandleFailure()) {
-                    setLoggedInUser(null);
-                    callback.asyncCallback.onSuccess(callback.getModel(), 
null);
+                if (retryManager.canRetry()) {
+                    final AsyncCallback<VdcReturnValueBase> callback = this;
+                    retryManager.retry(new RetryCallback() {
+
+                        @Override
+                        public void executeRetry() {
+                            service.Login(userName, password, domain, 
callback);
+                        }
+                    });
+                    retryManager.incrementRetry();
+                } else {
+                    logger.log(Level.SEVERE, "Failed to execute RunQuery: " + 
caught, caught); //$NON-NLS-1$
+                    getEventsHandler().runQueryFailed(null);
+                    failureEventHandler(caught);
+                    if (callback.isHandleFailure()) {
+                        setLoggedInUser(null);
+                        callback.asyncCallback.onSuccess(callback.getModel(), 
null);
+                    }
                 }
             }
         });
     }
 
-    public static void LogoffAsync(VdcUser vdcUser, final AsyncQuery callback) 
{
+    /**
+     * Log off the passed in user asynchronously.
+     * @param vdcUser The user object to log off.
+     * @param callback The callback to call when finished.
+     */
+    public static void LogoffAsync(final VdcUser vdcUser, final AsyncQuery 
callback) {
         logger.finer("Frontend: Invoking async Logoff."); //$NON-NLS-1$
 
-        GenericApiGWTServiceAsync service = 
GenericApiGWTServiceAsync.Util.getInstance();
+        final GenericApiGWTServiceAsync service = 
GenericApiGWTServiceAsync.Util.getInstance();
+        final RetryManager retryManager = new RetryManager();
         service.logOff(vdcUser, new AsyncCallback<VdcReturnValueBase>() {
             @Override
             public void onSuccess(final VdcReturnValueBase result) {
@@ -664,10 +748,22 @@
                 if (ignoreFailure(caught)) {
                     return;
                 }
-                logger.log(Level.SEVERE, "Failed to execute Logoff: " + 
caught, caught); //$NON-NLS-1$
-                getEventsHandler().runQueryFailed(null);
-                failureEventHandler(caught);
-                callback.asyncCallback.onSuccess(callback.getModel(), null);
+                if (retryManager.canRetry()) {
+                    final AsyncCallback<VdcReturnValueBase> callback = this;
+                    retryManager.retry(new RetryCallback() {
+
+                        @Override
+                        public void executeRetry() {
+                            service.logOff(vdcUser, callback);
+                        }
+                    });
+                    retryManager.incrementRetry();
+                } else {
+                    logger.log(Level.SEVERE, "Failed to execute Logoff: " + 
caught, caught); //$NON-NLS-1$
+                    getEventsHandler().runQueryFailed(null);
+                    failureEventHandler(caught);
+                    callback.asyncCallback.onSuccess(callback.getModel(), 
null);
+                }
             }
         });
     }
@@ -688,7 +784,7 @@
         logger.finer("Determining whether user is logged in..."); //$NON-NLS-1$
 
         final GenericApiGWTServiceAsync service = 
GenericApiGWTServiceAsync.Util.getInstance();
-
+        final RetryManager retryManager = new RetryManager();
         service.getLoggedInUser(new AsyncCallback<VdcUser>() {
             @Override
             public void onFailure(final Throwable caught) {
diff --git 
a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/RetryManager.java
 
b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/RetryManager.java
new file mode 100644
index 0000000..bf348f2
--- /dev/null
+++ 
b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/RetryManager.java
@@ -0,0 +1,101 @@
+package org.ovirt.engine.ui.frontend;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.google.gwt.user.client.Random;
+import com.google.gwt.user.client.Timer;
+
+/**
+ * This class manages the retry counter for the {@code Frontend}.
+ */
+public class RetryManager {
+    /**
+     * Implement this interface if you want the retry manager to make a 
callback.
+     */
+    public interface RetryCallback {
+        /**
+         * The method to execute when retrying.
+         */
+        void executeRetry();
+    }
+
+    /**
+     * The logger.
+     */
+    private static final Logger log = 
Logger.getLogger(RetryManager.class.getName());
+
+    /**
+     * Maximum number of retries.
+     */
+    private static final int MAX_RETRY_COUNT = 5;
+
+    /**
+     * The starting sleep time in seconds.
+     */
+    private static final int START_SLEEP = 1; // Sleep 1 seconds.
+
+    /**
+     * Number of milliseconds in a second.
+     */
+    private static final int MILLISECONDS = 1000; // Number of milliseconds in 
a second.
+
+    /**
+     * The max random time to add to wait interval.
+     */
+    private static final int MAX_RANDOM_SLEEP = 250; // Add a maximum 250 
milliseconds.
+
+    /**
+     * The retry count.
+     */
+    private int counter = 0;
+
+    /**
+     * Increment the retry counter.
+     */
+    public void incrementRetry() {
+        counter++;
+    }
+
+    /**
+     * Check if we can still retry whatever we are trying.
+     * @return {@code true} if the counter is less than max, {@code false} 
otherwise
+     */
+    public boolean canRetry() {
+        log.log(Level.FINEST, "canRetry called, can we retry? " + (counter < 
MAX_RETRY_COUNT)); //$NON-NLS-1$
+        return counter < MAX_RETRY_COUNT;
+    }
+
+    /**
+     * execute the retry after a calculated number of seconds.
+     * @param retryCallback The callback to use to retry.
+     */
+    public void retry(final RetryCallback retryCallback) {
+        Timer retryTimer = new Timer() {
+            public void run() {
+                if (retryCallback != null) {
+                    retryCallback.executeRetry();
+                } else {
+                    log.log(Level.WARNING, "retry called without callback, not 
retrying anything"); //$NON-NLS-1$
+                }
+            }
+        };
+        retryTimer.schedule(calculateSleep() * MILLISECONDS + 
Random.nextInt(MAX_RANDOM_SLEEP));
+    }
+
+    /**
+     * Calculate the retry sleep time in seconds.
+     * @return The number of seconds to wait before retrying.
+     */
+    private int calculateSleep() {
+        int sleep = 1;
+        for (int i = 1; i <= counter; i++) {
+            if (i == 1) {
+                sleep = START_SLEEP;
+            }
+            sleep = sleep * 2; // Double sleep each retry.
+        }
+        log.log(Level.INFO, "Sleeping for: " + sleep + " seconds"); 
//$NON-NLS-1$ //$NON-NLS-2$
+        return sleep;
+    }
+}
diff --git 
a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/server/gwt/GenericApiGWTServiceImpl.java
 
b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/server/gwt/GenericApiGWTServiceImpl.java
index f65a690..c858a72 100644
--- 
a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/server/gwt/GenericApiGWTServiceImpl.java
+++ 
b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/server/gwt/GenericApiGWTServiceImpl.java
@@ -30,6 +30,7 @@
 
     static Random r = new Random();
     boolean noBackend = false;
+    int errorCount = 0;
 
     private static final Logger log = 
Logger.getLogger(GenericApiGWTServiceImpl.class);
 


--
To view, visit http://gerrit.ovirt.org/14583
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I68461d76cbbfa2f1c218f23023ce0e044ba9387e
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Alexander Wels <aw...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to