A reference whose path is under no configured root is meant to be left alone
entirely, but needs_verify was decided before the classification guard, so it
was the one write of four that did not skip. Classification now comes first,
which also stops an out-of-view row being counted as changed or unchanged when
the reset did nothing with it either way.
Stamping the version was also the only database access in the runner that could
throw into its caller, so a transient lock while stamping aborted the seeder's
whole scan -- prune, fast phase and enrichment -- over a step whose own writes
were already committed. A failed stamp is now logged and leaves the step
pending, like every other failure there.
A reference whose file is on disk but whose path is under no configured root
was skipped so that a missing extra_model_paths.yaml could not strip tags off
assets that were merely out of view. But the step still finished successfully
and the version was still stamped, so restoring the root repaired nothing: the
step never ran again, and no other path re-derives an existing reference's
loader_path -- the scan only builds specs for paths it has not seen, and the
enricher computes a loader path without writing it back. The guard turned
destroying the data into never repairing it.
A step now reports whether it finished its work, and an unfinished one is not
stamped. A file that is simply gone still does not count as unfinished; that is
the scan's business under its own missing semantics.
Two ordering fixes in the scan around the same call:
The walk is handed the seeder's pause-aware checkpoint rather than a
cancel-only check. The seeder is paused while a prompt runs, so a check that
ignores pause left the reset statting the whole asset table during generation
while the status reported PAUSED.
Cancellation is checked immediately after the reset instead of after the prune.
Cancelling during a long reprojection otherwise fell through into the prune and
temp reconciliation, doing state-mutating work on a scan that had been told to
stop.
Renames so the code states its own invariants: _SINGLETON_ROW_ID for the
one-row version table, get_tag_origins_by_reference so the inner mapping's
direction is in the name, _ROWS_PER_TRANSACTION for what the batch size bounds.
In the tests, a named helper replaces the explanation of why the engine is
shared across sessions, a named constant replaces the empty-string "any unique
hash" sentinel, and each test's claim moves into its assertion message, where
whoever's build just went red will actually read it.
Alembic migrates the shape of the assets tables. Nothing migrated their
meaning, so a row could be structurally current and still hold values a
superseded rule computed, with no maintenance path that ever repaired it.
loader_path is the clearest case: the column was added to existing databases
with no backfill, and it is only ever written when a reference is first
created. The scan computes it for paths it has not seen before, so every
reference older than the column serves a null loader path forever -- while the
API tells clients to prefer loader_path over name.
A semantics version now records which generation of the derivation logic
produced a database's rows, tracked separately from the Alembic schema version
because the two move independently. Reset steps are numbered and applied in
order from the stored version, each stamped only once it finishes, so an
interrupted run resumes instead of half-applying.
The first step re-derives what a file's location implies -- loader_path, the
backend tags a path carries, and whether the file is there -- and leaves
everything else alone. It reads no file contents: verify_file_unchanged says
whether a row's recorded hash and size still describe the file, and a file that
has moved on is handed to the existing needs_verify path rather than re-read,
so an untouched model library costs one stat per file and no hashing. Manual
tags, user metadata, previews, deletions and job ids are never touched, nor are
references whose file is gone or whose path falls outside every root this
install currently knows about.
It runs at the start of a scan, before anything reads or extends those rows. A
database already at the current version costs one indexed row read.
* Keep temp-directory assets visible while their files exist
Assets written to the temp directory were flagged as missing and dropped
from GET /api/assets, even with the file sitting on disk. One list of
directories was answering two different questions -- where the scanner
looks for new files, and which files ComfyUI considers its own -- and
temp belongs only in the second, so every temp reference was disowned by
the prune that runs at startup and on POST /api/assets/prune.
Ownership now covers temp. Discovery still does not: the temp directory
is wiped before the scan runs, and assets written there are already
registered with a hash, mime type and dimensions, so walking it would
find nothing. Temp references are instead reconciled against the
filesystem directly, so a temp file that really is gone is still retired
rather than lingering as a broken entry.
get_prefixes_for_root becomes get_scan_prefixes_for_root so the two
questions are told apart by name rather than by comment.
* Cover the unhashed temp asset in the reconciliation tests
The existing temp tests all registered hashed assets, so they never
exercised the path an unhashed asset takes when its file is gone: the
orphaned rows are removed rather than kept as missing, exactly as under
any other root.
* Stop adding an opaque alpha channel to API node images
bytesio_to_image_tensor converted every downloaded image to RGBA, so nodes
whose API returns no transparency still emitted a 4 channel IMAGE. Keep the
alpha when the decoded image has one, stay RGB when it does not.
---------
Signed-off-by: bigcat88 <bigcat88@icloud.com>
Co-authored-by: bigcat88 <bigcat88@icloud.com>