Removing orphaned entities following 'clear-orphans' command - symfony

I'm using the OneUp Uploader Bundle, with the orphanage, and I'm unsure about how to handle cleaning up entities (that were created by the listener), after the file has been cleaned up by the 'clear-orphans' command - how is this commonly handled?
I'd love to see an event fired for each file that is cleaned up (passing the filename and the mapping) but haven't found anything (assuming the event dispatcher is available to a command).

The idea of the orphanage in the OneupUploaderBundle is that you don't pollute your upload folder with files that don't belong to any entities. This implies that if you use the uploaded files in your entities you should move them out of the orphanage. If you configured a mapping to use the orphanage, all the uploaded files will be stored in a separate folder after uploading.
Citing the documentation:
They will be moved to the correct place as soon as you trigger the uploadFiles method on the Storage.
This means that you can move the logic out of the event listener (which will be called non the less), but move it to the controller where you want to finally upload and store the files in the orphanage.
// src/Acme/Controller/AcmeController.php
class AcmeController extends Controller
{
public function storeAction()
{
// ...
if ($form->isValid()) {
$orphanageManager = $this->get('oneup_uploader.orphanage_manager')->get('gallery');
// upload all files to the configured storage
$files = $manager->uploadFiles();
// your own logic to apply the files to the entity
// ...
}
}
}
Be sure to only use the orphanage if you really have to. It has some drawbacks.

Related

in ASP.NET core (.NET5) how can i write logs for each request on separate files? Using Serilog or other

