Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Redis

सर्वरलेस रेडिस का उपयोग करके स्केलेबल SvelteKit एप्लिकेशन बनाएं

SvelteKit, Svelte के लिए आगामी फुल-स्टैक एप्लिकेशन फ्रेमवर्क है, जो UI फ्रेमवर्क है जो आपके ऐप को कंपाइल टाइम पर बिल्ड करता है ताकि छोटा, तेज़ जावास्क्रिप्ट उत्पन्न हो सके। जबकि SvelteKit आपको एंडपॉइंट्स का उपयोग करके सर्वर-साइड लॉजिक लिखने की अनुमति देता है, यह आप पर निर्भर करता है कि आप अपने एप्लिकेशन के डेटा को कैसे बनाए रखना चाहते हैं।

इस पोस्ट में, मैं दिखाऊंगा कि रेडिस का उपयोग करके SvelteKit एप्लिकेशन में डेटा कैसे स्टोर किया जाए। हम मूवी API रिस्पॉन्स को कैश करने और एक रैंडम मूवी प्रदर्शित करने के लिए रेडिस का उपयोग करेंगे, The Movie Database (TMDB) API के डेटा का उपयोग करके।

आपको इस डेमो के साथ चलने के लिए या तो एक रेडिस कनेक्शन स्ट्रिंग की आवश्यकता होगी या स्थानीय रूप से रेडिस चलाना होगा। यदि आपके पास पहले से रेडिस इंस्टेंस नहीं है, तो मैं अपस्टैश की सिफारिश करता हूं। SvelteKit की तरह, यह सर्वरलेस एप्लिकेशन के लिए अनुकूलित है और फ्री है यदि आप बहुत अधिक रिक्वेस्ट नहीं कर रहे हैं (लेखन के समय कैप 10k/दिन है)। चाहे आप अपना रेडिस इंस्टेंस कहीं से भी प्राप्त करें, आपको यह सुनिश्चित करना चाहिए कि यह वहां स्थित है जहां आपका एप्लिकेशन डिप्लॉय किया गया है ताकि लेटेंसी कम हो।

पूर्वापेक्षाएँ

  • SvelteKit के साथ बेसिक परिचितता (जैसे पेज बनाम एंडपॉइंट्स, लोडिंग, दिए गए पेज के लिए क्वेरी और पैरामीटर प्राप्त करना)
  • एक TMDB API की और रेडिस इंस्टेंस (उदाहरण के लिए अपस्टैश पर) यदि आप डेमो चलाना या डिप्लॉय करना चाहते हैं

स्टार्टर अवलोकन

स्टार्टर रेपो क्लोन करें। main ब्रांच में अंतिम परिणाम है, इसलिए इस पोस्ट के साथ चलने के लिए initial ब्रांच चेकआउट करें। यदि आप अपने परिवर्तनों को पुश करना चाहते हैं, तो पहले रेपो को फोर्क करें।

git clone https://github.com/geoffrich/movie-search-redis.git
cd movie-search-redis
git checkout initial

यह एक छोटा SvelteKit एप्लिकेशन है जो TMDB API का उपयोग करके फिल्मों को खोजने और उनके विवरण देखने की अनुमति देता है। यह API रिस्पॉन्स के साथ इंटरैक्ट करना आसान बनाने के लिए TypeScript का उपयोग करता है, लेकिन रेडिस या SvelteKit का उपयोग करने के लिए यह आवश्यक नहीं है। निम्नलिखित रूट्स पहले से मौजूद हैं (src/routes में फाइलों के अनुरूप):

  • / होम पेज रेंडर करता है
  • /search खोज परिणामों की सूची रेंडर करता है। यह क्वेरी पैरामीटर के रूप में query और page लेता है, उदा. ?query=star wars&page=3 "Star Wars" के लिए परिणामों का तीसरा पेज दिखाता है
  • /search.json एक सर्वर एंडपॉइंट है जो TMDB API को क्वेरी करता है और परिणामों की सूची वापस करता है। यह /search के समान क्वेरी पैरामीटर लेता है
  • /movie/[id] दिए गए ID वाली मूवी के लिए विवरण रेंडर करता है, उदा. /movie/11
  • /movie/[id].json एक सर्वर एंडपॉइंट है जो TMDB API से मूवी विवरण वापस करता है। चूंकि TMDB रिस्पॉन्स हमारे द्वारा पेज पर उपयोग किए जाने वाले डेटा से अधिक डेटा वापस करता है, हम रिस्पॉन्स को डेटा के सबसेट को वापस करने के लिए अनुकूलित करते हैं।

