mirror of
https://github.com/Drop-OSS/drop.git
synced 2025-11-09 20:12:10 +10:00
Merge branch 'Huskydog9988-more-stuff' into develop
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="hidden lg:flex bg-zinc-950 flex-row px-12 xl:px-48 py-5">
|
<div class="hidden lg:flex bg-zinc-950 flex-row px-12 xl:px-48 py-5">
|
||||||
<div class="grow inline-flex items-center gap-x-20">
|
<div class="grow inline-flex items-center gap-x-20">
|
||||||
<NuxtLink to="/store">
|
<NuxtLink :to="homepageURL">
|
||||||
<DropWordmark class="h-8" />
|
<DropWordmark class="h-8" />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<nav class="inline-flex items-center">
|
<nav class="inline-flex items-center">
|
||||||
@ -62,7 +62,10 @@
|
|||||||
<div
|
<div
|
||||||
class="sticky lg:hidden top-0 z-40 flex h-16 justify-between items-center gap-x-4 border-b border-zinc-700 bg-zinc-950 px-4 shadow-sm sm:gap-x-6 sm:px-6 lg:px-8"
|
class="sticky lg:hidden top-0 z-40 flex h-16 justify-between items-center gap-x-4 border-b border-zinc-700 bg-zinc-950 px-4 shadow-sm sm:gap-x-6 sm:px-6 lg:px-8"
|
||||||
>
|
>
|
||||||
|
<NuxtLink :to="homepageURL">
|
||||||
<DropWordmark class="mb-0.5" />
|
<DropWordmark class="mb-0.5" />
|
||||||
|
</NuxtLink>
|
||||||
|
|
||||||
<div class="flex gap-x-4 lg:gap-x-6">
|
<div class="flex gap-x-4 lg:gap-x-6">
|
||||||
<div class="flex items-center gap-x-3">
|
<div class="flex items-center gap-x-3">
|
||||||
<!-- Profile dropdown -->
|
<!-- Profile dropdown -->
|
||||||
@ -132,7 +135,7 @@
|
|||||||
class="flex grow flex-col gap-y-5 overflow-y-auto bg-zinc-950 px-6 pb-4"
|
class="flex grow flex-col gap-y-5 overflow-y-auto bg-zinc-950 px-6 pb-4"
|
||||||
>
|
>
|
||||||
<div class="flex shrink-0 h-16 items-center justify-between">
|
<div class="flex shrink-0 h-16 items-center justify-between">
|
||||||
<NuxtLink to="/store">
|
<NuxtLink :to="homepageURL">
|
||||||
<DropLogo class="h-8 w-auto" />
|
<DropLogo class="h-8 w-auto" />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
||||||
@ -180,7 +183,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { BellIcon, UserGroupIcon } from "@heroicons/vue/16/solid";
|
import {
|
||||||
|
BellIcon,
|
||||||
|
UserGroupIcon,
|
||||||
|
ArrowDownTrayIcon,
|
||||||
|
} from "@heroicons/vue/16/solid";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogPanel,
|
DialogPanel,
|
||||||
@ -196,6 +203,7 @@ import { XMarkIcon } from "@heroicons/vue/24/solid";
|
|||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
const homepageURL = "/store";
|
||||||
const navigation: Array<NavigationItem> = [
|
const navigation: Array<NavigationItem> = [
|
||||||
{
|
{
|
||||||
prefix: "/store",
|
prefix: "/store",
|
||||||
|
|||||||
@ -9,7 +9,8 @@ export default defineNuxtConfig({
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
telemetry: false,
|
telemetry: false,
|
||||||
timeline: {
|
timeline: {
|
||||||
// seems to break things
|
// this seems to be the tracking issue, composables not registered
|
||||||
|
// https://github.com/nuxt/devtools/issues/662
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -47,6 +48,20 @@ export default defineNuxtConfig({
|
|||||||
},
|
},
|
||||||
|
|
||||||
compressPublicAssets: true,
|
compressPublicAssets: true,
|
||||||
|
|
||||||
|
storage: {
|
||||||
|
appCache: {
|
||||||
|
driver: "lru-cache",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
devStorage: {
|
||||||
|
appCache: {
|
||||||
|
// store cache on fs to handle dev server restarts
|
||||||
|
driver: "fs",
|
||||||
|
base: "./.data/appCache",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
typescript: {
|
typescript: {
|
||||||
|
|||||||
@ -31,7 +31,6 @@
|
|||||||
"fast-fuzzy": "^1.12.0",
|
"fast-fuzzy": "^1.12.0",
|
||||||
"file-type-mime": "^0.4.3",
|
"file-type-mime": "^0.4.3",
|
||||||
"jdenticon": "^3.3.0",
|
"jdenticon": "^3.3.0",
|
||||||
"lru-cache": "^11.1.0",
|
|
||||||
"luxon": "^3.6.1",
|
"luxon": "^3.6.1",
|
||||||
"micromark": "^4.0.1",
|
"micromark": "^4.0.1",
|
||||||
"nuxt": "^3.16.2",
|
"nuxt": "^3.16.2",
|
||||||
@ -40,6 +39,7 @@
|
|||||||
"sharp": "^0.33.5",
|
"sharp": "^0.33.5",
|
||||||
"stream-mime-type": "^2.0.0",
|
"stream-mime-type": "^2.0.0",
|
||||||
"turndown": "^7.2.0",
|
"turndown": "^7.2.0",
|
||||||
|
"unstorage": "^1.15.0",
|
||||||
"vue": "latest",
|
"vue": "latest",
|
||||||
"vue-router": "latest",
|
"vue-router": "latest",
|
||||||
"vue3-carousel": "^0.15.0",
|
"vue3-carousel": "^0.15.0",
|
||||||
@ -75,4 +75,4 @@
|
|||||||
"prisma": {
|
"prisma": {
|
||||||
"schema": "./prisma"
|
"schema": "./prisma"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
generator client {
|
generator client {
|
||||||
provider = "prisma-client-js"
|
provider = "prisma-client-js"
|
||||||
previewFeatures = ["prismaSchemaFolder", "omitApi", "fullTextSearchPostgres"]
|
previewFeatures = ["prismaSchemaFolder", "fullTextSearchPostgres"]
|
||||||
}
|
}
|
||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import notificationSystem from "~/server/internal/notifications";
|
import notificationSystem from "~/server/internal/notifications";
|
||||||
import aclManager from "~/server/internal/acls";
|
import aclManager from "~/server/internal/acls";
|
||||||
|
import cacheHandler from "~/server/internal/cache";
|
||||||
|
|
||||||
// TODO add web socket sessions for horizontal scaling
|
|
||||||
// Peer ID to user ID
|
// Peer ID to user ID
|
||||||
const socketSessions = new Map<string, string>();
|
const socketSessions = cacheHandler.createCache<string>("notificationSocketSessions");
|
||||||
|
|
||||||
export default defineWebSocketHandler({
|
export default defineWebSocketHandler({
|
||||||
async open(peer) {
|
async open(peer) {
|
||||||
@ -23,7 +23,7 @@ export default defineWebSocketHandler({
|
|||||||
userIds.push("system");
|
userIds.push("system");
|
||||||
}
|
}
|
||||||
|
|
||||||
socketSessions.set(peer.id, userId);
|
await socketSessions.set(peer.id, userId);
|
||||||
|
|
||||||
for (const listenUserId of userIds) {
|
for (const listenUserId of userIds) {
|
||||||
notificationSystem.listen(listenUserId, peer.id, (notification) => {
|
notificationSystem.listen(listenUserId, peer.id, (notification) => {
|
||||||
@ -32,7 +32,7 @@ export default defineWebSocketHandler({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async close(peer, _details) {
|
async close(peer, _details) {
|
||||||
const userId = socketSessions.get(peer.id);
|
const userId = await socketSessions.get(peer.id);
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
console.log(`skipping websocket close for ${peer.id}`);
|
console.log(`skipping websocket close for ${peer.id}`);
|
||||||
return;
|
return;
|
||||||
@ -40,6 +40,6 @@ export default defineWebSocketHandler({
|
|||||||
|
|
||||||
notificationSystem.unlisten(userId, peer.id);
|
notificationSystem.unlisten(userId, peer.id);
|
||||||
notificationSystem.unlisten("system", peer.id); // In case we were listening as 'system'
|
notificationSystem.unlisten("system", peer.id); // In case we were listening as 'system'
|
||||||
socketSessions.delete(peer.id);
|
await socketSessions.remove(peer.id);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import taskHandler from "~/server/internal/tasks";
|
import taskHandler from "~/server/internal/tasks";
|
||||||
import type { MinimumRequestObject } from "~/server/h3";
|
import type { MinimumRequestObject } from "~/server/h3";
|
||||||
|
import cacheHandler from "~/server/internal/cache";
|
||||||
|
|
||||||
// TODO add web socket sessions for horizontal scaling
|
|
||||||
// ID to admin
|
// ID to admin
|
||||||
const socketHeaders = new Map<string, MinimumRequestObject>();
|
const socketHeaders = cacheHandler.createCache<MinimumRequestObject>("taskSocketHeaders");
|
||||||
|
|
||||||
export default defineWebSocketHandler({
|
export default defineWebSocketHandler({
|
||||||
async open(peer) {
|
async open(peer) {
|
||||||
@ -13,15 +13,15 @@ export default defineWebSocketHandler({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
socketHeaders.set(peer.id, {
|
await socketHeaders.set(peer.id, {
|
||||||
headers: request.headers ?? new Headers(),
|
headers: request.headers ?? new Headers(),
|
||||||
});
|
});
|
||||||
peer.send(`connect`);
|
peer.send(`connect`);
|
||||||
},
|
},
|
||||||
message(peer, message) {
|
async message(peer, message) {
|
||||||
if (!peer.id) return;
|
if (!peer.id) return;
|
||||||
const headers = socketHeaders.get(peer.id);
|
const headers = await socketHeaders.get(peer.id);
|
||||||
if (headers === undefined) return;
|
if (!headers) return;
|
||||||
const text = message.text();
|
const text = message.text();
|
||||||
if (text.startsWith("connect/")) {
|
if (text.startsWith("connect/")) {
|
||||||
const id = text.substring("connect/".length);
|
const id = text.substring("connect/".length);
|
||||||
@ -29,10 +29,10 @@ export default defineWebSocketHandler({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
close(peer, _details) {
|
async close(peer, _details) {
|
||||||
if (!peer.id) return;
|
if (!peer.id) return;
|
||||||
if (!socketHeaders.has(peer.id)) return;
|
if (!socketHeaders.has(peer.id)) return;
|
||||||
socketHeaders.delete(peer.id);
|
await socketHeaders.remove(peer.id);
|
||||||
|
|
||||||
taskHandler.disconnectAll(peer.id);
|
taskHandler.disconnectAll(peer.id);
|
||||||
},
|
},
|
||||||
|
|||||||
33
server/internal/cache/cacheHandler.ts
vendored
Normal file
33
server/internal/cache/cacheHandler.ts
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { prefixStorage, type StorageValue, type Storage } from "unstorage";
|
||||||
|
|
||||||
|
export interface CacheProviderOptions {
|
||||||
|
/**
|
||||||
|
* Max number of items in the cache
|
||||||
|
*/
|
||||||
|
max?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time to live (in ms)
|
||||||
|
*/
|
||||||
|
ttl?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and manages the lifecycles of various caches
|
||||||
|
*/
|
||||||
|
export class CacheHandler {
|
||||||
|
private caches = new Map<string, Storage<StorageValue>>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new cache
|
||||||
|
* @param name
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
createCache<V extends StorageValue>(name: string) {
|
||||||
|
// will allow us to dynamicing use redis in the future just by changing the storage used
|
||||||
|
const provider = prefixStorage<V>(useStorage<V>("appCache"), name);
|
||||||
|
// hack to let ts have us store cache
|
||||||
|
this.caches.set(name, provider as unknown as Storage<StorageValue>);
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
}
|
||||||
4
server/internal/cache/index.ts
vendored
Normal file
4
server/internal/cache/index.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { CacheHandler } from "./cacheHandler";
|
||||||
|
|
||||||
|
export const cacheHandler = new CacheHandler();
|
||||||
|
export default cacheHandler;
|
||||||
@ -1,12 +1,12 @@
|
|||||||
import type { ObjectMetadata, ObjectReference, Source } from "./objectHandler";
|
import type { ObjectMetadata, ObjectReference, Source } from "./objectHandler";
|
||||||
import { ObjectBackend } from "./objectHandler";
|
import { ObjectBackend } from "./objectHandler";
|
||||||
|
|
||||||
import { LRUCache } from "lru-cache";
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { Readable } from "stream";
|
import { Readable } from "stream";
|
||||||
import { createHash } from "crypto";
|
import { createHash } from "crypto";
|
||||||
import prisma from "../db/database";
|
import prisma from "../db/database";
|
||||||
|
import cacheHandler from "../cache";
|
||||||
|
|
||||||
export class FsObjectBackend extends ObjectBackend {
|
export class FsObjectBackend extends ObjectBackend {
|
||||||
private baseObjectPath: string;
|
private baseObjectPath: string;
|
||||||
@ -34,7 +34,7 @@ export class FsObjectBackend extends ObjectBackend {
|
|||||||
if (!fs.existsSync(objectPath)) return false;
|
if (!fs.existsSync(objectPath)) return false;
|
||||||
|
|
||||||
// remove item from cache
|
// remove item from cache
|
||||||
this.hashStore.delete(id);
|
await this.hashStore.delete(id);
|
||||||
|
|
||||||
if (source instanceof Readable) {
|
if (source instanceof Readable) {
|
||||||
const outputStream = fs.createWriteStream(objectPath);
|
const outputStream = fs.createWriteStream(objectPath);
|
||||||
@ -54,7 +54,7 @@ export class FsObjectBackend extends ObjectBackend {
|
|||||||
const objectPath = path.join(this.baseObjectPath, id);
|
const objectPath = path.join(this.baseObjectPath, id);
|
||||||
if (!fs.existsSync(objectPath)) return undefined;
|
if (!fs.existsSync(objectPath)) return undefined;
|
||||||
// remove item from cache
|
// remove item from cache
|
||||||
this.hashStore.delete(id);
|
await this.hashStore.delete(id);
|
||||||
return fs.createWriteStream(objectPath);
|
return fs.createWriteStream(objectPath);
|
||||||
}
|
}
|
||||||
async create(
|
async create(
|
||||||
@ -99,7 +99,7 @@ export class FsObjectBackend extends ObjectBackend {
|
|||||||
if (!fs.existsSync(objectPath)) return true;
|
if (!fs.existsSync(objectPath)) return true;
|
||||||
fs.rmSync(objectPath);
|
fs.rmSync(objectPath);
|
||||||
// remove item from cache
|
// remove item from cache
|
||||||
this.hashStore.delete(id);
|
await this.hashStore.delete(id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
async fetchMetadata(
|
async fetchMetadata(
|
||||||
@ -121,36 +121,41 @@ export class FsObjectBackend extends ObjectBackend {
|
|||||||
}
|
}
|
||||||
async fetchHash(id: ObjectReference): Promise<string | undefined> {
|
async fetchHash(id: ObjectReference): Promise<string | undefined> {
|
||||||
const cacheResult = await this.hashStore.get(id);
|
const cacheResult = await this.hashStore.get(id);
|
||||||
if (cacheResult !== undefined) return cacheResult;
|
if (cacheResult !== null) return cacheResult;
|
||||||
|
|
||||||
const obj = await this.fetch(id);
|
const obj = await this.fetch(id);
|
||||||
if (obj === undefined) return;
|
if (obj === undefined) return;
|
||||||
|
|
||||||
// local variable to point to object
|
|
||||||
const cache = this.hashStore;
|
|
||||||
|
|
||||||
// hash object
|
// hash object
|
||||||
const hash = createHash("md5");
|
const hash = createHash("md5");
|
||||||
hash.setEncoding("hex");
|
hash.setEncoding("hex");
|
||||||
|
|
||||||
// read obj into hash
|
// local variable to point to object
|
||||||
obj.pipe(hash);
|
const store = this.hashStore;
|
||||||
await new Promise<void>((r) => {
|
let hashResult = "";
|
||||||
obj.on("end", function () {
|
|
||||||
|
const objEnd = new Promise<void>((r) => {
|
||||||
|
obj.on("end", async function () {
|
||||||
hash.end();
|
hash.end();
|
||||||
cache.save(id, hash.read());
|
hashResult = hash.read();
|
||||||
r();
|
r();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// read obj into hash
|
||||||
|
obj.pipe(hash);
|
||||||
|
await objEnd;
|
||||||
|
|
||||||
return await this.hashStore.get(id);
|
// if hash isn't a string somehow, mark as unknown hash
|
||||||
|
if (typeof hashResult !== "string") {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
await store.save(id, hashResult);
|
||||||
|
return typeof hashResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FsHashStore {
|
class FsHashStore {
|
||||||
private cache = new LRUCache<string, string>({
|
private cache = cacheHandler.createCache<string>("ObjectHashStore");
|
||||||
max: 1000, // number of items
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets hash of object
|
* Gets hash of object
|
||||||
@ -158,8 +163,10 @@ class FsHashStore {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async get(id: ObjectReference) {
|
async get(id: ObjectReference) {
|
||||||
const cacheRes = this.cache.get(id);
|
const cacheRes = await this.cache.get(id);
|
||||||
if (cacheRes !== undefined) return cacheRes;
|
if (cacheRes !== null) {
|
||||||
|
return cacheRes;
|
||||||
|
}
|
||||||
|
|
||||||
const objectHash = await prisma.objectHash.findUnique({
|
const objectHash = await prisma.objectHash.findUnique({
|
||||||
where: {
|
where: {
|
||||||
@ -170,7 +177,7 @@ class FsHashStore {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (objectHash === null) return undefined;
|
if (objectHash === null) return undefined;
|
||||||
this.cache.set(id, objectHash.hash);
|
await this.cache.set(id, objectHash.hash);
|
||||||
return objectHash.hash;
|
return objectHash.hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +198,7 @@ class FsHashStore {
|
|||||||
hash,
|
hash,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.cache.set(id, hash);
|
await this.cache.set(id, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -199,7 +206,7 @@ class FsHashStore {
|
|||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
async delete(id: ObjectReference) {
|
async delete(id: ObjectReference) {
|
||||||
this.cache.delete(id);
|
await this.cache.remove(id);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// need to catch in case the object doesn't exist
|
// need to catch in case the object doesn't exist
|
||||||
|
|||||||
@ -1,16 +1,13 @@
|
|||||||
import { LRUCache } from "lru-cache";
|
|
||||||
import prisma from "../db/database";
|
import prisma from "../db/database";
|
||||||
import type { Session, SessionProvider } from "./types";
|
import type { Session, SessionProvider } from "./types";
|
||||||
|
import cacheHandler from "../cache";
|
||||||
|
|
||||||
export default function createDBSessionHandler(): SessionProvider {
|
export default function createDBSessionHandler(): SessionProvider {
|
||||||
const cache = new LRUCache<string, Session>({
|
const cache = cacheHandler.createCache<Session>("DBSession");
|
||||||
max: 50, // number of items
|
|
||||||
ttl: 30 * 100, // 30s (in ms)
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
async setSession(token, session) {
|
async setSession(token, session) {
|
||||||
cache.set(token, session);
|
await cache.set(token, session);
|
||||||
|
|
||||||
// const strData = JSON.stringify(data);
|
// const strData = JSON.stringify(data);
|
||||||
await prisma.session.upsert({
|
await prisma.session.upsert({
|
||||||
@ -29,8 +26,8 @@ export default function createDBSessionHandler(): SessionProvider {
|
|||||||
return await this.setSession(token, data);
|
return await this.setSession(token, data);
|
||||||
},
|
},
|
||||||
async getSession<T extends Session>(token: string) {
|
async getSession<T extends Session>(token: string) {
|
||||||
const cached = cache.get(token);
|
const cached = await cache.get(token);
|
||||||
if (cached !== undefined) return cached as T;
|
if (cached !== null) return cached as T;
|
||||||
|
|
||||||
const result = await prisma.session.findUnique({
|
const result = await prisma.session.findUnique({
|
||||||
where: {
|
where: {
|
||||||
@ -45,7 +42,7 @@ export default function createDBSessionHandler(): SessionProvider {
|
|||||||
return result as unknown as T;
|
return result as unknown as T;
|
||||||
},
|
},
|
||||||
async removeSession(token) {
|
async removeSession(token) {
|
||||||
cache.delete(token);
|
await cache.remove(token);
|
||||||
await prisma.session.delete({
|
await prisma.session.delete({
|
||||||
where: {
|
where: {
|
||||||
token,
|
token,
|
||||||
|
|||||||
@ -2,15 +2,17 @@
|
|||||||
Handles managing collections
|
Handles managing collections
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import cacheHandler from "../cache";
|
||||||
import prisma from "../db/database";
|
import prisma from "../db/database";
|
||||||
|
|
||||||
class UserLibraryManager {
|
class UserLibraryManager {
|
||||||
// Caches the user's core library
|
// Caches the user's core library
|
||||||
private userCoreLibraryCache: { [key: string]: string } = {};
|
private coreLibraryCache =
|
||||||
|
cacheHandler.createCache<string>("UserCoreLibrary");
|
||||||
|
|
||||||
private async fetchUserLibrary(userId: string) {
|
private async fetchUserLibrary(userId: string) {
|
||||||
if (this.userCoreLibraryCache[userId])
|
const cached = await this.coreLibraryCache.get(userId);
|
||||||
return this.userCoreLibraryCache[userId];
|
if (cached !== null) return cached;
|
||||||
|
|
||||||
let collection = await prisma.collection.findFirst({
|
let collection = await prisma.collection.findFirst({
|
||||||
where: {
|
where: {
|
||||||
@ -28,7 +30,7 @@ class UserLibraryManager {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.userCoreLibraryCache[userId] = collection.id;
|
await this.coreLibraryCache.set(userId, collection.id);
|
||||||
|
|
||||||
return collection.id;
|
return collection.id;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import prisma from "../internal/db/database";
|
import prisma from "~/server/internal/db/database";
|
||||||
|
|
||||||
export default defineNitroPlugin(async (_nitro) => {
|
export default defineNitroPlugin(async (_nitro) => {
|
||||||
// Ensure system user exists
|
// Ensure system user exists
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import prisma from "../internal/db/database";
|
import prisma from "~/server/internal/db/database";
|
||||||
|
|
||||||
export default defineNitroPlugin(async (_nitro) => {
|
export default defineNitroPlugin(async (_nitro) => {
|
||||||
const userCount = await prisma.user.count({
|
const userCount = await prisma.user.count({
|
||||||
7
server/plugins/tasks.ts
Normal file
7
server/plugins/tasks.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export default defineNitroPlugin(async (_nitro) => {
|
||||||
|
// all tasks we should run on server boot
|
||||||
|
await Promise.all([
|
||||||
|
runTask("cleanup:invitations"),
|
||||||
|
runTask("cleanup:sessions"),
|
||||||
|
]);
|
||||||
|
});
|
||||||
@ -5,6 +5,8 @@ export default defineTask({
|
|||||||
name: "cleanup:invitations",
|
name: "cleanup:invitations",
|
||||||
},
|
},
|
||||||
async run() {
|
async run() {
|
||||||
|
console.log("[Task cleanup:invitations]: Cleaning invitations");
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
await prisma.invitation.deleteMany({
|
await prisma.invitation.deleteMany({
|
||||||
@ -15,6 +17,7 @@ export default defineTask({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log("[Task cleanup:invitations]: Done");
|
||||||
return { result: true };
|
return { result: true };
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,11 +2,12 @@ import sessionHandler from "~/server/internal/session";
|
|||||||
|
|
||||||
export default defineTask({
|
export default defineTask({
|
||||||
meta: {
|
meta: {
|
||||||
name: "cleanup:invitations",
|
name: "cleanup:sessions",
|
||||||
},
|
},
|
||||||
async run() {
|
async run() {
|
||||||
|
console.log("[Task cleanup:sessions]: Cleaning up sessions");
|
||||||
await sessionHandler.cleanupSessions();
|
await sessionHandler.cleanupSessions();
|
||||||
|
console.log("[Task cleanup:sessions]: Done");
|
||||||
return { result: true };
|
return { result: true };
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user