Closed MrMDavidson closed 5 years ago
Just a note on this; I'm not sure how to manage this, it ties into #50, but I'd suggest going forward for "new" installs making either the SHA2-512, or human+SHA2-512, based naming scheme the default. They both have the advantage of not imposing a limit on the length of the saga data type name as well as allowing generic saga data types to not conflict on the same correlation id (Eg. BaseSagaData<RemoveCustomer>
will no longer clash with BaseSagaData<AnnualBirthdayReminder>
).
I wonder if it's worth introducing the concept of some kind of "Compatability" level and using a similar approach to ASP.Net Core where you might configure the saga something like this...
config.Sagas(o => o.StoreInSqlServer(SqlSagaCompatabilityVersion.Version_1_0, "connectionString", "Saga", "SagaIndex"));
As API changes are made you'd introduce SqlSagaCompatabilityVersion.Version_1_1
(or whatever). And as a result the saga storage would switch to using a different saga name strategy as a result. Docs would then be updated to say to use SqlSagaCompatabilityVersion.Version_1_1
and so new "users" would get the new naming. But users upgrading wouldn't have everything break on them. 🤔
This supersedes #38 to provide improved saga name handling. It is by default backwards compatible with prior versions... otherwise everyone's sagas would break.
Introduces a new
ISagaTypeNamingStrategy
that can be registered in the injector. If one is not registered at the time theSqlServerSagaStorage
is constructed then a default,LegacySagaTypeNamingStrategy
will be used which generates the name as per the existing method (Type.Name
). However some other versions are provided;Sha512SagaTypeNamingStrategy
: Generates a SHA2-512 hash of the types simple assembly qualified name (This means that, for instance,GenericSagaContainer<SomeUnderlyingType>
will be hashed based on something likeGenericSagaContainer'1[[SomeUnderlyingType]]
. As such, hashes will not clash. Additionally it will take a portion of the hash up to the maximum allowed bytes. According to https://crypto.stackexchange.com/questions/161/should-i-use-the-first-or-last-bits-from-a-sha-256-hash/163#163 this should be safe to do.CachedSagaTypeNamingStrategy
: Intended to wrap around another instance of aISagaTypeNamingStrategy
so that costly saga type name calculations will only be performed once.HumanReadableHashedSagaTypeNamingStrategy
: ExtendsSha512SagaTypeNamingStrategy
so that a portion of the class name is prefixed before the hash. For an input ofSampleProject.DeleteCustomerSaga
it'd generate an output something likeDeleteCustHc2dpZJ/0b4cJEQB8rCqQXPYtheEx
instead ofHc2dpZJ/0b4cJEQB8rCqQXPYtheEx78Tvgm7o7H
which is a little harder to peek at the database and see what's going on.Consumers can register their own implementation of
ISagaTypeNamingStrategy
with Injectionist prior to setting upSqlSagaStorage
.WARNING: Using anything other than the default
LegacySagaTypeNamingStrategy
will break any inflight sagas... migration of sagas to new naming schemes is left as an exercise for the reader 😜Rebus is MIT-licensed. The code submitted in this pull request needs to carry the MIT license too. By leaving this text in, I hereby acknowledge that the code submitted in the pull request has the MIT license and can be merged with the Rebus codebase.