Open tystol opened 6 years ago
I had a similar scenario and created NStateManager to address. In my case, having the state manager coupled to a single instance of a managed object also led to having to instantiate a few other classes per request. Moving to a single instance of these led to a significant performance improvement. Take a look and let me know what you think.
The main problem belongs to the design of Stateless machine don't support pass context of state(Accessor/Mutator)/callback(OnEntry/OnExit/OnActivated/OnExit) so when configure state machine coupled with the object inside.
I think need some overload method inside Stateless can support pass object so can help resolve this case.
@scottctr @tystol I looked deep into the design of Stateless C# and found it's only supported for instance and not for configuration as you request. The solution from @scottctr is suitable for this case. I think there are 2 approaches to support separate between configuration & instance.
@nblumhardt @scottctr @tystol I have implemented support separate State machine definition vs state machine instance in typescript version. https://github.com/tangkhaiphuong/stateless/tree/master/src/context
Basically, the new approach can apply for Stateless C# without breaking original design by implement overload generic class with support take TContext for instance. Mean:
StateMachine<TState, TTrigger>
then we implement new class: StateMachine<TState, TTrigger, TContext>
And same for remain class to support both modes: state machine host embedded to object and separate state machine configuration then create context.
I implement in my fork branch for Stateless C# to support this and pull to request review and merge this feature.
@tangkhaiphuong Was this pull request ever put into Stateless?
@patrious Not yet implement. I only implement base on my approach for TypeScript version. I wait from the more discuss from others for any new ideal.
I like this idea for a number of reasons:
Fire()
(or FireAsync()
or whatever) is called.I prefer a builder design to passing a context, but one can be wrapped to produce the other.
I agree, this is a feature we should implement, and it's quite high up on the things-I'd-Like-To-Do list.
Like OP i'm running into this issue with thousands of instances per-request and was wondering if there is a consensus on how to approach this issue?
@tystol did you solve your challenge and if so, which route did you take? And was it successfull or just another fist full of angry killerbees?
I have created a gist with a workaround to use a single state machine per configuration https://gist.github.com/josellm/95b04a3e1c45a4c0fb01a0186865a109
I may be falling into the premature optimisation trap, but I have a requirement to process bulk actions, that may result in 10's of thousands of individual triggers on individual state machines (web app, so will be loading the state of each one from db and re-instantiating the state machines per request).
So it got me thinking, why is the definition of the state machine tied to the state? If it wasn't, I could have a single static instance of the state machine definition, and only load the state, rather than running all the
Configure
methods 10,000 times. Something like this:Or is it simply that the perf gain of not re-running the
Configure
methods negligible?