59 Skema dan Resolver Subscription: Memahami Konsep, Praktik, dan Implementasi dalam GraphQL
Berbicara tentang GraphQL, kita tidak bisa lepas dari tiga pilar utama: schema, resolver, dan subscription. Khusus untuk artikel ini, saya akan mengupas tuntas skema dan resolver subscription dan pentingnya mereka dalam pengembangan API modern.
Saya asumsikan pembaca sudah familiar dengan konsep dasar query dan mutation di GraphQL. Kali ini kita akan fokus pada mekanisme subscription, yang menjadi jembatan antara backend dan real-time frontend. Anda akan menemukan penjelasan, simulasi, tabel perbandingan, hingga contoh kode nyata seputar subscription di GraphQL.
1. Subscription di GraphQL: Apa itu dan Kenapa Penting?
Sebelum masuk ke skema dan resolver, mari kita refresh sedikit tentang subscription.
Subscription memungkinkan klien untuk berlangganan event tertentu dan menerima data secara real-time, tanpa harus melakukan polling manual ke server. Sangat bermanfaat untuk aplikasi chat, dashboard analytics, notifikasi, dan berbagai aplikasi yang mengusung konsep real-time.
Perbandingan model komunikasi data:
Query | Mutation | Subscription | |
---|---|---|---|
Sifat | Request/response | Write | Stream/push |
Respon | Sekali | Sekali | Berkala (realtime) |
Contoh Usecase | Fetch tabel | Hapus data | Chat masuk |
2. Diagram Alur Subscription
Agar lebih mudah membayangkan, berikut diagram alur subscription yang akan kita implementasikan nantinya menggunakan Mermaid syntax:
sequenceDiagram participant Client participant Server participant PubSub Client->>Server: Kirim request subscription Server-->>Client: Mendengar event (connection ack) PubSub-->>Server: New event published Server-->>Client: Kirim data baru via websocket
Di sini, Server akan mendengarkan event dari PubSub (Publish/Subscribe mechanism) lalu meneruskan ke Client yang sudah membuka connection.
3. Deklarasi Skema Subscription di GraphQL
Schema pada GraphQL mendefinisikan bagaimana bentuk serta jenis event yang dapat di-subscribe oleh client.
type Subscription {
messageSent(roomId: ID!): Message
}
type Message {
id: ID!
content: String!
sender: String!
sentAt: String!
}
Penjelasan:
- Subscription bernama
messageSent
, bertipe returnMessage
. - Parameter
roomId
bertipe ID — hanya akan menerima message dari ruang tertentu. - Type
Message
mendeskripsikan bentuk object yang dikirim ke klien.
4. Resolver: Jembatan Skema dan Backend
Resolver adalah kode logika yang menghubungkan schema dengan data sumber (entah database, event emitter, dsb).
Implementasi Subscription berbeda dengan Query/Mutation. Resolver subscription harus mengembalikan sebuah async iterator agar server bisa stream data ke klien.
Kita akan gunakan package populer graphql-subscriptions
yang menyediakan PubSub sederhana dengan EventEmitter internal.
Langkah 1: Setup PubSub dan Resolver
const { PubSub } = require('graphql-subscriptions');
const pubsub = new PubSub();
const SUBSCRIPTION_TOPIC = 'MESSAGE_SENT';
const resolvers = {
Subscription: {
messageSent: {
subscribe: (_, { roomId }) =>
pubsub.asyncIterator(`${SUBSCRIPTION_TOPIC}_${roomId}`),
},
},
};
Penjelasan:
- Ketika klien subscribe ke
messageSent
, resolver akan mengembalikan async iterator ke topik tertentu (dalam hal ini, berdasarkan roomId).
Langkah 2: Publish Event saat Message baru
Simulasikan publish event ketika pesan baru dikirim (misal lewat mutation sendMessage
):
const resolvers = {
Mutation: {
sendMessage: async (_, { roomId, content, sender }) => {
const message = { id: Date.now(), content, sender, sentAt: new Date().toISOString() };
// Simulasi simpan ke DB
// db.saveMessage(message);
// Publish event ke subscriber topik yang sesuai
await pubsub.publish(`${SUBSCRIPTION_TOPIC}_${roomId}`, {
messageSent: message,
});
return message;
},
},
};
5. Simulasi Alur Subscription
Mari kita uji prosesnya:
Langkah Simulasi
Client A subscribe ke subscription berikut:
subscription { messageSent(roomId: "room-59") { id content sender sentAt } }
Client B mengirim pesan via mutation:
mutation { sendMessage(roomId: "room-59", content: "Halo, GraphQL!", sender: "Budi") { id content } }
Client A menerima pesan baru tanpa perlu polling. Server otomatis push data:
{ "data": { "messageSent": { "id": "1718717500000", "content": "Halo, GraphQL!", "sender": "Budi", "sentAt": "2024-06-15T19:38:20Z" } } }
Seringkali, Anda akan menggunakan WebSocket (contohnya subscriptions-transport-ws
atau package di Apollo Server) sebagai protokol underlying agar benar-benar real-time.
6. Studi Kasus: Tabel Perbandingan (Query vs Subscription)
Fitur | Query | Subscription |
---|---|---|
Mekanisme | HTTP, stateless | WebSocket, stateful connection |
Kapan dipakai | Data snapshot | Real-time streaming event |
Skalabilitas | Mudah (caching, CDN) | Cukup sulit, butuh infra proper |
Use-case populer | Laporan, statistik | Chat, notif, harga realtime |
7. Best Practice & Tips
- Gunakan Filtering: Selalu batasi event yang dikirim. Gunakan parameter pada subscription (misal, roomId).
- Autentikasi: Pastikan hanya klien terotorisasi yang boleh subscribe; filter di layer resolver.
- Scalability: Implementasikan alat seperti Redis PubSub atau Kafka kalau aplikasi sudah skala besar.
- Handle Disconnect: Pastikan client dapat reconnect/subscribe ulang jika koneksi WebSocket terputus.
8. Contoh Implementasi End-to-End (Mini Project)
Berikut potongan kode server GraphQL (Node.js + Apollo Server) yang menjalankan subscription dengan PubSub local:
const { ApolloServer, gql } = require('apollo-server');
const { PubSub } = require('graphql-subscriptions');
const pubsub = new PubSub();
const typeDefs = gql`
type Message {
id: ID!
content: String!
sender: String!
sentAt: String!
}
type Query {
_empty: String
}
type Mutation {
sendMessage(roomId: ID!, content: String!, sender: String!): Message!
}
type Subscription {
messageSent(roomId: ID!): Message!
}
`;
const SUBSCRIPTION_TOPIC = 'MESSAGE_SENT';
const resolvers = {
Mutation: {
sendMessage: async (_, { roomId, content, sender }) => {
const message = { id: Date.now(), content, sender, sentAt: new Date().toISOString() };
await pubsub.publish(`${SUBSCRIPTION_TOPIC}_${roomId}`, {
messageSent: message,
});
return message;
},
},
Subscription: {
messageSent: {
subscribe: (_, { roomId }) =>
pubsub.asyncIterator(`${SUBSCRIPTION_TOPIC}_${roomId}`),
},
},
};
const server = new ApolloServer({ typeDefs, resolvers });
server.listen().then(({ url, subscriptionsUrl }) => {
console.log(`🚀 Server ready at ${url}`);
console.log(`🚀 Subscriptions ready at ${subscriptionsUrl}`);
});
9. Penutup: Subscription = Future of Real-Time Web
Dengan memahami skema dan resolver subscription, kita bisa membangun fitur real-time yang efisien, clean, dan maintainable. GraphQL subscription menawarkan solusi ideal di era aplikasi yang makin interaktif dan responsif.
Tantangan utamanya ada pada skalabilitas dan manajemen koneksi, namun dengan arsitektur dan best practice yang tepat, subscription bisa jadi senjata andalan backend modern.
Tertarik mencoba di project Anda? Let’s subscribe to the future! 🚀
81. Unit Test untuk Handler gRPC
Artikel Terhangat
59 Skema dan Resolver Subscription
08 Aug 2025
81. Unit Test untuk Handler gRPC
08 Aug 2025
79. gRPC Logging Terstruktur dengan Zap
08 Aug 2025
56 Apa Itu Subscription di GraphQL?
08 Aug 2025
78. Men-deploy gRPC Service di Docker
08 Aug 2025

59 Skema dan Resolver Subscription

81. Unit Test untuk Handler gRPC

79. gRPC Logging Terstruktur dengan Zap

56 Apa Itu Subscription di GraphQL?
