Mano GraphQL įgūdžių išlyginimas: prenumeratos realiuoju laiku

Mano GraphQL įgūdžių išlyginimas: prenumeratos realiuoju laiku


Jau kelerius metus bandžiau nustatyti sistemas, produktus ir paslaugas, kurios leistų technologams toliau sutelkti dėmesį į savo intelektinės nuosavybės vertės didinimą. Tai man ir toliau yra nuostabi kelionė, kupina unikalių mokymosi galimybių.

Mano inžinierius neseniai susimąstė, ar yra situacija, kai galėčiau rasti antrinės naudos esamai koncepcijai, apie kurią jau kalbėjau anksčiau. Kitaip tariant, ar galėčiau nustatyti kitą naudą, kurios poveikis toks pat, kaip ir anksčiau pripažintas pirminis sprendimas?

Šiam straipsniui norėjau pasinerti į GraphQL, kad pamatyčiau, ką galėčiau rasti.

Straipsnyje „Kai laikas pailsėti“ kalbėjau apie tai, kaip egzistuoja realūs scenarijai, kai „GraphQL“ yra geriau nei „RESTful“ paslauga. Apžvelgėme, kaip sukurti ir įdiegti GraphQL API naudojant „Apollo Server“.

Šiame tolesniame įraše planuoju patobulinti savo žinias apie GraphQL, eidamas per prenumeratas, skirtas duomenų gavimui realiuoju laiku. Taip pat sukursime „WebSocket“ paslaugą, kad sunaudotume prenumeratas.

Santrauka: Kliento 360 naudojimo atvejis

Mano ankstesnis straipsnis buvo susijęs su „Customer 360“ naudojimo atvejis, kai mano išgalvotos įmonės globėjai saugo šiuos duomenų rinkinius:

  • Kliento informacija
  • Adreso informacija
  • Susisiekimo būdai
  • Kredito atributai

Didžiulis laimėjimas naudojant GraphQL yra tai, kad viena GraphQL užklausa gali gauti visus reikiamus duomenis kliento prieigos raktui (unikali tapatybė).

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
}

Naudojant RESTful metodą norint gauti vieną (360) kliento vaizdą, būtų reikėję sujungti keletą užklausų ir atsakymų. GraphQL suteikia mums sprendimą, kuris veikia daug geriau.

Tikslai aukštyn lygiu

Norint pasiekti aukštesnį lygį bet kurioje gyvenimo srityje, reikia siekti naujų tikslų. Mano tikslams čia tai reiškia:

  • „GraphQL“ prenumeratos vertės pasiūlymo supratimas ir įgyvendinimas.
  • „WebSocket“ diegimo naudojimas norint sunaudoti „GraphQL“ prenumeratą.

Idėja naudoti prenumeratas per GraphQL užklausas ir mutacijas yra tinkamiausias metodas, kai tenkinamos šios sąlygos:

  • Maži, laipsniški didelių objektų pakeitimai
  • Mažos delsos atnaujinimai realiuoju laiku (pvz., pokalbių programa)

Tai svarbu, nes prenumeratos įdiegimas GraphQL nėra trivialus. Reikės atnaujinti ne tik pagrindinį serverį, bet ir daug naudojančią programą.

Laimei, naudojimo atvejis, kurio ieškome su „Customer 360“ pavyzdžiu, puikiai tinka prenumeratai. Be to, mes įgyvendinsime WebSocket metodą, kad panaudotume šias prenumeratas.

Kaip ir anksčiau, toliau naudosiu „Apollo“.

Išlyginimas su prenumeratos kreditais

Pirmiausia turime įdiegti reikiamas bibliotekas, kad palaikytume prenumeratas su mano Apollo GraphQL serveriu:

npm install ws
npm install graphql-ws @graphql-tools/schema
npm install graphql-subscriptions 

Įdiegęs tuos elementus sutelkiau dėmesį į atnaujinimą index.ts iš mano pradinės saugyklos, kad pratęsčiau typedefs pastovus su šiais dalykais:

type Subscription {
    creditUpdated: Credit
}

Taip pat įkūriau pastovią, kad įsikurčiau naują PubSub pavyzdį ir sukūrėme prenumeratos pavyzdį, kurį naudosime vėliau:

