ในบทความก่อนหน้านี้ เราได้พูดคุยถึงวิธีที่เราสามารถใช้ Redis เพื่อจัดเก็บสถานะโควต้าผู้ใช้ของคุณบนแอป Next.js แบบเต็มสแต็ก การทำเช่นนี้ช่วยให้เราสามารถปรับปรุงประสิทธิภาพของแอปพลิเคชันของเราได้ เนื่องจากโดยทั่วไปแล้ว Redis จะเร็วกว่าฐานข้อมูลมาก
Upstash Redis เป็นตัวเลือกที่ยอดเยี่ยมเป็นพิเศษสำหรับกรณีการใช้งานนี้ เนื่องจากเป็นฐานข้อมูล Redis ที่มีการจัดการเต็มรูปแบบและเข้าถึงได้ผ่าน HTTP ซึ่งหมายความว่าเรายังสามารถใช้รันไทม์ Edge เช่น Vercel เพื่อรันโค้ดของเราใกล้กับผู้ใช้โดยมีเวลาแฝงขั้นต่ำ
QStash คืออะไร
QStash เป็นโซลูชันการส่งข้อความและกำหนดเวลาที่ใช้ HTTP สำหรับรันไทม์แบบไร้เซิร์ฟเวอร์และ Edge . กล่าวอีกนัยหนึ่ง ช่วยให้คุณสามารถรันงาน CRON โดยการส่งคำขอ HTTP .
งาน CRON เป็นวิธีที่ยอดเยี่ยมในการจัดตารางเวลางานให้ทำงานตามเวลาที่กำหนด งาน CRON นี้อาจใช้เวลามากเท่าที่ต้องการในการทำงานโดยไม่ส่งผลกระทบต่อประสิทธิภาพของแอปพลิเคชันหรือผู้ใช้ปลายทางของคุณ
เป้าหมายของงาน CRON ของเราในบทความนี้คือการซิงค์สถานะโควต้าผู้ใช้จาก Redis ไปยังฐานข้อมูลของเรา เราจะทำให้งานนี้ทำงานทุกชั่วโมง .
การสร้างจุดสิ้นสุดงาน CRON ด้วย QStash
ต่อไปนี้คือสรุปโดยย่อของบทความก่อนหน้านี้เกี่ยวกับวิธีที่เราจัดการสถานะโควต้าผู้ใช้ใน Redis:
// Key stored in Redis. A key is created for each user, and made unique by their ID.
const quotaKey = `user:${userId}:quota`;
// Call the INCR command to increment the value of the key by 1.
const quota = await redis.incr(quotaKey);
// If the value of the key is 1, it means the key has been created.
// We can set an expiration date of 24 hours to this key by using the EXPIRE command.
if (quota === 1) {
await redis.expire(quotaKey, 60 * 60 * 24);
}
ด้วยโค้ดนี้ ตอนนี้เราสามารถสร้างจุดสิ้นสุดงาน CRON โดยใช้ QStash ได้แล้ว ตำแหน่งข้อมูลงาน CRON ของเราจะถูกทริกเกอร์ที่ URL 07 .
มาสร้างไฟล์ใหม่สำหรับปลายทาง Next.js ของเรา:
touch pages/api/cron/update-usage.ts
จากนั้น เราต้องการให้แน่ใจว่ามีเพียง QStash เท่านั้นที่สามารถทริกเกอร์ตำแหน่งข้อมูลนี้ได้ นี่คือสิ่งที่ 19 จัดการสำหรับเรา หากเราไม่ทำเช่นนี้ ใครๆ ก็สามารถ มีศักยภาพ ได้ ทริกเกอร์ตำแหน่งข้อมูลงาน CRON ซึ่งอาจนำไปสู่ปัญหาด้านความปลอดภัยได้
มาติดตั้ง 21 กัน :
npm install @upstash/qstash ตอนนี้เราสามารถมุ่งเน้นไปที่โค้ดของจุดสิ้นสุดงาน CRON ของเราได้แล้ว
ต่อไปนี้เป็นสรุปสั้นๆ เกี่ยวกับสิ่งที่เราจะทำ:
- รับโควต้าคีย์ของผู้ใช้ทั้งหมดจาก Redis โดยใช้
38(การแบ่งหน้าตามเคอร์เซอร์ที่มีประสิทธิภาพ) . - สำหรับแต่ละคีย์ที่พบจาก
48ให้สร้าง55อาร์เรย์ของออบเจ็กต์ที่มี ID ผู้ใช้และโควต้า - สร้างธุรกรรมสำหรับผู้ใช้แต่ละรายภายใน
63อาร์เรย์เพื่ออัพเดตโควต้าในฐานข้อมูล ซึ่งทำได้โดยใช้ Prisma - ส่งออกฟังก์ชันปลายทางด้วย
78ฟังก์ชั่นจาก82เพื่อให้แน่ใจว่ามีเพียง QStash เท่านั้นที่สามารถทริกเกอร์ตำแหน่งข้อมูลได้
จุดสิ้นสุดของโค้ดแบบเต็มอยู่ที่นี่ ฉันแน่ใจว่าจะแสดงความคิดเห็นในทุกแง่มุมของโค้ด:
// /pages/api/cron/update-usage.ts
import type { NextApiRequest, NextApiResponse } from "next";
import { verifySignature } from "@upstash/qstash/nextjs";
import prisma from "@/lib/prisma";
// Generate an Upstash Redis instance using environment variables.
// Make sure those are defined in your .env file.
const redis = new Redis({
url: process.env.UPSTASH_REDIS_REST_URL!,
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
});
// Required by `@upstash/qstash`.
export const config = { api: { bodyParser: false } };
// Update the usage of every user by pulling the data from the Redis database into the Prisma database.
async function handler(req: NextApiRequest, res: NextApiResponse) {
// Contains all the keys found during the `SCAN`.
const keys: string[] = [];
// Current position of the cursor, updated after each `SCAN`.
let cursor = 0;
// Execute the cursor-based pagination using the `SCAN` command.
// Redis return `0` when the cursor is at the end of the pagination.
do {
const [nextCursor, newKeys] = await redis.scan(cursor, {
// Match the pattern of the keys we want to find, where `*` is a wildcard.
match: "user:*:quota",
// Limit the number of keys returned by the `SCAN` command.
count: 10,
});
cursor = nextCursor;
keys.push(...newKeys);
} while (cursor !== 0);
// Array of objects containing the user's ID and their quota.
const users: { id: number; quota: number }[] = [];
// Get the usage of each user from Redis based on the keys found.
for (const key of keys) {
// A key should be in the format `user:${id}:quota`. Split the key to get the ID.
const id = key.split(":")[1];
// Get the current quota of the user using the `GET` command.
const quota = await redis.get(`user:${id}:quota`);
users.push({ id: parseInt(id, 10), quota });
}
// Create a transaction for each user to update their quota in the database.
const promises = users.map((user) =>
prisma.user.update({
where: { id: user.id },
data: { quota: user.quota },
}),
);
// Run all transactions.
await Promise.all(promises);
return res.status(200).json({ message: "OK" });
}
// Export the handler with the `verifySignature` function to make sure only
// QStash can authenticate to trigger the CRON job.
export default verifySignature(handler); ส่วนที่ยากที่สุดเสร็จแล้ว!
การตั้งค่า QStash
ตอนนี้ก่อนที่จะพุชโค้ดของเรา เราจำเป็นต้องตั้งค่า QStash QStash มอบระดับฟรีที่กว้างขวาง เราสามารถใช้คำขอได้มากถึง 500 คำขอ ต่อวัน .
เข้าสู่ระบบภายใน Upstash Console ของคุณแล้วคลิกที่ QStash แท็บ
จากนั้น เรามาสร้างงาน CRON ตามกำหนดการใหม่โดยใช้ ตัวสร้างคำขอ . มันง่ายมากด้วย UI ที่ใช้งานง่าย:

