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

Upstash और Next.js के साथ अपने SaaS के लिए एक विश्वसनीय कोटा सिस्टम बनाएं

इस पोस्ट में, हम आपको दिखाएंगे कि Next.js और Prisma के साथ बने SaaS एप्लिकेशन के लिए कोटा सिस्टम बनाने के लिए Upstash का उपयोग कैसे करें। हम एक साधारण API बनाने के लिए Next.js API रूट का उपयोग करेंगे।

कई SaaS एप्लिकेशन में, आपने कोटा सिस्टम का सामना किया होगा। यह एक ऐसा सिस्टम है जो एक दिए गए समय में यूजर द्वारा की जा सकने वाली क्रियाओं की संख्या को सीमित करता है।

हमारे उदाहरण में, "Free" प्लान पर एक यूजर प्रति माह केवल 1,000 API अनुरोध भेज सकता है। यदि यूजर 1,000 से अधिक API अनुरोध भेजने का प्रयास करता है, तो एप्लिकेशन यूजर को और अनुरोध भेजने से रोक देगा।

ये API अनुरोध स्प्रेडशीट की सामग्री को पुनर्प्राप्त करने और इसे JSON में बदलने के लिए उपयोग किए जाते हैं। यह वही है जो fastsheet करता है, किसी भी Google Sheets स्प्रेडशीट को कुछ क्लिक में JSON API में बदल देता है।

Upstash और Next.js के साथ अपने SaaS के लिए एक विश्वसनीय कोटा सिस्टम बनाएं

डेटाबेस स्कीमा परिभाषित करना

जैसा कि पहले कहा गया है, हम डेटाबेस के साथ इंटरैक्ट करने के लिए ORM के रूप में Prisma का उपयोग करेंगे। यहां एक User मॉडल का उदाहरण है जो कोटा सिस्टम को लागू करता है, साथ ही स्प्रेडशीट को संग्रहीत करने के लिए इसका Spreadsheet मॉडल:

model User {
  id        Int      @id @default(autoincrement())
  planId    String   @default("FREE")
  email     String   @unique
  quota     Int      @default(0)
  spreadsheets Spreadsheet[]
}
model Spreadsheet {
  id        Int         @id @default(autoincrement())
  userId    Int
  user      User        @relation(fields: [userId], references: [id])
  content   String
}
  • planId फ़ील्ड वह प्लान है जिसकी यूजर ने सदस्यता ली है।
  • quota फ़ील्ड वर्तमान महीने में यूजर द्वारा किए गए API अनुरोधों की संख्या है।
  • Spreadsheet मॉडल एक स्प्रेडशीट को दर्शाता है, जो एक User से जुड़ा हुआ है।
  • एक User के पास इससे जुड़े कई Spreadsheet हो सकते हैं।

चीजों को सरल रखने के लिए, हम केवल "FREE" प्लान को संभालेंगे, जो प्रति माह 1,000 API अनुरोध की अनुमति देता है।

यूजर का कोटा बढ़ाना

हम हर बार यूजर द्वारा API अनुरोध करने पर यूजर का कोटा बढ़ाना चाहते हैं।

पहली नज़र में, यह आसान और सीधा लगता है। हम बस अपने Next.js API रूट पर हर बार जब यूजर API अनुरोध करता है यूजर के कोटा को 1 से बढ़ा सकते हैं:

// pages/api/spreadsheets/[id]/index.ts
import type { NextApiRequest, NextApiResponse } from "next";
const MAX_FREE_TIER_QUOTA = 1000;
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  // URL से स्प्रेडशीट की ID प्राप्त करें।
  const { id } = req.params;
  // डेटाबेस से स्प्रेडशीट और उससे जुड़े यूजर को प्राप्त करें।
  const spreadsheet = await prisma.spreadsheet.findUnique({
    where: { id: Number(id) },
    include: { user: true },
  });
  // सत्यापित करें कि स्प्रेडशीट मौजूद है।
  if (!spreadsheet) {
    return res.status(404).json({ error: "Spreadsheet not found" });
  }
  // सत्यापित करें कि यूजर कोटा से अधिक नहीं है।
  if (spreadsheet.user.quota >= MAX_FREE_TIER_QUOTA) {
    return res.status(429).json({ error: "Quota exceeded" });
  }
  // यूजर का कोटा 1 से बढ़ाएं।
  await prisma.user.update({
    where: { id: spreadsheet.user.id },
    data: { quota: { increment: 1 } },
  });
  // स्प्रेडशीट की सामग्री वापस करें।
  return res.json({ content: spreadsheet.content });
}

