working on runtime executions

This commit is contained in:
2026-02-16 22:04:20 -06:00
parent f52320f889
commit 904ede04be
99 changed files with 6778 additions and 5929 deletions

View File

@@ -0,0 +1,114 @@
# Fix: Pack Installation Virtualenv Ordering & FK ON DELETE Constraints
**Date:** 2026-02-05
## Problems
### 1. Virtualenv Not Created at Permanent Location
When installing a Python pack (e.g., `python_example`), no virtualenv was created at the permanent storage location. Attempting to run an action yielded:
```json
{
"error": "Execution failed during preparation",
"succeeded": false
}
```
### 2. Pack Deletion Blocked by Foreign Key Constraints
Deleting a pack that had been used (with executions) failed with:
```json
{
"error": "Constraint violation: execution_action_fkey",
"code": "CONFLICT"
}
```
## Root Causes
### Virtualenv Ordering Bug
In `install_pack` (`crates/api/src/routes/packs.rs`), the operation ordering was incorrect:
1. Pack downloaded to temp directory (`/tmp/attune-pack-installs/...`)
2. `register_pack_internal(temp_path)` called — creates DB record **and sets up virtualenv at temp path**
3. `storage.install_pack()` copies pack from temp to permanent storage (`packs/{pack_ref}/`)
4. Temp directory cleaned up
Python virtualenvs are **not relocatable** — they contain hardcoded paths in shebang lines, `pyvenv.cfg`, and pip scripts. The copied `.venv` was non-functional.
### Missing ON DELETE Clauses on Foreign Keys
Several foreign key constraints in the schema had no `ON DELETE` behavior (defaulting to `RESTRICT`), which blocked cascading deletes:
- `execution.action``action(id)`**no ON DELETE** (blocks action deletion)
- `execution.parent``execution(id)`**no ON DELETE**
- `execution.enforcement``enforcement(id)`**no ON DELETE**
- `rule.action``action(id)`**no ON DELETE**, also `NOT NULL`
- `rule.trigger``trigger(id)`**no ON DELETE**, also `NOT NULL`
- `event.source``sensor(id)`**no ON DELETE**
- `workflow_execution.workflow_def``workflow_definition(id)`**no ON DELETE**
When deleting a pack, the cascade deleted actions (`action.pack ON DELETE CASCADE`), but executions referencing those actions blocked the delete.
## Fixes
### 1. Pack Installation Ordering
Restructured `install_pack` to move the pack to permanent storage **before** calling `register_pack_internal`:
1. Pack downloaded to temp directory
2. `pack.yaml` read to extract `pack_ref`
3. **Pack moved to permanent storage** (`packs/{pack_ref}/`)
4. `register_pack_internal(permanent_path)` called — virtualenv creation and dependency installation now happen at the final location
5. Temp directory cleaned up
Added error handling to clean up permanent storage if registration fails after the move.
### 2. Foreign Key ON DELETE Fixes (Merged into Original Migrations)
Fixed all missing ON DELETE behaviors directly in the original migration files (requires DB rebuild):
| Table.Column | Migration File | ON DELETE | Notes |
|---|---|---|---|
| `execution.action` | `000006_execution_system` | `SET NULL` | Already nullable; `action_ref` text preserved |
| `execution.parent` | `000006_execution_system` | `SET NULL` | Already nullable |
| `execution.enforcement` | `000006_execution_system` | `SET NULL` | Already nullable |
| `rule.action` | `000006_execution_system` | `SET NULL` | Made nullable; `action_ref` text preserved |
| `rule.trigger` | `000006_execution_system` | `SET NULL` | Made nullable; `trigger_ref` text preserved |
| `event.source` | `000004_trigger_sensor_event_rule` | `SET NULL` | Already nullable; `source_ref` preserved |
| `workflow_execution.workflow_def` | `000007_workflow_system` | `CASCADE` | Meaningless without definition |
### 3. Model & Code Updates
- **Rule model** (`crates/common/src/models.rs`): Changed `action: Id` and `trigger: Id` to `Option<Id>`
- **RuleResponse DTO** (`crates/api/src/dto/rule.rs`): Changed `action` and `trigger` to `Option<i64>`
- **Enforcement processor** (`crates/executor/src/enforcement_processor.rs`): Added guards to skip execution when a rule's action or trigger has been deleted (SET NULL)
- **Pack delete endpoint** (`crates/api/src/routes/packs.rs`): Added filesystem cleanup to remove pack directory from permanent storage on deletion
### 4. Test Updates
- `crates/common/tests/rule_repository_tests.rs`: Updated assertions to use `Some(id)` for nullable fields
- `crates/executor/src/enforcement_processor.rs` (tests): Updated test Rule construction with `Some()` wrappers
## Files Changed
- `migrations/20250101000004_trigger_sensor_event_rule.sql` — Added `ON DELETE SET NULL` to `event.source`
- `migrations/20250101000006_execution_system.sql` — Added `ON DELETE SET NULL` to `execution.action`, `.parent`, `.enforcement`; made `rule.action`/`.trigger` nullable with `ON DELETE SET NULL`
- `migrations/20250101000007_workflow_system.sql` — Added `ON DELETE CASCADE` to `workflow_execution.workflow_def`
- `crates/api/src/routes/packs.rs` — Reordered `install_pack`; added pack directory cleanup on delete
- `crates/api/src/dto/rule.rs` — Made `action`/`trigger` fields optional in `RuleResponse`
- `crates/common/src/models.rs` — Made `Rule.action`/`Rule.trigger` `Option<Id>`
- `crates/executor/src/enforcement_processor.rs` — Handle nullable action/trigger in enforcement processing
- `crates/common/tests/rule_repository_tests.rs` — Fixed test assertions
## Design Philosophy
Historical records (executions, events, enforcements) are preserved when their referenced entities are deleted. The text ref fields (`action_ref`, `trigger_ref`, `source_ref`, etc.) retain the reference for auditing, while the FK ID fields are set to NULL. Rules with deleted actions or triggers become non-functional but remain in the database for traceability.
## Verification
- `cargo check --all-targets --workspace` — zero warnings
- `cargo test --workspace --lib` — all 358 unit tests pass