आप डेमो को नेटलीफाई पर चलते हुए देख सकते हैं।

ध्यान दें कि TMDB API कॉल केवल सर्वर एंडपॉइंट्स में होते हैं। ऐसा इसलिए है ताकि हमारी API की क्लाइंट के सामने उजागर न हो।

स्थानीय रूप से डेमो चलाने के लिए, प्रोजेक्ट के रूट में .env फाइल बनाएं और अपना TMDB API की और रेडिस कनेक्शन स्ट्रिंग जोड़ें (नीचे नमूना)। फिर निर्भरताएं इंस्टॉल करने के लिए npm install चलाएं और ऐप चलाने के लिए npm run dev चलाएं।

TMDB_API_KEY=KEY_GOES_HERE
REDIS_CONNECTION=CONNECTION_GOES_HERE

रनटाइम पर, हम इन मानों को process.env['TMDB_API_KEY'] या process.env['REDIS_CONNECTION'] का उपयोग करके एक्सेस कर सकते हैं। मान dotenv का उपयोग करके .env फाइल से hooks.ts में पढ़े जाते हैं।

रेडिस में API रिस्पॉन्स कैश करना

मौजूदा प्रोजेक्ट में हम एक सुधार कर सकते हैं वह है इंडिविजुअल मूवी के लिए API रिस्पॉन्स को रेडिस में कैश करना। वर्तमान में, ऐप हर बार मूवी पेज लोड होने पर TMDB API को रिक्वेस्ट करता है। जब हम पहली बार रिक्वेस्ट करते हैं, तो हम API रिस्पॉन्स को रेडिस में स्टोर कर सकते हैं ताकि हमें TMDB से डेटा बार-बार मांगने की आवश्यकता न हो।

जबकि TMDB API तेज़ है और इसे कैश करने की आवश्यकता नहीं है, यह उन API के लिए एक उपयोगी तकनीक हो सकती है जिनका रिस्पॉन्स आने में समय लगता है या जिनकी रिक्वेस्ट लिमिट होती है। यह एक स्तर की लचीलापन भी प्रदान करता है यदि API डाउन हो जाता है।

हमने पहले ही ioredis को डिपेंडेंसी के रूप में जोड़ दिया है। यह Node के लिए एक रेडिस क्लाइंट है जो हमें अपने रेडिस डेटाबेस के साथ इंटरैक्ट करने में मदद करेगा।

src/lib/redis.ts फाइल बनाएं। यह फाइल रेडिस क्लाइंट को इनिशियलाइज़ करती है और अन्य फंक्शन द्वारा उपयोग के लिए एक्सपोर्ट करती है। इसमें कीज़ प्राप्त करने के लिए कुछ हेल्पर फंक्शन भी हैं। नीचे दिए गए कोड को फाइल में जोड़ें।

import Redis from "ioredis";

const connectionString = process.env["REDIS_CONNECTION"];
export const MOVIE_IDS_KEY = "movie_ids";

/** रेडिस में दिए गए ID के लिए मूवी डिटेल्स स्टोर करने के लिए उपयोग की जाने वाली की लौटाएं */
export function getMovieKey(id): string {
  return `movie:${id}`;
}

export default connectionString
  ? new Redis(connectionString)
  : new Redis();

ध्यान दें कि यह इम्प्लीमेंटेशन प्रति सर्वरलेस इंस्टेंस एक सिंगल रेडिस क्लाइंट बनाता है। दूसरा विकल्प प्रति रिक्वेस्ट एक रेडिस कनेक्शन बनाना और बंद करना है। अपस्टैश में एक REST API भी है जिसके लिए आपको रेडिस कनेक्शन इनिशियलाइज़ करने की आवश्यकता नहीं है। सबसे अच्छा विकल्प आपके ऐप की लेटेंसी और मेमोरी आवश्यकताओं पर निर्भर करता है।

/src/routes/movie/[id].json.ts फाइल पर जाएं। redis.ts से रेडिस क्लाइंट और getMovieKey फंक्शन इम्पोर्ट करें।

import redis, { getMovieKey } from "$lib/redis";

getMovieDetailsFromApi फंक्शन पर एक नज़र डालें। यह TMDB API को कॉल करके मूवी डिटेल्स और क्रेडिट प्राप्त करता है और उन्हें वापस करता है। डेटा वापस करने से पहले, हम इसे अपने रेडिस कैश में स्टोर करना चाहते हैं ताकि अगली बार हम API को कॉल करने के बजाय कैश्ड वर्जन प्राप्त करें। फाइल में एक नया cacheMovieResponse फंक्शन जोड़ें ताकि डेटा को रेडिस में कैश किया जा सके।

