Strategi untuk versioning field dan direktif
Harap baca terlebih dahulu panduan Mengembangkan skema melalui field versioning, yang menjelaskan fitur "field versioning" di Gato GraphQL.
Gato GraphQL memungkinkan field dan direktif menerima argumen versionConstraint, untuk memilih versi spesifik (yaitu implementasi) dari field/direktif yang akan digunakan:
query GetPosts {
posts(versionConstraint: "^1.0") {
id
title(versionConstraint: ">=2.1")
excerpt @strUpperCase(versionConstraint: "~1.5.3")
}
}Apa yang seharusnya terjadi ketika kita tidak menentukan argumen versionConstraint? Misalnya, ke versi mana seharusnya field surname dalam query di bawah ini diselesaikan?
query GetSurname {
account(id: 1) {
# Versi mana yang harus digunakan? 1.0.0? 2.0.0?
surname
}
}Kita memiliki dua perhatian di sini:
- Menentukan versi default yang akan digunakan ketika tidak ada yang diberikan
- Menginformasikan klien bahwa ada beberapa versi yang dapat dipilih
Sebelum menangani perhatian-perhatian ini, kita perlu mengetahui seberapa baik GraphQL menyediakan umpan balik kontekstual saat menjalankan sebuah query.
Menyediakan umpan balik kontekstual saat menjalankan queries
Kita perlu menunjukkan kondisi yang kurang ideal dengan GraphQL saat ini: GraphQL tidak menawarkan informasi kontekstual yang baik saat menjalankan queries. Hal ini terlihat jelas terkait dengan deprecation, di mana data deprecation hanya ditampilkan melalui introspeksi dengan melakukan query pada field isDeprecated dan deprecationReason pada tipe Field dan Enum:
{
__type(name: "Account") {
name
fields {
name
isDeprecated
deprecationReason
}
}
}Responsnya akan berupa:
{
"data": {
"__type": {
"name": "Account",
"fields": [
{
"name": "id",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "surname",
"isDeprecated": true,
"deprecationReason": "Use `personSurname`"
},
{
"name": "personSurname",
"isDeprecated": false,
"deprecationReason": null
}
]
}
}
}Namun, ketika menjalankan sebuah query yang melibatkan field yang sudah deprecated…
query GetSurname {
account(id: 1) {
surname
}
}...informasi deprecation tidak akan muncul dalam respons:
{
"data": {
"account": {
"surname": "Owens"
}
}
}Ini berarti bahwa pengembang yang menjalankan query harus secara aktif menjalankan introspection queries untuk mengetahui apakah skema telah diperbarui dan ada field yang deprecated. Hal itu mungkin terjadi… sesekali? Kemungkinan besar tidak pernah?
Akan menjadi peningkatan yang besar menuju peninjauan queries yang sudah usang jika GraphQL API menyediakan informasi deprecation saat menjalankan queries yang melibatkan field yang deprecated. Informasi ini idealnya diberikan di bawah entri top-level baru deprecations, yang muncul setelah errors dan sebelum data (mengikuti saran spesifikasi untuk format respons).
Karena entri top-level deprecations bukan bagian dari spesifikasi, fitur "Proactive Feedback" Gato GraphQL menambahkan dukungan untuk umpan balik yang lebih baik dalam respons query dengan menggunakan entri top-level wildcard extensions, yang memungkinkan perluasan protokol sesuai kebutuhan:

Mempublikasikan versi melalui warnings
Kita baru saja mengetahui bahwa server GraphQL dapat menggunakan entri top-level extensions untuk menyediakan informasi deprecation. Kita dapat menggunakan metodologi yang sama untuk menambahkan entri warnings, di mana kita menginformasikan kepada pengembang bahwa sebuah field telah di-versioning. Kita tidak selalu menyediakan informasi ini; hanya ketika query melibatkan field yang telah di-versioning, dan argumen versionConstraint tidak ada.
Menentukan versi default untuk sebuah field
Ada beberapa pendekatan yang dapat kita gunakan, termasuk:
- Membuat
versionConstraintwajib diisi - Menggunakan versi lama secara default hingga tanggal tertentu, di mana versi baru menjadi default
- Menggunakan versi terbaru secara default dan mendorong para pengembang query untuk secara eksplisit menyatakan versi mana yang akan digunakan
Mari kita jelajahi setiap strategi ini dan lihat responsnya saat menjalankan query ini:
query GetSurname {
account(id: 1) {
surname
}
}1. Membuat versionConstraint wajib diisi
Ini adalah yang paling jelas: larang klien untuk tidak menentukan batasan versi dengan membuat argumen field tersebut wajib diisi. Kemudian, setiap kali tidak diberikan, query akan mengembalikan error.
Menjalankan query akan merespons dengan:
{
"errors": [
{
"message": "Argument 'versionConstraint' in field 'surname' cannot be empty"
}
],
"data": {
"account": {
"surname": null
}
}
}2. Menggunakan versi lama secara default hingga tanggal tertentu di mana versi baru menjadi default
Tetap menggunakan versi lama hingga tanggal tertentu, ketika versi baru akan menjadi default. Selama masa transisi ini, minta para pengembang query untuk secara eksplisit menambahkan batasan versi ke versi lama sebelum tanggal tersebut melalui entri extensions.warnings baru dalam query.
Menjalankan query dapat merespons dengan:
{
"extensions": {
"warnings": [
{
"message": "Field 'surname' has a new version: '2.0.0'. This version will become the default one on January 1st. We advise you to use this new version already and test that it works fine; if you find any problem, please report the issue in https://github.com/mycompany/myproject/issues. To do the switch, please add the 'versionConstraint' field argument to your query (using Composer's semver constraint rules; see https://getcomposer.org/doc/articles/versions.md#writing-version-constraints): surname(versionConstraint:\"^2.0\"). If you are unable to switch to the new version, please make sure to explicitly point to the current version '1.0.0' before January 1st: surname(versionConstraint:\"^1.0\"). In case of doubt, please contact us at name@company.com.",
]
},
"data": {
"account": {
"surname": "Owens"
}
}
}3. Menggunakan versi terbaru dan mendorong pengguna untuk secara eksplisit menyatakan versi mana yang akan digunakan
Gunakan versi terbaru dari field ketika versionConstraint tidak diatur, dan dorong para pengembang query untuk secara eksplisit mendefinisikan versi mana yang harus digunakan, dengan menampilkan daftar semua versi yang tersedia untuk field tersebut melalui entri extensions.warnings baru:
Menjalankan query dapat merespons dengan:
{
"extensions": {
"warnings": [
{
"message": "Field 'surname' has more than 1 version. Please add the 'versionConstraint' field argument to your query to indicate which version to use (using Composer's semver constraint rules; see https://getcomposer.org/doc/articles/versions.md#writing-version-constraints). To use the latest version, use: surname(versionConstraint:\"^2.0\"). Available versions: '2.0.0', '1.0.0'.",
]
},
"data": {
"account": {
"surname": "Owens"
}
}
}Versioning direktif
Kita dapat menggunakan strategi yang sama untuk melakukan versioning pada direktif. Misalnya, saat menjalankan query tanpa memberikan batasan versi:
query {
post(by: { id: 1 }) {
title @strTitleCase
}
}Ini dapat mengasumsikan versi default yang akan digunakan dan menghasilkan pesan peringatan bagi pengembang untuk meninjau kembali query:
