fastprocesses 0.22.1__tar.gz → 0.22.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/PKG-INFO +4 -3
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/README.md +1 -1
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/pyproject.toml +1 -1
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/worker/chord_tasks.py +13 -3
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/worker/job_status.py +82 -1
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/AUTHORS.md +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/__init__.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/api/__init__.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/api/manager.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/api/router.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/api/server.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/common.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/core/__init__.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/core/base_process.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/core/cache.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/core/config.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/core/exceptions.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/core/logging.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/core/models.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/core/output_protocol.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/core/output_schema_resolver.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/core/outputs_handler.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/core/redis_connection.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/core/types.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/processes/__init__.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/processes/process_registry.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/py.typed +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/static/style.css +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/templates/landing.html +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/worker/__init__.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/worker/celery_app.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/worker/executors.py +0 -0
- {fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/worker/pipeline.py +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: fastprocesses
|
|
3
|
-
Version: 0.22.
|
|
3
|
+
Version: 0.22.2
|
|
4
4
|
Summary: A library to create a FastAPI-based OGC API Processes wrapper around existing projects.
|
|
5
|
+
License-File: AUTHORS.md
|
|
5
6
|
Author: Stefan Schuhart
|
|
6
7
|
Author-email: stefan.schuhart@gv.hamburg.de
|
|
7
8
|
Requires-Python: >=3.12
|
|
@@ -38,7 +39,7 @@ A library to create a FastAPI-based OGC API Processes wrapper around existing pr
|
|
|
38
39
|
|
|
39
40
|
AI helped to create this code.
|
|
40
41
|
|
|
41
|
-
## Version: 0.22.
|
|
42
|
+
## Version: 0.22.2
|
|
42
43
|
|
|
43
44
|
### Description
|
|
44
45
|
|
|
@@ -79,7 +79,7 @@ exclude = [
|
|
|
79
79
|
|
|
80
80
|
[tool.poetry]
|
|
81
81
|
name = "fastprocesses"
|
|
82
|
-
version = "0.22.
|
|
82
|
+
version = "0.22.2"
|
|
83
83
|
description = "A library to create a FastAPI-based OGC API Processes wrapper around existing projects."
|
|
84
84
|
authors = ["Stefan Schuhart <stefan.schuhart@gv.hamburg.de>"]
|
|
85
85
|
readme = "README.md"
|
|
@@ -17,7 +17,10 @@ from fastprocesses.core.models import CalculationTask, JobStatusCode
|
|
|
17
17
|
from fastprocesses.processes.process_registry import get_process_registry
|
|
18
18
|
from fastprocesses.worker.job_status import (
|
|
19
19
|
_cleanup_progress_counter,
|
|
20
|
+
_cleanup_scatter_roster,
|
|
20
21
|
_increment_and_report_progress,
|
|
22
|
+
_init_scatter_roster,
|
|
23
|
+
_record_scatter_step_done,
|
|
21
24
|
update_job_status,
|
|
22
25
|
)
|
|
23
26
|
|
|
@@ -270,7 +273,7 @@ def execute_scatter_step(
|
|
|
270
273
|
result = jsonable_encoder(partial)
|
|
271
274
|
rkey = _result_key(job_id, step_name)
|
|
272
275
|
temp_result_cache.put(key=rkey, value=result)
|
|
273
|
-
|
|
276
|
+
_record_scatter_step_done(job_id, step_name, total)
|
|
274
277
|
return {"__claim_check__": rkey}
|
|
275
278
|
except Exception as exc:
|
|
276
279
|
update_job_status(
|
|
@@ -310,6 +313,7 @@ def _run_scatter(
|
|
|
310
313
|
f"{total} step(s): {step_names}."
|
|
311
314
|
)
|
|
312
315
|
|
|
316
|
+
_init_scatter_roster(job_id, step_names)
|
|
313
317
|
pkey = _payload_key(job_id)
|
|
314
318
|
temp_result_cache.put(
|
|
315
319
|
key=pkey,
|
|
@@ -357,7 +361,12 @@ def finalize_scatter(
|
|
|
357
361
|
|
|
358
362
|
payload = temp_result_cache.get(payload_key)
|
|
359
363
|
temp_result_cache.delete(payload_key)
|
|
360
|
-
|
|
364
|
+
# step_input is the resolved data (after resolve_remote_inputs + pipeline).
|
|
365
|
+
# original_input is the wire-format exec_body (may contain URL strings)
|
|
366
|
+
# and is used only for deriving the stable cache key — never for business
|
|
367
|
+
# logic, because the resolved content may change between cache fills.
|
|
368
|
+
exec_body: dict = payload["step_input"] if payload else {}
|
|
369
|
+
original_input: dict = payload.get("original_input", exec_body) if payload else {}
|
|
361
370
|
|
|
362
371
|
update_job_status(
|
|
363
372
|
job_id, 95, "Merging scatter results.", JobStatusCode.RUNNING
|
|
@@ -366,7 +375,7 @@ def finalize_scatter(
|
|
|
366
375
|
merged = merge_result.model_dump(mode="json")
|
|
367
376
|
|
|
368
377
|
try:
|
|
369
|
-
calculation_task = CalculationTask(**
|
|
378
|
+
calculation_task = CalculationTask(**original_input)
|
|
370
379
|
temp_result_cache.put(key=calculation_task.celery_key, value=merged)
|
|
371
380
|
# Also store under job_id so get_job_result can retrieve it.
|
|
372
381
|
temp_result_cache.put(key=job_id, value=merged)
|
|
@@ -382,6 +391,7 @@ def finalize_scatter(
|
|
|
382
391
|
job_id, 100, "Process completed.", JobStatusCode.SUCCESSFUL
|
|
383
392
|
)
|
|
384
393
|
_cleanup_progress_counter(job_id)
|
|
394
|
+
_cleanup_scatter_roster(job_id)
|
|
385
395
|
logger.info(
|
|
386
396
|
f"Scatter process {process_id} (job {job_id}) completed successfully."
|
|
387
397
|
)
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from datetime import datetime, timezone
|
|
2
|
-
|
|
2
|
+
import json
|
|
3
3
|
from fastprocesses.common import job_status_cache
|
|
4
4
|
from fastprocesses.core.logging import logger
|
|
5
5
|
from fastprocesses.core.models import JobStatusCode, JobStatusInfo, Link
|
|
6
6
|
|
|
7
7
|
_SUBTASK_PROGRESS_KEY = "fp:subtask_progress"
|
|
8
|
+
_SCATTER_ALL_KEY = "fp:scatter_all"
|
|
9
|
+
_SCATTER_DONE_KEY = "fp:scatter_done"
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
def update_job_status(
|
|
@@ -144,3 +146,82 @@ def _cleanup_progress_counter(job_id: str) -> None:
|
|
|
144
146
|
logger.warning(
|
|
145
147
|
"Could not clean up progress counter for job {}: {!r}", job_id, exc
|
|
146
148
|
)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _init_scatter_roster(job_id: str, step_names: list[str]) -> None:
|
|
152
|
+
"""
|
|
153
|
+
Stores the full list of scatter step names for *job_id* so that any
|
|
154
|
+
subtask can later read it back to build the step-status message.
|
|
155
|
+
Called once by ``_run_scatter`` before the chord is dispatched.
|
|
156
|
+
"""
|
|
157
|
+
try:
|
|
158
|
+
redis = job_status_cache.redis_connection
|
|
159
|
+
all_key = f"{_SCATTER_ALL_KEY}:{job_id}"
|
|
160
|
+
|
|
161
|
+
redis._execute_redis_command("set", all_key, json.dumps(step_names))
|
|
162
|
+
redis._execute_redis_command("expire", all_key, 86400)
|
|
163
|
+
except Exception as exc: # pragma: no cover
|
|
164
|
+
logger.warning(
|
|
165
|
+
"Could not initialise scatter roster for job {}: {!r}", job_id, exc
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _record_scatter_step_done(job_id: str, step_name: str, total: int) -> None:
|
|
170
|
+
"""
|
|
171
|
+
Marks *step_name* as completed for *job_id* and updates the job status
|
|
172
|
+
message with a human-readable roster:
|
|
173
|
+
|
|
174
|
+
Steps: vulnerability_pipeline ✓, exposure_pipeline ✓,
|
|
175
|
+
hazard_wb_pipeline …, hazard_ma_pipeline … (2/4 done)
|
|
176
|
+
|
|
177
|
+
Uses an atomic INCR for the progress percentage (same 0-90 % band as
|
|
178
|
+
``_increment_and_report_progress``) and a Redis set for the done-step
|
|
179
|
+
roster so concurrent workers never race.
|
|
180
|
+
|
|
181
|
+
All exceptions are swallowed so a Redis hiccup never causes a subtask
|
|
182
|
+
to fail.
|
|
183
|
+
"""
|
|
184
|
+
import json as json
|
|
185
|
+
counter_key = f"{_SUBTASK_PROGRESS_KEY}:{job_id}"
|
|
186
|
+
done_key = f"{_SCATTER_DONE_KEY}:{job_id}"
|
|
187
|
+
all_key = f"{_SCATTER_ALL_KEY}:{job_id}"
|
|
188
|
+
try:
|
|
189
|
+
redis = job_status_cache.redis_connection
|
|
190
|
+
completed = redis._execute_redis_command("incr", counter_key)
|
|
191
|
+
if completed == 1:
|
|
192
|
+
redis._execute_redis_command("expire", counter_key, 86400)
|
|
193
|
+
redis._execute_redis_command("sadd", done_key, step_name)
|
|
194
|
+
redis._execute_redis_command("expire", done_key, 86400)
|
|
195
|
+
|
|
196
|
+
# Read back all_steps and done_steps to build the message.
|
|
197
|
+
raw_all = redis._execute_redis_command("get", all_key)
|
|
198
|
+
all_steps: list[str] = json.loads(raw_all) if raw_all else []
|
|
199
|
+
done_raw = redis._execute_redis_command("smembers", done_key)
|
|
200
|
+
done_steps: set[str] = {
|
|
201
|
+
m.decode() if isinstance(m, bytes) else m for m in (done_raw or [])
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
parts = [
|
|
205
|
+
f"{s} \u2713" if s in done_steps else f"{s} \u2026"
|
|
206
|
+
for s in (all_steps or [step_name])
|
|
207
|
+
]
|
|
208
|
+
message = ", ".join(parts) + f" ({len(done_steps)}/{total} done)"
|
|
209
|
+
|
|
210
|
+
progress = min(int(completed / total * 90), 90)
|
|
211
|
+
update_job_status(job_id, progress, message, JobStatusCode.RUNNING)
|
|
212
|
+
except Exception as exc: # pragma: no cover
|
|
213
|
+
logger.warning(
|
|
214
|
+
"Could not record scatter step progress for job {}: {!r}", job_id, exc
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _cleanup_scatter_roster(job_id: str) -> None:
|
|
219
|
+
"""Deletes scatter roster keys for *job_id* after the job completes."""
|
|
220
|
+
try:
|
|
221
|
+
redis = job_status_cache.redis_connection
|
|
222
|
+
redis._execute_redis_command("delete", f"{_SCATTER_ALL_KEY}:{job_id}")
|
|
223
|
+
redis._execute_redis_command("delete", f"{_SCATTER_DONE_KEY}:{job_id}")
|
|
224
|
+
except Exception as exc: # pragma: no cover
|
|
225
|
+
logger.warning(
|
|
226
|
+
"Could not clean up scatter roster for job {}: {!r}", job_id, exc
|
|
227
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/core/output_schema_resolver.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastprocesses-0.22.1 → fastprocesses-0.22.2}/src/fastprocesses/processes/process_registry.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|