Choose patch storage
The patch manager is only as durable as the record of what it has applied. Patching needs an IPatchStorage, and starting
without one throws when the silo starts. That is intentional: patching against a store that cannot remember what ran would
apply every patch on every start.
The record is per store, not per scope or namespace. A patch changes the store itself, so every silo in the cluster must read and write the same record. This differs from jobs storage; see Storage. Pick the storage you deploy, not the one that is convenient locally, and register it next to your jobs storage.
| Storage | Survives a restart | Use it for |
|---|---|---|
| In-memory | No | Tests and local development |
| MongoDB | Yes | Hosts that run on MongoDB |
| SQL | Yes | Hosts that run on SQL Server, PostgreSQL or SQLite |
In-memory
Section titled “In-memory”using Cratis.Choreography.Storage;
builder.Services.AddCratisChoreographyInMemoryPatchStorage();With CratisChoreographyOptions.Patching and Storage = GrainStorageMode.InMemory, the co-hosted silo registers it for you.
Nothing survives the process, so every start applies every patch again.
MongoDB
Section titled “MongoDB”using Cratis.Choreography.Setup;using MongoDB.Driver;
builder.Services.AddCratisChoreographyMongoDBPatchStorage( new MongoClient("mongodb://localhost:27017"), options => options.DatabaseName = "choreography");Records go to one database, choreography unless you change MongoDBPatchStorageOptions.DatabaseName:
| Collection | Document |
|---|---|
patches | One per applied patch, keyed by patch name, with version and appliedAt |
patch-versions | A patched document and a host document, each with a version |
Saving a patch that is already recorded replaces its document. A client registered earlier, for example by the jobs storage, is kept. More in MongoDB storage.
using Cratis.Choreography.Setup;using Cratis.Choreography.Storage.Sql.Patching;using Microsoft.EntityFrameworkCore;
builder.Services.AddCratisChoreographySqlPatchStorage(options => options.OptionsResolver = () => new DbContextOptionsBuilder<PatchesDbContext>() .UseNpgsql("Host=localhost;Database=choreography;Username=app;Password=<password>") .Options);The resolver takes no arguments: unlike jobs storage it is not asked about a scope or namespace. The tables are Patches
(Name, Version, AppliedAt) and PatchVersions (Id of patched or host, and Version). You do not create them;
SqlPatchStorage applies its migration the first time it is used. More in SQL storage.
Why two versions are stored
Section titled “Why two versions are stored”IPatchStorage keeps the applied patches plus two versions: the patched version (the newest patch applied) and the host
version (the newest host with a known version that patched the store). The first stops a patch from running twice, the
second stops an older host from patching a newer store. The overview explains how the manager uses them. If you
write your own IPatchStorage, see the reference for the members.