এই পোস্টে, আমরা Vercel Edge ফাংশন এবং Upstash Redis ব্যবহার করে আপনার Next.js অ্যাপ্লিকেশনের জন্য একটি ওয়েটিং রুম তৈরি করব৷
আপনি সোর্স কোড এবং ডেমো অ্যাপ চেক করতে পারেন।
ওয়েটিং রুম?
ওয়েটিং রুমটি উপযোগী যখন আপনি আপনার ওয়েবসাইটে সক্রিয় দর্শকের সংখ্যা সীমিত করতে চান যাতে আপনার সংস্থানগুলি অতিরিক্ত বোঝা না যায়৷
আমাদের বাস্তবায়নে, আপনি সক্রিয় দর্শকদের সর্বোচ্চ সংখ্যক সেট করতে সক্ষম হবেন। ট্রাফিক নিয়ন্ত্রণের জন্য দুটি প্যারামিটার থাকবে:
- সর্বোচ্চ ওয়েবসাইটের ক্ষমতা:একই সময়ে ওয়েবসাইটে ভিজিটরের সর্বোচ্চ সংখ্যা?
- সর্বোচ্চ সেশনের সময়সীমা:সর্বাধিক সেকেন্ডের সংখ্যা যা একজন দর্শক নিষ্ক্রিয় থাকতে পারে
ধাপ 1:প্রকল্প সেটআপ
একটি Next.js অ্যাপ তৈরি করুন:
examples git:(master) ✗ npx create-next-app@latest --typescript
✔ What is your project named? … nextjs-waiting-room
Creating a new Next.js app in /Users/enes/dev/examples/nextjs-waiting-room.
upstash-redis ইনস্টল করুন:
npm install @upstash/redis
ধাপ 2:বাস্তবায়ন
Vercel Next.js মিডলওয়্যারের মাধ্যমে এজ ফাংশন সমর্থন করে। তাই আমরা pages/api/
এর অধীনে _middleware.ts যোগ করব . মিডলওয়্যার কোড /api-তে করা সমস্ত অনুরোধকে বাধা দেয়। বিভিন্ন কনফিগারেশনের জন্য এখানে দেখুন।
pages/api/_middleware.ts
আপডেট করুন নীচের হিসাবে:
import { Redis } from "@upstash/redis";
import { NextFetchEvent, NextRequest, NextResponse } from "next/server";
const COOKIE_NAME_ID = "__waiting_room_id";
const COOKIE_NAME_TIME = "__waiting_room_last_update_time";
const UPSTASH_REDIS_REST_TOKEN = "REPLACE_HERE";
const UPSTASH_REDIS_REST_URL = "REPLACE_HERE";
const TOTAL_ACTIVE_USERS = 10;
const SESSION_DURATION_SECONDS = 30;
const redis = new Redis({
url: UPSTASH_REDIS_REST_URL,
token: UPSTASH_REDIS_REST_TOKEN,
});
export async function middleware(req: NextRequest, ev: NextFetchEvent) {
const cookies = req.cookies;
let userId;
if (cookies[COOKIE_NAME_ID] != null) {
userId = cookies[COOKIE_NAME_ID];
} else {
userId = makeid(8);
}
const size = await redis.dbsize();
console.log("current capacity:" + size);
// there is enough capacity
if (size < TOTAL_ACTIVE_USERS) {
return getDefaultResponse(req, userId);
} else {
// site capacity is full
const user = await redis.get(userId);
if (user === "1") {
// the user has already active session
return getDefaultResponse(req, userId);
} else {
// capacity is full so the user is forwarded to waiting room
return getWaitingRoomResponse();
}
}
}
function makeid(length: number) {
let result = "";
const characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
async function getDefaultResponse(request: NextRequest, userId: string) {
// uncomment below to test the function with a static html content
let newResponse = new NextResponse(default_html);
newResponse.headers.set("content-type", "text/html;charset=UTF-8");
// const response = await fetch(request)
// const newResponse = new Response(response.body, response)
const cookies = request.cookies;
const now = Date.now();
let lastUpdate = cookies[COOKIE_NAME_TIME];
let lastUpdateTime = 0;
if (lastUpdate) lastUpdateTime = parseInt(lastUpdate);
const diff = now - lastUpdateTime;
const updateInterval = (SESSION_DURATION_SECONDS * 1000) / 2;
if (diff > updateInterval) {
await redis.setex(userId, SESSION_DURATION_SECONDS, "1");
newResponse.cookie(COOKIE_NAME_TIME, now.toString());
}
newResponse.cookie(COOKIE_NAME_ID, userId);
return newResponse;
}
async function getWaitingRoomResponse() {
const newResponse = new NextResponse(waiting_room_html);
newResponse.headers.set("content-type", "text/html;charset=UTF-8");
return newResponse;
}
const waiting_room_html = `
<title>Waiting Room</title>
<meta http-equiv='refresh' content='30' />
<style>*{box-sizing:border-box;margin:0;padding:0}body{line-height:1.4;font-size:1rem;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif;padding:2rem;display:grid;place-items:center;min-height:100vh}.container{width:100%;max-width:800px}p{margin-top:.5rem}</style>
<div class='container'>
<h1>
<div>You are now in line.</div>
<div>Thanks for your patience.</div>
</h1>
<p>We are experiencing a high volume of traffic. Please sit tight and we will let you in soon. </p>
<p><b>This page will automatically refresh, please do not close your browser.</b></p>
</div>
`;
const default_html = `
<title>Waiting Room Demo</title>
<style>*{box-sizing:border-box;margin:0;padding:0}body{line-height:1.4;font-size:1rem;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif;padding:2rem;display:grid;place-items:center;min-height:100vh}.container{width:100%;max-width:800px}p{margin-top:.5rem}</style>
<div class="container">
<h1>
<div>Waiting Room Demo</div>
</h1>
<p>
Visit this site from a different browser, you will be forwarded to the waiting room when the capacity is full.
</p>
<p> Check <a href='//github.com/upstash/redis-examples/tree/master/nextjs-waiting-room' style={{"color": "blue"}}>this project </a> to set up a waiting room for your website.</p>
</div>
`;
সক্রিয় ব্যবহারকারীর সেশন রাখতে আমরা রাষ্ট্রীয় দোকান হিসাবে Upstash Redis ব্যবহার করি। এর REST API এর জন্য ধন্যবাদ, upstash-redis Vercel Edge ফাংশনগুলির সাথে সামঞ্জস্যপূর্ণ৷
আপনাকে Upstash কনসোল থেকে একটি গ্লোবাল ডাটাবেস তৈরি করতে হবে। কনসোল থেকে REST টোকেন এবং REST URL কপি এবং পেস্ট করুন। Redis ডাটাবেস খালি হওয়া উচিত এবং শুধুমাত্র এই অ্যাপ্লিকেশন দ্বারা ব্যবহার করা উচিত।
এছাড়াও আপনার নিজের প্রয়োজনীয়তার উপর নির্ভর করে TOTAL_ACTIVE_USERS এবং SESSION_DURATION_SECONDS সেট করুন৷
অ্যাপ্লিকেশনটি নতুন দর্শকদের জন্য একটি অনন্য আইডি তৈরি করে এবং এটি একটি কুকি হিসাবে সেট করে এবং এটিকে রেডিস-এ পুশ করে। তাই পরের বার, অ্যাপ্লিকেশনটি পরীক্ষা করে যে ভিজিটরের ইতিমধ্যেই একটি সেশন চেকিং Redis আছে কিনা। Redis-এ সন্নিবেশ করার সময়, এটি সেশন নিষ্ক্রিয় সময়সীমা হিসাবে একটি মেয়াদ শেষ হওয়ার সময় সেট করে। যদি সেশনের সংখ্যা সর্বোচ্চ-ক্ষমতা অতিক্রম করে, নতুন ব্যবহারকারীকে ওয়েটিং রুমের পৃষ্ঠায় ফরোয়ার্ড করা হয়৷
আপনি waiting_room_html
আপডেট করতে পারেন ওয়েটিং রুম পেজ কাস্টমাইজ করতে।
আপনি getDefaultResponse()
আপডেট করতে পারেন NextResponse ব্যবহার করে আপনার নিজের পৃষ্ঠায় ফরওয়ার্ড করার পদ্ধতি।
ধাপ 3:চালান এবং স্থাপন করুন
অ্যাপ্লিকেশনটি স্থানীয়ভাবে npm run dev
দ্বারা চালান . আপনি TOTAL_ACTIVE_USERS
এ 1 সেট করতে চাইতে পারেন এবং ওয়েটিং রুম সহজে পরীক্ষা করতে বিভিন্ন ব্রাউজারে পৃষ্ঠা খুলুন (https://localhost:3000/api/hello)।
আপনি আপনার অ্যাপ্লিকেশনটি ভার্সেলে
এর মাধ্যমে স্থাপন করতে পারেন৷
vercel deploy –prod
বিশ্বব্যাপী লেটেন্সি কমানোর জন্য Vercel প্রান্তের স্থানে _middleware.ts চালাবে।
উপসংহার
এই টিউটোরিয়ালটি দেখায় যে ভার্সেল এবং আপস্ট্যাশকে ধন্যবাদ প্রান্তে একটি গতিশীল অ্যাপ্লিকেশন তৈরি করা কতটা সহজ। আরও উদাহরণের জন্য আমাদের উদাহরণগুলি দেখুন৷
৷টুইটার বা ডিসকর্ডে আপনার প্রতিক্রিয়ার জন্য অপেক্ষা করছি।