const pubsub = new PubSub();

pubsub.publish('CREDIT_BALANCE_UPDATED', {
    creditUpdated: {
    }
});

Išvaliau esamus sprendimus ir pridėjau naują Subscription šiam naujam naudojimo atvejui:

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')),
        }
    }
};

Tada pakeičiau serverio konfigūraciją ir pristatau prenumeratos dizainą:

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`);
});

Siekdamas imituoti klientų pagrįstus atnaujinimus, sukūriau šį metodą, kad padidinčiau kredito likutį 50 USD kas penkias sekundes, kol paslauga veikia. Kai likutis pasiekia (arba viršija) 10 000 USD kredito limitą, iš naujo nustatau likutį į 2 500 USD, imituodamas atliekamą balanso mokėjimą.

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();

Pilnas index.ts failą galite rasti čia.

Dislokuoti į Heroku

Kai paslauga yra paruošta, laikas įdiegti paslaugą, kad galėtume su ja bendrauti. Kadangi „Heroku“ praeitą kartą pasiteisino puikiai (ir man juo lengva naudotis), laikykimės šio požiūrio.

Norėdami pradėti, turėjau paleisti šias Heroku CLI komandas:

$ 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

Komanda taip pat automatiškai įtraukė saugyklą, kurią Heroku naudojo kaip nuotolinį:

$ git remote
heroku
origin

Kaip jau minėjau savo ankstesniame straipsnyje, „Apollo Server“ išjungia „Apollo Explorer“ gamybos aplinkoje. Kad „Apollo Explorer“ būtų prieinama mūsų poreikiams, turėjau nustatyti NODE_ENV vystymuisi kintama aplinka. Aš tai nustatiau su šia CLI komanda:

$ heroku config:set NODE_ENV=development

Setting NODE_ENV and restarting ⬢ jvc-graphql-server-sub... done, v3
NODE_ENV: development

Buvau pasirengęs įdiegti savo kodą Heroku:

$ git commit --allow-empty -m 'Deploy to Heroku'
$ git push heroku

Greitas „Heroku“ prietaisų skydelio vaizdas parodė, kad mano „Apollo“ serveris veikia be jokių problemų:

Skiltyje „Nustatymai“ radau šios paslaugos egzemplioriaus „Heroku“ programos URL:

https://jvc-graphql-server-sub-1ec2e6406a82.herokuapp.com/

Atkreipkite dėmesį – paskelbus šį straipsnį ši nuoroda nebebus naudojama.

Kol kas prie šio URL galėčiau pridėti GraphQL, kad paleisčiau „Apollo Server Studio“. Tai leis man pamatyti, kaip prenumeratos veikia taip, kaip tikėtasi:

Atkreipkite dėmesį į prenumeratos atsakymus dešinėje ekrano pusėje.

Lygių padidinimas naudojant „WebSocket Skillz“.

Galime panaudoti „WebSocket“ palaikymą ir „Heroku“ galimybes, kad sukurtume diegimą, kuris sunaudoja mūsų sukurtą prenumeratą.

Mano atveju sukūriau failą index.js su tokiu turiniu. Iš esmės tai sukūrė „WebSocket“ klientą ir taip pat sukūrė netikrą HTTP paslaugą, kurią galėjau naudoti norėdamas patikrinti, ar klientas veikia:

import { createClient } from "graphql-ws";
import { WebSocket } from "ws";
import http from "http";

// Create a dummy HTTP server to bind to Heroku's $PORT
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);
}

// Subscribe to the creditUpdated subscription
client.subscribe(
  {
    query,
  },
  {
    next: (data) => handleCreditUpdated(data.data.creditUpdated),
    error: (err) => console.error('Subscription error:', err),
    complete: () => console.log('Subscription complete'),
  }
);

Pilnas index.js failą galite rasti čia.

Šią paprastą „Node.js“ programą galime įdiegti ir „Heroku“, būtinai nustatydami GRAPHQL_SUBSCRIPTION_HOST aplinkos kintamąjį į Heroku programos URL, kurį naudojome anksčiau.

Taip pat sukūriau štai ką Procfile pasakyti Heroku, kaip paleisti programą:

web: node src/index.js

Tada sukūriau naują Heroku programą:

$ 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

Tada aš nustatiau GRAPHQL_SUBSCRIPTION_HOST aplinkos kintamasis, nurodantis į mano veikiantį GraphQL serverį:

$ heroku --app jvc-websocket-example \
    config:set \
GRAPHQL_SUBSCRIPTION_HOST=ws://jvc-graphql-server-sub-1ec2e6406a82.herokuapp.com/graphql

Šiuo metu esame pasirengę įdiegti savo kodą Heroku:

$ git commit --allow-empty -m 'Deploy to Heroku'
$ git push heroku

Kai WebSocket klientas paleidžiamas, jo būseną galime pamatyti Heroku prietaisų skydelyje:

Peržiūrėdami žurnalus „Heroku“ prietaisų skydelyje jvc-websocket-example Pavyzdžiui, galime matyti kelis atnaujinimus balance nuosavybė jvc-graphql-server-sub paslauga. Savo demonstracijoje netgi galėjau užfiksuoti naudojimo atvejį, kai likutis buvo sumažintas iki nulio, imituojant, kad buvo atliktas mokėjimas:

Terminale tuos pačius žurnalus galime pasiekti naudodami CLI komandą heroku žurnalai.

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): }

Mes ne tik turime GraphQL paslaugą su prenumeratos diegimu, bet dabar turime WebSocket klientą, kuris naudoja tuos naujinimus.

Išvada

Mano skaitytojai gali prisiminti mano asmeninę misiją, kuri, manau, gali būti taikoma bet kuriam IT specialistui:

„Sutelkite savo laiką į funkcijų / funkcijų, kurios padidina jūsų intelektinės nuosavybės vertę, pristatymą. Visam kitam pritaikykite sistemas, produktus ir paslaugas. – J. Vesteris

Šiame gilumoje į GraphQL prenumeratas sėkmingai panaudojome naujinius iš „Apollo“ serverio, veikiančio „Heroku“, naudodami kitą paslaugą, taip pat veikiančią „Heroku“ – „Node.js“ pagrindu veikiančią programą, kuri naudoja „WebSockets“. Naudodami lengvas prenumeratas išvengėme užklausų dėl nesikeičiančių duomenų siuntimo, o tiesiog užsiprenumeravome, kad gautume kredito likučio atnaujinimus, kai jie įvyktų.

Įžangoje minėjau ieškoti papildomos vertės principo temoje, apie kurią rašiau anksčiau. „GraphQL“ prenumeratos yra puikus pavyzdys to, ką turėjau omenyje, nes tai leidžia vartotojams nedelsiant gauti naujinimus, nereikalaujant šaltinio duomenų užklausų. Tai labai sujaudins „Customer 360“ duomenų vartotojus, žinodami, kad jie galės gauti naujinius, kai jie įvyks.

Heroku yra dar vienas pavyzdys, kuris ir toliau laikosi mano misijos, siūlydamas platformą, leidžiančią greitai sukurti sprendimų prototipus naudojant CLI ir standartines Git komandas. Tai ne tik suteikia man paprastą būdą parodyti savo prenumeratos naudojimo atvejį, bet ir pritaikyti vartotoją naudojant WebSockets.

Jei jus domina šio straipsnio šaltinio kodas, peržiūrėkite mano „GitLab“ saugyklas:

Jaučiuosi užtikrintai, kai sakau, kad šiomis pastangomis sėkmingai ištobulinau savo GraphQL įgūdžius. Ši kelionė man buvo nauja ir sudėtinga… be to, labai smagi!

Toliau ketinu pasinerti į autentifikavimą, kuris, tikiuosi, suteiks dar vieną galimybę pasiekti aukštesnį lygį naudojant „GraphQL“ ir „Apollo Server“. Sekite naujienas!

Tikrai puikios dienos!



Source link

Draugai: - Marketingo agentūra - Teisinės konsultacijos - Skaidrių skenavimas - Fotofilmų kūrimas - Miesto naujienos - Šeimos gydytojai - Saulius Narbutas - Įvaizdžio kūrimas - Veidoskaita - Nuotekų valymo įrenginiai - Teniso treniruotės - Pranešimai spaudai -