feat: add support for UUIDv7 generation and update command options to use UUIDv7 - #22
Conversation
WalkthroughReplaces default UUID generation from uuid4 to uuid7 across command dispatch and in-memory event storage. Adds Commanded.UUID.uuid7/0 delegating to the configured UUID provider. Updates documentation examples to reference uuid7. No public signatures changed; behavior updates are default-value substitutions. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor C as Client
participant R as Router
participant U as Commanded.UUID
participant P as UUID Provider
participant H as Handler/Aggregate
participant ES as Event Store (InMemory)
C->>R: dispatch(command)
R->>U: uuid7() for command_uuid
U->>P: uuid7()
P-->>U: time-ordered UUID
U-->>R: uuid7
R->>U: uuid7() for correlation_id
U->>P: uuid7()
P-->>U: time-ordered UUID
U-->>R: uuid7
R->>H: execute(command, ids)
H-->>ES: append(event[, event_id?])
alt event_id not provided
ES->>U: uuid7() fallback
U->>P: uuid7()
P-->>U: time-ordered UUID
U-->>ES: uuid7
end
ES-->>C: ack
sequenceDiagram
autonumber
participant App as Application Code
participant U as Commanded.UUID
participant P as UUID Provider (config)
App->>U: uuid7()
U->>P: delegate uuid7()
P-->>U: uuid7 value
U-->>App: uuid7 value
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
… use UUIDv7 Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
5151e1b to
1297471
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
lib/commanded/commands/router.ex(1 hunks)lib/commanded/event/mapper.ex(1 hunks)lib/commanded/event_store/adapters/in_memory.ex(1 hunks)lib/commanded/uuid.ex(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Quality Assurance (1.18.x, 27)
🔇 Additional comments (3)
lib/commanded/event/mapper.ex (1)
40-41: Docs: switch to UUIDv7 in examples looks good.Keeps examples aligned with the new defaults.
lib/commanded/event_store/adapters/in_memory.ex (1)
455-455: Default event_id uses UUIDv7 — ensure custom providers implement uuid7/0 or add fallbackevent_id: event_id || UUID.uuid7() — lib/commanded/event_store/adapters/in_memory.ex:455.
The provided rg search returned no matches; absence of matches is not conclusive.
Confirm whether any apps configure a custom Commanded.UUID provider. Custom providers must implement uuid7/0; otherwise add a safe fallback in lib/commanded/uuid.ex.
lib/commanded/commands/router.ex (1)
528-530: Switching defaults to UUIDv7 for command_uuid and correlation_id — LGTM.The
Keyword.get_lazy/3usage with&UUID.uuid7/0is correct and aligns with the new API.
| @doc """ | ||
| Generates a UUIDv7 using the configured provider (defaults to `Uniq.UUID`). | ||
| """ | ||
| defdelegate uuid7, to: @uuid_mod | ||
| end |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Prevent runtime breakages with custom providers: add uuid7/0 fallback (or update docs and enforce).
Today uuid7/0 is a direct delegate; if a custom provider lacks uuid7/0, calls from the router/in-memory adapter will crash. Suggest a backward-compatible fallback to uuid4/0 when uuid7/0 isn’t exported.
Apply this change:
- @doc """
- Generates a UUIDv7 using the configured provider (defaults to `Uniq.UUID`).
- """
- defdelegate uuid7, to: @uuid_mod
+ @doc """
+ Generates a UUIDv7 using the configured provider (defaults to `Uniq.UUID`).
+ Falls back to `uuid4/0` if the configured provider does not implement `uuid7/0`.
+ """
+ def uuid7 do
+ if function_exported?(@uuid_mod, :uuid7, 0) do
+ @uuid_mod.uuid7()
+ else
+ @uuid_mod.uuid4()
+ end
+ endAdditionally, the moduledoc still states “Your custom module must provide a uuid4/0 function.” Please update it to reflect uuid7/0 usage or the fallback, e.g.:
@moduledoc """
Configurable UUID generation...
By default uses `Uniq.UUID` (supports uuid1/3/4/5, v6, and v7).
config :commanded, Commanded.UUID, module: MyApp.CustomUUID
Your custom module must provide `uuid4/0`. If it also provides `uuid7/0`,
Commanded will use it; otherwise `uuid7/0` falls back to `uuid4/0`.
"""Note: The default provider Uniq.UUID already supports uuid7/0. (github.com)
If you prefer strictness over fallback, we can instead keep the delegate and raise early with a clear error if uuid7/0 is missing. Want a patch for that path instead?
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "---- file: lib/commanded/uuid.ex (if present) ----"
if [ -f lib/commanded/uuid.ex ]; then
sed -n '1,240p' lib/commanded/uuid.ex
else
echo "lib/commanded/uuid.ex not found"
fi
echo
echo "---- search: occurrences of 'uuid7' ----"
rg -n --hidden --no-ignore -S '\buuid7\b' || true
echo
echo "---- search: defdelegate uuid7 ----"
rg -n --hidden --no-ignore -S 'defdelegate\s+uuid7' || true
echo
echo "---- search: '@moduledoc' and look for 'uuid4' text ----"
rg -n --hidden --no-ignore -S '@moduledoc' lib/commanded/uuid.ex || true
rg -n --hidden --no-ignore -S 'Your custom module must provide' || true
rg -n --hidden --no-ignore -S 'uuid4/0' || trueLength of output: 1887
Prevent runtime breakages with custom providers: add uuid7/0 fallback (or update docs and enforce).
defdelegate uuid7/0 currently delegates directly; if a configured provider doesn't export uuid7/0, callers will crash at runtime (seen in lib/commanded/event/mapper.ex, lib/commanded/commands/router.ex, lib/commanded/event_store/adapters/in_memory.ex). Replace the delegate with a safe fallback and update docs.
Apply this change to lib/commanded/uuid.ex:
- @doc """
- Generates a UUIDv7 using the configured provider (defaults to `Uniq.UUID`).
- """
- defdelegate uuid7, to: @uuid_mod
+ @doc """
+ Generates a UUIDv7 using the configured provider (defaults to `Uniq.UUID`).
+ Falls back to `uuid4/0` if the configured provider does not implement `uuid7/0`.
+ """
+ def uuid7 do
+ if function_exported?(@uuid_mod, :uuid7, 0) do
+ @uuid_mod.uuid7()
+ else
+ @uuid_mod.uuid4()
+ end
+ endAlso update the moduledoc and guides (lib/commanded/uuid.ex @moduledoc and guides/explanations/commands.md) to reflect the fallback, e.g.:
@moduledoc """
Configurable UUID generation...
By default uses `Uniq.UUID` (supports uuid1/3/4/5, v6, and v7).
config :commanded, Commanded.UUID, module: MyApp.CustomUUID
Your custom module must provide `uuid4/0`. If it also provides `uuid7/0`,
Commanded will use it; otherwise `uuid7/0` falls back to `uuid4/0`.
"""If you prefer strictness instead of a fallback, keep the delegate and raise early with a clear error — I can provide that patch.
No description provided.