Updates
v2.0.1
Fixes
- Moved Fluent API Extension Methods into Abstraction Package.
v2.0.0
BREAKING CHANGES
-
Interface signatures have changed.
Core interface updates may break plugin‑based systems if the core updates while plugins do not.
This is only safe when proper plugin isolation is respected. -
Reducers now run before effects.
The default dispatch order has changed.
Pipelines that rely on reducers running after effects must update their configuration to restore the previous behavior. -
Middleware between individual effects has been removed.
Per‑effect middleware proved unreliable and is no longer supported.
All effects now run as a batch, followed by a single AfterEffect phase.
Middleware can still be awaited before the BeforeEffect phase and after the AfterEffect phase. Middlewares for effects if not awaited they are still ganrantueed to be running sequentially BeforeEffect Parallel with Effects then AfterEffects. -
Effects, Reducers, Middleware, EffectValidators no long transient
Transient lifetime for those is unecessary as none of them should ever hold state of their own therefore they act like static method filled with logic alone... let's eliminate transient overhead and put scoped as default and singleton with the singleton interfaces. -
Configuration Scan Assembly Type Changed
The propertyConfigureOptions.ScanAssembliesis now taking aAssembly[]instead ofType[]. -
IPulseGlobalTracker registration changed
The IPulseGlobalTracker is now registered as Scoped instead of singleton... issues were occuring with some blazor server projects. -
Removed
.AddStatePulse<Action,Effect,Reducer,State>
the extension method were removed from public access... now you use.AddStatePulseService<Implementation>()which will auto detect from action to effect to reducers to middlewares. Reason: Better dev experience less confusing and annoying when having to register stuff manually instead of by scanning. Alternative: You can also add types into.AddStatePulseServices(o=>{ o.AutoRegisterTypes = [typeof(AAA)];});which will perform manual registration automatically without scanning assemblies. -
Added to IDispatchMiddleware
OnDispatchFailure(Exception exception, object action)is now available to middleware hit is receive on any dispatch failure... -
Removed Throw for Dispatch Failure Re-Throw only occurs when using Synchronous
Await()otherwise dispatch will swallow any uncaught exception thrown at it. -
Reducers are no longer Tasks With the full introduction of middlewares it is no longer justifiable to have reducers as Task... nothing should be in the reducers to the exception of generating a new state.
-
ReducerExt is removed ReducerExt is no longer available as it was used as helper for Task return.
-
IDispatcherPrepper<TAction> Prepare<TAction>(Func<TAction> createInstance)deprecated Use Prepared(instance).DispatchAsync() instead;
New Features
- Enhanced Configuration Options - New global configuration properties:
DispatchOrderBehavior- Set default ordering (EffectsFirst/ReducersFirst)
- Configurable Dispatch Ordering - Choose between
EffectsFirst(default) orReducersFirstexecution order globally or per-dispatch - Configurable Dispatch Ordering - The Middleware BeforeReducers will run before the AfterReducer as garantueed...
- The reducer will however run in parallel with BeforeReducing if settings is to not await for middlewares.
- Per-Dispatch Execution Control - Override global settings per dispatch with fluent API:
.EffectsFirst()- Run effects before reducers.ReducersFirst()- Run reducers before effects.SequentialEffects()- Force effects to run in sequence.ParallelEffects()- Force effects to run in parallel
- Invalid Configuration Detection - New
InvalidDispatchCombinationExceptionthrown at dispatch time for incompatible configuration combinations (Plan to generate compiler errors later) - Recursive Dispatch Support - Fire-and-forget mode enables safe recursive dispatch patterns without deadlocks
PulseTrackingModel- Clear option for the tracking model! Either Thread-Safe (Default) or Single Threaded Fast Application... WASM/Blazor Server.GlobalTrackerLifetime- Define clearly lifetime scope for the Global Tracker singleton or scoped.BlazorServer,WASM,Scoped(Default) orSingleton.IStateFeatureSingleton- Define a singleton state across your app... not useful in WASM but very useful in Blazor Server... where one can share the state across client each client run their own action but the state update spread across all circuits.StateVersioninglong global ticker used to calculate version of a state... this will help prevent further race conditions related to multi-threading (blazor server singleton).- State update will automatically discard stale states. you can also acces the information using
IStateAccessor - Roslyn Analyzer will now trigger error
.Prepare<OBJECT>(entity)if constructor object does not match the underlying object's constructor type and it supports overload. - Roslyn Analyzer will now trigger error
.Prepare<OBJECT>().With(p => p.PROP, data)when PROP isinit;orget;only... this will eleminate runtime issues.
Security
- Roslyn will now enforce
_statePulse.StateOf<StateMe>(() => this, OnUpdate);on the two arguments this will avoid runtime errors and potential memory leaks. - Fixed All Configure Internal...
Fixes
- Fixed Various Warnings
- Fixed All Configure Internal...
- Fixed Middleware are now added via Scanned Assemblies.
- Fixed some issues where
Await()was not respected. - Fixed major issue where all race condition elements where cancelled leading to full chain cancellation including the last action.
- Fixed inconsistence with race conditions.
- Fixed
StateOf<TState>()throwing inability to cast toIStateAccessor<object>. - Fixed AddStatePulseServices() configuration not optional.
v1.1.0
Minor Change
- Upgraded to .NET 10
v1.0.2
Fixes
- Added StatePulse.Net.Abstractions package reference instead of project reference to fix IL trimming issues.
v1.0.1
Minor Change
- Splited Abstractions into StatePulse.Net.Abstractions (Will not break anything Namespace is the same)
v1.0.0
New Features
- Action Effect Validator: Allows effects to run conditionally by validating them before execution.
- Middleware Support:
IEffectMiddlewareIReducerMiddlewareIDispatchMiddleware
- Behavior Configuration: You can configure execution behaviors via:
DispatchEffectBehaviorMiddlewareEffectBehaviorMiddlewareTaskBehavior
- Strict Manual Registration: Manual service registration must use extension methods:
AddStatePulse()AddStatePulseEffect<>()AddStatePulseAction<>()AddStatePulseReducer<>()AddStatePulseStateFeature<>()AddStatePulseEffectValidator<>()
💥 Breaking Changes
- Removed Action Validator – validating action data is not the responsibility of the state management layer.
- Renamed:
IStateAccessor<>.StateChanged→OnStateChangedUsingSynchronousMode→ RemovedSync()→Await()for clarity and accuracy
🚀 Performance Improvements
- Improved dispatcher caching
- Enhanced type cache in
StatePulseRegistry - Replaced reflection with dynamic method caching for faster dispatching
🧼 Clean Code Improvements
- Refactored
DispatchPrepperfor cleaner and lighter internal logic
🐞 Fixes
- Resolved several null reference warnings
- Removed leftover internal artifacts
v0.9.41
- Fix: Added Anti-Service duplication to avoid double triggers.
v0.9.4
- Breaking Change, StateOf no longer accept lambda will throw exception you must define a Task directly... this was necessary due to Garbage Collector and tracking behavior.
- Deprecated UsingSynchronousMode() instead use Sync().
v0.9.21
- Implement the Blazor Package and removed dependencies to Blazor ComponentBase which is no longer required...
- Any objects within .NET can now use IStatePulse and benefit from state management without extra implementations.
- Renamed IPulse to IStatePulse
using IStatePulse.StateOf(()=>this, () => InvokeAsync(StateHasChanged));
v0.9.2 (Blazor Packages)
- Deprecated now part of StatePulse regular since we have removed the dependencies to blazor component. ... that was quick!