CacheTower: Upgrading from v0.11.x to Custom Serializers with RedisCacheLayer breaks existing caches

What does the bug do?

The new Protobuf serializer breaks upgrade path from 0.11.x to latest when used in conjunction with the Redis layer

ProtoBuf.ProtoException: Invalid wire-type (Varint); this usually means you have over-written a file without truncating or setting the length; see https://stackoverflow.com/q/2152978/23354
   at ProtoBuf.ProtoReader.State.ThrowProtoException(String message) in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 770
   at ProtoBuf.ProtoReader.State.ThrowWireTypeException() in /_/src/protobuf-net.Core/ProtoReader.State.ReadMethods.cs:line 763
   at proto_8(State& , CachedFeature )
   at ProtoBuf.ProtoReader.State.ReadMessage[TSerializer,T](SerializerFeatures features, T value, TSerializer& serializer)
   at proto_6(State& , CacheEntry`1 )
   at ProtoBuf.ProtoReader.State.ReadAsRoot[T](T value, ISerializer`1 serializer)
   at ProtoBuf.ProtoReader.State.DeserializeRoot[T](T value, ISerializer`1 serializer)
   at ProtoBuf.Serializer.Deserialize[T](Stream source)
   at CacheTower.Providers.Redis.RedisCacheLayer.GetAsync[T](String cacheKey)
   at CacheTower.CacheStack.GetWithLayerIndexAsync[T](String cacheKey)
   at CacheTower.CacheStack.GetOrSetAsync[T](String cacheKey, Func`2 valueFactory, CacheSettings settings)
   at CacheTower.CacheStack`1.GetOrSetAsync[T](String cacheKey, Func`3 getter, CacheSettings settings)

How can it be reproduced?

Generate some caches in a redis layer on 0.11.3 Update CacheTower to latest Read caches

Diagnostic

I believe the issue stems from the fact that historically this wrapper was used when persisting items to the redis cache layer

https://github.com/TurnerSoftware/CacheTower/pull/172/files#diff-972f6f8307717fcd20b6599842d83ab73931e2aa4b483e5076ab39d5f5109e0dL13

Now, CacheEntry’T is used directly.

I’m not quite sure how this type serializes without the ProtoXXX attributes on the class, but magically it does. Unfortunately, it isn’t binary compatible with RedisCacheEntry and things go bang.

Obviously we could consider purging the cache to solve the issue, but the problem is more significant for us as we have a wide range of services, and we would have to take everything offline, update them all, purge old caches, then bring it all back up again in order to update.

Any ideas would be appreciated!

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 32 (31 by maintainers)

Most upvoted comments

@Turnerj We just got hit by this as well on a clear cache instance. I found one of our developers had added an explicit reference to protobuf-net in a project in order to get the model attributes (ProtoContract etc). Versions > 3.1.22 now throw during the serializer constructor (I’m assuming that’s when protobuf-net changed behavior per your bug report). This was not easy to track down so we’d really appreciate a CacheTower update to fix this.

Very interesting! Thanks for the investigation, glad we have an answer for the strangeness now.

There isn’t any rush for the changes, I was only just getting around to upgrading (finally!) from 0.11.3! Thanks for taking the time to look at the issue!

Next thing I would quickly check is if you define the RuntimeTypeConfig specifically with CacheEntry<string> rather than the open-generic workaround. Then we have reduced it to it’s simplest form?

Technically it isn’t an open generic, that’s what the magic is actually trying to fix. The T type you see that we pass into the RuntimeTypeModel is the CacheEntry<YourType>.

image 😦

Sorry, ignore me, that’s a different type 🤦