Comments (12)
Clearing the cache and compilation are separate tasks. It sounds like you want a CacheRefresh feature that clears the cache and re-compiles the cleared keys?
Updating the layout, e.g. on disk, is not sufficient.
from razorlight.
That's basically right @jzabroski . Except I would not want to clear the whole compilation cache every time I update a single include. I would like to clear the cache selectively, supplying the IDs of the templates for which I want the compilation cache cleared. Then, it should add those that need to be compiled as required, as it does right now. I just want to be able to say: OK, I updated template no. 17, so clear the compilation cache for that one, but I also know that templates 23, 24, 41 and 50 directly or indirectly depend on it so clear the cache for those as well, if any of them have been compiled and stored in the compilation cache.
Clearing the compilation cache wholesale would be a "poor man's" solution as I would prefer to keep all the unaffected templates that I may want to view compiled and not waste time recompiling those, but at this point, I'd even welcome that solution. It would still be better than restarting the whole application.
from razorlight.
To repeat back to you what I heard, you want something like:
public interface ITemplateCacheReload {
Task<ISet<string>> SnapshotKeys(); // take a snapshot of keys. debatable this is necessary. just brainstorming interface.
Task CacheRefresh(ISet<string> keys); // supply a snapshot of keys. refresh would call renderCallback.
}
Clearing the whole compilation cache, while likely never to be used, could then be achieved via:
await CacheRefresh(await SnapshotKeys());
With this API, you would be responsible for tracking the dependency tree across templates yourself. I don't think we track that currently. Hence why I suggested clearing the whole compilation cache. Of course if you know the tree yourself, e.g., because you are storing the dependencies in a database as a nested set, then this is mostly trivial.
EDIT: Actually, this won't work right - there will be sequential coupling in the ISet<string> keys
parameter. Unless we know the DAG and refresh bottom-up, we can't guarantee write-through cache coherence.
from razorlight.
Yep, that's look all right. I just need something to clear the cache - per template or at worst completely.
I sure am tracking all the dependencies in the database so I know exactly what other templates I need to clear from the cache.
I've basically build an email template editor where the user can easily switch between templates and the user may want edit the base template, like the footer, which is refrerenced by the main layout, which is then used in specific email templates. I even use more depths than that in the software I built this editor for, but that is enough to demonstrate the use case. If the user cannot see the change in the footer in this example, they will think something did not work. And the only way for them to see it is for me or the application / server admin to restart the app, which surely is not the best for usability :).
Re your EDIT: I'm not sure what you are specifically talking about there as I do not know the source code that intimately, but thre surely needs to be a way to clear the compilation cache programmatically.
from razorlight.
I meant that the interface as a set of keys is a leaky/incorrect abstraction since the issue you are trying to address is fundamentally a dag, not a set. Getting all snapshot keys if therefore not helpful even. So the minimal viable product would simply be:
Task RefreshCachedTemplate(string key);
You would then need to sequentially call await RefreshCachedTemplae(key)
bottom-up.
The cost of this is that others who use this will not understand that it won't work well unless they track the DAG themselves.
from razorlight.
OK, had to look up what is a DAG :). I did not go to UNI for programming so I sometimes am not aware of these generic concepts...
Anyway
Task RefreshCachedTemplate(string key);
sounds fine to me. Although I would prefer
Task RemoveCachedTemplate(string key);
because at the point the template (let's say the footer from my earlier example) is edited I just need to make sure that its previous compiled version is removed from the cache, not that it or any of the higher level templates that depend on it, are recompiled right then. The user may not even go back to the previously opened template that depends on it even if they did have it open before. The "Remove..." function would allow me to simply make sure that I removed all the cached templates in the tree of dependencies that have been compiled into the cache and whether or not they get re-compiled and put back into the cache later is going to be taken care of by the already existing code I believe, where if a required Include is not found in the cache it is requested by the component from the code that uses it and it gets compiled then.
from razorlight.
Oh, and as for the cost, I think there are lots of things that may be unclear in any component out there. Naturally, you have to read up on it or simply look into the IntelliSense description of the function.
I think that much more confusing, for example, is the ability to remove the templates from LookupCache which does not currently remove it from the compilation cache. I probably do not understand what the difference is there, but I for one would expect the action of removing something from LookupCache (or whatever other name it could have been called) would do what it says, which is "removing the template from the cache" and that, in my mind, should include automatically removing the template from all the caches that the component may be maintaining, so also from the compilation cache.
So in fact, if the above made sense, there would be no special need for any new function like RemoveCachedTemplate if the Remove function of the LookupCache class did this by default. In that case, I would not even have to change anything in my own code except just updating the version of RazorLight :), bacause that is the behaviour I was in fact expecting.
So unless there is a reason to keep the remove functions separate for those two types of caches, I'd vote for just extending the functionality of the existing remove function to make sure the cached compiled template is removed as well.
from razorlight.
I think that much more confusing, for example, is the ability to remove the templates from LookupCache which does not currently remove it from the compilation cache.
Just a guess: I think it was never intended to be 'removed' from the cache. One immediate workaround is to de-allocate the EngineHandler, call the GC, and instantiate a new EngineHandler. Calling the GC is useful as you may have items in third generation storage, that might not be immediately finalized.
In looking at the code... it does seem a bit of an oversight.
The two types of caches already exist today:
- RazorTemplateCompiler, inside CompileAsync, caches a CompiledTemplateDescriptor
- This is the 'first tier' of the cache.
- It is designed to avoid CPU overhead.
- EngineHandler caches the output of RazorTemplateCompiler.CompileAsync
- This is the 'second tier' of the cache.
- It is designed to avoid non-CPU overhead/resource constraints.
- This is the cache interface you are removing from
- It is designed to allow multiple cache providers, including a file system ,which would relieve memory pressure/memory resource constraints as well as open the door to using a content delivery network over fast broadband connections like Amazon S3. An example would be generating large printable HTML documents that might be 200 megs in size.
RazorLight/src/RazorLight/Compilation/RazorTemplateCompiler.cs
Lines 72 to 95 in c7f97d6
RazorLight/src/RazorLight/EngineHandler.cs
Lines 50 to 79 in 22381db
from razorlight.
I think the takeaway is that the EngineHandler should handle template cache invalidation and forced cache eviction. The other cache should probably only be used in the sense of relieving memory pressure from a cache eviction standpont.
Do you agree?
from razorlight.
Yes, that sounds correct to me.
Thank you for looking into this. And thank you for the two snippets above. That should help me to make the necessary changes to implement the behavior I need.
Do you think that is also something that may get implemented in the near future? My software won't be out for a while so if I knew there is a good chance this will get implemented by the original author(s) I wouldn't have to spend time fixing it for myself, where my fix may be sub-optimal.
from razorlight.
I would love a PR. I am pretty busy these days with a 5 month old baby boy.
from razorlight.
OK, I'll try to do that when I get around trying to fix it. However I cannot say that I'll be very confident in offering the best solution for a public component. As soon as it starts working for me I need to be on other things.
Thanks again! :)
from razorlight.
Related Issues (20)
- Failed to find type or namespace name 'Dictionary'
- Project can not find template with key HOT 3
- The CompileRenderStringAsync still caching templates HOT 7
- Even if @ using System.Collections.Generic is used; Nor can. any() be used
- The type or namespace name 'Razor' does not exist in the namespace 'RazorLight' HOT 4
- Unable to use Linq extension methods HOT 1
- Inject page to @RenderBody programmatically HOT 3
- [Question] Pros of using Cache System HOT 1
- The library states it is .Net System 2.0 HOT 3
- How to use method 'IncludeAsync()' to import partial view in root view?
- Entity Framework Core and RazorLight : "An error occurred while accessing the Microsoft.Extensions.Hosting service"
- IncludeAsync but truncate if too long.
- AddDynamicTemplates for embedded resources HOT 1
- Exception : One or more section(s) have been ignored. Ignored section(s)
- Unable to use 'media' queries in html templates
- Make sure PreserveCompilationContext is set to true
- Update for .NET 8.0, consider removing deprecated .NET versions HOT 9
- Have more than one operatingAssembly ... or included assemblies HOT 1
- Azure functions V4 issue HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from razorlight.