mirror of
https://github.com/SrIzan10/hctv.git
synced 2026-06-06 00:56:56 +00:00
feat: bullmq poc
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -38,6 +38,7 @@ next-env.d.ts
|
||||
|
||||
certificates
|
||||
dev/psql
|
||||
dev/redis
|
||||
|
||||
.turbo
|
||||
packages/db/generated/client
|
||||
|
||||
@@ -32,11 +32,13 @@
|
||||
"@slack/web-api": "^7.9.1",
|
||||
"@uidotdev/usehooks": "^2.4.1",
|
||||
"arctic": "^3.1.1",
|
||||
"bullmq": "^5.45.2",
|
||||
"cheerio": "^1.0.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.0",
|
||||
"cmdk": "1.0.0",
|
||||
"hls-video-element": "^1.5.0",
|
||||
"ioredis": "^5.6.0",
|
||||
"livekit-client": "^2.8.0",
|
||||
"livekit-server-sdk": "^2.9.7",
|
||||
"lucia": "^3.2.2",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { validateRequest } from '@/lib/auth/validate';
|
||||
import { getPgBoss } from '@/lib/workers';
|
||||
import { getNotificationQueue } from '@/lib/workers';
|
||||
import { prisma } from '@hctv/db';
|
||||
import { NextRequest } from 'next/server';
|
||||
|
||||
@@ -42,7 +42,7 @@ export async function GET(request: NextRequest) {
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const { user } = await validateRequest();
|
||||
const boss = await getPgBoss();
|
||||
const queue = getNotificationQueue();
|
||||
const searchParams = new URL(request.url).searchParams;
|
||||
const username = searchParams.get('username');
|
||||
if (!user) {
|
||||
@@ -102,7 +102,7 @@ export async function POST(request: NextRequest) {
|
||||
},
|
||||
});
|
||||
|
||||
const jobId = await boss.send('notifier:sendMsg', {
|
||||
const jobId = await queue.add('notifier:sendMsg', {
|
||||
text: `You started following \`${username}\`!\n_Stream notifications are enabled by default. If you want to disable them, you can do so in \`Profile > Notifications\`._`,
|
||||
channel: user.slack_id,
|
||||
});
|
||||
|
||||
@@ -3,11 +3,8 @@ export async function register() {
|
||||
await (await import('@/lib/instrumentation/streamInfo')).default();
|
||||
}
|
||||
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
||||
const { getPgBoss } = await import('@/lib/workers');
|
||||
const { registerWorkers } = await import('@/lib/workers/register');
|
||||
|
||||
await getPgBoss();
|
||||
|
||||
await registerWorkers();
|
||||
|
||||
console.log('pgboss workers registered');
|
||||
|
||||
30
apps/web/src/lib/services/redis.ts
Normal file
30
apps/web/src/lib/services/redis.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import Redis from 'ioredis';
|
||||
|
||||
const createRedisConnection = () => {
|
||||
return new Redis(process.env.REDIS_URL || 'redis://localhost:6379', { maxRetriesPerRequest: null });
|
||||
};
|
||||
|
||||
const globalForQueue = global as unknown as {
|
||||
redisConnection: Redis | null;
|
||||
};
|
||||
|
||||
if (!globalForQueue.redisConnection) {
|
||||
globalForQueue.redisConnection = null;
|
||||
}
|
||||
|
||||
export function getRedisConnection(): Redis {
|
||||
if (!globalForQueue.redisConnection) {
|
||||
console.log('Creating new Redis connection...');
|
||||
globalForQueue.redisConnection = createRedisConnection();
|
||||
}
|
||||
return globalForQueue.redisConnection;
|
||||
}
|
||||
|
||||
export async function closeRedisConnection(): Promise<void> {
|
||||
// Close Redis connection
|
||||
if (globalForQueue.redisConnection) {
|
||||
await globalForQueue.redisConnection.quit();
|
||||
globalForQueue.redisConnection = null;
|
||||
console.log('Redis connection closed');
|
||||
}
|
||||
}
|
||||
@@ -1,112 +1,50 @@
|
||||
import type { ChatPostMessageArguments } from '@slack/web-api';
|
||||
import PgBoss from 'pg-boss';
|
||||
import { Queue, Worker } from 'bullmq';
|
||||
import { getRedisConnection } from '@/lib/services/redis';
|
||||
import snClient from '../services/slackNotifier';
|
||||
|
||||
export type JobName =
|
||||
| 'notifier:sendMsg';
|
||||
// Singleton instances for notifier
|
||||
const globalForNotifier = global as unknown as {
|
||||
notificationQueue: Queue | null;
|
||||
notificationWorker: Worker | null;
|
||||
};
|
||||
|
||||
export interface JobDefinitions {
|
||||
'notifier:sendMsg': {
|
||||
payload: ChatPostMessageArguments;
|
||||
result: {
|
||||
success: boolean;
|
||||
error?: string;
|
||||
};
|
||||
};
|
||||
// Initialize if they don't exist
|
||||
if (!globalForNotifier.notificationQueue) {
|
||||
globalForNotifier.notificationQueue = null;
|
||||
globalForNotifier.notificationWorker = null;
|
||||
}
|
||||
|
||||
export type PayloadFor<T extends JobName> = JobDefinitions[T]['payload'];
|
||||
export type ResultFor<T extends JobName> = JobDefinitions[T]['result'];
|
||||
|
||||
export class TypedPgBoss {
|
||||
private instance: PgBoss;
|
||||
|
||||
constructor(connectionString: string) {
|
||||
this.instance = new PgBoss(connectionString);
|
||||
}
|
||||
|
||||
async start(): Promise<PgBoss> {
|
||||
return this.instance.start();
|
||||
}
|
||||
|
||||
async stop(): Promise<void> {
|
||||
return this.instance.stop();
|
||||
}
|
||||
|
||||
async send<T extends JobName>(
|
||||
name: T,
|
||||
payload: PayloadFor<T>,
|
||||
options?: PgBoss.SendOptions
|
||||
): Promise<string | null> {
|
||||
await this.instance.createQueue(name);
|
||||
return this.instance.send(name, payload, options!);
|
||||
}
|
||||
|
||||
async schedule<T extends JobName>(
|
||||
name: T,
|
||||
payload: PayloadFor<T>,
|
||||
cron: string,
|
||||
options?: PgBoss.ScheduleOptions
|
||||
): Promise<void> {
|
||||
return this.instance.schedule(name, cron, payload, options);
|
||||
}
|
||||
|
||||
async work<T extends JobName>(
|
||||
name: T,
|
||||
handler: (job: PgBoss.Job<PayloadFor<T>>) => Promise<ResultFor<T>> | void,
|
||||
options?: PgBoss.WorkOptions
|
||||
): Promise<string> {
|
||||
const wrappedHandler: PgBoss.WorkHandler<unknown> = async (job: PgBoss.Job<unknown> | PgBoss.Job<unknown>[]) => {
|
||||
const singleJob = Array.isArray(job) ? job[0] : job;
|
||||
const processedJob = {...singleJob};
|
||||
if (Array.isArray(singleJob.data) && singleJob.data.length === 1) {
|
||||
processedJob.data = singleJob.data[0];
|
||||
// Get or create the notification queue
|
||||
export function getNotificationQueue(): Queue {
|
||||
if (!globalForNotifier.notificationQueue) {
|
||||
globalForNotifier.notificationQueue = new Queue('notifications', {
|
||||
connection: getRedisConnection(),
|
||||
defaultJobOptions: {
|
||||
attempts: 3,
|
||||
backoff: {
|
||||
type: 'exponential',
|
||||
delay: 5000,
|
||||
},
|
||||
}
|
||||
|
||||
return await handler(processedJob as PgBoss.Job<PayloadFor<T>>);
|
||||
};
|
||||
|
||||
return this.instance.work(name, options || {}, wrappedHandler);
|
||||
});
|
||||
}
|
||||
return globalForNotifier.notificationQueue;
|
||||
}
|
||||
|
||||
// Cleanup function for notification resources
|
||||
export async function closeNotificationResources(): Promise<void> {
|
||||
// Close worker
|
||||
if (globalForNotifier.notificationWorker) {
|
||||
await globalForNotifier.notificationWorker.close();
|
||||
globalForNotifier.notificationWorker = null;
|
||||
console.log('Notification worker closed');
|
||||
}
|
||||
|
||||
getInstance(): PgBoss {
|
||||
return this.instance;
|
||||
// Close queue
|
||||
if (globalForNotifier.notificationQueue) {
|
||||
await globalForNotifier.notificationQueue.close();
|
||||
globalForNotifier.notificationQueue = null;
|
||||
console.log('Notification queue closed');
|
||||
}
|
||||
}
|
||||
|
||||
const globalForPgBoss = global as unknown as { pgBoss: TypedPgBoss | null };
|
||||
|
||||
// Initialize if it doesn't exist yet
|
||||
if (!globalForPgBoss.pgBoss) {
|
||||
globalForPgBoss.pgBoss = null;
|
||||
}
|
||||
|
||||
// Get or create the singleton instance
|
||||
export async function getPgBoss(): Promise<TypedPgBoss> {
|
||||
if (!globalForPgBoss.pgBoss) {
|
||||
if (!process.env.DATABASE_URL) {
|
||||
throw new Error('DATABASE_URL environment variable is not set');
|
||||
}
|
||||
|
||||
console.log('Creating new PgBoss instance...');
|
||||
const newBoss = new TypedPgBoss(process.env.DATABASE_URL);
|
||||
|
||||
try {
|
||||
await newBoss.start();
|
||||
console.log('PgBoss started successfully');
|
||||
globalForPgBoss.pgBoss = newBoss;
|
||||
} catch (error) {
|
||||
console.error('Failed to start PgBoss:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
return globalForPgBoss.pgBoss;
|
||||
}
|
||||
|
||||
export async function closePgBoss(): Promise<void> {
|
||||
if (globalForPgBoss.pgBoss) {
|
||||
await globalForPgBoss.pgBoss.stop();
|
||||
globalForPgBoss.pgBoss = null;
|
||||
console.log('PgBoss stopped successfully');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,7 @@
|
||||
import { getPgBoss } from '@/lib/workers';
|
||||
import snClient from '../services/slackNotifier';
|
||||
import { registerNotificationWorker } from './worker/notification';
|
||||
|
||||
export async function registerWorkers() {
|
||||
const boss = await getPgBoss();
|
||||
|
||||
await boss.work('notifier:sendMsg', async (job) => {
|
||||
console.log('Processing job:', job.id);
|
||||
|
||||
await snClient.chat.postMessage(job.data).catch(e => {
|
||||
return { success: false, error: e.message };
|
||||
});
|
||||
return { success: true };
|
||||
});
|
||||
|
||||
// Register all workers in one place
|
||||
export async function registerWorkers(): Promise<void> {
|
||||
await registerNotificationWorker();
|
||||
console.log('All workers registered successfully');
|
||||
}
|
||||
63
apps/web/src/lib/workers/worker/notification.ts
Normal file
63
apps/web/src/lib/workers/worker/notification.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { Worker } from 'bullmq';
|
||||
import { getRedisConnection } from '@/lib/services/redis';
|
||||
import snClient from '@/lib/services/slackNotifier';
|
||||
|
||||
const globalForWorker = global as unknown as {
|
||||
notificationWorker: Worker | null;
|
||||
};
|
||||
|
||||
if (!globalForWorker.notificationWorker) {
|
||||
globalForWorker.notificationWorker = null;
|
||||
}
|
||||
|
||||
// Register the Slack notification worker
|
||||
export async function registerNotificationWorker(): Promise<void> {
|
||||
if (globalForWorker.notificationWorker) {
|
||||
console.log('Notification worker already registered');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Registering notification worker...');
|
||||
|
||||
const worker = new Worker('notifications', async (job) => {
|
||||
console.log('Processing job:', job.id);
|
||||
console.log('Job data:', job.data);
|
||||
|
||||
try {
|
||||
await snClient.chat.postMessage(job.data);
|
||||
return { success: true };
|
||||
} catch (e) {
|
||||
console.error('Slack notification failed:', e);
|
||||
// @ts-ignore e is unknown
|
||||
return { success: false, error: e.message };
|
||||
}
|
||||
}, {
|
||||
connection: getRedisConnection(),
|
||||
concurrency: 1,
|
||||
limiter: {
|
||||
max: 45,
|
||||
duration: 60000
|
||||
}
|
||||
});
|
||||
|
||||
// Set up event handlers
|
||||
worker.on('completed', job => {
|
||||
console.log(`Job ${job.id} completed successfully`);
|
||||
});
|
||||
|
||||
worker.on('failed', (job, error) => {
|
||||
console.error(`Job ${job?.id} failed:`, error);
|
||||
});
|
||||
|
||||
globalForWorker.notificationWorker = worker;
|
||||
console.log('Notification worker registered successfully');
|
||||
}
|
||||
|
||||
// Close the worker
|
||||
export async function closeNotificationWorker(): Promise<void> {
|
||||
if (globalForWorker.notificationWorker) {
|
||||
await globalForWorker.notificationWorker.close();
|
||||
globalForWorker.notificationWorker = null;
|
||||
console.log('Notification worker closed');
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,12 @@ services:
|
||||
- ./psql:/var/lib/postgresql/data
|
||||
ports:
|
||||
- 5555:5432
|
||||
redis:
|
||||
image: redis:7.4-alpine
|
||||
volumes:
|
||||
- ./redis:/data
|
||||
ports:
|
||||
- 6379:6379
|
||||
nginx-rtmp:
|
||||
# ports:
|
||||
# - 1935:1935
|
||||
|
||||
142
yarn.lock
142
yarn.lock
@@ -604,6 +604,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz#56f00962ff0c4e0eb93d34a047d29fa995e3e342"
|
||||
integrity sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==
|
||||
|
||||
"@ioredis/commands@^1.1.1":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11"
|
||||
integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==
|
||||
|
||||
"@isaacs/cliui@^8.0.2":
|
||||
version "8.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
|
||||
@@ -690,6 +695,36 @@
|
||||
resolved "https://registry.yarnpkg.com/@lucia-auth/adapter-prisma/-/adapter-prisma-4.0.1.tgz#8f8aa95bf0ac266fd2fb8ac3dc6dd9faec53342f"
|
||||
integrity sha512-3SztRhj1RAHbbhI/0aB7YC5zl6Z6aktPhkWpn2CHhiB03B9x/+A+M6pqJuAt1usU8PzkjVilgRPhrPymMar66A==
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz#9edec61b22c3082018a79f6d1c30289ddf3d9d11"
|
||||
integrity sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz#33677a275204898ad8acbf62734fc4dc0b6a4855"
|
||||
integrity sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz#19edf7cdc2e7063ee328403c1d895a86dd28f4bb"
|
||||
integrity sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz#94fb0543ba2e28766c3fc439cabbe0440ae70159"
|
||||
integrity sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz#4a0609ab5fe44d07c9c60a11e4484d3c38bbd6e3"
|
||||
integrity sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz#0aa5502d547b57abfc4ac492de68e2006e417242"
|
||||
integrity sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==
|
||||
|
||||
"@napi-rs/wasm-runtime@^0.2.5", "@napi-rs/wasm-runtime@^0.2.7":
|
||||
version "0.2.7"
|
||||
resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.7.tgz#288f03812a408bc53c2c3686c65f38fe90f295eb"
|
||||
@@ -2109,6 +2144,19 @@ buffer@^6.0.3:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.2.1"
|
||||
|
||||
bullmq@^5.45.2:
|
||||
version "5.45.2"
|
||||
resolved "https://registry.yarnpkg.com/bullmq/-/bullmq-5.45.2.tgz#88e19db218e5f7eceb5885ffac9334c87586701a"
|
||||
integrity sha512-wHZfcD4z4aLolxREmwNNDSbfh7USeq2e3yu5W2VGkzHMUcrH0fzZuRuCMsjD0XKS9ViK1U854oM9yWR6ftPeDA==
|
||||
dependencies:
|
||||
cron-parser "^4.9.0"
|
||||
ioredis "^5.4.1"
|
||||
msgpackr "^1.11.2"
|
||||
node-abort-controller "^3.1.1"
|
||||
semver "^7.5.4"
|
||||
tslib "^2.0.0"
|
||||
uuid "^9.0.0"
|
||||
|
||||
bundle-require@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/bundle-require/-/bundle-require-5.1.0.tgz#8db66f41950da3d77af1ef3322f4c3e04009faee"
|
||||
@@ -2287,6 +2335,11 @@ clsx@2.1.1, clsx@^2.1.0, clsx@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
|
||||
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
|
||||
|
||||
cluster-key-slot@^1.1.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac"
|
||||
integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==
|
||||
|
||||
cmdk@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cmdk/-/cmdk-1.0.0.tgz#0a095fdafca3dfabed82d1db78a6262fb163ded9"
|
||||
@@ -2508,12 +2561,17 @@ delayed-stream@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
|
||||
|
||||
denque@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1"
|
||||
integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==
|
||||
|
||||
dequal@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
|
||||
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
|
||||
|
||||
detect-libc@^2.0.3:
|
||||
detect-libc@^2.0.1, detect-libc@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700"
|
||||
integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==
|
||||
@@ -3492,6 +3550,21 @@ internal-slot@^1.1.0:
|
||||
hasown "^2.0.2"
|
||||
side-channel "^1.1.0"
|
||||
|
||||
ioredis@^5.4.1, ioredis@^5.6.0:
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.6.0.tgz#faa2a27132f8a05c0ddfef400b01d1326df211a0"
|
||||
integrity sha512-tBZlIIWbndeWBWCXWZiqtOF/yxf6yZX3tAlTJ7nfo5jhd6dctNxF7QnYlZLZ1a0o0pDoen7CgZqO+zjNaFbJAg==
|
||||
dependencies:
|
||||
"@ioredis/commands" "^1.1.1"
|
||||
cluster-key-slot "^1.1.0"
|
||||
debug "^4.3.4"
|
||||
denque "^2.1.0"
|
||||
lodash.defaults "^4.2.0"
|
||||
lodash.isarguments "^3.1.0"
|
||||
redis-errors "^1.2.0"
|
||||
redis-parser "^3.0.0"
|
||||
standard-as-callback "^2.1.0"
|
||||
|
||||
is-array-buffer@^3.0.4, is-array-buffer@^3.0.5:
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280"
|
||||
@@ -3941,6 +4014,16 @@ lodash.debounce@^4.0.8:
|
||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
|
||||
|
||||
lodash.defaults@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
|
||||
integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==
|
||||
|
||||
lodash.isarguments@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
|
||||
integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==
|
||||
|
||||
lodash.merge@^4.6.2:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
@@ -4109,6 +4192,27 @@ ms@^2.1.1, ms@^2.1.3:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
msgpackr-extract@^3.0.2:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz#e9d87023de39ce714872f9e9504e3c1996d61012"
|
||||
integrity sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==
|
||||
dependencies:
|
||||
node-gyp-build-optional-packages "5.2.2"
|
||||
optionalDependencies:
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-arm64" "3.0.3"
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-x64" "3.0.3"
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm" "3.0.3"
|
||||
"@msgpackr-extract/msgpackr-extract-linux-arm64" "3.0.3"
|
||||
"@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.3"
|
||||
"@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.3"
|
||||
|
||||
msgpackr@^1.11.2:
|
||||
version "1.11.2"
|
||||
resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.11.2.tgz#4463b7f7d68f2e24865c395664973562ad24473d"
|
||||
integrity sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==
|
||||
optionalDependencies:
|
||||
msgpackr-extract "^3.0.2"
|
||||
|
||||
mz@^2.7.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
|
||||
@@ -4156,6 +4260,11 @@ next@^15.2.3:
|
||||
"@next/swc-win32-x64-msvc" "15.2.3"
|
||||
sharp "^0.33.5"
|
||||
|
||||
node-abort-controller@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548"
|
||||
integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==
|
||||
|
||||
node-domexception@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
|
||||
@@ -4170,6 +4279,13 @@ node-fetch@^3.3.0:
|
||||
fetch-blob "^3.1.4"
|
||||
formdata-polyfill "^4.0.10"
|
||||
|
||||
node-gyp-build-optional-packages@5.2.2:
|
||||
version "5.2.2"
|
||||
resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz#522f50c2d53134d7f3a76cd7255de4ab6c96a3a4"
|
||||
integrity sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==
|
||||
dependencies:
|
||||
detect-libc "^2.0.1"
|
||||
|
||||
node-releases@^2.0.19:
|
||||
version "2.0.19"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314"
|
||||
@@ -4793,6 +4909,18 @@ recast@^0.23.2:
|
||||
tiny-invariant "^1.3.3"
|
||||
tslib "^2.0.1"
|
||||
|
||||
redis-errors@^1.0.0, redis-errors@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad"
|
||||
integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==
|
||||
|
||||
redis-parser@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4"
|
||||
integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==
|
||||
dependencies:
|
||||
redis-errors "^1.0.0"
|
||||
|
||||
reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9"
|
||||
@@ -5006,7 +5134,7 @@ semver@^6.3.1:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||
|
||||
semver@^7.6.0, semver@^7.6.3:
|
||||
semver@^7.5.4, semver@^7.6.0, semver@^7.6.3:
|
||||
version "7.7.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f"
|
||||
integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
|
||||
@@ -5212,6 +5340,11 @@ stable-hash@^0.0.5:
|
||||
resolved "https://registry.yarnpkg.com/stable-hash/-/stable-hash-0.0.5.tgz#94e8837aaeac5b4d0f631d2972adef2924b40269"
|
||||
integrity sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==
|
||||
|
||||
standard-as-callback@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45"
|
||||
integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==
|
||||
|
||||
stdin-discarder@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz#22b3e400393a8e28ebf53f9958f3880622efde21"
|
||||
@@ -5782,6 +5915,11 @@ util-utils@^1.0.3:
|
||||
resolved "https://registry.yarnpkg.com/util-utils/-/util-utils-1.0.3.tgz#abde6c79d373eb7fae42f28933273eab6d895dd3"
|
||||
integrity sha512-KXQzb5Y1cmQOubnYn2TMSJDwX+cLrFNi3CRp0bm+yTUdR4tV4LDkk2RAzGSweucwvTdhuoDdZrY67ds7QDRYXQ==
|
||||
|
||||
uuid@^9.0.0:
|
||||
version "9.0.1"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30"
|
||||
integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==
|
||||
|
||||
valtio@^2.1.2:
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/valtio/-/valtio-2.1.4.tgz#6f0978b1d6a0a5eed70a1c55981a80c7e2b6e76a"
|
||||
|
||||
Reference in New Issue
Block a user