async function cacheMovieResponse(id: number, movie, credits) {
  try {
    const cache: MovieDetails = {
      movie,
      credits,
    };
    // मूवी रिस्पॉन्स को 24 घंटे के लिए स्टोर करें
    await redis.set(getMovieKey(id), JSON.stringify(cache), "EX", 24 * 60 * 60);
  } catch (e) {
    console.log("Unable to cache", id, e);
  }
}

प्रत्येक मूवी ID को एक अलग की के तहत स्टोर किया जाएगा। उदाहरण के लिए, यदि हम ID 11 वाली मूवी की जानकारी प्राप्त कर रहे थे, तो की movie:11 होगी। redis.set के अंतिम दो आर्गुमेंट कहते हैं कि हमें डेटा को केवल 24 घंटे (86400 सेकंड) के लिए कैश करना चाहिए। हमें डेटा को हमेशा के लिए कैश नहीं करना चाहिए—यह उपयोग की शर्तों का उल्लंघन करता है, और डेटा अंततः बासी हो जाएगा।

ध्यान दें कि JS ऑब्जेक्ट को कैश में स्टोर करने से पहले आपको इसे स्ट्रिंगिफाई करना होगा। हम इस ऑपरेशन के दौरान फेंके गए किसी भी एक्सेप्शन को कैच करते हैं ताकि हमारा एंडपॉइंट अधिक लचीला हो। अगर हम डेटा को कैश नहीं कर सकते, तो हमें अनहैंडल्ड एक्सेप्शन फेंकने के बजाय API से डेटा वापस करना चाहिए।

अब हम नए cacheMovieResponse फंक्शन का उपयोग getMovieDetailsFromApi के अंदर API रिस्पॉन्स को कैश में स्टोर करने के लिए कर सकते हैं।

async function getMovieDetailsFromApi(id: number) {
  const [movieResponse, creditsResponse] = await Promise.all([
    getMovieDetails(id),
    getCredits(id),
  ]);
  if (movieResponse.ok) {
    const movie = await movieResponse.json();
    const credits = await creditsResponse.json();
    // यह लाइन जोड़ें
    await cacheMovieResponse(id, movie, credits);
    return {
      movie,
      credits,
    };
  }
  return {
    status: movieResponse.status,
  };
}

अब हमने डेटा को कैश में स्टोर कर दिया है, लेकिन हमें अभी भी कैश्ड डेटा को पुनः प्राप्त करने की आवश्यकता है। आइए कैश से मूवी डिटेल्स पढ़ने के लिए एक फंक्शन जोड़ें।

async function getMovieDetailsFromCache(
  id: number
): Promise<MovieDetails | Record<string, never>> {
  try {
    const cached: string = await redis.get(getMovieKey(id));
    if (cached) {
      const parsed: MovieDetails = JSON.parse(cached);
      console.log(`Found ${id} in cache`);
      return parsed;
    }
  } catch (e) {
    console.log("Unable to retrieve from cache", id, e);
  }
  return {};
}

चूंकि डेटा को स्ट्रिंग के रूप में स्टोर किया गया था, हमें इसे ऑब्जेक्ट में पार्स करने की आवश्यकता है ताकि यह उपयोग करने योग्य हो सके। पिछले फंक्शन के समान, हम किसी भी एक्सेप्शन को लॉग करते हैं, लेकिन उन्हें कैशिंग फंक्शन से बाहर नहीं निकलने देते। हम हमेशा API से डेटा प्राप्त करने पर वापस आ सकते हैं।

अंत में, हम अपने कैशिंग फंक्शन को मेन रिक्वेस्ट हैंडलर में कॉल कर सकते हैं। अगर हमें डेटा कैश में मिल जाता है, तो हम इसे तुरंत वापस कर देते हैं; अन्यथा, हम पहले की तरह API से पढ़ते हैं।

