কম্পিউটার টিউটোরিয়াল

QStash ব্যবহার করে রেডিস স্টেট আপনার ডেটাবেসের সাথে সিমলেসলি সিঙ্ক করুন

একটি পূর্ববর্তী আর্টিকেলে, আমরা আলোচনা করেছি কীভাবে আমরা একটি ফুল-স্ট্যাক Next.js অ্যাপে ব্যবহারকারীর কোটার স্টেট রেডিসে সংরক্ষণ করতে পারি। এটি করার মাধ্যমে আমরা আমাদের অ্যাপ্লিকেশনের পারফরম্যান্স উন্নত করতে পারি, কারণ রেডিস সাধারণত একটি ডেটাবেসের চেয়ে খুব দ্রুত।

আপস্ট্যাশ রেডিস বিশেষভাবে এই ব্যবহারের ক্ষেত্রে একটি চমৎকার পছন্দ, কারণ এটি একটি ফুলি ম্যানেজড রেডিস ডেটাবেস এবং HTTP-এর মাধ্যমে অ্যাক্সেসযোগ্য। এর মানে আমরা Vercel-এর মতো Edge রানটাইমও ব্যবহার করতে পারি আমাদের কোড ব্যবহারকারীর কাছাকাছি চালানোর জন্য ন্যূনতম লেটেন্সির সাথে।

QStash কী?

QStash হলো সার্ভারলেস এবং Edge রানটাইমের জন্য একটি HTTP-ভিত্তিক মেসেজিং এবং শিডিউলিং সমাধান। অন্য কথায়, এটি আপনাকে HTTP রিকোয়েস্ট পাঠিয়ে CRON জব চালানোর অনুমতি দেয়।

CRON জব নির্দিষ্ট সময়ে টাস্ক চালানোর জন্য একটি চমৎকার উপায়। এই CRON জব যতক্ষণ চায় ততক্ষণ চালাতে পারে আপনার অ্যাপ্লিকেশন বা এন্ড-ইউজারদের পারফরম্যান্স প্রভাবিত ছাড়া।

এই আর্টিকেলে আমাদের CRON জবের লক্ষ্য হলো আমাদের ব্যবহারকারীদের কোটার স্টেট রেডিস থেকে আমাদের ডেটাবেসে সিঙ্ক করা। আমরা এই টাস্কটি প্রতি ঘণ্টায় একবার চালাতে পারি।

QStash-এ CRON জব এন্ডপয়েন্ট তৈরি

এখানে পূর্ববর্তী আর্টিকেলের একটি কুইক রিক্যাপ, কীভাবে আমরা আমাদের ব্যবহারকারীদের কোটার স্টেট রেডিসে হ্যান্ডল করি:

// রেডিসে সংরক্ষিত কী। প্রতিটি ব্যবহারকারীর জন্য একটি কী তৈরি হয়, তাদের আইডি দ্বারা ইউনিক করা হয়।
const quotaKey = `user:${userId}:quota`;
// কীটির মান ১ দ্বারা ইনক্রিমেন্ট করতে INCR কমান্ড কল করুন।
const quota = await redis.incr(quotaKey);
// যদি কীটির মান ১ হয়, মানে কীটি তৈরি হয়েছে।
// আমরা এই কীতে ২৪ ঘণ্টার এক্সপায়ারেশন ডেট সেট করতে পারি EXPIRE কমান্ড ব্যবহার করে।
if (quota === 1) {
  await redis.expire(quotaKey, 60 * 60 * 24);
}

এই কোডটি দিয়ে, আমরা এখন QStash ব্যবহার করে একটি CRON জব এন্ডপয়েন্ট তৈরি করতে পারি। আমাদের CRON জব এন্ডপয়েন্ট /api/cron/update-usage URL-এ ট্রিগার হবে।

আমাদের Next.js এন্ডপয়েন্টের জন্য একটি নতুন ফাইল তৈরি করি:

touch pages/api/cron/update-usage.ts

তারপর, আমরা নিশ্চিত করতে চাই শুধু QStash এই এন্ডপয়েন্ট ট্রিগার করতে পারে, এটিই @upstash/qstash হ্যান্ডেল করে। যদি আমরা এটি না করি, কেউ সম্ভবত CRON জব এন্ডপয়েন্ট ট্রিগার করতে পারে যা নিরাপত্তা সমস্যা সৃষ্টি করতে পারে।

@upstash/qstash ইনস্টল করি:

npm install @upstash/qstash

এখন আমরা আমাদের CRON জব এন্ডপয়েন্টের কোডে ফোকাস করতে পারি।

