{@thread.name}
moissela:
Hi there, already released a new Ash extension for enhancing Ash UUID fields support.
AshUUID allows usage for UUID v4 and the new v7 draft (official paper: https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-04.html#name-uuid-version-7 , more about: https://blog.devgenius.io/analyzing-new-unique-identifier-formats-uuidv6-uuidv7-and-uuidv8-d6cc5cd7391a ).
You can use public shortened version of UUIDs through base62 encoding while keeping them stored as native raw uuid column on Postgres (with all the indexing / querying benefits).
AshUUID allows using public shortened version with prefix at the beginning (configurable, default to resource name) like Stripe does for better APIs (more about: https://dev.to/stripe/designing-apis-for-humans-object-ids-3o5a ).
New AshPostgres feature (
https://github.com/ash-project/ash_postgres/pull/162
) allows Ash extensions to easily ship Postgres functions extensions through the new
AshPostgres.CustomExtension
behaviour (example:
https://github.com/zoonect-oss/ash_uuid/blob/main/lib/ash_uuid/postgres_extension.ex
).
With AshPostgres v1.3.41 release, AshUUID provides Postgres-side UUIDv7 generation (through
uuid_generate_v7
sql function) for better db integrity.
AshUUID adoption:
-
add
{:ash_uuid, "~> 0.2"}
to yourmix.exs
project deps; -
add
AshUUID.PostgresExtension
to your app Repo’sinstalled_extensions
and set AshUUID configmigration_default?: true
if Postgres-side UUIDs generation is needed; -
use the extension in your resources
use Ash.Resource, data_layer: AshPostgres.DataLayer, extensions: [AshUUID]
-
simply use that for your fields
uuid_attribute :id
v0.2.2 is released on Hex: feel free to open issues/PRs or to reply to this thread, feedbacks are welcome 🙂
Happy for my first contribution to the Ash community 💪🏼
jharton:
This is awesome work!
Eduardo B. Alexandre:
Great extension man!
Quick question, I disabled prefixes globally, but when relationships are loaded, they all come with “id_” as the prefix, how can I remove that?
moissela:
Thank you! Try to force recompilation of the extension with: mix deps.compile ash_uuid –force
Eduardo B. Alexandre:
Nah, it still shows up as “id_” for every relationship (belongs_to) that I load when reading a resource
moissela:
mmm ok <@816769011533742100>: I’ll check and try to fix that as soon as possible. Could you open an issue on GH for this?
moissela:
<@816769011533742100> I did a quick test on an open project using ash_uuid and it seems to work fine 🤷🏼♂️
I realized this could probably be something not well described in the readme: the configuration is described like this
config :ash_uuid, :ash_uuid, prefixed?: false
but the first
:ash_uuid
should match your project’s application otp name, for example
config :example_app, :ash_uuid, prefixed?: false
Eduardo B. Alexandre:
Ah, yes, I’m aware of that, it did confuse me the first time tbh, but I’m using it the correct way now:
config :feedback_cupcake, :ash_uuid,
version: 7,
encoded?: true,
prefixed?: false,
migration_default?: true
But I still have the problem above.
I will try to create a small example that triggers the issue and will create a new issue in GH (I already created one there about resources that have relationships it themselves btw).
moissela:
thanks! I’ll check both together
Eduardo B. Alexandre:
<@477481255097597972> https://github.com/zoonect-oss/ash_uuid/issues/2
moissela:
Hi <@816769011533742100> I’ve released v0.3.0 fixing both 🤞🏼
Eduardo B. Alexandre:
Amazing! I will be testing it right now 🚀
Eduardo B. Alexandre:
<@477481255097597972> I just tested it, resources with relationships with themselves seems to be working great, but many to_many relationships still returns the ids with the default prefix (`id `). Both when creating the resource or when retrieving it (like the example I gave in the GH issue ticket)
Eduardo B. Alexandre:
moissela:
Have you added AshUUID like I wrote here https://github.com/zoonect-oss/ash_uuid/issues/2#issuecomment-1675939636 ?
moissela:
You’ve to include AshUUID extension also in the BlibsBlobs resource to fix.
Eduardo B. Alexandre:
Ah.. I totally missed that comment 🤦♂️ Working great after adding AshUUID in the resource. Thanks again for the help and great extension!
Eduardo B. Alexandre:
Quick question, seems like the extension doesn’t work when a resource doesn’t have
AshPostgres.Datalayer
data_layer, is that by design?
moissela:
No, not by design 😅 I’ll check that too
Eduardo B. Alexandre:
I can create a new issue ticket in GH if you prefer
moissela:
Yep, it would be great
Eduardo B. Alexandre:
There you go: https://github.com/zoonect-oss/ash_uuid/issues/3
moissela:
Thanks, I’ll check that as soon as possible
moissela:
Hi <@816769011533742100>, v0.4.0 released with volatile and embedded resources support 😉
Eduardo B. Alexandre:
Amazing, working like a charm!
Eduardo B. Alexandre:
Hey <@477481255097597972> I believe I found another bug when using AshUUID with embedded resources, I created a ticket describing the issue: https://github.com/zoonect-oss/ash_uuid/issues/4
moissela:
Hi <@816769011533742100>, v.0.5.0 just released should fix that 🙂
kernel_io:
I’m having the occasional issue
kernel_io:
kernel_io:
kernel_io:
kernel_io:
this only happening when I try and load something related on the Queue
kernel_io:
i.e:
kernel_io:
and get_by_id is just a code_interface with
get_by: [:id]
kernel_io:
it seems to think it’s initially in integer format 🤔
kernel_io:
kernel_io:
tags are a many_to_many on queue
kernel_io:
kernel_io:
hmm
kernel_io:
it could be my UUID’s aren’t actually v7 uuids
kernel_io:
I might have missed some data conversion
kernel_io:
🤡 how the hell do I have V2 UUID’s in my DB 😆
kernel_io:
okay all the data is v7 now
kernel_io:
but now I get this
kernel_io:
because it seems to think the prefix should be
id
, instead of
queue
kernel_io:
kernel_io:
feels like Ash or whatever doesn’t look at the prefix which is set automatically on the Resource when trying to build the belongs_to relationship
kernel_io:
right, so the ‘fix’ for this is to do this
kernel_io:
add the constraints to the uuid arg so that ash_uuid knows what it is expecting, makes me think maybe we shouldn’t fail so hard when it’s an unknown prefix
kernel_io:
hope you all enjoyed being my rubber ducks 🙂
kernel_io:
so I’ve set prefixed? to false, as I don’t really need it, but I’m still getting something trying to be prefixed, I’ve deleted the _build dir numerous times so no idea why something is still trying to add prefixes
kernel_io:
I’m trying to delete a related item - it had worked before adding ash uuid, but now I see that its trying to add an
id_
prefix infront of the id for the changeset - so the changeset fails as it will create a new record instead of deleting what there is
kernel_io:
<:thinkies:915154230078222336>
kernel_io:
thats the id from my event handler at the top, and then the changeset contains id_ <:thinkies:915154230078222336>
kernel_io:
need to add prefixed? false on the constraint, I swear it’s not reading my config.exs defaults
kernel_io:
okay this whole thing is tripping hard
kernel_io:
I have prefixed?: false on my app config, but occasionally cast_input/2 still gets called with prefix set to “id” and prefixed? set to true
kernel_io:
<@477481255097597972> what’s the recommended way forward for this then? all I can think of is modifying the cast_input to check the resource’s definition
kernel_io:
I don’t think it does that currently
kernel_io:
and Ash just sets the defaults on it
kernel_io:
I honestly feel like it’s a bug with Ash, as it’s only in very specific cases
kernel_io:
kernel_io:
these are just the defaults from the type, not the configured types on the app
kernel_io:
so is this a fix in ash or in this?
kernel_io:
<@197905764424089601> pinging you for input as this probably should have been in a support thread 😬
moissela:
Hi <@891520354802106389>, I can’t well understand what is the current issue by your messages, if it’s one or plus related issues and if it concern to AshUUID (I bet on that 😅) or Ash. Can you put together some code to reproduce the bug and submit an issue on github so I can try to help?
moissela:
Have you tried to run a
mix deps.compile ash --force
after editing the config.exs file? Sometimes it helps 🤷🏼♂️
moissela:
Here it should be
argument :tag_id, AshUUID.UUID, allon_nil?: false
I think, because
:uuid
is the Ash uuid standard type
zachdaniel:
Yeah, a small reproduction would be the next step here 🙂
zachdaniel:
And to make sure you’re on the latest ash and ash postgres
kernel_io:
I’ll summarise here
kernel_io:
- I override :uuid with AshUUID.UUID (although this wouldn’t affect what I see as the ‘bug’)
- when I have an action argument (and I’ll assume elsewhere) that uses :uuid (or AshUUID.UUID), the action gets built with the default constraints from AshUUID.UUID instead of the constraints that I define in the config.exs file
- this means I need to explicitly override the constraints on each argument to disable the prefixes - otherwise AshUUID will add a prefix etc to the ID, and things will start acting weird
kernel_io:
I think 2 is just due to how Ash works, I don’t think there is a way for it to know what the constraints should be in an agnostic way
kernel_io:
- other than the bug described in #2, I have had issues at times where AshUUID.UUID is too strict with parsing the ids - i.e: I have a read action that wants an ID which I’ll use to load a resource which is prefixed with a custom prefix, obviously there is no way for anything to know what I mean to use that id for, but AshUUID will explode - because by default it wants “id” prefix, and I might pass it a “fish” prefix, I don’t necessarily care about what the prefix is, all I want is for the type to drop the prefix and decode the encoded UUID
kernel_io:
to get around #4 you need to be explicit, I don’t really consider it a bug, #2 I consider being a bug, if there is a default set which gets applied to the uuid_attribute macro, then I’d expect that default to be used elsewhere AshUUID is used
kernel_io:
I’m always on the latest 😜
zachdaniel:
<@891520354802106389> hat do you mean “constraints that you define in the config.exs file”?
zachdaniel:
I haven’t used AshUUID myself yet, so maybe I’m missing something
kernel_io:
in the config.exs you set some defaults, i.e: enable prefixing, enabled encoding, what version of uuid to use. these defaults get used in the uuid_attribute macro, but not in anything else that uses AshUUID.UUID
kernel_io:
config :vmx, :ash_uuid,
version: 7,
encoded?: true,
prefixed?: false,
migration_default?: true
kernel_io:
and this is the action argument not respecting the setup I have in config.exs
moissela:
I think that I can add an uuid_argument macro for using configured defaults while keeping that overridable also in arguments
kernel_io:
🙏🏿 would be amazing, I looked through ash source code and didn’t see a way to hook it easily
moissela:
yes, without another macro it could be difficult
moissela:
I will try to fix 1) 2) 3) with a new uuid_argument macro tomorrow
moissela:
and I will add a new “strict: true | false” config for 4)
moissela:
both as default and as override
zachdaniel:
We should talk about how this is being done and where those config values are used
zachdaniel:
If you pull those in and make them defaults in the
constraints
function on the type, then you can apply them for any usage of the type
kernel_io:
I was messing about with that but I’m honestly not very good at macro / precompilation type stuff
kernel_io:
currently the constraints function just returns a nimble opts stuct
kernel_io:
so I wasn’t sure of how you’d make that dynamic based on application env 🙂
zachdaniel:
You could set the defaults to the values from the config
zachdaniel:
You’d do something like thisL
def constraints() do
[
version: [
...,
default: get_config(:version, ...)
]
]
end
zachdaniel:
Then each can be ovverriden per type, but will take the defaults from the config
moissela:
<@197905764424089601> Is there already an example of configurable extension so that I can take a look at code?
moissela:
which module the
get_config
fn came from? is your only an example?
kernel_io:
only as an example
moissela:
ah no! you’re referencing mine AshUUID.Config.get_config/1 <@197905764424089601> , right?
kernel_io:
nope
moissela:
so, based on your advice <@197905764424089601> I think I now understand something that I didn’t understand when I developed AshUUID and I would like you to confirm it for me
moissela:
Ash will call CustomType.constraints/0 for getting constraints defaults and merge them with user’s overrides?
moissela:
If so, yes <@891520354802106389> : I can change
constraints/0
for using configured defaults
kernel_io:
I have this so far
@impl true
def constraints() do
Enum.map(@constraints, fn {key, value} ->
{key, Keyword.replace(value, :default, AshUUID.Config.get_config([]) |> Map.get(key, ""))}
end)
end
kernel_io:
just playing with it
kernel_io:
I think we could make prefix nillable also
kernel_io:
either nil or string
moissela:
<@891520354802106389> can you submit an issue with a small resource and an action with an AshUUID argument, describing your actual problem? So that I’ve a reproducible example of your case that I can add to tests I will try to release a fix for that (and the new strict mode for 4) today
kernel_io:
I won’t have time to do it for a while unfortunately 😦
kernel_io:
have just tested this snippet of code above and it works
kernel_io:
I can make an issue with some basic code in it
kernel_io:
but won’t be able to do set up test cases etc
kernel_io:
i.e: config.ex …. resource.ex …..
expected output …..
actual output …..
kernel_io:
okay snippet doesn’t fix #4 , but it fixes #2
moissela:
I think we can remove the global configured prefix default because it make no sense. If a project needs prefixed ids is because that ids should clarify which resource belongs to, so having a global unique prefix make no sense.
kernel_io:
yup, especially considering you already precompute it when using the macro
kernel_io:
I’ve never seen an “id_”
kernel_io:
as everything has a pregenerated prefix already
moissela:
For the issue I need only the example case, I’ll take care of test cases on myself
moissela:
yes, per-resource prefix default generation through macro came next the global configured default that was present from beginning and now I think we can clear that config 🙂
moissela:
I think #4 will be resolved through removing the global configured prefix and the new “non-strict mode” config that I’ll add, can you fill an issue also for #4 ?
kernel_io:
yup
moissela:
thank you! I’ve some time to work on AshUUID this afternoon (italian time zone)
kernel_io:
I don’t think #4 is a bug to be honest
kernel_io:
I think #4 can be left alone (apart from removing the global configured prefix)
kernel_io:
because if I am using prefixes then I should be explicit with my actions to say what type of resource it’s expecting right
moissela:
Ok, I agree
moissela:
Hi <@891520354802106389> and sorry for the delay, I’ve been very busy. Just released v0.6.0 with configurable defaults on standard arguments, new uuid_argument macro (for prefixed mode when automatic prefix based on resource name is needed), some bug fixes and the new deactivable strict mode. Let me know 😉
kernel_io:
installed it and will play with it tonight’ish