I'm new to .NET and to webservice development, so i'm not exactly sure how to implement the requirement i have.
My webservice gets a POST request with some data, which i need to
process to generate a pdf file: name_YYYYMMDDHHmmss.pdf.
For monitoring this i want to have a separate logfile for each request, named like the output file: name_YYYYMMDDHHmmss.log
I would like to avoid passing a config object into every class/function in which i need to add stuff to the log file
I've managed to install Serilog and it works for what i need, but not when i get concurrent requests. I'm also not exactly sure how simultaneous requests are handled in .NET (i have no thread specific code written so far), but as far as i can tell, when i change Global Logger file name, that object is shared across all threads so all of them write to the same file.
I've looked at a bunch of solutions, but i haven't managed to find nothing that suits this, and it seems most people have everything into 1 file...
Is there any clue or tips you can give me? I'm open to using something other than Serilog.
One way to have dynamic file names based on a specific context is by using the Serilog.Sinks.Map and then, via a middleware in the request pipeline, you can add a property to the log context that drives the file name to be used when writing to the log.
Examples of similar usage of Serilog.Sinks.Map to decide which file name to use at run-time:
Serilog - can not log to multiple files based on property
In Serilog dynamically changing log file path?
The best solution that I found to this problem was using Serilog.Sinks.Map. I configured my Logger something like this:
Log.Logger = new LoggerConfiguration()
.WriteTo.Map("Name", "Default", (name, wt) => {
var fileName = name == "Default" ? "log" : $"{log-{name}}"
wt.File($"./{fileName}-.txt");
}).CreateLogger();
Then on my controller, on each method where I needed this feature, I enclosed all the instructions inside a LongContext like this:
[HttpGet]
public IHttpActionResult Get() {
using (LogContext.PushProperty("Name", "theFileName") {
// ...
_myService.Method1();
// ...
}
}
public class MyService : IMyService {
// ...
public void Method1() {
// ...
Log.Information("This is what happened at this point…");
// ...
}
// ...
}
So all the Log's inside will use that context and it will write on a different file with the name you set for that context without having to modify any Log.Information/Error/Warning/etc that you already have on your code.
This is the ugly part... you have to define a context on a root place in order to make those Logs write on a different file. So for a controller method, the first thing you have to do is to enclose all with a LogContext.

Symfony2/Doctrine: How to persist an entity from the entity class?

Short Description of the problem:
I generate a file inside the entity class and would like to save the filename to the database. The controller doesn't know about this (wheter or not the filename has changed, so it's not practical to persist from the controller.
Is there a way for an Entity to persist itself?
Example of my use:
The entity class is for an image in a gallery. I always keep the original file and work with a cached version of the file. When the image is changed (rotated for example), the cached version is deleted. The cached version also be deleted in other cases. When the file is needed, I check if the cached file exists, otherwise it is regenerated with a new filename from the archived image. I need a new filename because that resets the cache for various thumbnail sizes.
When I generate that new file, I have to save its filename to the database somehow. Because it is only decided in the Entity when to regenerate the image, it would be practical if the entity could persist itself to the database, but I haven't found a solution for that.
Is there a way to do this or is there a whole different concept I should be using to regenerate the image file?
Entities in Doctrine are not active records - they cannot perform persistance actions by themselves, so they rely on a Big Brother [the entity manager].
Even if the controller doesn't know wether any filename as changed or not, you do - just persist your picture every time: if nothing changed, Doctrine won't touch the entity.
Have a look at lifecycle events too, maybe you can find useful to fire a #PreUpdate method before persistance [e.g. generating thumbnails].

How to dynamically load and switch the resource file in the web app (ASP.NET) without recompiling?

I would like to store the resource files (containing texts for labels etc.) for my web application in the database to be able to edit and create them dynamically later (probably in the UI). My idea was to store the whole resx file in an xml column and simply load it on demand - depending on the language and some other attributes of the current user when he is logging into the application or switching the context. The important thing is that the resources do not only depend on the culture info of the user but also on some context information that can be switched by user without logging off and on again (in our case called "group", not having anything to do with a group of users).
Is it possible somehow to load the contents of the resources from an external source and simply switch them without web application being recompiled by the server ? I know that there are some interfaces on which I could hook up and implement a custom resources provider which reads from the database directly but if it could work somehow with the resx files it would probably make things a lot easier..
Pretty late but since there is no answer as of yet.
System.Resources.ResourceReader resourceReader
= new System.Resources.ResourceReader("PathToResourceFile");
That's pretty much it. Now you can create resource files like en.resx or de.resx and load them depending on the users language. Something like
System.Resources.ResourceReader resourceReader
= new System.Resources.ResourceReader(HttpContext.Current.Request.UserLanguages[0]
+ ".resource");
Keep in mind to provide a default language (resource file) for a user with a language you don't support.
Edit:
Take a look at this link.
The question is 6 years old, but I'm still gonna answer it :)
To read .resx files, you need to use System.Resources.ResXResourceReader class from System.Windows.Forms.dll
This is nicely explained here. Just a quick sample for completeness:
using (ResXResourceReader resxReader = new ResXResourceReader(#".\CarResources.resx"))
{
foreach (DictionaryEntry entry in resxReader) {
// ...
}
}
Sure you can do this easily, and it works for straight XML files. You don't need to use a resx file.
/// <summary>
/// Sets or replaces the ResourceDictionary by dynamically loading
/// a Localization ResourceDictionary from the file path passed in.
/// </summary>
/// <param name="resourceDictionaryFile">The resource dictionary to use to set/replace
/// the ResourceDictionary.</param>
private void SetCultureResourceDictionary(String resourceDictionaryFile)
{
// Scan all resource dictionaries and remove, if it is string resource distionary
for ( int index= 0; index < Resources.MergedDictionaries.Count; ++index)
{
// Look for an indicator in the resource file that indicates the resource is
// swappable. For instance in our files the header contains this:
// <sys:String x:Key="ResourceDictionaryName">Resources-en-CA</sys:String>
if (Resources.MergedDictionaries[index].Contains("ResourceDictionaryName"))
{
if ( File.Exists(resourceDictionaryFile) )
{
Resources.MergedDictionaries.Remove(Resources.MergedDictionaries[index]);
}
}
}
// read required resource file to resource dictionary and add to MergedDictionaries collection
ResourceDictionary newResourceDictionary = new ResourceDictionary();
newResourceDictionary.Source = new Uri(resourceDictionaryFile);
Resources.MergedDictionaries.Add(newResourceDictionary);
}

Reading Application Configuration during Application_Start

Consider a web application that resizes large tiff files on the fly. Each large tiff file is resized into a jpg thumbnail and larger jpg when the user invokes the operation. The dimensions of these converted files is always the same.
During a code review yesterday, one of the other developers asked me why I set those dimensions in my global.asax like so:
Application["resizedImageWidth"] = int.Parse(ConfigurationManager.AppSettings["ResizedImageWidth"]);
, instead of just looking up the value via a Configuration file during the actual method invocation. I store the widths in the configuration file in the event the end user's after testing the application would like to alter dimensions so I would not have to change code inline.
The reasoning I gave was to prevent the read from the configuration file each time an image was generated, but could not answer if there was similar overhead during a lookup to application level variables. This optimization probably doesn't affect performance to a large scale, but I wanted to know what the community thought the more efficient solution was, i.e. set them during Application start up, or read them on the fly during method invocation.
Generally you should read from the configuration on the fly as you need it. The framework will cache the configuration file, so it is fairly performant. And I believe (Don't quote me) that ASP.Net can monitor and bring in the changes to a configuration file without restarting the application.
I typically like to create a Configuration class which will hide the details of where the value is stored:
public static class Config
{
public static int GetXDimension()
{
...
}
}
This keeps your calling code clean from the configuration code, and if you find I'm wrong, you won't have to change your code everywhere.
You are correct to store this value in an Application object. Indeed, that is the express purpose behind the provision of Application: to hold values that are to be available across all pages and users of the application.
It will indeed be more performant as the application settings are held in memory. It should be pretty obvious that reading from memory is significantly faster than reading from your configuration file (not to mention the lookup via the ConfigurationManager.AppSettings class method and the integer parse).
Any changes to the web.config file will indeed result in a restart of the application. Indeed, this is how I restart my application (when needed) during testing. If you need to change this value "on the fly" you may even want to store this value in a "Configuration" table in your database rather than keeping it in the Web.config file so that changing it doesn't reboot the App.
One trick that I have used is similar to Josh's Config class: I have a "BusinessLogic" class and I place a small handful of settings in static variables of this class so that I can access them in a type-safe manner. It isn't hard and the payoff is pretty obvious in terms of readability.
I would recommend expanding Josh's answer and call it on demand, but then cache it into a private variable:
public static class Config
{
private static int? xDimension;
public static int GetXDimension()
{
if(xDimension == null)
xDimension = int.Parse(ConfigurationManager.AppSettings["ResizedImageWidth"]);
return xDimension.Value;
}
}
or into the Application:
public static class Config
{
public static int GetXDimension()
{
if(Application["xDimension"] == null)
Application["xDimension"] = int.Parse(ConfigurationManager.AppSettings["ResizedImageWidth"]);
return (int)Application["xDimension"];
}
}

Write to a log file in ASP.NET

I am writing event data to a log file in an asp.net httphandler by using the File.AppendAllText method. I am concerned with what will happen when multiple requests are received simultaneously. Does AppendAllText lock the file it's writing to?
I recommend using the TextWriterTraceListener instead of trying to manage this your self.
It is very simple to setup and use:
TextWriterTraceListener logListener = new TextWriterTraceListener("C:\log.txt", "My Log Name");
Trace.Listeners.Add(logListener);
And then to log something:
Trace.WriteLine("Log this text");
It is very simple to use and also there are many different types of listeners for SQL, Event Log, text file, etc. So you won't have to adjust your code if you want to change out the listener.
no, you should have a static lock object guarding the log-file write, e.g.
public static object LockingTarget = new object();
public void LogToFile(string msg)
{
lock(LockingTarget)
{
//append to file here as fast as possible
}
}
You can use My.Log to write to log files.
Edit: If you use the FileLogTraceListener, that listener is thread-safe.
Doing this also allows you to control and configure the logging through the web.config file.

Resources