chronoxor / NetCoreServer

Ultra fast and low latency asynchronous socket server & client C# .NET Core library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and 10K connections problem solution
https://chronoxor.github.io/NetCoreServer
MIT License
2.74k stars 567 forks source link

Why the cache is not updated? #276

Closed vvyoko closed 10 months ago

vvyoko commented 10 months ago

I use the http server and set static server.AddStaticContent(www); FileSystemWatcher event trigger fine

But cache not update After test I find problem in FileCache.Find Add trigger in file changed Find trigger in request

s0 s1 s2 is the new value but s3 Call in Add() is the new value In browser request is the old value

I suspect they're not even the same instance But b1 and b2 is true

What might be the problem? Sorry for my English...

static FileCache cache1 = new FileCache();
static FileCache cache2 = new FileCache();
public bool Add(string key, byte[] value, TimeSpan timeout = new TimeSpan())
{
    cache1 = this;
    bool b1 = ReferenceEquals(cache1, cache2);
    var response = Find(key);
    string s0 = new string(System.Text.Encoding.UTF8.GetChars(response.Item2));
    using (new ReadLock(_lockEx))
    {
        if (_entriesByKey.TryGetValue(key, out var cacheValue))
        {
            string s1 = new string(System.Text.Encoding.UTF8.GetChars(cacheValue.Value));
        }
    }

    using (new WriteLock(_lockEx))
    {
        string s2 = new string(System.Text.Encoding.UTF8.GetChars(value));
        _entriesByKey[key] = new MemCacheEntry(value, timeout);
        return true;
    }
}

 public (bool, byte[]) Find(string key)
 {
     cache2 = this;
     bool b2 = ReferenceEquals(cache1, cache2);
     using (new ReadLock(_lockEx))
     {
         // Try to find the given key
         if (!_entriesByKey.TryGetValue(key, out var cacheValue))
             return (false, new byte[0]);

         string s3 = new string(System.Text.Encoding.UTF8.GetChars(cacheValue.Value));

         return (true, cacheValue.Value);
     }
 }
stratdev3 commented 10 months ago

Depending what process is updating (writing) your static file, there is a glitch with the underlying FileSystemWatcher not reading correct data. This lead to incorrect cache update.

The bug can be reproduced by using server.AddStaticContent(www); and editing some html/js/css files with VisualCode. Then, after writing, NetCoreServer does not see the change.

vvyoko commented 10 months ago

Depending what process is updating (writing) your static file, there is a glitch with the underlying FileSystemWatcher not reading correct data. This lead to incorrect cache update.

The bug can be reproduced by using server.AddStaticContent(www); and editing some html/js/css files with VisualCode. Then, after writing, NetCoreServer does not see the change.

FileSystemWatcher event trigger fine

For test,just put a test.txt in www Every change will trigger Add() func and in Add() func s0 s1 s2 can get the new value and Call Find() in Add() it can get the new value

just request outside(browser or etc...) it get the first value breakpoint in s3 will get thd first value

stratdev3 commented 10 months ago

Depending the tool (ie: vscode, sublime text...) used to edit a file while server is running, events like OnChanged() can be fired multiple times with read or write lock by the underlying saving process.

So ReadAllBytes() will at best thrown an exception and sometimes return 0 byte content. Cache will be invalid.

I made a workaround for this based on a on retry (try/catch/sleep/read). Works for 2 yr in production.

vvyoko commented 10 months ago

Depending the tool (ie: vscode, sublime text...) used to edit a file while server is running, events like OnChanged() can be fired multiple times with read or write lock by the underlying saving process.

So ReadAllBytes() will at best thrown an exception and sometimes return 0 byte content. Cache will be invalid.

I made a workaround for this based on a on retry (try/catch/sleep/read). Works for 2 yr in production.

Sorry,It seems like we're all talking to each other ReadAllBytes() work fine in my case I debug in vs step and step,s2 can get value

Now problem is Find() in server can return new value but in client if always return this filrst value(not updata)

I just test httpserver in examples

int port = 7777;
string www = @"D:\www";
var server = new HttpCacheServer(IPAddress.Any, port);
server.AddStaticContent(www);

in D:\www ,just a file test.text change file Then flush page http://localhost:7777/test.txt It not changed

chronoxor commented 10 months ago

Reproduced! I'll fix this soon

chronoxor commented 10 months ago

Fixed in 8.0.4

vvyoko commented 10 months ago

Fixed in 8.0.4

Thx,it work fine now