Skip to content

Prevalence for .Net avoiding common binary versioning problems

Notifications You must be signed in to change notification settings

jlarsson/Kiwi.Prevalence

Repository files navigation

Kiwi.Prevalence

Kiwi.Prevalence is a .NET System Prevalence Layer. As such, it maintains an application model in memory, providing gated access to ensure consistency and journalling to provide persistence and durability.

License

Quite simple, use this without restrictions, but don't blame us. For a formal specification, checkout the MIT licence.

Prerequisites

  • requires .NET 4.
  • best downloaded from nuget

The model

The application model is mainatined by a Repository<TModel> which owns an instance of your preferred model, TModel.

Gated access

To maintain model consistency over time, its not allowed to interact directly with the model. Instead, the methods Repository<TModel>::Query(λ) and Repository<TModel>::Execute(command) must be used.

Synchronization

Repository<TModel>::Qyery(λ) ensures that your λ (on the form Func<TModel,TResult>) can access the model in assumed read-only mode (a read lock is taken).

Modyfying operations are taken out by Repository<TModel>::Query(command) where the command must implement ICommand<TModel,TResult> and is executed in exclusive-write mode (a write lock is taken).

Marshalling

To further protect the model, results from either Query or Execute is marshalled, which in this contect means that a deep copy of the result is taken. This guarantess that the results are detached from the model, preventing nasty concurrency bugs.

Snapshots

A snapshot is the model serialized to disk. A snapshot in essence captures the model state at a given point in time.

Journalling

All commands must be Json-serializable and are captured in a journal file. Whenever a repository is restored (typically during application startup), the journal is replayed on the current snapshot to catch up with latest changes in the model.

Serialization

The model and all commands must be Json-serializable and Json-deserializable.

  • The JSON format somewhat limits the expressiveness of your model. In particular, it may not contain cycles.
  • The JSON format is chosen since its so forgiving and most of all, human and machine readable.

Actual serialization is carried out by Kiwi.Json.

Persistence

In few words - JSON serialized to disk files. Expect to find some or all of these files

  • <repo name>.journal - contains JSON-serialized commands
  • <repo name>.snapshot - contains a JSON-serialized model
  • <repo name>.journal.<revision> - backup of journal taken at a specific journal revision
  • <repo name>.snapshot.<revision> - backup of snapshot taken at a specific journal revision

Performance tuning

Parametrized instantiation

The Repository class takes most strategic decisions from a IRepositoryConfiguration. A custom implementation (or instantiation of the default) allows customization of

  • Command serialization (the format used in the journal)
  • Marshalling
  • Synchronization

Each of the above strategies are quite small abstractions and should be fairly easy to implement if a non-default behaviour is wanted.

Skip marshalling

For applications where the model isn't at risk of being compromised by pusblishing results from Query or Execute, an additional parameter QueryOptions.NoMarshall can be supplied that effectively skips the marshalling step all together.

Custom marshalling

Since marshalling doesn't affect persistence in the journal or snapshot in any way, it's possible to setup a repository with a custom marshaller (say one based on BinaryFormatter, allowing cycles in the data).

Custom synchronization

The default synchronization uses System.Threading.ReaderWriterLock, but other schemes can be specified by passing a custom ISynchronize instance to the repository.

What if I think prevalence is better than sliced bread but dislike this particular implementation?

  • Fork and patch, fork and patch...
  • or, use another library. Personally, I can recommend #livedb.
  • or, if you rather roll your own, use our code as inspiration or
  • or, start from this minimal implementation provided by by one of the early driving forces, Klaus Wuestefeld.

About

Prevalence for .Net avoiding common binary versioning problems

Resources

Stars

Watchers

Forks

Packages

No packages published