Browse Source

Add locking in cache manager.

pull/967/head
Sebastian 4 years ago
parent
commit
d86072a346
  1. 152
      backend/src/Squidex.Web/Pipeline/CachingManager.cs

152
backend/src/Squidex.Web/Pipeline/CachingManager.cs

@ -50,22 +50,24 @@ public sealed class CachingManager : IRequestCache
public void AddDependency(string key, long version) public void AddDependency(string key, long version)
{ {
if (!string.IsNullOrWhiteSpace(key)) if (string.IsNullOrWhiteSpace(key))
{ {
slimLock.EnterWriteLock(); return;
try }
{
keys.Add(key);
hasher.AppendData(Encoding.Default.GetBytes(key)); slimLock.EnterWriteLock();
hasher.AppendData(BitConverter.GetBytes(version)); try
{
keys.Add(key);
hasDependency = true; hasher.AppendData(Encoding.Default.GetBytes(key));
} hasher.AppendData(BitConverter.GetBytes(version));
finally
{ hasDependency = true;
slimLock.ExitWriteLock(); }
} finally
{
slimLock.ExitWriteLock();
} }
} }
@ -73,19 +75,21 @@ public sealed class CachingManager : IRequestCache
{ {
var formatted = value?.ToString(); var formatted = value?.ToString();
if (formatted != null) if (formatted == null)
{ {
slimLock.EnterWriteLock(); return;
try }
{
hasher.AppendData(Encoding.Default.GetBytes(formatted));
hasDependency = true; slimLock.EnterWriteLock();
} try
finally {
{ hasher.AppendData(Encoding.Default.GetBytes(formatted));
slimLock.ExitWriteLock();
} hasDependency = true;
}
finally
{
slimLock.ExitWriteLock();
} }
} }
@ -100,82 +104,92 @@ public sealed class CachingManager : IRequestCache
// Set to finish before we start to ensure that we do not call it again in case of an error. // Set to finish before we start to ensure that we do not call it again in case of an error.
isFinished = true; isFinished = true;
if (hasDependency && !response.Headers.ContainsKey(HeaderNames.ETag)) slimLock.EnterWriteLock();
try
{ {
using (Telemetry.Activities.StartActivity("CalculateEtag")) if (hasDependency && !response.Headers.ContainsKey(HeaderNames.ETag))
{ {
var cacheBuffer = hasher.GetHashAndReset(); using (Telemetry.Activities.StartActivity("CalculateEtag"))
var cacheString = cacheBuffer.ToHexString(); {
var cacheBuffer = hasher.GetHashAndReset();
var cacheString = cacheBuffer.ToHexString();
response.Headers.Add(HeaderNames.ETag, cacheString); response.Headers.Add(HeaderNames.ETag, cacheString);
}
} }
}
if (keys.Count > 0 && maxKeysSize > 0) if (keys.Count > 0 && maxKeysSize > 0)
{
var stringBuilder = stringBuilderPool.Get();
try
{ {
foreach (var key in keys) var stringBuilder = stringBuilderPool.Get();
try
{ {
var encoded = Uri.EscapeDataString(key); foreach (var key in keys)
if (stringBuilder.Length == 0)
{ {
if (stringBuilder.Length + encoded.Length > maxKeysSize) var encoded = Uri.EscapeDataString(key);
if (stringBuilder.Length == 0)
{ {
break; if (stringBuilder.Length + encoded.Length > maxKeysSize)
{
break;
}
} }
} else
else
{
if (stringBuilder.Length + encoded.Length + 1 > maxKeysSize)
{ {
break; if (stringBuilder.Length + encoded.Length + 1 > maxKeysSize)
{
break;
}
stringBuilder.Append(' ');
} }
stringBuilder.Append(' '); stringBuilder.Append(encoded);
} }
stringBuilder.Append(encoded); if (stringBuilder.Length > 0)
{
response.Headers["Surrogate-Key"] = stringBuilder.ToString();
}
} }
finally
if (stringBuilder.Length > 0)
{ {
response.Headers["Surrogate-Key"] = stringBuilder.ToString(); stringBuilderPool.Return(stringBuilder);
} }
} }
finally
if (headers.Count > 0)
{ {
stringBuilderPool.Return(stringBuilder); response.Headers[HeaderNames.Vary] = new StringValues(headers.ToArray());
} }
} }
finally
if (headers.Count > 0)
{ {
response.Headers[HeaderNames.Vary] = new StringValues(headers.ToArray()); slimLock.ExitWriteLock();
} }
} }
public void AddHeader(string header, StringValues values) public void AddHeader(string header, StringValues values)
{ {
if (!string.IsNullOrWhiteSpace(header)) if (string.IsNullOrWhiteSpace(header))
{ {
try return;
{ }
slimLock.EnterWriteLock();
headers.Add(header); try
} {
finally slimLock.EnterWriteLock();
{
slimLock.ExitWriteLock();
}
foreach (var value in values) headers.Add(header);
{ }
AddDependency(value); finally
} {
slimLock.ExitWriteLock();
}
foreach (var value in values)
{
AddDependency(value);
} }
} }
} }

Loading…
Cancel
Save