MichaCo / CacheManager

CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features.
http://cachemanager.michaco.net
Apache License 2.0
2.33k stars 458 forks source link

GzJsonCacheSerializer The magic number in GZip header is not correct. Make sure you are passing in a GZip stream. #283

Closed macchmie3 closed 4 years ago

macchmie3 commented 4 years ago

Hi, I started using GzJsonCacheSerializer and I noticed that sometimes I get an exception like the following one:

System.IO.InvalidDataException: The magic number in GZip header is not correct. Make sure you are passing in a GZip stream.
   at System.IO.Compression.GZipDecoder.ReadHeader(InputBuffer input)
   at System.IO.Compression.Inflater.Decode()
   at System.IO.Compression.Inflater.Inflate(Byte[] bytes, Int32 offset, Int32 length)
   at System.IO.Compression.DeflateStream.Read(Byte[] array, Int32 offset, Int32 count)
   at System.IO.Compression.GZipStream.Read(Byte[] array, Int32 offset, Int32 count)
   at CacheManager.Serialization.Json.GzJsonCacheSerializer.Decompression(Byte[] compressedData)
   at CacheManager.Serialization.Json.GzJsonCacheSerializer.Deserialize(Byte[] data, Type target)
   at CacheManager.Redis.RedisValueConverter.Deserialize(RedisValue value, String valueType)
   at CacheManager.Redis.RedisValueConverter.CacheManager.Redis.IRedisValueConverter<System.Object>.FromRedisValue(RedisValue value, String type)
   at CacheManager.Redis.RedisCacheHandle`1.FromRedisValue(RedisValue value, String valueType)
   at CacheManager.Redis.RedisCacheHandle`1.GetCacheItemAndVersion(String key, String region, Int32& version)
   at CacheManager.Redis.RedisCacheHandle`1.<>c__DisplayClass42_0.<Update>b__0()
   at CacheManager.Redis.RetryHelper.Retry[T](Func`1 retryme, Int32 timeOut, Int32 retries, ILogger logger)
   at CacheManager.Redis.RedisCacheHandle`1.Retry[T](Func`1 retryme)
   at CacheManager.Redis.RedisCacheHandle`1.Update(String key, String region, Func`2 updateValue, Int32 maxRetries)
   at CacheManager.Core.BaseCacheManager`1.UpdateInternal(BaseCacheHandle`1[] handles, String key, String region, Func`2 updateValue, Int32 maxRetries, Boolean throwOnFailure, TCacheValue& value)
   at CacheManager.Core.BaseCacheManager`1.TryUpdate(String key, String region, Func`2 updateValue, Int32 maxRetries, TCacheValue& value)
   at CacheManager.Core.BaseCacheManager`1.AddOrUpdateInternal(CacheItem`1 item, Func`2 updateValue, Int32 maxRetries)
   at CacheManager.Core.BaseCacheManager`1.AddOrUpdate(CacheItem`1 addItem, Func`2 updateValue, Int32 maxRetries)
   at CacheManager.Core.BaseCacheManager`1.AddOrUpdate(String key, String region, TCacheValue addValue, Func`2 updateValue, Int32 maxRetries)
   at Powel.Contractor.Infrastructure.Cache.Extensions.CacheManagerExtensions.TryAddOrUpdate[T](ICacheManager`1 cache, String key, String tenantId, T addValue, Func`2 updateFunc)

We use the same Redis server across multiple apps and all are configured as follows:

cache = CacheFactory.Build(settings =>
                {
                    settings.WithGzJsonSerializer()
                        .WithUpdateMode(CacheUpdateMode.Up)
                        .WithMaxRetries(int.Parse(ConfigurationManager.AppSettings["azure.cache.maxRetries"]))
                        .WithMicrosoftMemoryCacheHandle("inProcessCache")
                        .And
                        .WithRedisConfiguration("RedisCache", secretsManager.GetSecret("RedisConnection"))
                        .WithRedisBackplane("RedisCache")
                        .WithRedisCacheHandle("RedisCache")
                        .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromMinutes(int.Parse(ConfigurationManager.AppSettings["azure.cache.expirationInMinutes"])));
                });

Do you know If i need any extra code or annotations on serialized/deserialized classess? Can it be connected to the fact that we use this cache on several machines? (allthough all have the same nuget versions etc.) All of the errors appear during deserialization of course.

MichaCo commented 4 years ago

Could that be old cached values which were not serialized with GZip? And now you try to deserialize them with GZip? You might have to clean up your redis cache

macchmie3 commented 4 years ago

@MichaCo

Yes, since I have multiple apps "talking" to the same instance of Redis server, I must have omitted one of the Apps. Thanks for your help.