हालांकि इस दृष्टिकोण के साथ एक समस्या है, यह उतना तेज़ नहीं है जितना होना चाहिए।

वास्तव में, हम हर API अनुरोध पर यूजर का कोटा बढ़ाने के लिए एक डेटाबेस ट्रांजैक्शन बना रहे हैं।

हम यूजर का कोटा प्राप्त करने के लिए डेटाबेस एक्सेस करते हैं, कोटा को 1 से बढ़ाने के लिए एक ट्रांजैक्शन बनाते हैं, और फिर स्प्रेडशीट सामग्री भेजते हैं।

यह कई कारणों से इष्टतम नहीं है:

  • आपका डेटाबेस धीमा हो सकता है, यह आपकी प्रतिक्रिया समय को धीमा कर देगा।
  • आपका डेटाबेस आपके सर्वर से दूर हो सकता है, यह फिर से आपकी प्रतिक्रिया समय को धीमा कर देगा।
  • इस कोड को एज संगत बनाना कठिन है, आपको दुनिया भर में कई डेटाबेस प्रतिकृतियां बनाने की आवश्यकता है (ऐसा करना आसान काम नहीं है!)।

यूजर का कोटा बढ़ाने के लिए Upstash का उपयोग करना

इस समस्या को हल करने के लिए, हम Upstash Redis® का उपयोग करके यूजर का कोटा बढ़ाएंगे। Upstash Redis® सर्वरलेस वातावरण के लिए बने एक तेज़ और विश्वसनीय Redis® डेटाबेस है, जो एज के लिए तैयार है (अपने यूजर्स के करीब कोड चलाएं)।

हम यूजर के कोटा को 1 से बढ़ाने के लिए INCR Redis® कमांड का उपयोग करेंगे। यह कमांड परमाणु है, जिसका अर्थ है कि यह केवल एक बार निष्पादित होगा, और यह तेज़ी से निष्पादित होगा।

यहां वही कोड है जैसा पहले था, लेकिन यूजर के कोटा को प्रबंधित करने के लिए Upstash Redis® का उपयोग करके:

// pages/api/spreadsheets/[id]/index.ts
import type { NextApiRequest, NextApiResponse } from "next";
import { Redis } from "@upstash/redis";
const MAX_FREE_TIER_QUOTA = 1000;
// एनवायरनमेंट वेरिएबल का उपयोग करके Upstash Redis इंस्टेंस जेनरेट करें।
// सुनिश्चित करें कि वे आपकी .env फाइल में परिभाषित हैं।
const redis = new Redis({
  url: process.env.UPSTASH_REDIS_REST_URL!,
  token: process.env.UPSTASH_REDIS_REST_TOKEN!,
});
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  // URL से स्प्रेडशीट की ID प्राप्त करें।
  const { id } = req.params;
  // डेटाबेस से स्प्रेडशीट और उससे जुड़े यूजर को प्राप्त करें।
  const spreadsheet = await prisma.spreadsheet.findUnique({
    where: { id: Number(id) },
    include: { user: true },
  });
  // सत्यापित करें कि स्प्रेडशीट मौजूद है।
  if (!spreadsheet) {
    return res.status(404).json({ error: "Spreadsheet not found" });
  }
  // Redis कोटा कुंजी, यूजर की ID द्वारा प्रत्येक यूजर के लिए अद्वितीय।
  const quotaKey = `user:${spreadsheet.user.id}:quota`;
  // Redis से यूजर का कोटा पुनर्प्राप्त करें।
  const quota = await redis.incr(quotaKey);
  // यदि कुंजी पहले मौजूद नहीं थी, तो वापस किया गया मान 1 होगा
  // और हम समाप्ति को 1 दिन पर सेट करते हैं।
  if (quota === 1) {
    await redis.expire(quotaKey, 60 * 60 * 24);
  }
  // सत्यापित करें कि यूजर कोटा से अधिक नहीं है।
  if (quota > MAX_FREE_TIER_QUOTA) {
    return res.status(429).json({ error: "Quota exceeded" });
  }
  // स्प्रेडशीट की सामग्री वापस करें।
  return res.json({ content: spreadsheet.content });
}

