Coverage for python/lsst/pipe/base/quantum_graph/aggregator/_structs.py: 98%
58 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-19 01:44 -0800
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-19 01:44 -0800
1# This file is part of pipe_base.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (http://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This software is dual licensed under the GNU General Public License and also
10# under a 3-clause BSD license. Recipients may choose which of these licenses
11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
12# respectively. If you choose the GPL option then the following text applies
13# (but note that there is still no warranty even if you opt for BSD instead):
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU General Public License as published by
17# the Free Software Foundation, either version 3 of the License, or
18# (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU General Public License for more details.
24#
25# You should have received a copy of the GNU General Public License
26# along with this program. If not, see <http://www.gnu.org/licenses/>.
28from __future__ import annotations
30__all__ = (
31 "IngestRequest",
32 "ScanReport",
33 "ScanResult",
34 "ScanStatus",
35)
37import dataclasses
38import enum
39import uuid
41from lsst.daf.butler.datastore.record_data import DatastoreRecordData
43from .._common import DatastoreName
44from .._predicted import PredictedDatasetModel
45from .._provenance import (
46 ProvenanceLogRecordsModel,
47 ProvenanceQuantumAttemptModel,
48 ProvenanceTaskMetadataModel,
49)
52class ScanStatus(enum.Enum):
53 """Status enum for quantum scanning.
55 Note that this records the status for the *scanning* which is distinct
56 from the status of the quantum's execution.
57 """
59 INCOMPLETE = enum.auto()
60 """The quantum is not necessarily done running, and cannot be scanned
61 conclusively yet.
62 """
64 ABANDONED = enum.auto()
65 """The quantum's execution appears to have failed but we cannot rule out
66 the possibility that it could be recovered, but we've also waited long
67 enough (according to `ScannerTimeConfigDict.retry_timeout`) that it's time
68 to stop trying for now.
70 This state means a later run with `ScannerConfig.assume_complete` is
71 required.
72 """
74 SUCCESSFUL = enum.auto()
75 """The quantum was conclusively scanned and was executed successfully,
76 unblocking scans for downstream quanta.
77 """
79 FAILED = enum.auto()
80 """The quantum was conclusively scanned and failed execution, blocking
81 scans for downstream quanta.
82 """
84 BLOCKED = enum.auto()
85 """A quantum upstream of this one failed."""
87 INIT = enum.auto()
88 """Init quanta need special handling, because they don't have logs and
89 metadata.
90 """
93@dataclasses.dataclass
94class ScanReport:
95 """Minimal information needed about a completed scan by the supervisor."""
97 quantum_id: uuid.UUID
98 """Unique ID of the quantum."""
100 status: ScanStatus
101 """Combined status of the scan and the execution of the quantum."""
104@dataclasses.dataclass
105class IngestRequest:
106 """A request to ingest datasets produced by a single quantum."""
108 producer_id: uuid.UUID
109 """ID of the quantum that produced these datasets."""
111 datasets: list[PredictedDatasetModel]
112 """Registry information about the datasets."""
114 records: dict[DatastoreName, DatastoreRecordData]
115 """Datastore information about the datasets."""
117 def __bool__(self) -> bool:
118 return bool(self.datasets or self.records)
121@dataclasses.dataclass
122class ScanResult:
123 """A struct that represents the result of scanning a quantum."""
125 quantum_id: uuid.UUID
126 """Unique ID for the quantum."""
128 status: ScanStatus
129 """Combined status for the scan and the execution of the quantum."""
131 attempts: list[ProvenanceQuantumAttemptModel] = dataclasses.field(default_factory=list)
132 """Provenance information about each attempt to run the quantum."""
134 existing_outputs: set[uuid.UUID] = dataclasses.field(default_factory=set)
135 """Unique IDs of the output datasets that were actually written."""
137 metadata_model: ProvenanceTaskMetadataModel | None = dataclasses.field(
138 default_factory=ProvenanceTaskMetadataModel
139 )
140 """Task metadata information for each attempt.
142 This is set to `None` to keep the pickle size small after it is saved
143 to `metadata_content`.
144 """
146 metadata_content: bytes = b""
147 """Serialized form of `metadata_model`."""
149 log_model: ProvenanceLogRecordsModel | None = dataclasses.field(default_factory=ProvenanceLogRecordsModel)
150 """Log records for each attempt.
152 This is set to `None` to keep the pickle size small after it is saved
153 to `log_content`.
154 """
156 log_content: bytes = b""
157 """Serialized form of `logs_model`."""
159 is_compressed: bool = False
160 """Whether the `metadata` and `log` attributes are compressed."""