এখানে আমরা কী করব তার একটি কুইক রিক্যাপ:

  • SCAN ব্যবহার করে রেডিস থেকে সব ব্যবহারকারীর কোটা কী পাওয়া (পারফরম্যান্ট কার্সর-ভিত্তিক পেজিনেশন)।
  • SCAN-এ서 পাওয়া প্রতিটি কী için, ব্যবহারকারীর আইডি এবং তাদের কোটা ধারণকারী একটি users অবজেক্ট অ্যারে তৈরি করা।
  • Prisma ব্যবহার করে users অ্যারেতে প্রতিটি ব্যবহারকারীর জন্য একটি ট্রানজেকশন তৈরি করা তাদের কোটা ডেটাবেসে আপডেট করতে।
  • @upstash/qstash/nextjs থেকে verifySignature ফাংশন সহ এন্ডপয়েন্ট ফাংশন এক্সপোর্ট করা শুধু QStash এন্ডপয়েন্ট ট্রিগার করতে পারে তা নিশ্চিত করতে।

পূর্ণ কোড এন্ডপয়েন্টটি এখানে, আমি কোডের প্রতিটি দিক কমেন্ট করে দেওয়া আছে:

// /pages/api/cron/update-usage.ts
import type { NextApiRequest, NextApiResponse } from "next";
import { verifySignature } from "@upstash/qstash/nextjs";
import prisma from "@/lib/prisma";
// এনভায়রনমেন্ট ভেরিয়েবল ব্যবহার করে একটি আপস্ট্যাশ রেডিস ইন্সট্যান্স জেনারেট করুন।
// নিশ্চিত করুন সেগুলো আপনার .env ফাইলে সংজ্ঞায়িত।
const redis = new Redis({
  url: process.env.UPSTASH_REDIS_REST_URL!,
  token: process.env.UPSTASH_REDIS_REST_TOKEN!,
});
// `@upstash/qstash`-এর জন্য প্রয়োজনীয়।
export const config = {
  api: {
    bodyParser: false
  }
};
// রেডিস ডেটাবেস থেকে ডেটা টান করে Prisma ডেটাবেসে প্রতিটি ব্যবহারকারীর ব্যবহার আপডেট করুন।
async function handler(req: NextApiRequest, res: NextApiResponse) {
  // `SCAN` sırasında পাওয়া সব কী ধারণ করবে।
  const keys: string[] = [];
  // কার্সারের বর্তমান পজিশন, প্রতিটি `SCAN`-এর পর আপডেট হয়।
  let cursor = 0;
  // `SCAN` কমান্ড ব্যবহার করে কার্সার-ভিত্তিক পেজিনেশন এক্সিকিউট করুন।
  // রেডিস `0` ফেরত দেয় যখন কার্সার পেজিনেশনের শেষে থাকে।
  do {
    const [nextCursor, newKeys] = await redis.scan(cursor, {
      // আমরা যে কীগুলো খুঁজতে চাই সেগুলোর প্যাটার্ন ম্যাচ করুন, যেখানে `*` একটি 와일্ডকার্ড।
      match: "user:*:quota",
      // `SCAN` কমান্ড দ্বারা ফেরত দেওয়া কী সংখ্যা লিমিট করুন।
      count: 10,
    });
    cursor = nextCursor;
    keys.push(...newKeys);
  } while (cursor !== 0);
  // ব্যবহারকারীর আইডি এবং তাদের কোটা ধারণকারী অবজেক্টের অ্যারে।
  const users: { id: number; quota: number }[] = [];
  // পাওয়া কীগুলোতে ভিত্তি করে রেডিস থেকে প্রতিটি ব্যবহারকারীর ব্যবহার পান।
  for (const key of keys) {
    // একটি কী ফরম্যাটে থাকা উচিত `user:${id}:quota`। আইডি পেতে কী Сп্লিট করুন।
    const id = key.split(":")[1];
    // `GET` কমান্ড ব্যবহার করে ব্যবহারকারীর বর্তমান কোটা পান।
    const quota = await redis.get(`user:${id}:quota`);
    users.push({ id: parseInt(id, 10), quota });
  }
  // ডেটাবেসে তাদের কোটা আপডেট করতে প্রতিটি ব্যবহারকারীর জন্য একটি ট্রানজেকশন তৈরি করুন।
  const promises = users.map((user) =>
    prisma.user.update({
      where: { id: user.id },
      data: { quota: user.quota },
    }),
  );
  // সব ট্রানজেকশন চালান।
  await Promise.all(promises);
  return res.status(200).json({ message: "OK" });
}
// `verifySignature` ফাংশন সহ হ্যান্ডলার এক্সপোর্ট করুন শুধু QStash অথেন্টিকেট করে CRON জব ট্রিগার করতে পারে তা নিশ্চিত করতে।
export default verifySignature(handler);

