Check for server recovery

Last post 10-10-2007 6:07 AM by NamelessParanoia. 2 replies.

Sort Posts:

  • Check for server recovery

    10-08-2007, 6:48 AM

    I'm creating a wallboard application that runs using an AJAX wepage to display the data from a database but I'm trying to make it resilient to server failure (or temporary network failure) since wallboards are often difficult to get to to manually refresh.  I've managed to suppress the error that occurs when IIS goes down (or the server that is running IIS goes down) using the code snippet below but I'm trying to get it to repeatedly poll the page and reload itself once it can find a connection to the server again.  Does anyone have any idea how I can get it to do this?  Currently the script I have below fails at the point where I attempt to set_executor with the XMLHttpRequest (the alert("Umm") is never executed).

    I tried creating a new webrequest object and invoking that but that created some strange behaviour; although I clean out the document body html using Javascript after the error the previously retrieved copy of the data on the page is flashed up as if it had been loaded from a cache and then the page fails over again as the update panel timer fails again.  I'm working on the premise that the API says I shouldn't really be invoking a webrequest directly and should instead pass and XMLHttpExecutor into the web request (which I hope will probably stop my strange page caching issue since I assume the XMLHttpExecutor operates in a Javascript side channel rather than refreshing the whole page).  I'm downloading VS2008 Beta to get some JS debugging but that's going to take a while.  In the meantime, does anyone have any input on a good way of causing a client side page refresh once the server becomes available again?
     

    The code I have so far is: 

    <script type="text/javascript" src="Namespace.js"></script>
    <script type="text/javascript" language="JavaScript">
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
    function EndRequestHandler(sender, args)
    {
       if (args.get_error() != undefined)
       {
           if ((args.get_response().get_statusCode() == '12007') || (args.get_response().get_statusCode() == '12029'))
           {
               //Show a Message like 'Please make sure you are connected to internet';
               args.set_errorHandled(true);
               document.body.innerHTML = "";
               document.body.innerHTML += "Communication with the server has been lost"
           }
           var repeatedLoopExit = false;
           while (!repeatedLoopExit)
           {
                alert("starting loop statement");
                // Give the function 15 seconds, since web request timeout takes 10 seconds
                repeatedLoopExit = setTimeout(RepeatedRefreshRequest(), 15000);
                alert("ending loop statement");
           }
       }
    }
    
    function RepeatedRefreshRequest()
    {
        // To use executeRequest you must instantiate the
        // executor, assign it to the Web request instance,
        // then call the executeRequest function.
        // Note: Normally to make a Web request you use
        // the invoke method of the WebRequest instance.
       var webServerCheckRequest = new Sys.Net.WebRequest();
       webServerCheckRequest.set_url(document.URL);
       webServerCheckRequest.set_httpVerb("GET");
       webServerCheckRequest.set_timeout(10000);
       webServerCheckRequest.add_completed(OnWebRequestCompleted);
       var executor = new Sys.Net.XMLHttpExecutor();
       alert("Setting executor");
       webServerRequest.set_executor(executor);
       alert("Umm");
       var executeRequestResponse = "";
       alert("Executing request");
       executor.executeRequest();
       alert(executeRequestResponse);
    }
    
    // This the handler for the Web request completed event
    // that is used to display return data.
    function OnWebRequestCompleted(executor, eventArgs)
    {
        if(executor.get_responseAvailable())
        {
            alert("reloading");
            location.reload(true);
        }
        else
        {
            alert("failed web request");
            if (executor.get_timedOut())
                return false;
            else
                if (executor.get_aborted())
                    alert("Aborted");
        }
    }

    Thanks in advance for your help

    Adam 

  • Re: Check for server recovery

    10-08-2007, 12:40 PM

    In case anyone does look at this, there's a few errors in the code that I've debugged using VS2008 - webServerRequest.set_executor(executor); should be webServerCheckRequest.set_executor(executor) and repeatedLoopExit = setTimeout(RepeatedRefreshRequest(), 15000); should be repeatedLoopExit = setTimeout('RepeatedRefreshRequest()', 15000);.  Oh, and I also hadn't returned the boolean results properly.

    Now my request executes, but it still cycles back to the old cached version of the page and it throws errors on the page_load header javascripts (I'm pretty sure this is because a timer is being fired looking for controls it can't reach).  I'm going to continue with this tomorrow now I have VS2008B2 (nice piece of kit!) - I'll probably post here if I get any further.

  • Re: Check for server recovery

    10-10-2007, 6:07 AM
    Answer

    Okay, so it took quite a while to work this one out but it got there eventually.  For the sake of anyone looking to do the same thing, here's what I found:

    Even if the server is down if you create a new XmlHttpExecutor (or any other executor for a webrequest) and invoke it or execute it to get the current website, you will get a response (which I'd guess is almost certainly a cached version of the page since the server can't be returning it).  This makes it very difficult to use javascript to determine whether the website has come back up.  The way I got around this was to create a simple hello world webservice on the site and use Ajax to retrieve the Hello world string - this method does fail reliably (helps that you can't realistically cache a webservice response) so you can use that to determine whether the service is running.

    Of course, while access to the page isn't available any post back calls from existing controls would cause another error to be thrown, so I overrided the postback function with a bypass variable that checks if the page has gone into a non-communicative state.  Anyway - code is below for anyone that requires it (don't forget you need to register any web services in the script manager and as web references once you're done).

    <script type="text/javascript" src="Namespace.js"></script>
    <script type="text/javascript" language="JavaScript">
    var webserverCheckDelay = 5000;
    var oldPostBack
       
    // Override postback function to allow a bypass when
    // communication goes down (prevents unexpected autopostbacks throwing an error
    var isFunctioning = true;
    function window.onload()
    {
       oldPostBack = __doPostBack;
       __doPostBack = MyFuntion;
    }
    function MyFuntion(eventTarget, eventArgument)
    {
        if (isFunctioning)
        {
            oldPostBack(eventTarget, eventArgument);
        }
    }

    // Add handler to pick up communication errors
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
    function EndRequestHandler(sender, args)
    {
       if (args.get_error() != undefined)
       {
           if ((args.get_response().get_statusCode() == '12007') || (args.get_response().get_statusCode() == '12029'))
           {
               isFunctioning = false;
           
               //Show a Message like 'Please make sure you are connected to internet';
               args.set_errorHandled(true);
               document.body.innerHTML = "";
               document.body.innerHTML += "<table class=\"wallboardLayoutTable\" cellpadding=\"0\" cellspacing=\"0\">";
               document.body.innerHTML += "<tr><td class=\"wallboardLayoutLeftMarginCell\"> \</td>";
               document.body.innerHTML += "<td class=\"wallboardLayoutMainContentCell\">";
               document.body.innerHTML += "<span style=\"font-size: 44pt; color: Red;\"><p align=\"center\">Communication with the server has been lost - please check network connectivity</p></span>"
               document.body.innerHTML += "</td></tr><tr><td class=\"wallboardLayoutBottomMarginCell\" colspan=\"2\"> </td></tr></table>";
              
               // Start the delayed calls to try and find the server
               setTimeout("RepeatedRefreshRequest()", webserverCheckDelay);
           }
        }
    }

    // Call the webservice to check for a response from the server
    function RepeatedRefreshRequest()
    {
        CmsWallboard.IsAliveService.IsAlive(webserviceReturn, webserviceFailure);
    }
      
    // If webservice call fails, check again after a delay
    function webserviceFailure(exception, userContext, methodName)
    {
        setTimeout("RepeatedRefreshRequest()", webserverCheckDelay);
    }
    // On success, reload the page (accept a page flash to get a clean load after the server is restored)
    function webserviceReturn(result,  userContext, methodName)
    {
        if(result.toString() == "Server is alive")
        {
            location.reload(true);
        }
        else
        {
            setTimeout("RepeatedRefreshRequest()", webserverCheckDelay);
        }
    }
           
    </script>

    Obviously I used some code samples from the web to help me along since I'm quite new to this - http://dotnetslackers.com/columns/ajax/ASPNETAjaxWebService.aspx and http://weblogs.asp.net/sbehera/archive/2005/08/04/421578.aspx were useful 

Page 1 of 1 (3 items)