summaryrefslogtreecommitdiffstats
path: root/stator
diff options
context:
space:
mode:
Diffstat (limited to 'stator')
-rw-r--r--stator/graph.py6
-rw-r--r--stator/models.py28
2 files changed, 26 insertions, 8 deletions
diff --git a/stator/graph.py b/stator/graph.py
index 424ea49..5c71d4a 100644
--- a/stator/graph.py
+++ b/stator/graph.py
@@ -87,10 +87,14 @@ class State:
try_interval: Optional[float] = None,
handler_name: Optional[str] = None,
externally_progressed: bool = False,
+ attempt_immediately: bool = True,
+ force_initial: bool = False,
):
self.try_interval = try_interval
self.handler_name = handler_name
self.externally_progressed = externally_progressed
+ self.attempt_immediately = attempt_immediately
+ self.force_initial = force_initial
self.parents: Set["State"] = set()
self.children: Set["State"] = set()
@@ -121,7 +125,7 @@ class State:
@property
def initial(self):
- return not self.parents
+ return self.force_initial or (not self.parents)
@property
def terminal(self):
diff --git a/stator/models.py b/stator/models.py
index bbff395..5257ac9 100644
--- a/stator/models.py
+++ b/stator/models.py
@@ -74,6 +74,10 @@ class StatorModel(models.Model):
def state_graph(cls) -> Type[StateGraph]:
return cls._meta.get_field("state").graph
+ @property
+ def state_age(self) -> int:
+ return (timezone.now() - self.state_changed).total_seconds()
+
@classmethod
async def atransition_schedule_due(cls, now=None) -> models.QuerySet:
"""
@@ -184,13 +188,23 @@ class StatorModel(models.Model):
state = state.name
if state not in self.state_graph.states:
raise ValueError(f"Invalid state {state}")
- self.__class__.objects.filter(pk=self.pk).update(
- state=state,
- state_changed=timezone.now(),
- state_attempted=None,
- state_locked_until=None,
- state_ready=True,
- )
+ # See if it's ready immediately (if not, delay until first try_interval)
+ if self.state_graph.states[state].attempt_immediately:
+ self.__class__.objects.filter(pk=self.pk).update(
+ state=state,
+ state_changed=timezone.now(),
+ state_attempted=None,
+ state_locked_until=None,
+ state_ready=True,
+ )
+ else:
+ self.__class__.objects.filter(pk=self.pk).update(
+ state=state,
+ state_changed=timezone.now(),
+ state_attempted=timezone.now(),
+ state_locked_until=None,
+ state_ready=False,
+ )
atransition_perform = sync_to_async(transition_perform)