You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor(precisely): observation-only — drop unverified submit + list-runs paths
Precisely Connect ETL publishes exactly one REST endpoint:
GET /projects/{jobRunId}/status (plain-text response).
The components shipped speculative integrations with two other
endpoints that Precisely does NOT document publicly:
- PreciselyResource.run_job() POSTed to /projects/{job_id}/run
- precisely_job_sensor mode-2 GET /api/v1/jobs/{job_id}/runs
Both were "best-guess RESTful shapes" — the docstrings admitted as
much. In real customer installs they 404 because the API surface
just isn't there. precisely_run_asset would never materialize.
This change:
1. precisely_run_asset is now an observable_source_asset that polls
the documented Job Status endpoint and emits ObserveResult with
status + is_terminal/is_success/is_in_progress flags. No submit.
Required field is job_run_id (the actual run-id from Precisely's
side), not job_id + speculative submit.
2. PreciselyResource drops run_job() and submit_path_template. Only
get_run_status() remains — the verified endpoint.
3. precisely_job_sensor drops the speculative list-runs mode
(job_id + list_runs_path_template). Only the verified
job_run_id-watching mode remains.
4. README + schema.json + example.yaml updated to reflect the new
observe-only shape.
Pair-of-components story:
- precisely_run_asset → catalog presence + lineage (observable_source_asset)
- precisely_job_sensor → event-driven downstream Dagster work (RunRequest on terminal SUCCESS)
Both poll the same verified endpoint; they're complementary, not
redundant — one is a graph node, one is an event source.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Triggers a [Precisely Connect ETL](https://www.precisely.com/product/precisely-connect/connect) (formerly Syncsort DMX / DMExpress) job on demand and surfaces the result as a Dagster asset. Dagster owns the schedule and orchestration; Precisely executes the integration.
3
+
Observes a [Precisely Connect ETL](https://www.precisely.com/product/precisely-connect/connect) (formerly Syncsort DMX / DMExpress) job run as a Dagster `observable_source_asset`. Precisely owns the schedule; Dagster surfaces the latest status in its catalog.
4
4
5
5
## What this does
6
6
7
-
When the asset is materialized:
7
+
When the asset is observed (manually, on a schedule, or by Dagster's automation):
8
8
9
-
1. POSTs to the Precisely Connect job-submit endpoint
10
-
2. Polls the documented Job Status endpoint until the job reaches a terminal status
11
-
3. Returns a `MaterializeResult` with run metadata on success, or raises on failure / timeout
9
+
1. Calls the documented Precisely Job Status endpoint (`GET /projects/{jobRunId}/status`)
10
+
2. Emits an `ObserveResult` with the run's current status, plus boolean flags for terminal / success / in-progress states
12
11
13
-
## API verification status
12
+
That's it. There is **no submit / trigger** — Precisely doesn't publish a job-submit REST endpoint, so this component never pretends to start runs. Use Precisely's own scheduler to launch the job; use this component to surface its state in the Dagster graph.
14
13
15
-
| Endpoint | Verification | Override field |
16
-
|---|---|---|
17
-
|**Job Status** — `GET /projects/{jobRunId}/status` (plain-text response) |**Verified** against Precisely's [public REST API docs](https://help.precisely.com/r/Connect-ETL/pub/Latest/en-US/Connect-ETL-Rest-API-Reference/Job-Status)| (path is fixed) |
18
-
|**Submit** — `POST /projects/{job_id}/run` with JSON `{parameters: {...}}`|**Best-guess** RESTful shape — Precisely's submit endpoint isn't in the public REST docs |`submit_path_template`|
14
+
For event-driven downstream Dagster work that fires when a Precisely run completes, pair with the [`precisely_job_sensor`](../../sensors/precisely_job_sensor/).
15
+
16
+
## API verification status
19
17
20
-
If your Connect ETL install uses a different submit path, override `submit_path_template`. The status-poll path is fixed because it's the documented one.
18
+
| Endpoint | Verification |
19
+
|---|---|
20
+
|**Job Status** — `GET /projects/{jobRunId}/status` (plain-text response) |**Verified** against Precisely's [public REST API docs](https://help.precisely.com/r/Connect-ETL/pub/Latest/en-US/Connect-ETL-Rest-API-Reference/Job-Status)|
| `poll_interval_seconds` | `float` | `10.0` | Seconds between status polls |
66
-
| `timeout_seconds` | `int` | `3600` | Max seconds to wait for job completion |
67
-
| `submit_path_template` | `str` | `"/projects/{job_id}/run"` | Template for the job-submit endpoint when not using a resource. Default is a best-guess RESTful shape; replace if your Connect ETL install uses a different path. Available placeholder: {job_id}. The status-poll path is fixed at /projects/{jobRunId}/status per Precisely's documented Connect ETL Job Status endpoint. |
68
-
69
60
### Catalog metadata
70
61
71
62
| Field | Type | Default | Description |
72
63
|---|---|---|---|
73
64
| `group_name` | `str` | `"precisely"` | Dagster asset group name |
74
-
| `deps` | `list[str]` | — | Upstream asset keys this asset depends on (e.g. ['raw_orders', 'schema/asset']) |
65
+
| `deps` | `List[str]` | — | Upstream asset keys this asset depends on |
75
66
| `description` | `str` | — | Asset description shown in the Dagster catalog. |
76
67
| `owners` | `List[str]` | — | Asset owners — team names ('team:analytics') or email addresses. |
77
68
| `asset_tags` | `Dict[str, str]` | — | Additional key-value tags applied to the asset in the Dagster catalog. |
78
-
| `kinds` | `List[str]` | — | Asset kinds for the catalog (e.g. ['snowflake', 'python']). Auto-inferred from component name when unset. |
79
-
| `column_lineage` | `Dict[str, List[str]]` | — | Column-level lineage: output column → list of upstream columns it derives from, e.g. {'revenue': ['price', 'quantity']}. |
80
-
81
-
### Freshness
82
-
83
-
| Field | Type | Default | Description |
84
-
|---|---|---|---|
85
-
| `freshness_max_lag_minutes` | `int` | — | Maximum acceptable lag in minutes before the asset is considered stale. Builds a FreshnessPolicy when set. |
86
-
| `freshness_cron` | `str` | — | Cron schedule string for the freshness policy, e.g. '0 9 * * 1-5' (weekdays 9am). |
87
-
88
-
### Partitions
89
-
90
-
| Field | Type | Default | Description |
91
-
|---|---|---|---|
92
-
| `partition_type` | `str` | — | Partition type: 'daily', 'weekly', 'monthly', 'hourly', 'static', 'multi', or None for unpartitioned. |
93
-
| `partition_start` | `str` | — | Partition start date in ISO format (e.g. '2024-01-01'). Required for time-based partition types. |
94
-
| `partition_date_column` | `str` | — | Column used to filter the upstream DataFrame to the current date partition key. |
95
-
| `partition_values` | `str` | — | Comma-separated values for static or multi partitioning, e.g. 'acme,globex,initech'. |
96
-
| `partition_static_dim` | `str` | — | Dimension name for the static axis in multi-partitioning, e.g. 'customer'. |
97
-
| `partition_static_column` | `str` | — | Column used to filter the upstream DataFrame to the current static partition value. |
98
-
99
-
### Retry policy
100
-
101
-
| Field | Type | Default | Description |
102
-
|---|---|---|---|
103
-
| `retry_policy_max_retries` | `int` | — | Max retries on failure. Defines a RetryPolicy when set. |
| `is_terminal` | `True` if status is one of the terminal states |
113
+
| `is_success` | `True` if status is `COMPLETED` or `COMPLETED_WITH_WARNINGS` |
114
+
| `is_in_progress` | `True` if status is `WAITING` or `RUNNING` |
115
+
| `precisely_host` | The Precisely host the status was polled from |
185
116
186
-
## Failure semantics
187
-
188
-
The asset raises (failing the materialization) if Precisely returns any of these terminal statuses:
189
-
190
-
| Status | Meaning |
191
-
|---|---|
192
-
| `COMPLETED_WITH_ERRORS` | Job ran but produced errors |
193
-
| `CANCELLED` | Run was cancelled |
194
-
| `ERRORED` | Run failed |
195
-
| `LOST_CONTACT` | Connect ETL lost contact with the runtime |
196
-
197
-
A timeout (`timeout_seconds` elapsed without reaching a terminal status) also raises. Combine with `retry_policy_max_retries` for fault tolerance.
117
+
The component does **not** raise on `COMPLETED_WITH_ERRORS` / `ERRORED` / `CANCELLED` / `LOST_CONTACT` — observation is reporting, not gating. If you want a failed Precisely run to fail a downstream Dagster job, use the [`precisely_job_sensor`](../../sensors/precisely_job_sensor/) (which only fires `RunRequest` on terminal SUCCESS) and watch the Dagster job for skips.
198
118
199
119
## Lineage
200
120
@@ -206,16 +126,6 @@ deps:
206
126
- staging/customers # path-prefixed asset key
207
127
```
208
128
209
-
For column-level lineage in the catalog, set `column_lineage`:
210
-
211
-
```yaml
212
-
column_lineage:
213
-
customer_revenue:
214
-
- orders.total
215
-
- orders.discount
216
-
- customers.id
217
-
```
218
-
219
129
Dependencies can also be wired externally via `map_resolved_asset_specs()` in `definitions.py`.
220
130
221
131
## Requirements
@@ -227,4 +137,4 @@ requests>=2.28.0
227
137
## See also
228
138
229
139
- [`precisely_job_sensor`](../../sensors/precisely_job_sensor/) — fire a Dagster job when a Precisely run reaches terminal success
230
-
- [`precisely_validation.md`](https://github.com/eric-thomas-dagster/dagster-community-components-cli/blob/main/examples/precisely_validation.md) — what's verified against Precisely's public REST docs and what's best-guess
140
+
- [`precisely_validation.md`](https://github.com/eric-thomas-dagster/dagster-community-components-cli/blob/main/examples/precisely_validation.md) — what's verified against Precisely's public REST docs
0 commit comments