Skip to content

Commit d7db7fc

Browse files
authored
Merge pull request #15 from ash-project/add-uuidv7
Add option for using uuidv7 as event primary key.
2 parents 843def8 + 710154c commit d7db7fc

File tree

20 files changed

+481
-11
lines changed

20 files changed

+481
-11
lines changed

.formatter.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ spark_locals_without_parens = [
88
ignore_actions: 1,
99
persist_actor_primary_key: 2,
1010
persist_actor_primary_key: 3,
11+
primary_key_type: 1,
1112
public?: 1,
1213
record_id_type: 1,
1314
replay_override: 2,

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ defmodule MyApp.Events.Event do
4545
# Module that implements clear_records! callback
4646
clear_records_for_replay MyApp.Events.ClearAllRecords
4747

48+
# Optional. Defaults to :integer, Ash.Type.UUIDv7 is the recommended option
49+
# if your event log is set up with multitenancy via the attribute-strategy.
50+
primary_key_type Ash.Type.UUIDv7
51+
4852
# Optional, defaults to :uuid
4953
record_id_type :uuid
5054

documentation/dsls/DSL-AshEvents.EventLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ end
3131

3232
| Name | Type | Default | Docs |
3333
|------|------|---------|------|
34+
| [`primary_key_type`](#event_log-primary_key_type){: #event_log-primary_key_type } | `:integer \| Ash.Type.UUIDv7` | `:integer` | The type of the primary key used by the event log resource. Valid options are :integer and :uuid_v7. Defaults to :integer. |
3435
| [`clear_records_for_replay`](#event_log-clear_records_for_replay){: #event_log-clear_records_for_replay } | `module` | | A module with the AshEvents.ClearRecords-behaviour, that is expected to clear all records before an event replay. |
3536
| [`record_id_type`](#event_log-record_id_type){: #event_log-record_id_type } | `any` | `:uuid` | The type of the primary key used by the system, which will be the type of the `record_id`-field on the events. Defaults to :uuid. |
3637

lib/event_log/event_log.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ defmodule AshEvents.EventLog do
8989
@event_log %Spark.Dsl.Section{
9090
name: :event_log,
9191
schema: [
92+
primary_key_type: [
93+
type: {:one_of, [:integer, Ash.Type.UUIDv7]},
94+
doc:
95+
"The type of the primary key used by the event log resource. Valid options are :integer and :uuid_v7. Defaults to :integer.",
96+
default: :integer
97+
],
9298
clear_records_for_replay: [
9399
type: {:behaviour, AshEvents.ClearRecordsForReplay},
94100
required: false,

lib/event_log/transformers/add_actions.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ defmodule AshEvents.EventLog.Transformers.AddActions do
44

55
def transform(dsl) do
66
replay_overrides = AshEvents.EventLog.Info.replay_overrides(dsl)
7+
primary_key = AshEvents.EventLog.Info.event_log_primary_key_type!(dsl)
78

89
persist_actor_primary_keys =
910
AshEvents.EventLog.Info.event_log(dsl)
@@ -26,7 +27,7 @@ defmodule AshEvents.EventLog.Transformers.AddActions do
2627
)
2728
|> Ash.Resource.Builder.add_action(:action, :replay,
2829
arguments: [
29-
Ash.Resource.Builder.build_action_argument(:last_event_id, :integer,
30+
Ash.Resource.Builder.build_action_argument(:last_event_id, primary_key,
3031
allow_nil?: true,
3132
description: "Replay events up to and including this event id."
3233
),

lib/event_log/transformers/add_attributes.ex

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,25 @@ defmodule AshEvents.EventLog.Transformers.AddAttributes do
99
persist_actor_primary_keys = AshEvents.EventLog.Info.event_log(dsl)
1010

1111
dsl
12-
|> Ash.Resource.Builder.add_attribute(:id, :integer,
13-
primary_key?: true,
14-
writable?: false,
15-
generated?: true,
16-
allow_nil?: false
17-
)
12+
|> then(fn dsl ->
13+
case AshEvents.EventLog.Info.event_log_primary_key_type!(dsl) do
14+
:integer ->
15+
Ash.Resource.Builder.add_attribute(dsl, :id, :integer,
16+
primary_key?: true,
17+
writable?: false,
18+
generated?: true,
19+
allow_nil?: false
20+
)
21+
22+
Ash.Type.UUIDv7 ->
23+
Ash.Resource.Builder.add_attribute(dsl, :id, Ash.Type.UUIDv7,
24+
primary_key?: true,
25+
writable?: false,
26+
allow_nil?: false,
27+
default: &Ash.UUIDv7.generate/0
28+
)
29+
end
30+
end)
1831
|> Ash.Resource.Builder.add_attribute(:record_id, record_primary_id_type, allow_nil?: false)
1932
|> Ash.Resource.Builder.add_attribute(:version, :integer, allow_nil?: false, default: 1)
2033
|> Ash.Resource.Builder.add_attribute(:metadata, :map,

priv/resource_snapshots/test_repo/events/20250417180632.json renamed to priv/resource_snapshots/test_repo/events/20250518192312.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
"custom_indexes": [],
117117
"custom_statements": [],
118118
"has_create_action": true,
119-
"hash": "8D17207A9355B81B847E9FC890B918E07A5E1631EADB1B55642755EC9B441582",
119+
"hash": "8311C593AA6579193E2787766F4AA510029E7B889ABDB606AA5C32A27BC24E9D",
120120
"identities": [],
121121
"multitenancy": {
122122
"attribute": null,
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
{
2+
"attributes": [
3+
{
4+
"allow_nil?": false,
5+
"default": "fragment(\"uuid_generate_v7()\")",
6+
"generated?": false,
7+
"primary_key?": true,
8+
"references": null,
9+
"size": null,
10+
"source": "id",
11+
"type": "uuid"
12+
},
13+
{
14+
"allow_nil?": false,
15+
"default": "nil",
16+
"generated?": false,
17+
"primary_key?": false,
18+
"references": null,
19+
"size": null,
20+
"source": "record_id",
21+
"type": "uuid"
22+
},
23+
{
24+
"allow_nil?": false,
25+
"default": "1",
26+
"generated?": false,
27+
"primary_key?": false,
28+
"references": null,
29+
"size": null,
30+
"source": "version",
31+
"type": "bigint"
32+
},
33+
{
34+
"allow_nil?": false,
35+
"default": "%{}",
36+
"generated?": false,
37+
"primary_key?": false,
38+
"references": null,
39+
"size": null,
40+
"source": "metadata",
41+
"type": "map"
42+
},
43+
{
44+
"allow_nil?": false,
45+
"default": "%{}",
46+
"generated?": false,
47+
"primary_key?": false,
48+
"references": null,
49+
"size": null,
50+
"source": "data",
51+
"type": "map"
52+
},
53+
{
54+
"allow_nil?": false,
55+
"default": "nil",
56+
"generated?": false,
57+
"primary_key?": false,
58+
"references": null,
59+
"size": null,
60+
"source": "occurred_at",
61+
"type": "utc_datetime_usec"
62+
},
63+
{
64+
"allow_nil?": false,
65+
"default": "nil",
66+
"generated?": false,
67+
"primary_key?": false,
68+
"references": null,
69+
"size": null,
70+
"source": "resource",
71+
"type": "text"
72+
},
73+
{
74+
"allow_nil?": false,
75+
"default": "nil",
76+
"generated?": false,
77+
"primary_key?": false,
78+
"references": null,
79+
"size": null,
80+
"source": "action",
81+
"type": "text"
82+
},
83+
{
84+
"allow_nil?": false,
85+
"default": "nil",
86+
"generated?": false,
87+
"primary_key?": false,
88+
"references": null,
89+
"size": null,
90+
"source": "action_type",
91+
"type": "text"
92+
},
93+
{
94+
"allow_nil?": true,
95+
"default": "nil",
96+
"generated?": false,
97+
"primary_key?": false,
98+
"references": null,
99+
"size": null,
100+
"source": "user_id",
101+
"type": "uuid"
102+
},
103+
{
104+
"allow_nil?": true,
105+
"default": "nil",
106+
"generated?": false,
107+
"primary_key?": false,
108+
"references": null,
109+
"size": null,
110+
"source": "system_actor",
111+
"type": "text"
112+
}
113+
],
114+
"base_filter": null,
115+
"check_constraints": [],
116+
"custom_indexes": [],
117+
"custom_statements": [],
118+
"has_create_action": true,
119+
"hash": "0C1C4372B47922C4FB743B1A19F1CEEED952C5DF51D996370C603750B47A068A",
120+
"identities": [],
121+
"multitenancy": {
122+
"attribute": null,
123+
"global": null,
124+
"strategy": null
125+
},
126+
"repo": "Elixir.AshEvents.TestRepo",
127+
"schema": null,
128+
"table": "events_uuidv7"
129+
}

priv/resource_snapshots/test_repo/routed_users/20250417180632.json renamed to priv/resource_snapshots/test_repo/routed_users/20250518192312.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
"custom_indexes": [],
6767
"custom_statements": [],
6868
"has_create_action": true,
69-
"hash": "E5F54D698514CBEDB5F826D048F176517634A84A2562AE4222B7E7386151E59C",
69+
"hash": "8B77D86AA0D43CC05EF93B99203FBFDA974DAE216284FA3E0D00B8972D020B4F",
7070
"identities": [],
7171
"multitenancy": {
7272
"attribute": null,

priv/resource_snapshots/test_repo/user_roles/20250417180632.json renamed to priv/resource_snapshots/test_repo/user_roles/20250518192312.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
"custom_indexes": [],
7676
"custom_statements": [],
7777
"has_create_action": true,
78-
"hash": "B15ADCAACA34F2C4A92283FAB90F3D4C6DDC8453AA91C742482C3C0CD6839F5D",
78+
"hash": "511750B7B3CCF003C8E3D096B1551AC6AA23946EC30D01E93A1A3B3FBC9D4673",
7979
"identities": [
8080
{
8181
"all_tenants?": false,

0 commit comments

Comments
 (0)