Problems with Auto-Versioning

Jan 6, 2010 at 8:29 AM

Hi,

We're trying to use the auto-versioning but we're having problems.

 

Looking through the source code may have discovered a possible issue:

 

In ChangeMonitor.cs, in the  "IsSamePath" method the path coming in is the full path and not the virtual one (so not "~" in front); therefore when we try to parse the string looking for the ~ symbol it fails and the method returns  false, stopping the version update process.

Does that make sense ? or are we missing something ?


In order for us to make this work we replace the ISSamePath method with the following code:

private static bool IsSamePath(string pathFromFileSystemWatcher, string path)
        {
            return pathFromFileSystemWatcher.Equals(path, StringComparison.OrdinalIgnoreCase);          
        }

 

With this patch the path is resolved correctly but the DefaultVersion Generator was failing.

Once we changed the configuration file to use the Sha512VersionGenerator it started to work.

 

Any feedback would be greatly appreciated.

 

regards,

Luca

 

 

 

Jan 6, 2010 at 8:59 AM

Hi Buu,

With regards to the above, I have also noticed that when a change is detected, all resource sets are removed from the cache, and the new version is calculated for all resource sets. Is this implemented like this for a reason, or could we not just remove the resource sets that have changed, and recompute their versions?

Regards,
Brian

 

Coordinator
Jan 6, 2010 at 1:09 PM
Edited Jan 6, 2010 at 1:11 PM

@lucagrulla:

Actually the parsing of '~' is not for the virtual path.  It's from my observation that FileSystemWatcher appends some string, starting with an '~', after the *actual* modified file name (note the word *actual* - if you change 1 file, FileSystemWatcher reports quite a number of events but only a few of them containing the actual file name;  those non-actual files are ignored [i.e. code return false]).  For example, the pathFromFileSystemWatcher argument might be: C:\\_Data\\Combres\\Samples\\MvcSample\\content\\jquery-ui-1.7.2.custom.css~RF24adb4c.TMP (note the bold part, which is the part the code try to eliminate before doing the comparison). 

So, it's by design.  This behavior of FileSsytemWatcher is consistent in both my XP 32-bit and Windows 7-64 bit, so I hope it is consistent across all machines.  Can you put a breakpoint at line #258 (i.e. after if (IsSamePath(arg.FullPath, combresConfigPath))) and make change to a file and see whether the debugger can hit it?  If it can, that means the code works fine.  If not, then if you can debug through IsSamePath() to see what's different in your machine (from the behavior I observed in mine) and report to me then it's very useful for me to fix the issue.

 

Coordinator
Jan 6, 2010 at 1:31 PM

Hi Brian,

There are 2 types of changes monitored by Combres:

1. Change to resource files (JS & CSS).  Only resources in the auto-version sets are monitored.  When there are changes to one or more resources belonging to a set, the new version for that set, and that set only, is recomputed.  Nothing happens to other sets.  You can see the code for this in method ApplyChanges() and ApplyChange(ChangeDetectedEventArg) of Configuration.cs.   The ApplyChange(ChangeDetectedEventArg) method attempts to remove the cached contents of the modified resources and then recompute the version for the changed set and does nothing else.

2. Change to Combres data file (e.g. combres.xml).  Combres always monitor changes to this file and if there's any change, Combres attempts to recreate the whole Settings object, which in turn creates ResourceSet objects, which in turn creates Resource objects and so forth.  During this process, the version for each set is recomputed since every set is newly created.  As you suggest, I could have made this a more efficient process by detecting the exact change (in the data file) and "refreshing" only the affected objects (filters, minifiers, resource sets, resources etc.)  However, that would complicate the code a great deal and then instead of having to deal with a readonly object hierarchy (only the version of resource set can be changed after the hierarchy is created - everything else is immutable), we have to deal with a mutable object hierarchy.  The latter would also complicate the client code (if the code happens to use the object model for some reason), not just the framework code in the context of a multithreaded environment like ASP.NET.  Therefore I took the simple path of creating a whole new hierarchy for each data file's change (just like ASP.NET restarts the whole app when s/o changes web.config, even when a change is minor and shouldn't cause an app restart at all).  In practice, I suppose people would not frequently update data file (likely every 5 minutes); but even when they do, only the first request after a change is time-consuming so I hope this isn't a big drawback.

Regards,

Buu

 

Jan 7, 2010 at 11:24 AM

Hi Buu,

Thank you for the quick response.

We are still having the same problem, It never does hit line 258 and the reason is because there is no ~ in Any of the paths coming through. The path do contain a tmp file name but no ~ (tilda) so they just come is as C:\\_Data\\Combres\\Samples\\MvcSample\\content\\RF24adb4c.TMP.

This is turn is always returning false when we call IsSamePath.

We think we we are getting this different behaviour because we are using IIS on Windows Vista (32 bit). 

so dealing with both the ~ and not ~ cases we need to change the code to something like the following:- 

 

 var index = pathFromFileSystemWatcher.LastIndexOf('~');
            if(index != -1)
            {
                return pathFromFileSystemWatcher.Substring(0, index).Equals(path,
                   StringComparison.OrdinalIgnoreCase);
            }
            return pathFromFileSystemWatcher.Equals(path, StringComparison.OrdinalIgnoreCase);

 var index = pathFromFileSystemWatcher.LastIndexOf('~');

           if(index != -1)

            {

                return pathFromFileSystemWatcher.Substring(0, index).Equals(path, StringComparison.OrdinalIgnoreCase);

            }

           return pathFromFileSystemWatcher.Equals(path, StringComparison.OrdinalIgnoreCase);

 

Thanks 

Luca's minions (Anwar / Mike)

 

Coordinator
Jan 8, 2010 at 2:41 AM

Hi Anwar/Mike,

I mentioned in my previous response that "FileSystemWatcher reports quite a number of events but only a few of them containing the actual file name;  those non-actual files are ignored [i.e. code return false])", the "C:\\_Data\\Combres\\Samples\\MvcSample\\content\\RF24adb4c.TMP" in your example is one of such non-actual files.  So it happens in my machine too, Combres just ignores such file until the actual file (appended with the '~.....' in the end) comes.  So the 1st part (non-actual files) behaves similar in your & my machine, I'm not sure about the latter (name of the actual file). 

However, your fix looks like it would address the issue, regardless which one of the above two behaviors happens.  I've changed the code a bit (below) and incorporated that to the code.  Thanks a lot for reporting the issue & posting the solution. 

var index = pathFromFileSystemWatcher.LastIndexOf('~');
if (index != -1)
{
      pathFromFileSystemWatcher = pathFromFileSystemWatcher.Substring(0, index);   
}
return pathFromFileSystemWatcher.Equals(path, StringComparison.OrdinalIgnoreCase);

Regards,

Buu