Repository navigation
Description
With resume_at_next_action=False, loading from a persister behaves the same as True: the app continues after the saved step instead of starting at default_entrypoint.
Current behavior
After loading, get_next_action() returns the action after the last saved step, whether resume_at_next_action is True or False.
Steps to replicate behavior
from burr.core import ApplicationBuilder, State, action, default
from burr.core.persistence import InMemoryPersister
@action(reads=[], writes=["count"])
def counter(state: State) -> State:
return state.update(count=state.get("count", 0) + 1)
@action(reads=["count"], writes=[])
def done(state: State) -> State:
return state
persister = InMemoryPersister()
def build(resume_at_next_action):
return (
ApplicationBuilder()
.with_actions(counter=counter, done=done)
.with_transitions(("counter", "done", default))
.initialize_from(
persister,
resume_at_next_action=resume_at_next_action,
default_state={},
default_entrypoint="counter",
)
.with_identifiers(app_id="app", partition_key="pk")
.with_state_persister(persister)
.build()
)
build(True).step() # runs "counter" and saves it
for flag in (True, False):
app = build(flag)
print(f"resume_at_next_action={flag}: next action = {app.get_next_action().name}")Output:
resume_at_next_action=True: next action = done
resume_at_next_action=False: next action = done
Library & System Information
apache-burr 0.43.0 and main (222b32c), Python 3.13, macOS
Expected behavior
docs/concepts/state-persistence.rst describes it as "whether to start where you left off, or go back to the default_entrypoint", so with False the next action should be counter, keeping the loaded state.
Additional context
In ApplicationBuilder._init_state_from_persister the False branch is just pass ("self.start is already set to the default"), but the loaded state still has __PRIOR_STEP, and get_next_action() uses it. The existing tests that use False load from a fake loader or from the local tracker, and neither has __PRIOR_STEP in the loaded state, so they don't catch this. For the same reason the local tracker isn't affected, only persisters (in-memory, SQLite, etc.).
With False, the starting point also depends on how many times a step failed: after one failed attempt the app starts at the failed action, after two at the entrypoint, because the failed-status path removes __PRIOR_STEP when it restarts the action. I mentioned this on the dev list durable-execution thread: https://lists.apache.org/thread/3xp1mfozrxtrc0w8oqh0xh5lgt22kvwj
I'm opening a PR with a fix (calling reset_to_entrypoint() there, like the failed-status branch already does) and tests. If the current behavior is intended, I'm happy to update the docs instead.
Activity