pd_session_orchestration¶
Manages the complete lifecycle of a plant design editing session: lock acquisition, working copy download/upload, crash recovery, and lock release.
Replaces S3ProjektManager (write-access flow) and S3ProjectShutdownHandler.
Structure¶
pd_session_orchestration/
model/
session_state.py SessionState enum, SessionError, constants
controller/
session_controller.py PlantDesignSession - main lifecycle API
crash_recovery.py CrashRecoveryHandler - atexit/signal hooks, emergency backups
file_transfer.py Parallel download/upload, R2 key builders, content type mapping
Usage¶
from src.modules.plant_design.startup_system.bound_subsystems.pd_session_orchestration.controller.session_controller import (
PlantDesignSession,
)
session = PlantDesignSession()
# Open session (acquires R2 lock, downloads working copy)
work_path = session.open(projekt_id="Kraftwerk_1234567", user="admin", stage="planning")
# ... caller works on files at work_path ...
# Close session (uploads changes, releases lock)
session.close()
Session Lifecycle¶
Online: IDLE -> ACQUIRING -> DOWNLOADING -> ACTIVE -> UPLOADING -> CLOSED
Resume: IDLE -> ACQUIRING -> RESTORING -> ACTIVE -> UPLOADING -> CLOSED
Crash: ACTIVE -> RECOVERING -> CLOSED
Abort: any -> CLOSED
open(projekt_id, user, stage)¶
- Acquires stage lock in R2 (
planning.lock.json) viaBucketService.acquire_lock() - Downloads working copy from R2 to
.app_temp/plant_design/in parallel (10 workers) - Registers atexit/signal hooks for crash recovery
- Returns the local
Pathwhere the caller can edit files
close()¶
- Uploads working directory back to R2 in parallel
- Releases the R2 lock
- Unregisters crash hooks, cleans up local working directory
abort()¶
Releases the lock and cleans up without uploading. Used when the user cancels editing.
Crash Recovery¶
When the application terminates unexpectedly during an active session:
- During crash (automatic via atexit/signal hooks):
- Working copy backed up from
.app_temp/topersistent_data/plant_design/recovery/ - R2 lock released (or expires automatically after 12h)
-
Recovery info file preserved on disk
-
Next startup (caller-driven):
- Call
session.check_previous_crash()to detect orphaned sessions - Returns recovery data (projekt_id, user, stage, backup_path) or
None - Caller shows recovery dialog, then either resumes or discards
Lock Management¶
- Lock file:
{stage}.lock.jsonwithuser,since,machine,expiresfields - Atomic acquisition via
IfNoneMatch="*"(R2 conditional put) - Same-user re-entry allowed (idempotent)
- 12-hour expiry as safety net
Signals¶
| Signal | Args | Description |
|---|---|---|
state_changed |
int (SessionState value) |
Emitted on every state transition |
progress |
str, int (message, percentage) |
Emitted during download/upload |
Dependencies¶
src.shared_services.cloud_com.r2_com- BucketService for all R2 operationssrc.shared_services.path_management- PathDef-based path resolutionsrc.modules.plant_design.startup_system.constants.paths- SessionPaths, RecoveryPaths