export const get: RequestHandler = async function ({ params }) {
  const { id: rawId } = params;
  // इनपुट को वैलिडेट और सैनिटाइज़ करें
  const id = parseInt(rawId);
  if (isNaN(id)) {
    return {
      status: 400,
    };
  }
  // ये लाइनें जोड़ें
  const { movie, credits } = await getMovieDetailsFromCache(id);
  if (movie && credits) {
    return {
      body: adaptResponse(movie, credits),
    };
  }
  // API पर फॉलबैक
  const result = await getMovieDetailsFromApi(id);

आप इस एंडपॉइंट के लिए अंतिम कोड डेमो रेपो में देख सकते हैं।

इन परिवर्तनों के साथ, किसी मूवी के पेज पर नेविगेट करने का प्रयास करें। जब आप पेज को रीफ्रेश करते हैं, तो आपको कंसोल लॉग में "Found id in cache" दिखाई देना चाहिए, यह दर्शाता है कि हमने सफलतापूर्वक उस मूवी को कैश में स्टोर और पुनः प्राप्त किया।

रैंडम मूवी प्राप्त करना

रेडिस केवल API रिस्पॉन्स कैश करने से कहीं अधिक कर सकता है। आइए देखें कि हम एक रूट कैसे बना सकते हैं जो यूजर को एक रैंडम मूवी पर रीडायरेक्ट करेगा।

यह 1 और 300000 के बीच एक रैंडम नंबर चुनने और उसे मूवी ID के रूप में उपयोग करने जितना सरल नहीं है। उस रेंज में हर नंबर मूवी से मेल नहीं खाएगा—उदाहरण के लिए, ID 1 या 1000 वाली कोई मूवी नहीं है। अधिकतम संभव ID क्या है, इसे ट्रैक करना भी मुश्किल होगा, क्योंकि नई फिल्में जोड़े जाने पर यह हमेशा बदलता रहता है। इसके बजाय, हम दो-चरणीय प्रक्रिया का उपयोग करके रैंडम मूवी चुनेंगे:

  1. जब एक खोज क्वेरी की जाती है, तो वापस किए गए सभी IDs को एक रेडिस सेट में रखें।
  2. जब /movie/random रूट का अनुरोध किया जाता है, तो उस सेट का एक रैंडम मेंबर प्राप्त करें और संबंधित मूवी डिटेल पेज पर रीडायरेक्ट करें।

वापस की गई संभावित रैंडम मूवी छोटी शुरू होगी, लेकिन जैसे-जैसे अधिक खोजें की जाएंगी, बड़ी होती जाएगी।

रैंडम सेट को पॉप्युलेट करने के लिए, /src/routes/search.json.ts को निम्नलिखित में अपडेट करें।

import type { RequestHandler } from "@sveltejs/kit";
import type { SearchResponse } from "$lib/types/tmdb";
import redis, { MOVIE_IDS_KEY } from "$lib/redis";

const VOTE_THRESHOLD = 20;

export const get: RequestHandler = async function ({ query }) {
  const searchQuery = query.get("query");
  const page = query.get("page") ?? 1;
  const response = await fetch(
    `https://api.themoviedb.org/3/search/movie?api_key=${process.env["TMDB_API_KEY"]}&page=${page}&include_adult=false&query=${searchQuery}`
  );
  const parsed: SearchResponse = await response.json();
  
  // ये लाइनें जोड़ें
  const filteredMovies = parsed.results.filter(
    (movie) => movie.vote_count >= VOTE_THRESHOLD
  );
  if (filteredMovies.length > 0) {
    try {
      await redis.sadd(MOVIE_IDS_KEY, ...filteredMovies.map((r) => r.id));
    } catch (e) {
      console.log(e);
    }
  }
  
  return {
    body: parsed,
  };
};

ध्यान दें कि हम वापस की गई हर मूवी को सेट में नहीं जोड़ रहे हैं। मैंने उन फिल्मों को फ़िल्टर करना चुना जिनके पास कई वोट नहीं हैं, क्योंकि उन फिल्मों के यूजर्स द्वारा जांचे जाने की संभावना कम होती है। आप VOTE_THRESHOLD को अपनी पसंद के अनुसार एडजस्ट कर सकते हैं।

इस परिवर्तन के साथ, मूवी खोजने से मूवी IDs का सेट पॉप्युलेट होना शुरू हो जाएगा। कुछ खोजें करके सेट में कुछ IDs जोड़ें। उदाहरण के लिए:

  • Star Wars
  • Lion King
  • Spider Man

कुछ खोजें करने के बाद, आपके पास रेडिस में स्टोर रैंडम IDs का एक सेट होना चाहिए। आइए /movie/random एंडपॉइंट और पेज के लिए रूट बनाएं।

src/routes/movie/random.json.ts

import type { RequestHandler } from "@sveltejs/kit";
import redis, { MOVIE_IDS_KEY } from "$lib/redis";

export const get: RequestHandler = async function () {
  const randomId = await redis.srandmember(MOVIE_IDS_KEY);
  return {
    body: randomId,
  };
};

यह सर्वर एंडपॉइंट मूवी ID सेट से रैंडम ID चुनने के लिए SRANDMEMBER का उपयोग करता है।

src/routes/movie/random.svelte

<script context="module" lang="ts">
import type { Load } from "@sveltejs/kit";

export const load: Load = async function ({ fetch }) {
  const result = await fetch(`/movie/random.json`);
  if (result.ok) {
    const id = await result.json();
    return {
      redirect: `/movie/${id}`,
      status: 303,
    };
  }
  return {
    status: result.status,
    error: new Error("Could not retrieve random id"),
  };
};
</script>

संबंधित Svelte पेज को केवल लोड फंक्शन की आवश्यकता है क्योंकि यह कोई UI रेंडर नहीं करता। यह हमारे द्वारा अभी जोड़े गए सर्वर एंडपॉइंट को कॉल करता है और संबंधित मूवी पेज पर रीडायरेक्ट करता है।

बस इतना ही! अब, https://localhost:3000/movie/random पर नेविगेट करें। आपको आपके द्वारा की गई पिछली खोजों से एक रैंडम मूवी पर ऑटोमैटिकली रीडायरेक्ट किया जाना चाहिए। इस रूट तक पहुंच को आसान बनाने के लिए, आप इसे /src/routes/__layout.svelte में नेविगेशन में जोड़ सकते हैं।

<header>
  <nav>
    <a href="/">Search</a>
    <a href="/movie/random">Random</a>
  </nav>
</header>

आप इसे लाइव डेमो में काम करते हुए देख सकते हैं।

समापन

रेडिस का उपयोग करने के कई और तरीके हैं, लेकिन मुझे उम्मीद है कि इस पोस्ट ने आपको SvelteKit ऐप में रेडिस को एकीकृत करने की बुनियादी बातों की अच्छी समझ दी। आप GitHub पर अंतिम कोड और Netlify पर लाइव डेमो देख सकते हैं।

कोई प्रश्न? ट्विटर पर संपर्क करें। आप मेरे ब्लॉग पर Svelte के बारे में मेरा अन्य लेखन भी पा सकते हैं।

  1. फ्लटर, सर्वरलेस फ्रेमवर्क और अपस्टैश रेडिस के साथ फुल-स्टैक सर्वरलेस ऐप बनाएं - भाग 1 फ्लटर, सर्वरलेस फ्रेमवर्क और अपस्टैश रेडिस के साथ फुल-स्टैक सर्वरलेस ऐप बनाएं - भाग 1

    इस पोस्ट में, हम फ्लटर, सर्वरलेस फ्रेमवर्क, अपस्टैश और डेटा स्टोर करने के लिए रेडिस के साथ एक सर्वरलेस मोबाइल एप्लिकेशन बनाएंगे। अपस्टैश क्या है? अपस्टैश रेडिस के लिए एक सर्वरलेस डेटाबेस है। अपस्टैश के साथ, आप प्रति-रिक्वेस्ट भुगतान करते हैं। इसका मतलब है कि जब डेटाबेस उपयोग में नहीं होता है तो आपस

  1. पाइपलाइन REST API के साथ सर्वरलेस Redis एक्सेस को बढ़ाएं पाइपलाइन REST API के साथ सर्वरलेस Redis एक्सेस को बढ़ाएं

    Upstash नेटिव Redis API के अलावा REST API का समर्थन करता है। REST API डेवलपर्स को सर्वरलेस और एज फ़ंक्शंस से कनेक्शन समस्याओं के बिना अपने Redis तक पहुंचने में मदद करता है। लेकिन यदि आप एक ही फ़ंक्शन में कई Redis कमांड निष्पादित करते हैं तो इसका मतलब है कि आप डेटाबेस को कई बार कॉल करेंगे। हमारे समुद

  1. Cloudflare Workers के साथ एज पर Redis की शक्ति का उपयोग करें Cloudflare Workers के साथ एज पर Redis की शक्ति का उपयोग करें

    एज पर कंप्यूटिंग हाल के वर्षों में सबसे रोमांचक क्षमताओं में से एक है। CDN आपको अपनी फ़ाइलों को अपने उपयोगकर्ताओं के करीब रखने की अनुमति देता है। एज कंप्यूटिंग आपको अपने एप्लिकेशन को अपने उपयोगकर्ताओं के करीब चलाने की अनुमति देता है। यह डेवलपर्स को विश्व स्तर पर वितरित, उच्च-प्रदर्शन एप्लिकेशन बनाने