Add injectable IScenarioStateStore for distributed scenario state#1430
Add injectable IScenarioStateStore for distributed scenario state#1430StefH merged 5 commits intowiremock:masterfrom
Conversation
31d252c to
0d0881a
Compare
|
@m4tchl0ck However I'm working on a 2.0 version which has a lot of changes, so I will complete that one first... About the CI fix: So maybe revert the CI changes for this PR |
a7f78fb to
b304b90
Compare
Hi @StefH, If you are working on version 2.0 and would like to finish it before merging my feature, maybe you have an easy way to release a preview package with my changes? |
b304b90 to
0d0881a
Compare
Ok, I reverted my change about CI as it doesn't work |
|
Would it also make sense to create a default implementation for file-based IScenarioStateStore ? |
Yes, I agree. It was not my goal... yet. |
|
Can be done in next PR sure. |
|
Version 2 is merged to master, so you probably need to resolve merge conflicts. |
180e1fb to
42f9513
Compare
I added FileBasedScenarioStateStore |
|
@m4tchl0ck |
42f9513 to
54dd45c
Compare
done |
| options.FileSystemHandler = settings.FileSystemHandler; | ||
| options.HandleRequestsSynchronously = settings.HandleRequestsSynchronously; | ||
| options.Logger = settings.Logger; | ||
| options.Scenarios = settings.ScenarioStateStore ?? options.Scenarios; |
There was a problem hiding this comment.
This should be
options.ScenarioStateStore = setings.ScenarioStateStore ?
There was a problem hiding this comment.
I guess the ?? is not needed. No need to take options.Scenarios ?
And also rename options.Scenarios also to options.ScenarioStateStore ?
There was a problem hiding this comment.
ScenarioStateStore is nullable in WireMockServerSettings
There was a problem hiding this comment.
done
Renamed to options.ScenarioStateStore. The ?? is kept because settings.ScenarioStateStore is nullable.
ScenarioState is moved to the Abstractions project so it can be referenced by the new IScenarioStateStore interface. The interface defines the contract for storing and retrieving scenario states, enabling distributed implementations.
Wraps ConcurrentDictionary with OrdinalIgnoreCase comparer, preserving exact current behavior. The Update method encapsulates read-modify-write so distributed implementations can make it atomic.
…mers Replace direct ConcurrentDictionary<string, ScenarioState> usage with IScenarioStateStore across all consumer files. The store is injectable via WireMockServerSettings.ScenarioStateStore, defaulting to the InMemoryScenarioStateStore for backward compatibility.
In-memory ConcurrentDictionary backed by JSON file persistence in __admin/scenarios/. Reads from cache, mutations write through to disk. Constructor loads existing state from disk on startup.
54dd45c to
37652f8
Compare
|
Review comments addressed:
|
…teStore Move InMemoryScenarioStateStore from WireMock.Net.Minimal to WireMock.Net.Shared so it lives alongside WireMockServerSettings. This allows WireMockServerSettings.ScenarioStateStore to be non-nullable with a default value, following the same pattern as DefaultJsonSerializer. The null-coalescing fallback in WireMockMiddlewareOptionsHelper is no longer needed.
8a2f593 to
2e3f52c
Compare
Summary
IScenarioStateStoreabstraction so users can inject a distributed implementation (Redis, SQL, etc.) to share scenario state across multiple WireMock.Net instancesInMemoryScenarioStateStoreas the default implementation, preserving exact current behavior (backed byConcurrentDictionarywithOrdinalIgnoreCase)FileBasedScenarioStateStorefor persistent scenario state across restarts — in-memory cache backed by JSON file persistence in__admin/scenarios/ScenarioStatetoWireMock.Net.Abstractionsso the interface can reference itScenarioStateStoreproperty toWireMockServerSettingsfor injection (following theIFileSystemHandlerpattern)ConcurrentDictionary<string, ScenarioState>usage in middleware, matcher, and server withIScenarioStateStoreTryGetpattern (bool TryGet(string, out ScenarioState?)) instead of nullableGetfor safer state lookupsFileBasedScenarioStateStore
Reads come from an in-memory
ConcurrentDictionary; all mutations (TryAdd, Update, AddOrUpdate, TryRemove, Clear) write through to disk as indented JSON files. The constructor loads existing state from disk on startup, enabling persistence across restarts and visibility into state via the filesystem.Test plan
InMemoryScenarioStateStoreTestspass (TryAdd, TryGet, GetAll, Update, AddOrUpdate, TryRemove, Clear, case-insensitivity)FileBasedScenarioStateStoreTestspass (15 mirrored behavior tests + 5 file-persistence tests: disk write, disk delete, clear files, constructor loading, update persistence)StatefulBehaviorTestspass unchanged — backward compatibility confirmed