Skip to content

Report failures and share a database - #6

Merged
daipham3213 merged 5 commits into
mainfrom
report-failures-and-share-a-database
Sep 3, 2026
Merged

Report failures and share a database#6
daipham3213 merged 5 commits into
mainfrom
report-failures-and-share-a-database

Conversation

@daipham3213

Copy link
Copy Markdown
Owner

No description provided.

daipham3213 and others added 5 commits September 3, 2026 10:26
The fold layer has always understood `failure` and `revert_failure`
and the persistence datasource has always filled them in, but the
listener never emitted either. Watching a running engine told a client
that an atom reached FAILURE and nothing more, while reading the same
run out of persistence told it why -- so which producer you were
attached to changed the answer, which is exactly what this package is
supposed to hide.

The listener has the `Failure` in hand: taskflow hands it over as the
atom's result on the very notification that carries the state. It now
renders it, in the same shape persistence reports, because the
renderer is one function that both call. `_failure_dict` moved out of
the persistence datasource into `models.failure_dict` for that reason
-- two renderers agreeing by inspection is not the same as one shape.

Which of the two keys it lands under follows from the state rather
than from the intention. Taskflow does not put an intention on these
notifications, and only a revert that itself failed reaches
REVERT_FAILURE, so the state is the whole of the information needed.

838 tests pass, including a flow whose task raises and whose snapshot
now carries the exception type and message.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`attach()` reported every run as being called "". The in-process
producer emits FLOW_STRUCTURE once, before anything runs, precisely
because taskflow never persists the edges -- so that is the event a run
gets seeded from, and it carries no flow name. The FLOW_STATE events
that follow do carry one, and fold was throwing it away: it replaced
the state and nothing else.

It now takes the name from whichever event has one, keeping what it
already holds otherwise. That leaves the persistence path unchanged,
where the first event seen is a state event and the name was never in
doubt, and fixes the path where it was.

838 tests pass, with an integration test that names a flow and reads
the name back out of a snapshot seeded by the graph.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This package is meant to be co-installed into a service, and a
deployment that puts the store in that service's database ends up with
two alembic trees in one schema. Both kept their revision in
`alembic_version`, so each read the other's revision as one it had
never heard of: the host's migrations fail against the store's
revision, or the store's against the host's, depending on who runs
first.

`upgrade()` now takes a `version_table`, passed through the alembic
config to both the offline and online paths. Nothing changes for a
deployment with a database of its own, which is why the default stays
`alembic_version` rather than something namespaced -- a database
already migrated under the old name keeps working untouched.

The docstring says the one thing that can go wrong afterwards: the
name has to be the same on every upgrade of a given database, because
pointing alembic at an empty table looks exactly like a database that
was never migrated.

838 tests pass, including one that upgrades into a named table, checks
`alembic_version` was never created, and upgrades again to confirm
idempotence against the table it was given.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The same argument as the dependency floors, one level down: this package
is co-installed into a service that has already chosen its interpreter,
so requiring 3.11 rules out hosts that are otherwise perfectly able to
run it -- Ubuntu 22.04 ships 3.10, and a good deal of OpenStack still
runs there. Nothing in the package needed 3.11. Two spellings did.

`typing.Self` was the return type of four `__enter__` methods and one
classmethod. Each is now a `TypeVar` bound to its own class, which is
how the same thing was written before 3.11 and which mypy strict checks
identically. `enum.StrEnum` is imported where it exists and falls back
to a `str, Enum` mixin whose `__str__` returns the value: the plain
mixin renders as `EventKind.FLOW_STATE`, and the value is what goes on
the wire.

Then running the suite on 3.10 found a bug, which is what running it is
for. The sleep between SSE polls suppresses `TimeoutError` around
`asyncio.wait_for`, and on 3.10 `asyncio.TimeoutError` is a class of its
own rather than the builtin -- so the suppression caught nothing and the
stream raised out of its own sleep at the first quiet interval. Four
tests fail on 3.10 and pass on every other version, which is the shape a
bug takes when the matrix does not cover the floor.

CI gains 3.10 in the test and conformance matrices, and the
lowest-direct job moves there, since it exists to install the oldest
releases on the oldest interpreter supported.

838 tests pass on 3.10, 3.12 and 3.14, and on 3.10 with every declared
floor installed exactly -- taskflow 4.2.0, oslo.config 6.9.0, SQLAlchemy
1.4.0, alembic 1.2.0, kombu 5.1.0, oslo.messaging 6.0.0. Lint, format,
hacking and mypy all pass with mypy targeting 3.10.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Five badges, each answering a question somebody arriving at the repository
asks before reading any prose: are the tests passing, do the host
frameworks still agree, what is released, what does it run on, and under
what licence. No coverage badge, because nothing publishes coverage to a
service that could back one -- CI keeps the report as an artifact, and a
badge for a number nobody can check is worse than none.

The licence badge links to `LICENSE` the way the rest of the README links
to `docs/` and `CHANGELOG.md`, rather than being the one absolute link on
the page.

While confirming those links resolve, the project URLs turned out not to.
Every one of them -- Homepage, Source, Issues, Changelog -- pointed at
github.com/daipham3213/taskflow-meter, which is the PyPI name and 404s;
the repository is taskflow.meter. That is four dead links on the PyPI
page of the released version, including the one PyPI's trusted publishing
matches on.

Checked rather than assumed: all five badge images render (ci passing,
conformance passing, pypi v1.1.0, python 3.11-3.14, Apache-2.0), the
repository URL answers 200 and the old one 404, and `twine check` passes
on both artifacts, since the README is also the long description.

The Python badge reads 3.11-3.14 until the next release, which is what
1.1.0 supports; 3.10 is in the metadata and will show once that ships.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@daipham3213
daipham3213 merged commit f12c2c6 into main Sep 3, 2026
10 checks passed
@daipham3213
daipham3213 deleted the report-failures-and-share-a-database branch September 3, 2026 03:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant