Skip to content

Commit 00acdd1

Browse files
committed
Upgrade to duroxide 0.1.26 and duroxide-pg-opt 0.1.23
1 parent 70f2a7e commit 00acdd1

5 files changed

Lines changed: 220 additions & 5 deletions

File tree

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ serde_json = "1.0"
3232
uuid = { version = "1.0", features = ["v4", "serde"] }
3333

3434
# duroxide integration
35-
duroxide = "=0.1.20"
35+
duroxide = "=0.1.26"
3636
duroxide-pg-opt = { path = "duroxide-pg-opt", package = "duroxide-pg-opt" }
3737
tokio = { version = "1", features = ["rt-multi-thread", "sync", "time"] }
3838

docs/plan-duroxide-26-update.md

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# Plan: Update to duroxide 0.1.26 + duroxide-pg-opt 4a6bf6b
2+
3+
## Status: Preparatory
4+
5+
This plan documents the work required to move pg_durable to duroxide 0.1.26 and
6+
duroxide-pg-opt commit `4a6bf6b`.
7+
8+
**Do not merge the implementation until there is a new duroxide-pg-opt release tag
9+
(expected: v0.1.24) that includes the `MigrationPolicy` commit `4a6bf6b`.** At that
10+
point this plan will likely need an update to account for any additional changes to
11+
duroxide-pg-opt between now and that tag, and possibly additional duroxide versions
12+
as well.
13+
14+
## Current vs. Target
15+
16+
| Dependency | Current | Target |
17+
|---|---|---|
18+
| `duroxide` (crates.io) | `=0.1.20` | `=0.1.26` |
19+
| `duroxide-pg-opt` (submodule) | `8ce65bd` (topic branch, based off ~v0.1.18) | `4a6bf6b` (origin/main, one commit past v0.1.23) |
20+
21+
The current submodule commit (`8ce65bd`) is the `MigrationPolicy` feature branch
22+
that adds `MigrationPolicy::VerifyOnly`. The target commit (`4a6bf6b`) is the
23+
mainline commit on `origin/main` that merged the same feature — so `VerifyOnly`
24+
is already present in pg_durable and nothing about that support changes.
25+
26+
**Note (commit 397fb93):** pg_durable no longer checks in duroxide migration files.
27+
The BGW now applies all duroxide migrations at startup via `MigrationPolicy::ApplyAll`;
28+
the backend connection uses `VerifyOnly`. `sql/duroxide_install.sql`,
29+
`sql/duroxide_upstream/`, and the scripts `gen-duroxide-install-sql.sh` and
30+
`verify-duroxide-migrations.sh` were deleted in that commit. Implementation steps
31+
that previously synced those files are therefore eliminated (see checklist below).
32+
33+
## What Changed in duroxide (0.1.20 → 0.1.26)
34+
35+
### 0.1.21 — Orphan queue message drop (no impact)
36+
37+
Drops `QueueMessage` work items that arrive before orchestration starts. Internal
38+
provider-level fix; no pg_durable code changes needed.
39+
40+
### 0.1.22 — Activity Tags
41+
42+
New `TagFilter` enum, `RuntimeOptions.worker_tag_filter`, and
43+
`DurableFuture::with_tag()`. The `Provider::fetch_work_item()` signature gains a
44+
`tag_filter: &TagFilter` parameter — a breaking change for provider implementors,
45+
fully absorbed by duroxide-pg-opt 0.1.20+. The default is `TagFilter::DefaultOnly`
46+
(process only untagged activities), so all existing `schedule_activity` calls are
47+
completely unaffected. No pg_durable source changes required.
48+
49+
### 0.1.23 — Bug fixes and docs only (no impact)
50+
51+
### 0.1.24 — Durable KV Store
52+
53+
New `ctx.set_value()` / `ctx.get_value()` orchestration API and a new
54+
`Provider::get_kv_value()` trait method. pg_durable does not use the KV API.
55+
Provider-level changes absorbed by duroxide-pg-opt 0.1.21+.
56+
57+
### 0.1.25 — KV API Rename + Bulk Reads (no pg_durable impact)
58+
59+
`ctx.set_value()``ctx.set_kv_value()` etc. New required Provider method
60+
`get_kv_all_values()`. `OrchestrationItem.kv_snapshot` type changes to
61+
`HashMap<String, KvEntry>`. All absorbed by duroxide-pg-opt.
62+
63+
### 0.1.26 — KV Delta Table (fixes RMW replay poisoning)
64+
65+
KV mutations during the current execution now stage to a `kv_delta` table; only
66+
merged to `kv_store` at execution boundaries (Completed/CAN/Failed). Fixes
67+
nondeterminism errors in read-modify-write patterns. Provider-and-migration-only
68+
change, fully absorbed by duroxide-pg-opt.
69+
70+
**Net impact on pg_durable Rust source code: zero required changes.**
71+
72+
## What Changed in duroxide-pg-opt (8ce65bd → 4a6bf6b)
73+
74+
The target includes duroxide-pg-opt versions v0.1.19–v0.1.23 plus the
75+
`MigrationPolicy` PR merged on top.
76+
77+
### New migrations (all additive/safe for rolling upgrades)
78+
79+
| Migration | Feature | Schema Changes |
80+
|---|---|---|
81+
| 0006 | Activity tag routing | `worker_queue.tag TEXT` column + index; updated `enqueue_worker_work` and `fetch_work_item` SPs |
82+
| 0007 | Retry on fetch contention | `fetch_orchestration_item` SP body change only (no schema change) |
83+
| 0008 | KV store | New `kv_store` table; updated `fetch_orchestration_item`, `ack_orchestration_item`, deletion/pruning SPs |
84+
| 0009 | KV timestamps | `kv_store.last_updated_at_ms BIGINT` column; updated KV materialization SPs |
85+
| 0010 | KV delta table | New `kv_delta` table; two-table KV write model; delta→store merge on terminal transition |
86+
87+
### API stability
88+
89+
All pg_durable call sites against duroxide-pg-opt remain valid:
90+
91+
- `PostgresProvider::new_with_config(url, config)` — unchanged
92+
- `ProviderConfig { schema_name, migration_policy, long_poll }` — unchanged
93+
- `MigrationPolicy::ApplyAll` (BGW) and `MigrationPolicy::VerifyOnly` (backend) — both present and in use
94+
- **New at `4a6bf6b`**: `schema_name` values are now validated against
95+
`[A-Za-z_][A-Za-z0-9_]*` on construction. `"duroxide"` passes this check.
96+
97+
## Implementation Checklist
98+
99+
### 1. Update submodule pointer
100+
101+
```bash
102+
cd duroxide-pg-opt
103+
git fetch origin
104+
git checkout 4a6bf6b
105+
cd ..
106+
```
107+
108+
### 2. Update `Cargo.toml`
109+
110+
```toml
111+
# Change:
112+
duroxide = "=0.1.20"
113+
# To:
114+
duroxide = "=0.1.26"
115+
```
116+
117+
~~### 3. Sync migrations to `sql/duroxide_upstream/`~~ **Eliminated by commit 397fb93.**
118+
119+
~~### 4. Regenerate install SQL~~ **Eliminated by commit 397fb93.**
120+
121+
Because the BGW now applies all duroxide migrations via `MigrationPolicy::ApplyAll`,
122+
pg_durable no longer needs to copy migration files or maintain `sql/duroxide_install.sql`.
123+
The extension SQL only creates an empty `duroxide` schema; the BGW populates it at runtime.
124+
125+
### 3. Update the pg_durable upgrade script
126+
127+
v0.2.0 has not yet shipped, so edit the existing `sql/pg_durable--0.1.1--0.2.0.sql`
128+
upgrade script. **Do not add the duroxide migrations to the upgrade script** — the BGW
129+
will apply any missing migrations (0006–0010) via `ApplyAll` at startup.
130+
The only df-schema DDL needed is the `df.is_ready()` function (already added by
131+
commit 397fb93).
132+
133+
### 4. Update `docs/upgrade-testing.md`
134+
135+
Add a "Version-Specific Changes" entry for the new version covering:
136+
137+
- **Scenario A**: The `df` schema equivalent contract holds; the `duroxide` schema
138+
is explicitly excluded from snapshot diffs because fresh installs start with an
139+
empty `duroxide` schema (BGW fills it in at runtime) while upgrades carry forward
140+
the fully-populated schema from v0.1.1. This divergence is expected and documented.
141+
- **Scenario B1 (binary backward compat)**: The BGW uses `MigrationPolicy::ApplyAll`.
142+
A database with only migrations 0001–0005 is handled gracefully — the BGW applies
143+
the missing migrations at startup rather than refusing to initialize.
144+
- **Scenario B2**: No new pg_durable DDL in this release (all new tables are
145+
duroxide-owned). Existing `df.*` data survives upgrade unchanged.
146+
147+
(Note: the BGW-applies-migrations entry was already added to `docs/upgrade-testing.md`
148+
by commit 397fb93; this step is to document any remaining version-specific notes.)
149+
150+
### 5. Run `cargo update`
151+
152+
```bash
153+
cargo update
154+
```
155+
156+
This refreshes all transitive dependencies, not just duroxide and duroxide-pg-opt.
157+
158+
### 6. Build and test
159+
160+
```bash
161+
cargo build --features pg17
162+
cargo clippy --features pg17
163+
./scripts/test-unit.sh
164+
./scripts/test-e2e-local.sh
165+
./scripts/test-upgrade.sh
166+
```
167+
168+
## Upgrade & Migration Impact
169+
170+
### B1 — Binary Backward Compatibility
171+
172+
The BGW uses `MigrationPolicy::ApplyAll`, so it will apply any missing duroxide
173+
migrations (0006–0010) at startup rather than refusing to initialize. A database
174+
that still has only migrations 0001–0005 is safe: the BGW detects the gap and
175+
applies the remaining migrations in order. The backend uses `MigrationPolicy::VerifyOnly`
176+
and will wait (via `df.is_ready()` polling) until the BGW has completed all
177+
migrations before accepting work.
178+
179+
### B2 — Data Compatibility After Upgrade
180+
181+
All five new migrations are additive (new tables, new columns with defaults or
182+
nullable). Existing `df.vars`, `df.nodes`, `df.instances`, and `df.graphs` data
183+
is untouched. No data migration is required.
184+
185+
## Opportunities for pg_durable Improvements
186+
187+
These are not required for this update but become available once the dependency
188+
versions are bumped. Consider as follow-on work:
189+
190+
1. **Activity Tags** (duroxide 0.1.22): Expose a `tag` parameter on `df.sql()`,
191+
`df.http()`, etc. to route activities to specialized worker pools. Workers
192+
would declare their `TagFilter` via a GUC or `pg_durable.worker_tag` setting.
193+
194+
2. **Durable KV Store** (duroxide 0.1.24): Expose `df.kv_set(key, value)` and
195+
`df.kv_get(key)` as first-class DSL nodes, allowing orchestrations to accumulate
196+
state durably without a side table pattern. Useful for loop counter and
197+
accumulator patterns.
198+
199+
3. **Custom Status** (duroxide 0.1.19): Enrich `df.status()` to surface a custom
200+
status string published from within an orchestration, enabling richer progress
201+
reporting beyond the Pending/Running/Completed/Failed states.

