doc/md: docs for new globalid feature (#4344)

This commit is contained in:
Jannik Clausen
2025-02-25 12:42:25 +01:00
committed by GitHub
parent fed373ab2f
commit 7f5f143bd2
3 changed files with 193 additions and 42 deletions

View File

@@ -413,3 +413,24 @@ client.User.
// INSERT INTO "users" (...) VALUES ... ON CONFLICT WHERE ... DO UPDATE SET ... WHERE ...
```
### Globally Unique ID
By default, SQL primary-keys start from 1 for each table; which means that multiple entities of different types
can share the same ID. Unlike AWS Neptune, where node IDs are UUIDs.
This does not work well if you work with [GraphQL](https://graphql.org/learn/schema/#scalar-types), which requires
the object ID to be unique.
To enable the Universal-IDs support for your project, simply use the `--feature sql/globalid` flag.
:::warning Note
If you have used the `migrate.WithGlobalUniqueID(true)` migration option in the past, please read
[this guide](globalid-migrate) before you switch your project to use the new globalid feature.
:::
**How does it work?** `ent` migration allocates a 1<<32 range for the IDs of each entity (table),
and store this information alongside your generated code (`internal/globalid.go`). For example, type `A` will have the
range of `[1,4294967296)` for its IDs, and type `B` will have the range of `[4294967296,8589934592)`, etc.
Note that if this option is enabled, the maximum number of possible tables is **65535**.

170
doc/md/globalid.mdx Normal file
View File

@@ -0,0 +1,170 @@
---
id: globalid-migrate
title: Migrate Globally Unique ID
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Prior to the baked-in global id feature flag, the migration tool had a `WithGlobalUniqueID` option that allowed users to
migrate their schema to use globally unique ids. This option is now deprecated and users should use the global id
feature flag instead. Existing users can migrate their schema to use globally unique ids by following the steps below.
The previous solution utilized a table called `ent_types` to store mapping information between an Ent schema, and it's
associated id range. The new solution uses a static configuration file to store this mapping. In order to migrate to the
new globalid feature, one can use the `entfix` command to migrate an existing `ent_types` table to the new configuration
file.
:::warning Attention
Please note, that the 'ent_types' table might differ between different environments where your app is deployed. This is
especially true if you are using auto-migration instead of versioned migrations. Please check, that all 'ent_types'
tables for all deployments are equal. If they aren't you cannot convert to the new global id feature.
:::
The first step is to install the `entfix` tool by running the following command:
```shell
go install entgo.io/ent/cmd/entfix@latest
```
Next, you can run the `entfix globalid` command to migrate your schema to use the global id feature. The command
requires access to a database to read the `ent_types` table. You can either connect to your deployed database, or
connect to a read replica or in case of versioned migrations, to an ephemeral database where you have applied all your
migrations.
```shell
entfix globalid --dialect mysql --dsn "root:pass@tcp(localhost:3306)/app" --path ./ent
IMPORTANT INFORMATION
'entfix globalid' will convert the allocated id ranges for your nodes from the
database stored 'ent_types' table to the new static configuration on the ent
schema itself.
Please note, that the 'ent_types' table might differ between different environments
where your app is deployed. This is especially true if you are using
auto-migration instead of versioned migrations.
Please check, that all 'ent_types' tables for all deployments are equal!
Only 'yes' will be accepted to approve.
Enter a value: yes
Success! Please run code generation to complete the process.
```
Finish the migration by running once again the code generation once. You should see a new file `internal/globalid.go`
in the generated code, containing just one line starting with `const IncrementStarts`, indicating the process finished
successfully. Last step is to make sure to remove the `migrate.WithGlobalUniqueID(true)` option from your migration
setup.
# Optional: Keep `ent_types` table
It might be desired to keep the `ent_types` in the database and not drop it until you are sure you do not need to
rollback compute. You can do this by using an Atlas composite schema:
<Tabs
defaultValue="schema"
values={[
{label: 'schema.my.sql', value: 'schema'},
{label: 'atlas-hcl', value: 'atlas'},
]}>
<TabItem value="schema">
```hcl
schema "ent" {}
table "ent_types" {
schema = schema.ent
collate = "utf8mb4_bin"
column "id" {
null = false
type = bigint
unsigned = true
auto_increment = true
}
column "type" {
null = false
type = varchar(255)
}
primary_key {
columns = [column.id]
}
index "type" {
unique = true
columns = [column.type]
}
}
```
</TabItem>
<TabItem value="atlas">
```hcl
data "composite_schema" "ent" {
schema "ent" {
url = "ent://./ent/schema?globalid=static"
}
# This exists to not delete the ent_types table yet.
schema "ent" {
url = "file://./schema.my.hcl"
}
}
env {
name = atlas.env
src = data.composite_schema.ent.url
dev = "docker://mysql/8/ent"
migration {
dir = "file://./ent/migrate/migrations"
}
}
```
</TabItem>
</Tabs>
## Universal IDs (deprecated migration option)
By default, SQL primary-keys start from 1 for each table; which means that multiple entities of different types
can share the same ID. Unlike AWS Neptune, where node IDs are UUIDs.
This does not work well if you work with [GraphQL](https://graphql.org/learn/schema/#scalar-types), which requires the object ID to be unique.
To enable the Universal-IDs support for your project, pass the `WithGlobalUniqueID` option to the migration.
:::note
Versioned-migration users should follow [the documentation](versioned-migrations.mdx#a-word-on-global-unique-ids)
when using `WithGlobalUniqueID` on MySQL 5.*.
:::
```go
package main
import (
"context"
"log"
"<project>/ent"
"<project>/ent/migrate"
)
func main() {
client, err := ent.Open("mysql", "root:pass@tcp(localhost:3306)/test")
if err != nil {
log.Fatalf("failed connecting to mysql: %v", err)
}
defer client.Close()
ctx := context.Background()
// Run migration.
if err := client.Schema.Create(ctx, migrate.WithGlobalUniqueID(true)); err != nil {
log.Fatalf("failed creating schema resources: %v", err)
}
}
```
**How does it work?** `ent` migration allocates a 1<<32 range for the IDs of each entity (table),
and store this information in a table named `ent_types`. For example, type `A` will have the range
of `[1,4294967296)` for its IDs, and type `B` will have the range of `[4294967296,8589934592)`, etc.
Note that if this option is enabled, the maximum number of possible tables is **65535**.

View File

@@ -72,48 +72,8 @@ if err != nil {
## Universal IDs
By default, SQL primary-keys start from 1 for each table; which means that multiple entities of different types
can share the same ID. Unlike AWS Neptune, where node IDs are UUIDs.
This does not work well if you work with [GraphQL](https://graphql.org/learn/schema/#scalar-types), which requires
the object ID to be unique.
To enable the Universal-IDs support for your project, pass the `WithGlobalUniqueID` option to the migration.
:::note
Versioned-migration users should follow [the documentation](versioned-migrations.mdx#a-word-on-global-unique-ids)
when using `WithGlobalUniqueID` on MySQL 5.*.
:::
```go
package main
import (
"context"
"log"
"<project>/ent"
"<project>/ent/migrate"
)
func main() {
client, err := ent.Open("mysql", "root:pass@tcp(localhost:3306)/test")
if err != nil {
log.Fatalf("failed connecting to mysql: %v", err)
}
defer client.Close()
ctx := context.Background()
// Run migration.
if err := client.Schema.Create(ctx, migrate.WithGlobalUniqueID(true)); err != nil {
log.Fatalf("failed creating schema resources: %v", err)
}
}
```
**How does it work?** `ent` migration allocates a 1<<32 range for the IDs of each entity (table),
and store this information in a table named `ent_types`. For example, type `A` will have the range
of `[1,4294967296)` for its IDs, and type `B` will have the range of `[4294967296,8589934592)`, etc.
Note that if this option is enabled, the maximum number of possible tables is **65535**.
can share the same ID. Unlike AWS Neptune, where node IDs are UUIDs. [Read this](features.md#globally-unique-id) to
learn how to enable universally unique ids when using Ent with a SQL database.
## Offline Mode