সবচেয়ে কঠিন অংশটি সম্পন্ন!

QStash সেটআপ

আমাদের কোড পুশ করার আগে, আমাদের QStash সেটআপ করতে হবে। QStash একটি উদার ফ্রি টিয়ার দেয়, আমরা প্রতিদিন ৫০০ রিকোয়েস্ট পর্যন্ত ব্যবহার করতে পারি।

আপস্ট্যাশ কনসোলে লগইন করুন এবং QStash ট্যাবে ক্লিক করুন।

তারপর, Request Builder ব্যবহার করে একটি নতুন শিডিউলড CRON জব তৈরি করুন। এটি সুবিধাজনক UI-এর কারণে খুব সহজ:

QStash ব্যবহার করে রেডিস স্টেট আপনার ডেটাবেসের সাথে সিমলেসলি সিঙ্ক করুন

Schedule বাটনে ক্লিক করার পর, আপনি নিচে স্ক্রল করলে, আপনার CRON জবটি Scheduled Jobs সেকশনে দেখতে পাবেন:

QStash ব্যবহার করে রেডিস স্টেট আপনার ডেটাবেসের সাথে সিমলেসলি সিঙ্ক করুন

শেষ ধাপ, আমাদের Next.js অ্যাপ্লিকেশনে ২টি এনভায়রনমেন্ট ভেরিয়েবল সেটআপ করতে হবে। এই ভেরিয়েবলগুলো সেই জায়গায় যোগ করা হবে যেখানে আমাদের Next.js অ্যাপ্লিকেশন হোস্ট করা আছে, এই কেসে Vercel-এ।

Request Builder সেকশনে, ২টি এনভায়রনমেন্ট ভেরিয়েবল কপি করার জন্য প্রস্তুত:

  • QSTASH_CURRENT_SIGNING_KEY
  • QSTASH_NEXT_SIGNING_KEY

ইনকামিং মেসেজ অথেন্টিকেট করার জন্য এগুলো প্রয়োজন। অন্যথায় কেউ আপনার এন্ডপয়েন্ট কল করতে পারত।

QStash ব্যবহার করে রেডিস স্টেট আপনার ডেটাবেসের সাথে সিমলেসলি সিঙ্ক করুন

এই ভেরিয়েবলগুলো পাওয়ার পর, আপনি আপনার Vercel প্রজেক্টে সেগুলো যোগ করতে পারেন।

এটি করতে, আপনার Vercel প্রজেক্টে যান, Settings-এ ক্লিক করুন এবং তারপর Environment Variables-এ:

QStash ব্যবহার করে রেডিস স্টেট আপনার ডেটাবেসের সাথে সিমলেসলি সিঙ্ক করুন

২টি এনভায়রনমেন্ট ভেরিয়েবল যোগ করার পর, আপনি আপনার কোড পুশ করতে পারেন।

QStash পিরিয়ডিকলি CRON জব এন্ডপয়েন্ট ট্রিগার করবে এবং প্রতিটি ব্যবহারকারীর ব্যবহার প্রতি ঘণ্টা আপডেট করবে।

উপসংহার

আপস্ট্যাশ সার্ভারলেস এনভায়রনমেন্টের জন্য অনেক টুল প্রদান করে। আমরা QStash এবং রেডিস একসাথে ব্যবহার করে অনেক ব্যবহারের ক্ষেত্রে পারফরম্যান্ট এবং স্কেলেবল অ্যাপ্লিকেশন তৈরি করতে পারি।

আপনি যদি লাইভ দেখতে চান, একই সিস্টেম fastsheet-এ বাস্তবায়ন করা হয়েছে, একটি টুল যা আপনার স্প্রেডশিটকে একটি API-এ রূপান্তর করে।

  1. জাভাস্ক্রিপ্টে ট্যাগের অর্ডার অনুযায়ী innerHTML পরিবর্তন করা

  2. অ্যান্ড্রয়েডে প্রোগ্রামেটিক্যালি স্ক্রিন ব্রাইটনেস পরিবর্তন করার পদ্ধতি

  3. জাভা উদাহরণ: OpenCV-এ Scharr এজ ডিটেকশন

  4. Matplotlib-এ অক্ষের বাইরে লাইন আঁকা