docs/upgrade-testing.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,17 @@ what the upgrade script handles, and any backward compatibility considerations.
209209
- **Scenario B1 considerations:** Readiness checking is internal to the Rust binary — no SQL function needs to be registered. The new `.so` continues to work against v0.1.1 schemas that have not run `ALTER EXTENSION UPDATE`.
210210
- **Scenario B2 considerations:** The BGW readiness check (`wait_for_ready()`) is called in both B1 and B2 scenarios to ensure the BGW has applied all pending duroxide migrations before exercising the extension.
211211
- **Current status on this branch:** Implemented. BGW now uses `MigrationPolicy::ApplyAll`, verifies duroxide schema extension ownership before applying, and writes `duroxide._worker_ready` after initialization completes.
212+
213+
#### Bump to duroxide 0.1.26 + duroxide-pg-opt 4a6bf6b (migrations 0006–0010)
214+
- **DDL change (df schema):** None. All new schema objects are in the `duroxide` schema and are applied at runtime by the BGW.
215+
- **DDL change (duroxide schema):** Five new migrations applied by BGW at startup:
216+
- 0006: `worker_queue.tag TEXT` column + index; updated `enqueue_worker_work` and `fetch_work_item` SPs
217+
- 0007: `fetch_orchestration_item` SP body change only (no schema change)
218+
- 0008: new `kv_store` table; updated `fetch_orchestration_item`, `ack_orchestration_item`, deletion/pruning SPs
219+
- 0009: `kv_store.last_updated_at_ms BIGINT` column; updated KV materialization SPs
220+
- 0010: new `kv_delta` table; two-table KV write model; delta→store merge on terminal transition
221+
- **Scenario A considerations:** The `df` schema equivalence contract is unchanged. The `duroxide` schema is excluded from snapshot diffs — fresh installs start with an empty `duroxide` schema (BGW fills it in at runtime) while upgrades carry forward the fully-populated schema from v0.1.1. This is expected and acceptable.
222+
- **Scenario B1 considerations:** The BGW uses `MigrationPolicy::ApplyAll`. A database that has only migrations 0001–0005 is handled gracefully: the BGW detects the gap and applies 0006–0010 at startup. No manual intervention is needed.
223+
- **Scenario B2 considerations:** All five new migrations are additive (new tables and columns with defaults or nullable). Existing `df.vars`, `df.nodes`, `df.instances`, and `df.graphs` data is untouched.
224+
- **Current status:** Implemented — submodule at `4a6bf6b`, `Cargo.toml` pinned to `duroxide = "=0.1.26"`.
225+
>>>>>>> dc6ab46 (Upgrade to duroxide 0.1.26 and duroxide-pg-opt 0.1.23)

duroxide-pg-opt

0 commit comments

Comments
 (0)