#17804: Ensure views are recompiled more aggressively

When a module changes, it's loader can change, which means the list
of dependencies can change to. Instead of trying to track the list
of dependencies, we now simply add a dependency on a file on disk
which describe the module compilation state.

As an aside, this also improves startup performance when
there were no changes to a site, since asp.net now only has
to check a single file instead of the list of dependencies.

--HG--
branch : 1.x
This commit is contained in:
Renaud Paquay
2011-05-26 18:11:51 -07:00
parent 1a30d2492f
commit 7084ecbbbc
3 changed files with 44 additions and 18 deletions

View File

@@ -43,10 +43,12 @@ namespace Orchard.FileSystems.Dependencies {
}
public IEnumerable<string> GetVirtualPathDependencies(DependencyDescriptor descriptor) {
// Currently, we return the same file for every module. An improvement would be to return
// a specific file per module (this would decrease the number of recompilations needed
// when modules change on disk).
yield return _appDataFolder.GetVirtualPath(PersistencePath);
if (IsSupportedLoader(descriptor.LoaderName)) {
// Currently, we return the same file for every module. An improvement would be to return
// a specific file per module (this would decrease the number of recompilations needed
// when modules change on disk).
yield return _appDataFolder.GetVirtualPath(PersistencePath);
}
}
private XDocument CreateDocument(IEnumerable<DependencyDescriptor> dependencies) {
@@ -54,22 +56,39 @@ namespace Orchard.FileSystems.Dependencies {
var document = new XDocument();
document.Add(new XElement(ns("Dependencies")));
var elements = dependencies.Select(d => new XElement("Dependency",
new XElement(ns("ModuleName"), d.Name),
new XElement(ns("LoaderName"), d.LoaderName),
new XElement(ns("VirtualPath"), d.VirtualPath),
new XElement(ns("FileHash"), _virtualPathProvider.GetFileHash(d.VirtualPath)),
new XElement(ns("References"), d.References
.Select(r => new XElement(ns("Reference"),
new XElement(ns("Name"), r.Name),
new XElement(ns("LoaderName"), r.LoaderName),
new XElement(ns("VirtualPath"), r.VirtualPath),
new XElement(ns("FileHash"), _virtualPathProvider.GetFileHash(r.VirtualPath)))).ToArray())));
var elements = FilterDependencies(dependencies).Select(
d => new XElement("Dependency",
new XElement(ns("ModuleName"), d.Name),
new XElement(ns("LoaderName"), d.LoaderName),
new XElement(ns("VirtualPath"), d.VirtualPath),
new XElement(ns("FileHash"), _virtualPathProvider.GetFileHash(d.VirtualPath)),
new XElement(ns("References"), FilterReferences(d.References)
.Select(r => new XElement(ns("Reference"),
new XElement(ns("Name"), r.Name),
new XElement(ns("LoaderName"), r.LoaderName),
new XElement(ns("VirtualPath"), r.VirtualPath),
new XElement(ns("FileHash"), _virtualPathProvider.GetFileHash(r.VirtualPath)))).ToArray())));
document.Root.Add(elements);
return document;
}
private IEnumerable<DependencyDescriptor> FilterDependencies(IEnumerable<DependencyDescriptor> dependencies) {
return dependencies.Where(dep => IsSupportedLoader(dep.LoaderName));
}
private IEnumerable<DependencyReferenceDescriptor> FilterReferences(IEnumerable<DependencyReferenceDescriptor> references) {
return references.Where(dep => IsSupportedLoader(dep.LoaderName));
}
private bool IsSupportedLoader(string loaderName) {
//Note: this is hard-coded for now, to avoid adding more responsibilities to the IExtensionLoader
// implementations.
return
loaderName == "DynamicExtensionLoader" ||
loaderName == "PrecompiledExtensionLoader";
}
private void WriteDocument(string persistancePath, XDocument document) {
using (var stream = _appDataFolder.CreateFile(persistancePath)) {
document.Save(stream, SaveOptions.None);

View File

@@ -21,13 +21,15 @@ namespace Orchard.FileSystems.Dependencies {
/// </summary>
public class WebFormVirtualPathProvider : VirtualPathProvider, ICustomVirtualPathProvider {
private readonly IDependenciesFolder _dependenciesFolder;
private readonly IModuleDependenciesManager _moduleDependenciesManager;
private readonly IEnumerable<IExtensionLoader> _loaders;
private readonly string[] _modulesPrefixes = { "~/Modules/" };
private readonly string[] _themesPrefixes = { "~/Themes/" };
private readonly string[] _extensions = { ".ascx", ".aspx", ".master" };
public WebFormVirtualPathProvider(IDependenciesFolder dependenciesFolder, IEnumerable<IExtensionLoader> loaders) {
public WebFormVirtualPathProvider(IDependenciesFolder dependenciesFolder, IModuleDependenciesManager moduleDependenciesManager, IEnumerable<IExtensionLoader> loaders) {
_dependenciesFolder = dependenciesFolder;
_moduleDependenciesManager = moduleDependenciesManager;
_loaders = loaders;
Logger = NullLogger.Instance;
}
@@ -60,7 +62,9 @@ namespace Orchard.FileSystems.Dependencies {
var dependencies =
virtualPathDependencies
.OfType<string>()
.Concat(file.Loaders.SelectMany(dl => dl.Loader.GetVirtualPathDependencies(dl.Descriptor)));
.Concat(file.Loaders.SelectMany(dl => _moduleDependenciesManager.GetVirtualPathDependencies(dl.Descriptor)))
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
if (Logger.IsEnabled(LogLevel.Debug)) {
Logger.Debug("GetFileHash(\"{0}\") - virtual path dependencies:", virtualPath);

View File

@@ -25,17 +25,20 @@ namespace Orchard.Mvc.ViewEngines.Razor {
/// </summary>
public class DefaultRazorCompilationEvents : IRazorCompilationEvents {
private readonly IDependenciesFolder _dependenciesFolder;
private readonly IModuleDependenciesManager _moduleDependenciesManager;
private readonly IBuildManager _buildManager;
private readonly IEnumerable<IExtensionLoader> _loaders;
private readonly IAssemblyLoader _assemblyLoader;
public DefaultRazorCompilationEvents(
IDependenciesFolder dependenciesFolder,
IModuleDependenciesManager moduleDependenciesManager,
IBuildManager buildManager,
IEnumerable<IExtensionLoader> loaders,
IAssemblyLoader assemblyLoader) {
_dependenciesFolder = dependenciesFolder;
_moduleDependenciesManager = moduleDependenciesManager;
_buildManager = buildManager;
_loaders = loaders;
_assemblyLoader = assemblyLoader;
@@ -67,7 +70,7 @@ namespace Orchard.Mvc.ViewEngines.Razor {
loader,
descriptor,
references = loader.GetCompilationReferences(descriptor),
dependencies = loader.GetVirtualPathDependencies(descriptor)
dependencies = _moduleDependenciesManager.GetVirtualPathDependencies(descriptor)
}));
foreach (var entry in entries) {