במשך מספר שנים, ניסיתי לזהות פרימיטים, מוצרים ושירותים שמאפשרים לטכנולוגים להשאיר את המיקוד שלהם על הרחבת הערך של הקנס העיון שלהם. זה ממשיך להיות לי מסע נפלא, מלא הזדמנויות ללמוד ייחודיות.
המהנדס בתוכי אדם שלי לאחרונה תהה אם היה מצב בו אני יכול למצוא תועלת שניה עבור הרעיון הקיים שדיברתי עליו פעם קודם. במילים אחרות, האם אני יכול לזהות תועלת נוספת עם אותו רמה השפעה כמו הפתרונות האב המקוריים שהוכרזו קודם?
למאמר הזה, רציתי לעבור עמוק יותר בGraphQLכדי לראות מה אני יכול למצוא.
במאמרי "" When It’s Time to Give REST a Rest "" שלי, דיברתי על אילו מצבים של העולם האמיתי אתם מועדים להשתמש בGraphQL במקום RESTful service. עברנו דרך איך לבנות ולשדר את ה API GraphQL בעזרת Apollo Server.
בפוסט הבא, אני מתכוון להעלות את ידידותי בGraphQL על ידי עיבוד הרשמות עבור הבאת מידע בזמן אמת. אנחנו גם נבנה שירות WebSocket על מנת לצרף את הרשמות.
סיכום: מושג הלקוח 360
המאמר הקודם שלי התמקד במשהו של מושג הלקוח 360, בו ללקוחות של העסק המדומי שלי משמרים על האוסף הבא:
- מידע לקוח
- מידע כתוביות
- שיטות קשר
- מפתרונות קרדיט
יש ניצחון ענק בשימוש בGraphQL בגלל שבקשת GraphQL אחת יכולה להשלים את כל הנתונים הנחוצים לטוkens הלקוח (מיденיטי).
type Query {
addresses: [Address]
address(customer_token: String): Address
contacts: [Contact]
contact(customer_token: String): Contact
customers: [Customer]
customer(token: String): Customer
credits: [Credit]
credit(customer_token: String): Credit
}
בשימוש בגישה RESTful כדי להשלים את המבט המקביל (360) של הלקוח היה דרוש מספר בקשות ותגובות ניתנות לשילוב. GraphQL מעניק לנו פתרון שמבצע טוב יותר.
מטרות רמוניות למעלה
על מנת להגדיל בכל אחד מהיבטי החיים, עליך להשלים מטרות חדשות. במטרות שלי פה, זה אומר:
- הבנה ויישום של ערך ה
הרשמות
בתוך GraphQL - שימוש בWebSocket להשתמש ברשימה GraphQL
הרעיון של השתמשות בהרשמות על גבי שאלות ומשפרות בתוך GraphQL הוא שיטה נחוצה כשמוגשות התנאים הבאים:
- שינויים קטנים, סדרתיים בגדולים
- עדכונים במהירות מוגבלת, בזמן אמת (כמו בית שיחה)
זה חשוב מפני שהמימוש בהרשמות בתוך GraphQL איננו קל. לא רק יהיה צריך לעדכן את השרת המקורי, אך גם היישום המצרף ידרוש רעיון חדש.
למרבה המזל, המקרה שאנחנו מתחילים בדוגמה של 360 הלקוח מושלם לגבי הרשמות. גם, אנחנו ניסוי בגישה WebSocket לנצחון אותם הרשמות.
כמו בעבר, אני ימשיך להשתמש בApollo בהמשך.
הגדילה עם הרשמות קרדס
ראשית, אנחנו צריכים להתקין את הספריות הנחוצות כדי לתמוך ברשימות עם השרת הApollo GraphQL שלי:
npm install ws
npm install graphql-ws @graphql-tools/schema
npm install graphql-subscriptions
עם החלקים האלה מותקנים, התמקדתי על עדכון את הindex.ts
מהאחסן המקורי שלי כדי להרחיב את המשתמש הtypedefs
עם הבאה:
type Subscription {
creditUpdated: Credit
}
גם יצרתי משתמש קבילה עבור מקום חדש PubSub
ויצרתי רישום ראיון שנהשתמש בו בזמן המה:
const pubsub = new PubSub();
pubsub.publish('CREDIT_BALANCE_UPDATED', {
creditUpdated: {
}
});
ניקיתי את המפעילים הקיימים והוספתי מפעיל חדש Subscription
עבור השימוש החדש הזה:
const resolvers = {
Query: {
addresses: () => addresses,
address: (parent, args) => {
const customer_token = args.customer_token;
return addresses.find(address => address.customer_token === customer_token);
},
contacts: () => contacts,
contact: (parent, args) => {
const customer_token = args.customer_token;
return contacts.find(contact => contact.customer_token === customer_token);
},
customers: () => customers,
customer: (parent, args) => {
const token = args.token;
return customers.find(customer => customer.token === token);
},
credits: () => credits,
credit: (parent, args) => {
const customer_token = args.customer_token;
return credits.find(credit => credit.customer_token === customer_token);
}
},
Subscription: {
creditUpdated: {
subscribe: () => pubsub.asyncIterator(['CREDIT_BALANCE_UPDATED']),
}
}
};
אחר כך, רפקטו את ההגדרות המערכת והצגתי את העיצוב של הרשימות:
const app = express();
const httpServer = createServer(app);
const wsServer = new WebSocketServer({
server: httpServer,
path: '/graphql'
});
const schema = makeExecutableSchema({ typeDefs, resolvers });
const serverCleanup = useServer({ schema }, wsServer);
const server = new ApolloServer({
schema,
plugins: [
ApolloServerPluginDrainHttpServer({ httpServer }),
{
async serverWillStart() {
return {
async drainServer() {
serverCleanup.dispose();
}
};
}
}
],
});
await server.start();
app.use('/graphql', cors(), express.json(), expressMiddleware(server, {
context: async () => ({ pubsub })
}));
const PORT = Number.parseInt(process.env.PORT) || 4000;
httpServer.listen(PORT, () => {
console.log(`Server is now running on http://localhost:${PORT}/graphql`);
console.log(`Subscription is now running on ws://localhost:${PORT}/graphql`);
});
כדי לדמות עדכונים מובילים על ידי לקוחות, יצרתי את השיטה הבאה כדי להגביר את החסרת הקרדיט בסך חמשה שניות בעוד השירות ממוקד. ברגע שהחסרת הקרדיט מגיעה (או מעלה) למסגרת קרדיט של $10,000, אני מסיים את החסרת הקרדיט חזרה ל $2,500, דמיית תשלום חסרת הקרדיט.
function incrementCreditBalance() {
if (credits[0].balance >= credits[0].credit_limit) {
credits[0].balance = 0.00;
console.log(`Credit balance reset to ${credits[0].balance}`);
} else {
credits[0].balance += 50.00;
console.log(`Credit balance updated to ${credits[0].balance}`);
}
pubsub.publish('CREDIT_BALANCE_UPDATED', { creditUpdated: credits[0] });
setTimeout(incrementCreditBalance, 5000);
}
incrementCreditBalance();
את הקובץ index.ts
המלא ניתן למצוא פה.
הדגמה ל-Heroku
עם השירות המוכן, הגיע הזמן להשתמש בהוצאה לשירות כך שנוכל לבוא במגע עם הו. בגלל שHeroku עבד מצוין בפעם הקודמת ושהוא קל לשימוש בשבילי, בואו נשמור על הגישה הזו.
כדי להתחיל, היה עליי לבצע את הפקודות הבאות של ה CLI של Heroku:
$ heroku login
$ heroku create jvc-graphql-server-sub
Creating jvc-graphql-server-sub... done
https://jvc-graphql-server-sub-1ec2e6406a82.herokuapp.com/ | https://git.heroku.com/jvc-graphql-server-sub.git
הפקודה ג
$ git remote
heroku
origin
כפי שציינתי במאמר הקודם שלי, שרת ה-Apollo מכבה את מדריך ה-Apollo בסביבות הייצור. כדי לשמור על מדריך ה-Apollo זמין לצרכים שלנו, הייתי צריך לקבע את המשתנה הסביבה NODE_ENV
לפיתוח. קבעתי את זה עם הפקודה הבאה של ה-CLI:
$ heroku config:set NODE_ENV=development
Setting NODE_ENV and restarting jvc-graphql-server-sub... done, v3
NODE_ENV: development
הייתי מוכן להפעיל את הקוד שלי ב-Heroku:
$ git commit --allow-empty -m 'Deploy to Heroku'
$ git push heroku
צפייה מהירה בלוח הבקרה של Heroku הראתה ששרת ה-Apollo רץ ללא בעיות:
בחלק ההגדרות מצאתי את כתובת ה-URL של היישומון של Heroku למודול זה:
https://jvc-graphql-server-sub-1ec2e6406a82.herokuapp.com/
- שים לב: הקישור הזה לא יהיה בשירות עד עתה שהמאמר יפורסם.
עד כה, יכולתי להוסיף graphql
לכתובת ה-URL הזו כדי להריץ את סטודיו ה-Apollo. זה איפשר לי לראות את הרשתות עובדות כפי שציפיתי:
שימו לב לתגובות הרשתות בצד הימני של המסך.
עלייה ביכולות עם כישורי ה-WebSocket
ניתן לנצל תמיכה ב-WebSocket ויכולותיו של Heroku כדי ליצור הימוש שמאכיל את הרשתה שיצרנו.
במקרה שלי, יצרתי קובץ index.js עם התוכן הבא. בעיקרון, זה יצר לי לקוח WebSocket וגם הקמה של שרות HTTP דומה שיכולתי להשתמש בו כדי לוודא שהלקוח רץ:
import { createClient } from "graphql-ws";
import { WebSocket } from "ws";
import http from "http";
// יצירת שרת HTTP דומה כדי לקשר את ה-PORT של Heroku
const PORT = process.env.PORT || 3000;
http.createServer((req, res) => res.end('Server is running')).listen(PORT, () => {
console.log(`HTTP server running on port ${PORT}`);
});
const host_url = process.env.GRAPHQL_SUBSCRIPTION_HOST || 'ws://localhost:4000/graphql';
const client = createClient({
url: host_url,
webSocketImpl: WebSocket
});
const query = `subscription {
creditUpdated {
token
customer_token
credit_limit
balance
credit_score
}
}`;
function handleCreditUpdated(data) {
console.log('Received credit update:', data);
}
// הרשמה לרשתת המעדכן החשבונות
client.subscribe(
{
query,
},
{
next: (data) => handleCreditUpdated(data.data.creditUpdated),
error: (err) => console.error('Subscription error:', err),
complete: () => console.log('Subscription complete'),
}
);
אתם יכולים למצוא את הקוד של index.js
כאן משהו.
אנחנו יכולים לשדר את היישום הפשוט של Node.js ל Heroku, ולהבטיח שאנחנו מגדירים את המידע הסביבתי GRAPHQL_SUBSCRIPTION_HOST
לכתובת היישום של Heroku שהשתמשנו קודם.
אני גם יצרתי את ה Procfile
הבא כדי לספר ל Heroku איך להתחיל את היישום שלי:
web: node src/index.js
בהמשך, יצרתי יישום חדש ב Heroku:
$ heroku create jvc-websocket-example
Creating jvc-websocket-example... done
https://jvc-websocket-example-62824c0b1df4.herokuapp.com/ | https://git.heroku.com/jvc-websocket-example.git
אחר כך, הגדירת את מידע הסביבתי GRAPHQL_SUBSCRIPTION_HOST
להציע את השרת ה GraphQL המופעל שלי:
$ heroku --app jvc-websocket-example \
config:set \
GRAPHQL_SUBSCRIPTION_HOST=ws://jvc-graphql-server-sub-1ec2e6406a82.herokuapp.com/graphql
בנקודה זו, אנחנו מוכנים לשדר את הקוד שלנו ל Heroku:
$ git commit --allow-empty -m 'Deploy to Heroku'
$ git push heroku
ברגע שהלקוח ה WebSocket מתחיל, אנחנו יכולים לראות את מצבו בלוח מבט Heroku:
על ידי הצגה של המידע בלוח מבט Heroku עבור המקטע jvc-websocket-example
, אנחנו יכולים לראות את העדכונים הרבים לתכונה balance
של השרת jvc-graphql-server-sub
. בדיוק, בדמות שלי, הצלחתי לתפוס את המקרה בו הסך החשבון צמח לאפס, מדמות שהיתה בה הוצאה של התשלום:
בתוצרת, אנחנו יכולים לגשת לאותם מידעים בשולחן השלטים בעזרת הפקודה הבאה של ה CLI heroku logs.
2024-08-28T12:14:48.463846+00:00 app[web.1]: Received credit update: {
2024-08-28T12:14:48.463874+00:00 app[web.1]: token: 'credit-token-1',
2024-08-28T12:14:48.463875+00:00 app[web.1]: customer_token: 'customer-token-1',
2024-08-28T12:14:48.463875+00:00 app[web.1]: credit_limit: 10000,
2024-08-28T12:14:48.463875+00:00 app[web.1]: balance: 9950,
2024-08-28T12:14:48.463876+00:00 app[web.1]: credit_score: 750
2024-08-28T12:14:48.463876+00:00 app[web.1]: }
לא רק שיש לנו שרת GraphQL עם יישום רשימה מופעל, אבל עכשיו יש לנו צרף WebSocket שצורך בעדכונים האלה.
סיכום
הקוראים שלי עשויים לזכור את המטרה ה
"תמקדו את זמנכם באספקת תכונות/פונקציונליות שמרחיבות את הערך של הקניין הרוחני שלכם. השתמשו במסגרות, מוצרים ושירותים עבור כל השאר."
— ג'. וסטר
בצלילה העמוקה הזו למנויים ב-GraphQL, צרכנו בהצלחה עדכונים מ-Apollo Server הפועל על Heroku באמצעות שירות נוסף שגם הוא פועל על Heroku — אפליקציה מבוססת Node.js שמשתמשת ב-WebSockets. על ידי השימוש במנויים קלים, נמנענו משליחת שאילתות עבור נתונים שלא השתנו ופשוט נרשמנו לקבלת עדכונים על יתרת האשראי כאשר הם התרחשו.
במבוא, הזכרתי את החיפוש אחר עקרון ערך נוסף בתוך נושא שכתבתי עליו בעבר. מנויי GraphQL הם דוגמה מצוינת למה שהתכוונתי כי הם מאפשרים לצרכנים לקבל עדכונים מיידיים, ללא צורך לבצע שאילתות נגד הנתונים המקוריים. זה ילהיב מאוד את צרכני נתוני Customer 360, בידיעה שהם יכולים לקבל עדכונים חיים בזמן אמת.
Heroku היא דוגמה נוספת שממשיכה לדבוק בהצהרת המשימה שלי על ידי הצעת פלטפורמה שמאפשרת לי להפיק במהירות פתרונות באמצעות CLI ופקודות Git סטנדרטיות. זה לא רק נותן לי דרך קלה להציג את מקרה השימוש במנויים שלי אלא גם ליישם צרכן באמצעות WebSockets.
אם אתם מעוניינים בקוד המקור של המאמר הזה, בדקו את המאגרים שלי ב-GitLab:
אני בטוח במדינת הדברים שאני הצלחתי להגבר את היכולת שלי בגרפיקל דרך המאמץ הזה. המסע הזה היה חדש ומאתגר בשבילי – וגם הוא היה מאד מהנה!
אני מתכוון להתעמס באופן הבא באמת המזהה, שבתקווה יעיד עוד הזדמנות להגבר את היכולת שלי בגרפיקל ובשרת אפולו הזה. המשך לרגע!
תהיה יום מעולה בגדול!
Source:
https://dzone.com/articles/leveling-up-my-graphql-skills-real-time-subscriptions