[API Proposal]: Microsoft.Extensions.FileProviders.Physical.PhysicalFilesWatcher should expose modified files (Alternative where standalone FilesystemWatcher won't work)

Open
#110,969 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
25/100
Issue type
Feature
Clarity
Needs clarification
Activity status
Stale
Tech stack
csharp

Research direction

Start by reading the existing PhysicalFilesWatcher, PollingFileChangeToken, IPollingChangeToken, and IChangeToken contracts, then review the concerns and prior discussion referenced in #17111. Done means reaching a concrete, maintainable API direction for exposing changed file information, with its compatibility, performance, and information-hiding tradeoffs resolved.

Written by the indexing model from the issue text.

Description

api-suggestion area-Extensions-FileSystem
Background and motivation

Currently, PhysicalFileProvider provides a configurable file modification detector via PhysicalFilesWatcher wrapped by FilesystemWatcher and offers a polling feature on request (either by API or via environment variables).

Unfortunately, IChangeToken hides file path information of the actual file changes to API user/client code. While information hiding is a quite common design technique, file path information may become quite useful for API users, especially when polling is the only option available to achieve modification tracking/observation and a fallback to a custom implementation based on (good-old) FilesystemWatcher is not an option.

Please consider to either enhance IPollingChangeToken to expose (physical) FileInfo or provide an extra IChangeToken which exposes file paths for all behaviors implemented in PhysicalFilesWatcher.

API Proposal
namespace Microsoft.Extensions.FileProviders.Physical
{
  
    public class PollingFileChangeToken : IPollingChangeToken
    {
        private readonly FileInfo _fileInfo;
        private DateTime _previousWriteTimeUtc;
        private DateTime _lastCheckedTimeUtc;
        private bool _hasChanged;
        private CancellationTokenSource? _tokenSource;
        private CancellationChangeToken? _changeToken;

        public PollingFileChangeToken(FileInfo fileInfo)
        {
            _fileInfo = fileInfo;
            _previousWriteTimeUtc = GetLastWriteTimeUtc();
        }


      public IFileInfo FileInfo => __fileInfo ;

  }
API Usage
  PhysicalFileProviderfileProvider = new (Directory.GetCurrentDirectory());
  CompositeChangeToken token = fileProvider.Watch(_fileFilter) as CompositeChangeToken ;
  ConcurrentQueue<IFileInfo> changeList = new ();

   token.RegisterChangeCallback(state => 
   {
         IFileInfo[] modifcationList =  token.ChangeTokens
                                             .Cast<PollingFileChangeToken>()
                                             .Select(token => token.FileInfo )
                                             .ToArray();
   } , default);

Drawback: This approch might not be perfomant. Neither it provides an elegant solution.

Alternative Designs

Alternativly please consider to extract polling feature as an independent (refactored/extracted) PollingFilesystemWatcher which offfers either customized IChangeToken or Rx.NET support if changing information hiding policy here violates IChangeToken concept or any SOLID principle , I might have missed in my orginal propoals (due to lack of insight and/or overview of your orginal design consideration and usage).

namespace Microsoft.Extensions.FileProviders.Physical
{
    /// <summary>
    /// Watches a physical file system for changes and triggers events on
    /// <see cref="IChangeToken" /> when files are created, change, renamed, or deleted.
    /// </summary>
    public class PhysicalFilesWatcher : IDisposable
    {
        
          public IObserable<IFileInfo> WhenFileSystemEntryChange()  
        
    }

Or

namespace Microsoft.Extensions.FileProviders
{
    public interface IFileChangeToken : IChangeToken
    {

        public IFileInfo RootPath { get; }

        IDisposable RegisterChangeCallback(Action<IFileInfo?> callback, object? state);

    }
}
 


namespace Microsoft.Extensions.FileProviders.Physical
{
   

   /// <summary>
    /// Watches a physical file system for changes and triggers events on
    /// <see cref="IChangeToken" /> when files are created, change, renamed, or deleted.
    /// </summary>
    public class PhysicalFilesWatcher : IDisposable
    {
        
          public IFileChangeToken  Start()  
        
    }

MIght Pick up some ideas already discussed in #17111

Risks
  • Violation of information hiding policy or intended contracts
  • Violoation of even more SOLID principles by just exposing IFileInfo when extraction and adding another level of abstraction might offer a more plausbile and solid concept
  • API suggestion (currently) neither elegant nor performant
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from dotnet/runtime

All issues in dotnet/runtime

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.