Git Product home page Git Product logo

Comments (5)

fgmacedo avatar fgmacedo commented on May 23, 2024 6

Hi @UweSauter, I've wrote a small example of how this can be done using a custom model.

Please note that I've implemented this as issue358_persistence.md example file, so the tests actually run locally (the getfixture is a fixture from pytest to get a temporary file)

Issue 358

A StateMachine that has its current state persisted automatically using a custom model.

Given a generic API from a model with a state property: GenericStorageModel:

>>> from abc import ABC

>>> from abc import abstractmethod

>>> class GenericStorageModel(ABC):
...     """Abstract Base Class for persistent models.
...
...     Sub classes should implement concrete strategies for:
...
...     - `_read_state`: Read the state from the concrete persistent layer.
...     - `_write_state`: Write the state from the concrete persistent layer.
...     """
...     def __init__(self,):
...         self._state = None
...
...     def __repr__(self):
...         return f"{type(self).__name__}(state={self.state})"
...
...     @property
...     def state(self):
...         if self._state is None:
...             self._state = self._read_state()
...         return self._state
...
...     @state.setter
...     def state(self, value):
...         self._state = value
...         self._write_state(value)
...
...     @abstractmethod
...     def _read_state(self):
...         raise NotImplementedError()
...
...     @abstractmethod
...     def _write_state(self, value):
...         raise NotImplementedError()

You can write many concrete implementations of a storage strategy, persisting to YAML, JSON,
database, etc. For this example to be complete, I have for you here a reference on how to write into a file.

>>> class FileStorageModel(GenericStorageModel):
...     """A concrete implementation of a storage strategy for a Model"""
...     def __init__(self, file_path):
...         super().__init__()
...         self.file_path = file_path
...
...     def _read_state(self):
...         if not self.file_path.exists():
...             return
...
...         with self.file_path.open('r') as f:
...             return f.read().strip()
...
...     def _write_state(self, value):
...         with self.file_path.open('w+') as f:
...             return f.write(value)

You can use this FileStorageModel or any other persistent strategy that you like as a domain
model
.

So, given this simple SM:

>>> from statemachine import StateMachine, State

>>> class ResourceManagement(StateMachine):
...     power_off = State(initial=True)
...     power_on = State()
...
...     turn_on = power_off.to(power_on)

We can create instances:

>>> tmp_path = getfixture('tmp_path')

>>> state_path = tmp_path / 'resource_state.txt'

>>> model = FileStorageModel(file_path=state_path)

>>> sm = ResourceManagement(model=model)

>>> sm.current_state.id
'power_off'

>>> sm.send("turn_on")

>>> sm.current_state.id
'power_on'

>>> del sm

>>> del model

Restore the previous state from disk:

>>> model = FileStorageModel(file_path=state_path)

>>> sm = ResourceManagement(model=model)

>>> sm.current_state.id
'power_on'

from python-statemachine.

UweSauter avatar UweSauter commented on May 23, 2024 1

Wow, thank you. I didn't expect to get such a detailed example.

I'll need to start coding to see if this fits my requirements.

Thanks again.

from python-statemachine.

fgmacedo avatar fgmacedo commented on May 23, 2024

Hi @UweSauter , how are you?

You can inspect the current state using the current_state property of the state machine, or in this case, you can also use the low level current_state_value property, that can be assigned to any valid state value completely bypassing all the hooks and validation. This way you can read/write the current state.

But there's no built-in function for serialization, and you can use plain standard Python to read current_state_value and write to disk.

As suggestion, you can implement a generic on_enter_state hook that does this at every state change.

Let me know if you need any help on this, if so, consider adding more concrete info about how is your use case and how do you plan to store the state.

Best regards!

from python-statemachine.

UweSauter avatar UweSauter commented on May 23, 2024

Hi Fernando,

thanks for the explanation.

So, I'm at the very early phase of making a concept for a compute resource management software. The software should track the various states the compute servers can have and transition between these states upon internal and external triggers.

An external trigger would be that the administrator wants to turn on power and the management software then calls ipmitool power on for that particular server (and transition the state from power_off to power_on).
An internal trigger would be the repeating health checks that are executed by the management software and upon success (or failure) of the check, the state is changed accordingly.

As suggestion, you can implement a generic on_enter_state hook that does this at every state change.

This way it would be able to store the state on disk, be it as JSON or YAML or in a database.
What I don't get is: how could I restore the states from disk when the management software is started (e.g. after a reboot)?

Would it also be possible to pickle.dumps() the state machine instance and restore that state machine later with pickle.loads()?

Regards,

Uwe

from python-statemachine.

fgmacedo avatar fgmacedo commented on May 23, 2024

@UweSauter I will close the issue for now, feel free to comment or open an issue if something is missing, ok?

Best regards!

from python-statemachine.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.