sloanelybutsurely / typeid-elixir

Elixir implementation of TypeIDs: type-safe, K-sortable, and globally unique identifiers inspired by Stripe IDs
MIT License
55 stars 6 forks source link

Automaticly generated ids don't appear to be k-sorted #31

Closed zolrath closed 1 week ago

zolrath commented 4 months ago

Hello, thank you very much for making this library!

I'm having an issue where it appears when I insert new rows into my database they are randomly sorted instead of utilizing the current time. I've got my schema set up with:

@primary_key {:id, TypeID, autogenerate: true, prefix: "client", type: :binary_id}
@foreign_key_type TypeID

As a test run, I created 6 new clients with a few seconds between each and the resulting primary keys (in order of generation) were:  

Autogenerated

client_2781hb3ysx8vkbvyjqva8jn8sf
client_6t2xhfj1bs847v0hj0xvt0zy0j
client_23tv3vfh1288k8cmjbmcj6sy3j
client_5qdn2175ga8zxt8fmhwacg7ksp
client_0h8yfhspdm9rgskv9y710rs9rz
client_56wqn921mw8z68qed0aa2pcqa4

When selecting the entries from this table ordered by the id, they do not return in the correct order and start with extremely dissimilar beginnings.

Manually generated

In iex if I use TypeID.new("client") the generated ids appear more immediately sensible and are correctly sorted so something seems amiss when I allow Ecto to autogenerate them.

iex(80)> TypeID.new("client") #repeat this for each line below
#TypeID<"client_01hwyg46cye1m8bp9c0bbyqgjb">
#TypeID<"client_01hwyg47dnevbrd93ypamb9tkf">
#TypeID<"client_01hwyg48zcegctnk497zkgm2bd">
#TypeID<"client_01hwyg4awqesdbp6t5c2agzg51">
#TypeID<"client_01hwyg4cxdfhv91crqy04aemnb">

I'm using: ecto 3.11.2 ecto_psql_extras 0.7.15 ecto_sql 3.11.1 typeid_elixir 0.6.0 phoenix 1.7.12 phoenix_ecto 4.5.1 postgrex 0.17.5 with Elixir 1.16.2 (compiled with Erlang/OTP 26)

Thanks again, let me know if you need any additional information!

zolrath commented 4 months ago

I've created a project exhibiting the issue here: https://github.com/zolrath/typeid_test Maybe there's something I'm missing/should be doing but if I attempt to use order_by like: Repo.all(from c in Client, order_by: [asc: c.id]) the sorting becomes random and non sequential.

sloanelybutsurely commented 4 months ago

Thanks for reporting this. It looks like Ecto isn't calling TypeID.autogenerate/1 for some reason. I'll look into this further.

andrewtimberlake commented 1 week ago

It looks like the binary type change is causing problems with many_to_many relationships where the query generated is trying to cast the uuid to bytea which Postgresql won’t do

(Postgrex.Error) ERROR 42846 (cannot_coerce) cannot cast type uuid to bytea

sloanelybutsurely commented 1 week ago

Fixed by #32 and #34