- Improve correctness of internal change counting to ensure that changes that happened during serialization are still tracked.
TryGetValuewill now return true forvalue typesthat have a default value since it is a valid value for them.Upsertcan returnfalseif aRollbackAsyncoccurred concurrently, indicating the write was not reliable relative to the rollback (retry after rollback completes if needed).TryRemoveandTryClearcan returnfalseif aRollbackAsyncoccurred concurrently, indicating the operation was not reliable relative to the rollback.Clearis now obsolete; useTryClearto detect rollback races.
- File based serializers
FileSerializerandAesFileSerializernow use a new base class implementation and have gained the ability tojournal(maintain durability through crashes and otherIOException, and ensure successful atomic write or complete rejection of changes), and cross-process isolation, preventing race condition that could be caused when multiple processes try to access the sameArrowDbfile.- If you had a class implementing
FileSerializerthis change may or may not break functionality and you should run tests to ensure everything still works as expected (With that said, my tests were not broken and did not require any adjusting).
- If you had a class implementing
- Thread-safe counters types were changed from
inttolong, this includesPendingChangesandRunningInstances. ArrowDbTransactionScopewas updated to allow nested transactions, and prevent corruption that can be caused by multiple transactions running concurrently on the sameArrowDbinstance. In addition, it was madepublicand also implements the regularIDisposableinterface to allow usage in synchronous context. However, it is still your responsibility to ensure the contexts match.Upsertand all its overloads will now reject (returnfalse) whenever the value to be upserted is anullreference type. This is to enforce a nonullpolicy that will simplify development by eliminatingnullchecks on retrieved values.
- Random queued (Non serialized) operations are up to 20% faster due to improvement in cross-threaded state management.
- Serialization allocates up to 250% less memory 🔥 across all benchmarks.
GetOrAddAsyncandUpsert(which has theupdateConditionargument) now both have overloads that accept aTArgparameter as well as a modified factory function that can use it, in order to avoid closures.
- Added overloads of
Upsertthat accept astringkey, while theReadOnlySpan<char>overloads are amazing in specific cases where its use can prevent a string allocation for the lookup, in other places where the input was originally astringthat was implicitly converted to aReadOnlySpan<char>for the parameter, this would've caused a copy to be allocated for the key when the key did not exist. The same scenario will now use thestringoverload and use it for the key directly, avoiding the intermediate copy. - Added a
ValueTaskbasedGetOrAddAsyncmethod, commonly used in caching scenarios.
- An overload to
UpsertwithoutupdateConditionwas added and would now act as default path in caseupdateConditionwasn't specified, this should further optimize such cases by removing condition checks and another reference from the stack during runtime. - Internal methods which are rather small and frequently invoked will now be prioritized for inlining by JIT, this should slightly improve perf, especially in NativeAot.
- Added a new factory initializer
CreateFromFileWithAesthat received anAesinstance as parameter. It will then use it to encrypt and decrypt the output and input during serialization and deserialization respectively.
- Fixed issue with
FileSerializerwhere serialization would write over existing file data which could create invalid tokens, causing deserialization to fail. - Added static
ArrowDb.GenerateTypedKey<T>method that accepts the type of the value, specific key (identifier) and a buffer, it returns aReadOnlySpan<char>key that prefixes the type to the specific key.
- Initial Release