1111
1212namespace ManagedCode . Storage . VirtualFileSystem . Streaming ;
1313
14- /// <summary>
15- /// Write stream implementation for VFS that buffers data and uploads on dispose
16- /// </summary>
1714internal class VfsWriteStream : Stream
1815{
1916 private readonly IStorage _storage ;
@@ -56,36 +53,12 @@ public VfsWriteStream(
5653 public override bool CanWrite => ! _disposed && _bufferStream . CanWrite ;
5754 public override long Length => _bufferStream . Length ;
5855
59- public override long Position
60- {
61- get => _bufferStream . Position ;
62- set => _bufferStream . Position = value ;
63- }
64-
65- public override void Flush ( )
66- {
67- _bufferStream . Flush ( ) ;
68- }
69-
70- public override async Task FlushAsync ( CancellationToken cancellationToken )
71- {
72- await _bufferStream . FlushAsync ( cancellationToken ) ;
73- }
74-
75- public override int Read ( byte [ ] buffer , int offset , int count )
76- {
77- throw new NotSupportedException ( "Read operations are not supported on write streams" ) ;
78- }
79-
80- public override long Seek ( long offset , SeekOrigin origin )
81- {
82- return _bufferStream . Seek ( offset , origin ) ;
83- }
84-
85- public override void SetLength ( long value )
86- {
87- _bufferStream . SetLength ( value ) ;
88- }
56+ public override long Position { get => _bufferStream . Position ; set => _bufferStream . Position = value ; }
57+ public override void Flush ( ) => _bufferStream . Flush ( ) ;
58+ public override Task FlushAsync ( CancellationToken cancellationToken ) => _bufferStream . FlushAsync ( cancellationToken ) ;
59+ public override int Read ( byte [ ] buffer , int offset , int count ) => throw new NotSupportedException ( "Read operations are not supported on write streams" ) ;
60+ public override long Seek ( long offset , SeekOrigin origin ) => _bufferStream . Seek ( offset , origin ) ;
61+ public override void SetLength ( long value ) => _bufferStream . SetLength ( value ) ;
8962
9063 public override void Write ( byte [ ] buffer , int offset , int count )
9164 {
@@ -99,16 +72,16 @@ public override void Write(ReadOnlySpan<byte> buffer)
9972 _bufferStream . Write ( buffer ) ;
10073 }
10174
102- public override async Task WriteAsync ( byte [ ] buffer , int offset , int count , CancellationToken cancellationToken )
75+ public override Task WriteAsync ( byte [ ] buffer , int offset , int count , CancellationToken cancellationToken )
10376 {
10477 ThrowIfDisposed ( ) ;
105- await _bufferStream . WriteAsync ( buffer , offset , count , cancellationToken ) ;
78+ return _bufferStream . WriteAsync ( buffer , offset , count , cancellationToken ) ;
10679 }
10780
108- public override async ValueTask WriteAsync ( ReadOnlyMemory < byte > buffer , CancellationToken cancellationToken = default )
81+ public override ValueTask WriteAsync ( ReadOnlyMemory < byte > buffer , CancellationToken cancellationToken = default )
10982 {
11083 ThrowIfDisposed ( ) ;
111- await _bufferStream . WriteAsync ( buffer , cancellationToken ) ;
84+ return _bufferStream . WriteAsync ( buffer , cancellationToken ) ;
11285 }
11386
11487 protected override void Dispose ( bool disposing )
@@ -117,7 +90,6 @@ protected override void Dispose(bool disposing)
11790 {
11891 try
11992 {
120- // Upload the buffered data
12193 UploadBufferedDataAsync ( ) . GetAwaiter ( ) . GetResult ( ) ;
12294 }
12395 catch ( Exception ex )
@@ -137,35 +109,30 @@ protected override void Dispose(bool disposing)
137109
138110 public override async ValueTask DisposeAsync ( )
139111 {
140- if ( ! _disposed )
112+ if ( _disposed ) { await base . DisposeAsync ( ) ; return ; }
113+
114+ try
141115 {
142- try
143- {
144- await UploadBufferedDataAsync ( ) ;
145- }
146- catch ( Exception ex )
147- {
148- _logger . LogError ( ex , "Error uploading data during stream dispose: {BlobKey}" , _blobKey ) ;
149- throw ;
150- }
151- finally
152- {
153- await _bufferStream . DisposeAsync ( ) ;
154- await _bufferFile . DisposeAsync ( ) ;
155- _disposed = true ;
156- }
116+ await UploadBufferedDataAsync ( ) ;
117+ }
118+ catch ( Exception ex )
119+ {
120+ _logger . LogError ( ex , "Error uploading data during stream dispose: {BlobKey}" , _blobKey ) ;
121+ throw ;
122+ }
123+ finally
124+ {
125+ await _bufferStream . DisposeAsync ( ) ;
126+ await _bufferFile . DisposeAsync ( ) ;
127+ _disposed = true ;
157128 }
158129
159130 await base . DisposeAsync ( ) ;
160131 }
161132
162133 private async Task UploadBufferedDataAsync ( )
163134 {
164- if ( _bufferStream . Length == 0 )
165- {
166- _logger . LogDebug ( "No data to upload for: {BlobKey}" , _blobKey ) ;
167- return ;
168- }
135+ if ( _bufferStream . Length == 0 ) { _logger . LogDebug ( "No data to upload for: {BlobKey}" , _blobKey ) ; return ; }
169136
170137 _logger . LogDebug ( "Uploading buffered data: {BlobKey}, size: {Size}" , _blobKey , _bufferStream . Length ) ;
171138
@@ -181,34 +148,28 @@ private async Task UploadBufferedDataAsync()
181148 } ;
182149
183150 var result = await _storage . UploadAsync ( _bufferStream , uploadOptions ) ;
184-
185151 if ( ! result . IsSuccess )
186- {
187152 throw new VfsOperationException ( $ "Failed to upload data for: { _blobKey } . Error: { result . Problem } ") ;
188- }
189-
190- // Invalidate cache after successful upload
191- if ( _vfsOptions . EnableCache )
192- {
193- var existsKey = $ "file_exists:{ _vfsOptions . DefaultContainer } :{ _blobKey } ";
194- _cache . Remove ( existsKey ) ;
195- var metadataCacheKey = $ "file_metadata:{ _vfsOptions . DefaultContainer } :{ _blobKey } ";
196- _cache . Remove ( metadataCacheKey ) ;
197- var customKey = $ "file_custom_metadata:{ _vfsOptions . DefaultContainer } :{ _blobKey } ";
198- _cache . Remove ( customKey ) ;
199- }
200153
154+ InvalidateCache ( ) ;
201155 _logger . LogDebug ( "Successfully uploaded data: {BlobKey}" , _blobKey ) ;
202156 }
203- catch ( Exception ex ) when ( ! ( ex is VfsOperationException ) )
157+ catch ( Exception ex ) when ( ex is not VfsOperationException )
204158 {
205159 _logger . LogError ( ex , "Error uploading buffered data: {BlobKey}" , _blobKey ) ;
206160 throw new VfsOperationException ( $ "Failed to upload data for: { _blobKey } ", ex ) ;
207161 }
208162 }
209163
210- private void ThrowIfDisposed ( )
164+ private void InvalidateCache ( )
211165 {
212- ObjectDisposedException . ThrowIf ( _disposed , this ) ;
166+ if ( ! _vfsOptions . EnableCache )
167+ return ;
168+
169+ _cache . Remove ( $ "file_exists:{ _vfsOptions . DefaultContainer } :{ _blobKey } ") ;
170+ _cache . Remove ( $ "file_metadata:{ _vfsOptions . DefaultContainer } :{ _blobKey } ") ;
171+ _cache . Remove ( $ "file_custom_metadata:{ _vfsOptions . DefaultContainer } :{ _blobKey } ") ;
213172 }
173+
174+ private void ThrowIfDisposed ( ) => ObjectDisposedException . ThrowIf ( _disposed , this ) ;
214175}
0 commit comments