Prefixed base62 UUIDv7 primary key implementation with Ash
Hi all,
I'm trying to implement a UUIDv7 based primary key for all our Ash resources (and relationships), storing that as UUID type column on PostgreSQL and presenting that outside as a prefixed base62 string (
0188aadc-f449-7818-8862-5eff12733f64
will be shown as acct_02tRrww6GFm4urcMhyQpAS
), like what is described here for Ecto (https://danschultzer.com/posts/prefixed-base62-uuidv7-object-ids-with-ecto).
I'll be happy to contribute with the result of this as a code sample or better as an elixir package as soon as I get it all working properly.
What I'd like to know, maybe from @Zach Daniel, is what is the better way with Ash to add a Resource's DSL helper like uuid_primary_key
?
With older version of Ash and Spark I've successfully patched the Resource's DSL, but with newer version it seems that here https://github.com/ash-project/ash/blob/main/lib/ash/resource/dsl.ex#L127 on Ash side is missing the patchable?: true
option that's is defined here https://github.com/ash-project/spark/blob/f997db91f74e772cd19656148092f439743f9cd8/lib/spark/dsl/section.ex#L42 on Spark side.
It seems a philosophical decision on the framework side to explicitly disallow DSL patching, so I'm wondering what is the correct way to do it.
It would be great to be able to contribute to ash via an external package that will add to the Resource's DSL a simple helper like prefix_uuidv7_primary_key
.
Another question is how to know in the Ash type module definition the Ash Resource in which it is included as an attribute, in order to generate or obtain the right prefix (maybe with Resource metadata or through a new DSL specific section).
Unfortunately I think this is not possible right now so I'm trying to get around the problem by using the constraints like constraints: [prefix: "acct"]
because that it's the only flexible parameter I found on the Ash types.
And of course any advice or tip is welcome π
17 Replies
I don't know how to extend Ash, so I'm useless. However, I want this solution, so I cheerlead thou. I built something that uses calculations but just as a spike. I know that's not what I or anyone else wants - for one, it doesn't work with Ash JSONApi or Ash GraphQL. https://gist.github.com/dev-guy/51a4c12983424d3480cd1201263b50c9
I think you could do this without an extension actually.
That is one potentially simple way of doing it, by just providing a macro that does that work
what you can also do is use transformers with your extension to alter the attribute and add that constraint. It's a bit more complex, but transformers can pretty much do anything they want to a resource.
Thanks Zach for the tip, I'll try both!
@Zach Daniel , do You mean through this https://ash-hq.org/docs/guides/ash/latest/tutorials/extending-resources#make-the-extension-configurable right?
Can I also auto add the postgres migration_defaults DSL part with the configurable extension?
Yes π
Youβd need to use
Transformer.set_opt
to set an updated value.Hi @Zach Daniel, another question for you π
I'm still working on this post's subject feature that I'm packaging as a hex module named Ash UUIDv7.
As promised I'll opensourcing that as soon as ready.
For completeness I would add this gist's psql function https://gist.github.com/kjmph/5bd772b2c2df145aa645b837da7eca74 as a migration so that there's also a postgres-side defined default for fields using the AshUUIDv7 type, of course I've implemented the Ash-side autogenerator yet.
I've seen how you've implemented a similar requirement for the
ash-functions
extension here https://github.com/ash-project/ash_postgres/blob/3d9a0cfb4f6748174bfa7396d4677b71f2556610/lib/migration_generator/migration_generator.ex#L276.
So my question: can I define a function in the project Repo, that people will inject using my module, so that for having that psql migration auto-generated the only requirements will be add use AshUUIDv7.Postgres
and add something like ashuuidv7-functions
to the installed_extensions/0
list?
I think that if we permit having a mix of string and function captures in the installed_extensions/0
list, it will be simple to modify how this is working right now in a retro-compatible way and easily add the feature that module like mine needed.
Of course I'm happy to try to contribute myself to the AshPostgres repo if you think that is a good idea πThere is not a way to have your own thing like the
ash-functions
extension currently
That would need to be added, happy for PRs in that directiona@moissela I too was trying to figure out how to use UUIDv7. Made a support post about it as well. I was thinking yesterday that maybe it could be added to something like the
uniq
package. They already define extentions for Ecto here: https://github.com/bitwalker/uniq/blob/f229d462c939ec655dd8ac8abbfe7325f2e83e6e/lib/uuid.ex#L951. Someone could define extensions for Ash similarly.Hi @Zach Daniel, PR ready here https://github.com/ash-project/ash_postgres/pull/162
Hi @Korbin , the ash extension is almost ready.
It uses Uniq for uuid generation with support for version 4 and 7, with outside prefixed and encoded strings, or only encoded, or straight raw uuid.
I'll post here as soon as releasing π
Are you still intending to release a completely new package or are you contributing that extension to Uniq?
actually a completely new package with Uniq as a dependency
Idk if Uniqβs maintainers would except an extension contribution in the first place, but why a new package vs contributing to existing package?
Iβm asking out curiosity as I donβt really know the advantages/disadvantages of either approach.
Simply because we've start working on the extension based on our company's projects needs and at that time we not used Uniq for uuids generation.
Right now we've switched to Uniq for releasing the extension as opensource but Uniq represents only a dependency for us and not all the extension.
In the future we could switch to a faster or better Uniq alternative, who knows
Hi @Zach Daniel, the AshUUID extension is ready here https://github.com/zoonect-oss/ash_uuid.
Unfortunately we can't release it on hex until this https://github.com/ash-project/ash_postgres/pull/162 will be merged: as you can see here https://github.com/zoonect-oss/ash_uuid/actions/runs/5796129613/job/15709244164#step:3:309:
how lucky: I needed this for a new project today, and it got published 4 hrs ago ! thanks @moissela!
@moissela I've merged your PR, but will not be at a computer until tonight to publish a new version of the package
Just released a new version of
ash_postgres
Thank you @Zach Daniel: I'm sorry to have disturbed you on vacation π
I'll post AshUUID to hex tomorrow ππ»
@moissela submitted a fix PR to AshUUID: https://github.com/zoonect-oss/ash_uuid/pull/7
GitHub
install
takes the old version, not the version being installed by...We fixed a bug in ash_postgres where it was doing the wrong thing here, so it makes sense that this broke, but the solution is to fix downstream extensions.