Upstash Redis® का उपयोग करके आपका कोड आसानी से स्केलेबल हो जाता है, क्योंकि आप अपने कोड को अपने यूजर्स के करीब चलाने के लिए Upstash Redis® Edge की शक्ति का लाभ उठा सकते हैं।

निष्कर्ष

Upstash Redis® सर्वरलेस वातावरण के लिए कैशिंग सिस्टम को लागू करना बहुत आसान बनाता है।

हमने इसका उपयोग कोटा सिस्टम को लागू करने के लिए किया लेकिन मूल विचार को बहुत अधिक उपयोग-मामलों पर लागू किया जा सकता है, जैसे अधिक डेटाबेस क्वेरी कैश करना, या API अनुरोध के परिणामों को कैश करना।

कैशिंग का अंतिम लक्ष्य आपके API को तेज़ बनाना और संसाधनों का कम उपभोग करने की संभावना बनाना है (उदाहरण के लिए Planetscale डेटाबेस रीड/राइट क्वेरी)।

भविष्य के लेख में, हम देखेंगे कि Upstash QStash का उपयोग करके यूजर के कोटा को Redis® से कैसे पुनर्प्राप्त करें और इसे डेटाबेस में संग्रहीत करें, ताकि यह सुनिश्चित हो सके कि यूजर का कोटा हमेशा अप-टू-डेट है और खो नहीं जाता।

इसे लाइव देखें

यदि आप इस तरह के ऑप्टिमाइज़ेशन को लाइव देखना चाहते हैं, तो आप fastsheet देख सकते हैं, एक API सेवा जो आपके Google Sheets को कुछ क्लिक में API में बदल देती है। यह उदार फ्री टियर के साथ उपयोग करने के लिए फ्री है।

  1. HTML DOM Button ऑब्जेक्ट HTML DOM Button ऑब्जेक्ट

    HTML DOM Button ऑब्जेक्ट <button> एलिमेंट से जुड़ा हुआ है। प्रॉपर्टीज HTML DOM button ऑब्जेक्ट के लिए निम्नलिखिक प्रॉपर्टीज हैं - प्रॉपर्टी विवरण autofocus पेज लोड होने पर बटन स्वचालित रूप से फोकस्ड है या नहीं सेट या लौटाने के लिए disabled दिए गए बटन को अक्षम किया गया है या नहीं सेट

  1. पायथन में सूची को स्टैक और क्यू के रूप में उपयोग करना पायथन में सूची को स्टैक और क्यू के रूप में उपयोग करना

    इस लेख में, हम पायथन 3.x (या पूर्व संस्करणों) में Stack और Queue संरचनाओं के बारे में सीखेंगे। यहाँ हम इन डेटा संरचनाओं के भीतर कार्य और संशोधन पर चर्चा करेंगे। इसमें शामिल हैं - सम्मिलन संक्रिया (Push, Enqueue) हटाने की संक्रिया (Pop, Dequeue) प्रदर्शन/ट्रैवर्सल संक्रिया पूर्वापेक्षाएँ: सूची औ

  1. HTML DOM Input Datetime required गुणधर्म HTML DOM Input Datetime required गुणधर्म

    HTML DOM Input Datetime required गुणधर्म यह निर्धारित करता है कि इनपुट डेटटाइम फ़ील्ड भरना अनिवार्य है या नहीं। वाक्य रचना (Syntax) निम्नलिखित वाक्य रचना है: बूलियन मान लौटाना - true/false inputDatetimeObject.required required को बूलियन मान पर सेट करना inputDatetimeObject.required = booleanValue