Recursive reflective generic error handling



  • <FONT size=2>Here's a little nugget for you all to digest.</FONT>

    <FONT size=2>    /// <summary>
        /// Contains Methods for implementing retry logic.
        /// </summary>
        internal static class RetryUtility
        {
            /// <summary>
            /// Runs the specified method, retrying on error
            /// </summary>
            /// <typeparam name="TResult">The type tof the return object from the method</typeparam>
            /// <param name="method">The method to execute</param>
            /// <param name="NumberOfTries">The number of times to try executing the method</param>
            /// <returns>The results of Method</returns>
            public static TResult ReTry<TResult>(Func<TResult> method, int NumberOfTries)
            {
                TResult retVal;</FONT><FONT size=2>

                try
                {
                    retVal = method.Invoke();
                }
                catch (System.Exception ex)
                {
                    if (NumberOfTries > 0)
                        retVal = ReTry<TResult>(method, NumberOfTries - 1);
                    else
                        throw new System.Exception("Retry Exceeded", ex);
                }
                return retVal;
            }

            /// <summary>
            /// Runs the specified method using the specified parameter, retrying on error
            /// </summary>
            /// <typeparam name="TResult">The type tof the return object from the method</typeparam>
            /// <param name="method">The method to execute</param>
            /// <param name="NumberOfTries">The number of times to try executing the method</param>
            /// <returns>The results of Method</returns>
            /// <typeparam name="T">The type of the parameter</typeparam>
            /// <param name="Parameter1">The parameter to be passed in</param>
            /// <remarks>To pass more than 1 parameter package them up into an object</remarks>
            public static TResult ReTry<T,TResult>(Func<T,TResult> method, T Parameter1, int NumberOfTries)
            {
                TResult retVal;

                try
                {
                    retVal = method.Invoke(Parameter1);
                }
                catch (System.Exception ex)
                {
                   
                    if (NumberOfTries > 0)
                        retVal = ReTry<T,TResult>(method,Parameter1, NumberOfTries - 1);
                    else
                        throw new System.Exception("Retry Exceeded", ex);
                }
                return retVal;
            }
        }

    </FONT>


  • I would prefer iteration here.  It wouldn't be half bad if they didn't catch the exception and rethrow with a new exception.  However, recursing in the catch block seems pretty ugly no matter what.


  • 🚽 Regular

    It's truly overengineering at its best. The "at-first-if-you-don't-succeed-try-again-a-few-times" pattern is something we sometimes have to reluctantly apply to get tricky problems solved under a short time restraint, but if you're using it often enough that you think it's a good idea to make an entire abstract class that encompasses the pattern (complete with overloaded methods to accomodate methods of varying parameter counts) you've got to rethink the design of your application.



  • (complete with overloaded methods to accomodate methods of varying parameter counts) you've got to rethink the design of your application.

    Indeed, you should add a dummy parameter to all your parameterless methods and use currying to eliminate multiparameter methods.




    Wait. They [i]are[/i] using currying, or there'd be more overloads.



  • @Code written by me said:

    def _insist(fn):
    """
        Sometimes Windows feels like throwing out "Access denied" errors
        when we're copying or removing a directory
        (probably some race condition over the file system or something).
        So we try again a couple of times to see if it gets over it.
        """
        attempts = 0

    <span style="color: rgb(128, 0, 0); font-weight: bold;">while</span> <span style="color: rgb(227, 74, 220);">True</span><span style="color: rgb(128, 128, 48);">:</span>
        <span style="color: rgb(128, 0, 0); font-weight: bold;">try</span><span style="color: rgb(128, 128, 48);">:</span>
            fn<span style="color: rgb(128, 128, 48);">(</span><span style="color: rgb(128, 128, 48);">)</span>
            <span style="color: rgb(128, 0, 0); font-weight: bold;">return</span> <span style="color: rgb(227, 74, 220);">True</span>
        
        <span style="color: rgb(128, 0, 0); font-weight: bold;">except</span> WindowsError as err<span style="color: rgb(128, 128, 48);">:</span>
            <span style="color: rgb(128, 0, 0); font-weight: bold;">import</span> errno
            <span style="color: rgb(105, 105, 105);">#if err.errno not in (errno.EACCES, 145):</span>
            <span style="color: rgb(105, 105, 105);">#    # 145 is ERROR_DIR_NOT_EMPTY</span>
            <span style="color: rgb(105, 105, 105);">#    raise err</span>
            
            attempts <span style="color: rgb(128, 128, 48);">+</span><span style="color: rgb(128, 128, 48);">=</span> <span style="color: rgb(0, 140, 0);">1</span>
            <span style="color: rgb(128, 0, 0); font-weight: bold;">if</span> attempts <span style="color: rgb(128, 128, 48);">&gt;</span> <span style="color: rgb(0, 140, 0);">5</span><span style="color: rgb(128, 128, 48);">:</span>
                <span style="color: rgb(128, 0, 0); font-weight: bold;">raise</span> err
            
            <span style="color: rgb(128, 0, 0); font-weight: bold;">import</span> time
            <span style="color: rgb(128, 0, 0); font-weight: bold;">if</span> attempts <span style="color: rgb(128, 128, 48);">=</span><span style="color: rgb(128, 128, 48);">=</span> <span style="color: rgb(0, 140, 0);">1</span><span style="color: rgb(128, 128, 48);">:</span>
                sleep_secs <span style="color: rgb(128, 128, 48);">=</span> <span style="color: rgb(0, 128, 0);">0.5</span>
            <span style="color: rgb(128, 0, 0); font-weight: bold;">elif</span> attempts <span style="color: rgb(128, 128, 48);">=</span><span style="color: rgb(128, 128, 48);">=</span> <span style="color: rgb(0, 140, 0);">2</span><span style="color: rgb(128, 128, 48);">:</span>
                sleep_secs <span style="color: rgb(128, 128, 48);">=</span> <span style="color: rgb(0, 128, 0);">1.0</span>
            <span style="color: rgb(128, 0, 0); font-weight: bold;">elif</span> attempts <span style="color: rgb(128, 128, 48);">=</span><span style="color: rgb(128, 128, 48);">=</span> <span style="color: rgb(0, 140, 0);">3</span><span style="color: rgb(128, 128, 48);">:</span>
                sleep_secs <span style="color: rgb(128, 128, 48);">=</span> <span style="color: rgb(0, 128, 0);">3.0</span>
            <span style="color: rgb(128, 0, 0); font-weight: bold;">elif</span> attempts <span style="color: rgb(128, 128, 48);">&gt;</span><span style="color: rgb(128, 128, 48);">=</span> <span style="color: rgb(0, 140, 0);">4</span><span style="color: rgb(128, 128, 48);">:</span>
                sleep_secs <span style="color: rgb(128, 128, 48);">=</span> <span style="color: rgb(0, 128, 0);">5.0</span>
            
            logger<span style="color: rgb(128, 128, 48);">.</span>info<span style="color: rgb(128, 128, 48);">(</span><span style="color: rgb(0, 0, 230);">"Sleeping for %.1f seconds before attempting operation again."</span><span style="color: rgb(128, 128, 48);">,</span> sleep_secs<span style="color: rgb(128, 128, 48);">)</span>
            time<span style="color: rgb(128, 128, 48);">.</span>sleep<span style="color: rgb(128, 128, 48);">(</span>sleep_secs<span style="color: rgb(128, 128, 48);">)</span>
        <span style="color: rgb(105, 105, 105);">#end of 'except WindowsError'</span>
        
    <span style="color: rgb(105, 105, 105);"># end of 'while True'</span>
    

    #end of function _insist()

    def copytree(src_dir, target_dir, ignore=None):
    import shutil
    def do_copy():
    shutil.copytree(src_dir, target_dir, ignore=ignore)
    _insist(do_copy)

    def rmtree(path):
    import os, stat

    path <span style="color: rgb(128, 128, 48);">=</span> os<span style="color: rgb(128, 128, 48);">.</span>path<span style="color: rgb(128, 128, 48);">.</span>abspath<span style="color: rgb(128, 128, 48);">(</span>path<span style="color: rgb(128, 128, 48);">)</span>
    os<span style="color: rgb(128, 128, 48);">.</span>chmod<span style="color: rgb(128, 128, 48);">(</span>path<span style="color: rgb(128, 128, 48);">,</span> stat<span style="color: rgb(128, 128, 48);">.</span>S_IWUSR<span style="color: rgb(128, 128, 48);">)</span> <span style="color: rgb(105, 105, 105);"># Clear read-only flag</span>
    
    <span style="color: rgb(128, 0, 0); font-weight: bold;">if</span> os<span style="color: rgb(128, 128, 48);">.</span>path<span style="color: rgb(128, 128, 48);">.</span>isdir<span style="color: rgb(128, 128, 48);">(</span>path<span style="color: rgb(128, 128, 48);">)</span><span style="color: rgb(128, 128, 48);">:</span>
        <span style="color: rgb(128, 0, 0); font-weight: bold;">for</span> entry <span style="color: rgb(128, 0, 0); font-weight: bold;">in</span> os<span style="color: rgb(128, 128, 48);">.</span>listdir<span style="color: rgb(128, 128, 48);">(</span>path<span style="color: rgb(128, 128, 48);">)</span><span style="color: rgb(128, 128, 48);">:</span>
            rmtree<span style="color: rgb(128, 128, 48);">(</span>os<span style="color: rgb(128, 128, 48);">.</span>path<span style="color: rgb(128, 128, 48);">.</span>join<span style="color: rgb(128, 128, 48);">(</span>path<span style="color: rgb(128, 128, 48);">,</span> entry<span style="color: rgb(128, 128, 48);">)</span><span style="color: rgb(128, 128, 48);">)</span>
        
        <span style="color: rgb(128, 0, 0); font-weight: bold;">def</span> do_rmdir<span style="color: rgb(128, 128, 48);">(</span><span style="color: rgb(128, 128, 48);">)</span><span style="color: rgb(128, 128, 48);">:</span>
            os<span style="color: rgb(128, 128, 48);">.</span>rmdir<span style="color: rgb(128, 128, 48);">(</span>path<span style="color: rgb(128, 128, 48);">)</span>
        _insist<span style="color: rgb(128, 128, 48);">(</span>do_rmdir<span style="color: rgb(128, 128, 48);">)</span>
    
        <span style="color: rgb(128, 0, 0); font-weight: bold;">assert</span> <span style="color: rgb(128, 0, 0); font-weight: bold;">not</span> os<span style="color: rgb(128, 128, 48);">.</span>path<span style="color: rgb(128, 128, 48);">.</span>isdir<span style="color: rgb(128, 128, 48);">(</span>path<span style="color: rgb(128, 128, 48);">)</span><span style="color: rgb(128, 128, 48);">,</span> <span style="color: rgb(0, 0, 230);">"It didn't delete!!!"</span>
    
    
    <span style="color: rgb(128, 0, 0); font-weight: bold;">elif</span> os<span style="color: rgb(128, 128, 48);">.</span>path<span style="color: rgb(128, 128, 48);">.</span>isfile<span style="color: rgb(128, 128, 48);">(</span>path<span style="color: rgb(128, 128, 48);">)</span><span style="color: rgb(128, 128, 48);">:</span>
        os<span style="color: rgb(128, 128, 48);">.</span>remove<span style="color: rgb(128, 128, 48);">(</span>path<span style="color: rgb(128, 128, 48);">)</span>
        <span style="color: rgb(128, 0, 0); font-weight: bold;">assert</span> <span style="color: rgb(128, 0, 0); font-weight: bold;">not</span> os<span style="color: rgb(128, 128, 48);">.</span>path<span style="color: rgb(128, 128, 48);">.</span>isfile<span style="color: rgb(128, 128, 48);">(</span>path<span style="color: rgb(128, 128, 48);">)</span><span style="color: rgb(128, 128, 48);">,</span> <span style="color: rgb(0, 0, 230);">"It didn't delete!!!"</span>
    
    
    <span style="color: rgb(128, 0, 0); font-weight: bold;">else</span><span style="color: rgb(128, 128, 48);">:</span>
        <span style="color: rgb(128, 0, 0); font-weight: bold;">raise</span> <span style="color: rgb(227, 74, 220);">Exception</span><span style="color: rgb(128, 128, 48);">(</span><span style="color: rgb(0, 0, 230);">"Humm.. what's this?"</span><span style="color: rgb(128, 128, 48);">,</span> path<span style="color: rgb(128, 128, 48);">)</span>  <span style="color: rgb(105, 105, 105);"># Never happened</span>, but...
    

    No, I'm not proud of it. Shut up.



  • @Zecc said:

    No, I'm not proud of it. Shut up.

    I like the part where you use import in a fricken except section. Though it would be better if you defined a class in there and created a few instances of it.

    Also, ever tried to rmtree a folder containing a symlink? I'd be curious to know whether it descends or raises a "Humm.. what's this?" exception. If it descends, try a recursive symlink (e.g. one that points to itself) and have fun with that.



  • @derula said:

    I like the part where you use import in a fricken except section.
    This is so I don't import stuff unnecessarily; most of the time the exceptions aren't thrown. Yeah, premature optimization... whatever.

    As for symlinks, I have no idea what would happen. This was on Windows, where such things are uncommon.

    Btw, I apologize to the OP for hijacking the thread.



  • @Zecc said:

    This was on Windows, where such things are uncommon.

    This is not an assumption you should make easily. No idea if this matters in your application, but Windows Vista and up use symlinks all over the place, especially in localized versions. E.g., there will be hidden symlinks C:\Documents and Settings\ and C:\Dokumente und Einstellungen\ leading to C:\Users, and C:\Programme\ leading to C:\Program Files\ (which is shown as Programme in Explorer through desktop.ini magic). It confuses the shit out of my dad because he's generally a more tech-savvy person and has hidden files visible, so now there's suddenly all these folders and he doesn't know where his fricken "home folder" is. Also, prepare for a slew of hidden symlinks inside $HOMEPATH (I don't know, the My Documents thing, I don't have a Vista / 7 handy)! He's really terribly confused.



    Granted, these are folders you rarely want to mass delete.

    Edit: Before the inevitable blakeyrant: I think that this "hidden symlink" strategy is a good thing. It fixes bugs with stupid installers / software that have hardcoded paths. Granted, I don't even know where to find such software these days, but I'm sure they still exist en masse.



  • @RHuckster said:

    The "at-first-if-you-don't-succeed-try-again-a-few-times" pattern is something we sometimes have to reluctantly apply to get tricky problems solved under a short time restraint,

    Or you're dealing with Twitter, Amazon SimpleDB, or other Web 2.0-y services where you have to basically expect every operation to fail often for stupid reasons, or no reason at all. The correct solution in that instance involves a loaded pistol aimed directly at the cranium.

    And yes, you need to work with synlinks, duh.


  • 🚽 Regular

    @blakeyrat said:

    Or you're dealing with Twitter, Amazon SimpleDB, or other Web 2.0-y services where you have to basically expect every operation to fail often for stupid reasons, or no reason at all.
     

    Funny you should mention that, since the last time I had to resort to the "jiggle-the-handle" approach was when I was working on an Amazon API. (not SimpleDB specifically, but I'm sure it's the same fail) :)



  • @derula said:

    If it descends, try a recursive symlink (e.g. one that points to itself) and have fun with that.

    Once I mounted a Samba share inside the shared directory. Let's just say it wasn't exactly the brightest idea.



  • @Vempele said:

    (complete with overloaded methods to accomodate methods of varying parameter counts) you've got to rethink the design of your application.

    Indeed, you should add a dummy parameter to all your parameterless methods and use currying to eliminate multiparameter methods.


    Wait. They are using currying, or there'd be more overloads.

    But a problem where an operation fails a few times and then succeeds seems more like a thyming issue.



  • @nonpartisan said:

    But a problem where an operation fails a few times and then succeeds seems more like a thyming issue.
    I prefer laureling, myself.



  • Berry oreganol, guys. :\



  • @dhromed said:

    Berry oreganol, guys. :<br>

    Yeah, I know. Looks like the meme is being kept at bay. But really, after the "currying" comment you should've been able to see this cumin.



  • @nonpartisan said:

    @dhromed said:

    Berry oreganol, guys. :\

    Yeah, I know. Looks like the meme is being kept at bay. But really, after the "currying" comment you should've been able to see this cumin.

    If we all manage to dilligently avoid peppering this thread with further puns, we might fennely bring this sad affair to an end before it goes too far.

     



  • This thread has started a new meme. It's not a very good one, but it's a new meme.


  • ♿ (Parody)

    @Quietust said:

    This thread has started a new meme. It's not a very good one, but it's a new meme.

    Let's not get caraway. This thread has mutated an existing meme. It's not really a new meme, but it's a mutated meme.


  • Considered Harmful

    @Anonymouse said:

    @nonpartisan said:

    @dhromed said:

    Berry oreganol, guys. :<br>

    Yeah, I know. Looks like the meme is being kept at bay. But really, after the "currying" comment you should've been able to see this cumin.

    If we all manage to dilligently avoid peppering this thread with further puns, we might fennely bring this sad affair to an end before it goes too far.

    We need to treat this matter very gingerly so as not to get the thread locked.



  • I'm sure the moderators will dill with this thread soon. So lets all savory the moment and maybe we can mustard up some more spices and seed it with some more spicey puns. :P



  • @joe.edwards said:

    @Anonymouse said:

    @nonpartisan said:

    @dhromed said:

    Berry oreganol, guys. :\

    Yeah, I know. Looks like the meme is being kept at bay. But really, after the "currying" comment you should've been able to see this cumin.

    If we all manage to dilligently avoid peppering this thread with further puns, we might fennely bring this sad affair to an end before it goes too far.

    We need to treat this matter very gingerly so as not to get the thread locked.

    You better not be chivin' me or I may have to assalt you ...



  • @zelmak said:

    @joe.edwards said:

    @Anonymouse said:

    @nonpartisan said:

    @dhromed said:

    Berry oreganol, guys. :\

    Yeah, I know. Looks like the meme is being kept at bay. But really, after the "currying" comment you should've been able to see this cumin.

    If we all manage to dilligently avoid peppering this thread with further puns, we might fennely bring this sad affair to an end before it goes too far.

    We need to treat this matter very gingerly so as not to get the thread locked.

    You better not be chivin' me or I may have to assalt you ...

    Come on! Don't be a jerk now. If we keep this up, Vegeta says me might go over 9000.



  • @Ragnax said:

    @zelmak said:

    @joe.edwards said:

    @Anonymouse said:

    @nonpartisan said:

    @dhromed said:

    Berry oreganol, guys. :\

    Yeah, I know. Looks like the meme is being kept at bay. But really, after the "currying" comment you should've been able to see this cumin.

    If we all manage to dilligently avoid peppering this thread with further puns, we might fennely bring this sad affair to an end before it goes too far.

    We need to treat this matter very gingerly so as not to get the thread locked.

    You better not be chivin' me or I may have to assalt you ...

    Come on! Don't be a jerk now. If we keep this up, Vegeta says me might go over 9000.

    Baby Spice, come on. This thread is already getting Scary Spice and overly Posh Spice for me.



  • @dohpaz42 said:

    @Ragnax said:

    @zelmak said:

    @joe.edwards said:

    @Anonymouse said:

    @nonpartisan said:

    @dhromed said:

    Berry oreganol, guys. :\

    Yeah, I know. Looks like the meme is being kept at bay. But really, after the "currying" comment you should've been able to see this cumin.

    If we all manage to dilligently avoid peppering this thread with further puns, we might fennely bring this sad affair to an end before it goes too far.

    We need to treat this matter very gingerly so as not to get the thread locked.

    You better not be chivin' me or I may have to assalt you ...

    Come on! Don't be a jerk now. If we keep this up, Vegeta says me might go over 9000.

    Baby Spice, come on. This thread is already getting Scary Spice and overly Posh Spice for me.

    Those are a lot less legit than Salt n Peppa.



  • @frits said:

    @dohpaz42 said:

    @Ragnax said:

    @zelmak said:

    @joe.edwards said:

    @Anonymouse said:

    @nonpartisan said:

    @dhromed said:

    Berry oreganol, guys. :\

    Yeah, I know. Looks like the meme is being kept at bay. But really, after the "currying" comment you should've been able to see this cumin.

    If we all manage to dilligently avoid peppering this thread with further puns, we might fennely bring this sad affair to an end before it goes too far.

    We need to treat this matter very gingerly so as not to get the thread locked.

    You better not be chivin' me or I may have to assalt you ...

    Come on! Don't be a jerk now. If we keep this up, Vegeta says me might go over 9000.

    Baby Spice, come on. This thread is already getting Scary Spice and overly Posh Spice for me.

    Those are a lot less legit than Salt n Peppa. Those spices are not as legit as Salt n Peppa, but they are legit spices.

    FTFY



  • @galgorah said:

    RetryUtility

    @galgorah said:

    public static TResult ReTry<TResult>(Func<TResult> method, int NumberOfTries)

    Is this language case-insensitive or will it fail to compile if you try to use the Retry method of class ReTryUtility?



  • @derula said:

    This is not an assumption you should make easily. No idea if this matters in your application, but Windows Vista and up use symlinks all over the place, especially in localized versions. E.g., there will be hidden symlinks C:\Documents and Settings\ and C:\Dokumente und Einstellungen\ leading to C:\Users, and C:\Programme\ leading to C:\Program Files\ (which is shown as Programme in Explorer through desktop.ini magic). It confuses the shit out of my dad because he's generally a more tech-savvy person and has hidden files visible, so now there's suddenly all these folders and he doesn't know where his fricken "home folder" is. Also, prepare for a slew of hidden symlinks inside $HOMEPATH (I don't know, the My Documents thing, I don't have a Vista / 7 handy)! He's really terribly confused.
    Actually, the only links (to be precise, specially crafted junctions that don't allow you to enumerate their content) are the pre-Vista names - Documents and Settings, Application Data, Start Menu etc. The localized names you see are an artifact of Explorer, as they don't exist anywhere on the disk, which is what makes them so confusing - they will work if you type them in Explorer's address bar, but if you try using them anywhere else, they'll fail, since there's no corresponding thing on the disk (and if you click the address bar after pressing Enter, you'll see the real names).@derula said:
    I think that this "hidden symlink" strategy is a good thing. It fixes bugs with stupid installers / software that have hardcoded paths.
    The junctions are OK, but Explorer showing something that's not really there isn't - it only serves a cosmetic purpose, and likely the only users that'd care about that are users who'll never see it. For everybody else it's just confusing.



  • @julmu said:

    @galgorah said:

    RetryUtility

    @galgorah said:

    public static TResult ReTry<TResult>(Func<TResult> method, int NumberOfTries)

    Is this language case-insensitive or will it fail to compile if you try to use the Retry method of class ReTryUtility?

    Language is C#


  • @aljopro said:

    I'm sure the moderators will dill with this thread soon. So lets all savory the moment and maybe we can mustard up some more spices and seed it with some more spicey puns. :P

    As the OP and an Admin, I can assure you, that is to say give my utmost guarentee, that I shall not Sir, do any of this here dilling, of which you speak.

  • Discourse touched me in a no-no place

    @galgorah said:

    @aljopro said:

    I'm sure the moderators will dill with this thread soon. So lets all savory the moment and maybe we can mustard up some more spices and seed it with some more spicey puns. :P

    As the OP and an Admin, I can assure you, that is to say give my utmost guarentee, that I shall not Sir, do any of this here dilling, of which you speak.
    Besides, we don't usually have the thyme to mace around with chili threads like this.



  • @PJH said:

    @galgorah said:

    @aljopro said:

    I'm sure the moderators will dill with this thread soon. So lets all savory the moment and maybe we can mustard up some more spices and seed it with some more spicey puns. :P

    As the OP and an Admin, I can assure you, that is to say give my utmost guarentee, that I shall not Sir, do any of this here dilling, of which you speak.
    Besides, we don't usually have the thyme to mace around with chili threads like this.

    I know. Some of us are just geting caraway with this thread :P Some may "rue" the day we started spicing up this thread Sesame.


Log in to reply