feat: enhance API and query handling with Redis caching; add QueryGuard for query validation; refactor services to utilize RedisClient for improved performance
This commit is contained in:
@ -11,6 +11,7 @@ import { Response } from "express";
|
||||
import { QueryHandlerService } from "../handler/query.handler.service";
|
||||
import { ApiTokenGuard } from "src/api/guards/api-token.guard";
|
||||
import { QueryExecuterService } from "../executer/query.executer.service";
|
||||
import { QueryGuard } from "src/api/guards/query.guard";
|
||||
|
||||
@UseGuards(ApiTokenGuard)
|
||||
export abstract class BaseQueryController {
|
||||
@ -31,22 +32,24 @@ export abstract class BaseQueryController {
|
||||
}
|
||||
|
||||
@Post("update/:id")
|
||||
@UseGuards(QueryGuard)
|
||||
async updateQuery(
|
||||
@Body() updateData: Partial<{ source: string }>,
|
||||
@Inject("id") id: string
|
||||
@Param("id") id: string
|
||||
) {
|
||||
return this.queryHandlerService.updateQuery(id, updateData);
|
||||
}
|
||||
|
||||
@Post("/run/:token")
|
||||
@Post("/run/:id")
|
||||
@UseGuards(QueryGuard)
|
||||
async runQuery(
|
||||
@Param("token") token: string,
|
||||
@Param("id") id: string,
|
||||
@Body() query: Record<string, any>,
|
||||
@Headers() headers: Record<string, any>,
|
||||
@Res() res: Response
|
||||
) {
|
||||
const queryResult = await this.queryExecuterService.runQueryQueued(
|
||||
token,
|
||||
id,
|
||||
query,
|
||||
headers
|
||||
);
|
||||
|
||||
@ -14,7 +14,7 @@ import { DatabaseManagerService } from "src/databaseManager/database/database.ma
|
||||
import { InjectQueue } from "@nestjs/bullmq";
|
||||
import { QUEUE_NAMES } from "src/queue/constants";
|
||||
import { Queue, QueueEvents } from "bullmq";
|
||||
import { FunctionService } from "src/project/function/function.service";
|
||||
import { FunctionService } from "src/query/function/function.service";
|
||||
|
||||
@Injectable()
|
||||
export class QueryExecuterService {
|
||||
|
||||
22
src/query/function/function.controller.ts
Normal file
22
src/query/function/function.controller.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { Controller, Inject, Post, UseGuards } from "@nestjs/common";
|
||||
import { ApiTokenGuard } from "src/api/guards/api-token.guard";
|
||||
import { FunctionService } from "./function.service";
|
||||
|
||||
@Controller("functions")
|
||||
@UseGuards(ApiTokenGuard)
|
||||
export class FunctionController {
|
||||
constructor(
|
||||
@Inject(FunctionService)
|
||||
private readonly functionService: FunctionService
|
||||
) {}
|
||||
|
||||
@Post("create")
|
||||
async createFunction(projectId: string, name: string, source: string) {
|
||||
return this.functionService.create(projectId, name, source);
|
||||
}
|
||||
|
||||
@Post("delete")
|
||||
async deleteFunction(projectId: string, name: string) {
|
||||
return this.functionService.deleteFunction(projectId, name);
|
||||
}
|
||||
}
|
||||
65
src/query/function/function.service.ts
Normal file
65
src/query/function/function.service.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { InjectRepository } from "@nestjs/typeorm";
|
||||
import { FunctionEntity } from "src/query/entities/function.entity";
|
||||
import { In, Repository } from "typeorm";
|
||||
import { ProjectService } from "../../project/project.service";
|
||||
|
||||
@Injectable()
|
||||
export class FunctionService {
|
||||
constructor(
|
||||
@InjectRepository(FunctionEntity)
|
||||
private readonly functionRepository: Repository<FunctionEntity>,
|
||||
@Inject(ProjectService)
|
||||
private readonly projectService: ProjectService
|
||||
) {}
|
||||
|
||||
async create(
|
||||
projectId: string,
|
||||
name: string,
|
||||
source: string
|
||||
): Promise<FunctionEntity> {
|
||||
const project = await this.projectService.findById(projectId);
|
||||
|
||||
if (!project) {
|
||||
throw new Error("Project not found");
|
||||
}
|
||||
|
||||
const existingFunction = await this.functionRepository.findOne({
|
||||
where: { name, project: { id: projectId } },
|
||||
});
|
||||
|
||||
if (existingFunction) {
|
||||
existingFunction.source = source;
|
||||
return this.functionRepository.save(existingFunction);
|
||||
}
|
||||
|
||||
const functionEntity = this.functionRepository.create({
|
||||
name,
|
||||
source,
|
||||
project,
|
||||
});
|
||||
|
||||
return this.functionRepository.save(functionEntity);
|
||||
}
|
||||
|
||||
async findByNames(
|
||||
projectId: string,
|
||||
names: string[]
|
||||
): Promise<FunctionEntity[]> {
|
||||
return this.functionRepository.find({
|
||||
where: { project: { id: projectId }, name: In(names) },
|
||||
});
|
||||
}
|
||||
|
||||
async deleteFunction(projectId: string, name: string): Promise<void> {
|
||||
const functionEntity = await this.functionRepository.findOne({
|
||||
where: { name, project: { id: projectId } },
|
||||
});
|
||||
|
||||
if (!functionEntity) {
|
||||
throw new Error("Function not found");
|
||||
}
|
||||
|
||||
await this.functionRepository.remove(functionEntity);
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ import { Repository } from "typeorm";
|
||||
import { Query } from "../entities/query.entity";
|
||||
import { InjectRepository } from "@nestjs/typeorm";
|
||||
import { ProjectService } from "src/project/project.service";
|
||||
import { RedisClient } from "src/redis/redis.service";
|
||||
|
||||
@Injectable()
|
||||
export class QueryHandlerService {
|
||||
@ -10,7 +11,9 @@ export class QueryHandlerService {
|
||||
@InjectRepository(Query)
|
||||
private readonly queryRepository: Repository<Query>,
|
||||
@Inject(ProjectService)
|
||||
private readonly projectService: ProjectService
|
||||
private readonly projectService: ProjectService,
|
||||
@Inject(RedisClient)
|
||||
private readonly redisClient: RedisClient
|
||||
) {}
|
||||
|
||||
async createQuery(
|
||||
@ -34,6 +37,25 @@ export class QueryHandlerService {
|
||||
return query;
|
||||
}
|
||||
|
||||
async getQueryById(id: string) {
|
||||
const cached = await this.redisClient.get(`query_${id}`);
|
||||
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
const query = await this.queryRepository.findOne({
|
||||
where: { id },
|
||||
relations: ["project"],
|
||||
});
|
||||
|
||||
if (query) {
|
||||
await this.redisClient.set(`query_${id}`, query, 300);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
async updateQuery(id: string, updateData: Partial<Query>) {
|
||||
const query = await this.queryRepository.findOne({ where: { id } });
|
||||
|
||||
@ -41,6 +63,8 @@ export class QueryHandlerService {
|
||||
throw new Error("Query not found");
|
||||
}
|
||||
|
||||
await this.redisClient.del(`query_${id}`);
|
||||
|
||||
Object.assign(query, updateData);
|
||||
return this.queryRepository.save(query);
|
||||
}
|
||||
|
||||
@ -10,9 +10,10 @@ import { CommandController } from "./command/command.controller";
|
||||
import { ApiModule } from "src/api/api.module";
|
||||
import { QueueModule } from "src/queue/queue.module";
|
||||
import { FunctionEntity } from "./entities/function.entity";
|
||||
import { FunctionService } from "src/project/function/function.service";
|
||||
import { FunctionController } from "src/project/function/function.controller";
|
||||
import { FunctionService } from "src/query/function/function.service";
|
||||
import { FunctionController } from "src/query/function/function.controller";
|
||||
import { RedisManagerModule } from "src/redisManager/redisManager.module";
|
||||
import { RedisModule } from "src/redis/redis.module";
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@ -20,11 +21,12 @@ import { RedisManagerModule } from "src/redisManager/redisManager.module";
|
||||
forwardRef(() => DatabaseManagerModule),
|
||||
forwardRef(() => ApiModule),
|
||||
forwardRef(() => QueueModule),
|
||||
forwardRef(() => RedisModule),
|
||||
forwardRef(() => RedisManagerModule),
|
||||
TypeOrmModule.forFeature([Query, FunctionEntity]),
|
||||
],
|
||||
controllers: [QueryController, CommandController, FunctionController],
|
||||
providers: [QueryExecuterService, QueryHandlerService, FunctionService],
|
||||
exports: [QueryExecuterService, TypeOrmModule],
|
||||
exports: [QueryExecuterService, TypeOrmModule, QueryHandlerService],
|
||||
})
|
||||
export class QueryModule {}
|
||||
|
||||
Reference in New Issue
Block a user