หลังจากคลิกที่กำหนดการ หากคุณเลื่อนลง คุณจะเห็นงาน CRON ของคุณใน งานที่กำหนดเวลาไว้ ส่วน:

ขั้นตอนสุดท้าย เราต้องตั้งค่าตัวแปรสภาพแวดล้อม 2 ตัว ในแอปพลิเคชัน Next.js ของเรา ตัวแปรเหล่านั้นจะถูกเพิ่มในตำแหน่งที่แอปพลิเคชัน Next.js ของเราโฮสต์อยู่ ในกรณีนี้คือบน Vercel
ใน ตัวสร้างคำขอ ส่วน มีตัวแปรสภาพแวดล้อม 2 ตัวที่พร้อมให้คัดลอก:
95รหัส>107รหัส>
สิ่งเหล่านี้จำเป็นในการตรวจสอบความถูกต้องของข้อความที่เข้ามา มิฉะนั้นใครก็ตามจะสามารถโทรหาตำแหน่งข้อมูลของคุณได้

เมื่อคุณมีตัวแปรเหล่านั้นแล้ว คุณสามารถเพิ่มลงในโปรเจ็กต์ Vercel ของคุณได้
ในการดำเนินการนี้ ไปที่โครงการ Vercel ของคุณ คลิกที่ การตั้งค่า จากนั้นไปที่ ตัวแปรสภาพแวดล้อม :

หลังจากเพิ่มตัวแปรสภาพแวดล้อม 2 ตัวแล้ว ตอนนี้คุณสามารถพุชโค้ดของคุณได้แล้ว
QStash จะทริกเกอร์ตำแหน่งข้อมูลงาน CRON เป็นระยะๆ และอัปเดตการใช้งานของผู้ใช้ทุกคนทุกชั่วโมง
บทสรุป
Upstash มีเครื่องมือมากมายสำหรับสภาพแวดล้อมแบบไร้เซิร์ฟเวอร์ เราสามารถใช้ QStash และ Redis ร่วมกันเพื่อสร้างแอปพลิเคชันที่มีประสิทธิภาพและปรับขนาดได้สำหรับกรณีการใช้งานต่างๆ มากมาย
หากคุณต้องการดูแบบสด ระบบเดียวกันนี้ได้ถูกนำมาใช้กับ fastsheet ซึ่งเป็นเครื่องมือที่จะเปลี่ยนสเปรดชีตของคุณให้เป็น API