duroxide-orchestration-versioning
Guidance for safely versioning Duroxide orchestrations — file structure, naming conventions, workflow, and registry registration.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Guidance for safely versioning Duroxide orchestrations — file structure, naming conventions, workflow, and registry registration.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Deploying and debugging Toygres on AKS (Azure Kubernetes Service). Use when deploying, debugging pods, viewing logs, troubleshooting SSL, or managing Kubernetes resources.
Making database schema changes to the CMS database. Use when adding columns, tables, running migrations, or updating the backend API and TypeScript types for new database fields.
Writing durable workflows using Duroxide in Rust. Use when creating orchestrations, activities, workflows, or when the user mentions duroxide, durable functions, or workflow orchestration.
Building full-stack features in Toygres from UI to database. Use when adding new features, API endpoints, React components, or implementing end-to-end functionality.
Implementing and debugging PostgreSQL image backup and restore features. Use when working with database snapshots, backup jobs, restore operations, azcopy blob transfers, or troubleshooting image-related provisioning failures.
Managing instance actor orchestrations for PostgreSQL health monitoring. Use when debugging stale actors, restarting actors, or troubleshooting health check issues.
| name | duroxide-orchestration-versioning |
| description | Guidance for safely versioning Duroxide orchestrations — file structure, naming conventions, workflow, and registry registration. |
Orchestration code is immutable once deployed.
Running instances replay historical events. If you change orchestration logic (or helpers it calls), replay can break in subtle ways.
This applies to:
OrchestrationContext)You MUST NOT cause ANY side effect on existing frozen orchestrations. This includes changes to shared types (e.g., activity input/output structs) that alter serialization behavior. If you add a field to a shared struct:
#[serde(default, skip_serializing_if = "Option::is_none")] for new Option<T> fields so None is omitted (not serialized as null)serde_json::to_string(&OldInput { field: None }) produces the same JSON as the original struct without the fieldtest-connection-v2) instead of modifying the shared typeCreate a new orchestration version for any logic change, including "small fixes":
Each orchestration lives in its own folder under toygres-orchestrations/src/orchestrations/:
instance_actor/
mod.rs # Wiring only: NAME const, pub mod, pub use
instance_actor_orchestration.rs # Latest version code (currently v1.0.2)
instance_actor_1_0_1_orchestration.rs # Frozen v1.0.1
instance_actor_1_0_0_orchestration.rs # Frozen v1.0.0
| Item | Pattern | Example |
|---|---|---|
| Function name (all versions) | {name}_{version}_orchestration | instance_actor_1_0_2_orchestration |
| Latest file | {name}_orchestration.rs | instance_actor_orchestration.rs |
| Frozen file | {name}_{version}_orchestration.rs | instance_actor_1_0_1_orchestration.rs |
mod.rs contains no orchestration logic — only wiring:
/// Orchestration name for registration and scheduling
pub const NAME: &str = "toygres-orchestrations::orchestration::instance-actor";
pub mod instance_actor_1_0_0_orchestration;
pub mod instance_actor_1_0_1_orchestration;
mod instance_actor_orchestration;
pub use instance_actor_1_0_0_orchestration::instance_actor_1_0_0_orchestration;
pub use instance_actor_1_0_1_orchestration::instance_actor_1_0_1_orchestration;
pub use instance_actor_orchestration::instance_actor_1_0_2_orchestration;
Note: frozen versions are pub mod (needed by registry), latest is mod (re-exported via pub use).
Shared helper functions (e.g., update_cms_state in delete_instance) may live in mod.rs since they are shared utilities, not orchestration logic.
Assume the current latest is v1.0.1 and you want to add v1.0.2.
cp instance_actor_orchestration.rs instance_actor_1_0_1_orchestration.rs
This frozen copy is byte-for-byte identical. Git shows it as all + lines (a new file) — reviewers can ignore it.
In instance_actor_orchestration.rs:
instance_actor_1_0_1_orchestration → instance_actor_1_0_2_orchestration[v1.0.1] → [v1.0.2]Git diff shows clean -/+ pairs for every real change — exactly what reviewers need.
Add the new frozen module and update re-exports:
pub mod instance_actor_1_0_0_orchestration;
pub mod instance_actor_1_0_1_orchestration; // ← new frozen module
mod instance_actor_orchestration;
pub use instance_actor_1_0_0_orchestration::instance_actor_1_0_0_orchestration;
pub use instance_actor_1_0_1_orchestration::instance_actor_1_0_1_orchestration; // ← new
pub use instance_actor_orchestration::instance_actor_1_0_2_orchestration; // ← updated
.register_versioned_typed(
instance_actor::NAME,
"1.0.2",
instance_actor::instance_actor_1_0_2_orchestration,
)
cargo build --workspace
Prefix all orchestration logs with the version for debugging:
ctx.trace_info("[v1.0.2] ...")start_orchestration(...) uses the latest registered version.continue_as_new boundaries, depending on the workflow design and Duroxide policy).If you want to "refactor" orchestration code:
Before shipping:
{name}_{old_version}_orchestration.rs)[vX.Y.Z] log prefixesmod.rs (added frozen module, updated re-export).register_versioned_typed(NAME, "X.Y.Z", ...)skip_serializing_if to preserve JSON compatibilityNone/default values produce identical JSON to the old structcargo build --workspace passes