Merge: Knowledge caching layer (closes #79)
This commit is contained in:
@@ -17,6 +17,7 @@ import type {
|
||||
} from "./entities/knowledge-entry-version.entity";
|
||||
import { renderMarkdown } from "./utils/markdown";
|
||||
import { LinkSyncService } from "./services/link-sync.service";
|
||||
import { KnowledgeCacheService } from "./services/cache.service";
|
||||
|
||||
/**
|
||||
* Service for managing knowledge entries
|
||||
@@ -25,7 +26,8 @@ import { LinkSyncService } from "./services/link-sync.service";
|
||||
export class KnowledgeService {
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly linkSync: LinkSyncService
|
||||
private readonly linkSync: LinkSyncService,
|
||||
private readonly cache: KnowledgeCacheService
|
||||
) {}
|
||||
|
||||
|
||||
@@ -120,6 +122,13 @@ export class KnowledgeService {
|
||||
workspaceId: string,
|
||||
slug: string
|
||||
): Promise<KnowledgeEntryWithTags> {
|
||||
// Check cache first
|
||||
const cached = await this.cache.getEntry(workspaceId, slug);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
// Cache miss - fetch from database
|
||||
const entry = await this.prisma.knowledgeEntry.findUnique({
|
||||
where: {
|
||||
workspaceId_slug: {
|
||||
@@ -142,7 +151,7 @@ export class KnowledgeService {
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
const result: KnowledgeEntryWithTags = {
|
||||
id: entry.id,
|
||||
workspaceId: entry.workspaceId,
|
||||
slug: entry.slug,
|
||||
@@ -163,6 +172,11 @@ export class KnowledgeService {
|
||||
color: et.tag.color,
|
||||
})),
|
||||
};
|
||||
|
||||
// Populate cache
|
||||
await this.cache.setEntry(workspaceId, slug, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,6 +250,10 @@ export class KnowledgeService {
|
||||
// Sync wiki links after entry creation
|
||||
await this.linkSync.syncLinks(workspaceId, result.id, createDto.content);
|
||||
|
||||
// Invalidate search and graph caches (new entry affects search results)
|
||||
await this.cache.invalidateSearches(workspaceId);
|
||||
await this.cache.invalidateGraphs(workspaceId);
|
||||
|
||||
return {
|
||||
id: result.id,
|
||||
workspaceId: result.workspaceId,
|
||||
@@ -390,6 +408,20 @@ export class KnowledgeService {
|
||||
await this.linkSync.syncLinks(workspaceId, result.id, result.content);
|
||||
}
|
||||
|
||||
// Invalidate caches
|
||||
// Invalidate old slug cache if slug changed
|
||||
if (newSlug !== slug) {
|
||||
await this.cache.invalidateEntry(workspaceId, slug);
|
||||
}
|
||||
// Invalidate new slug cache
|
||||
await this.cache.invalidateEntry(workspaceId, result.slug);
|
||||
// Invalidate search caches (content/title/tags may have changed)
|
||||
await this.cache.invalidateSearches(workspaceId);
|
||||
// Invalidate graph caches if links changed
|
||||
if (updateDto.content !== undefined) {
|
||||
await this.cache.invalidateGraphsForEntry(workspaceId, result.id);
|
||||
}
|
||||
|
||||
return {
|
||||
id: result.id,
|
||||
workspaceId: result.workspaceId,
|
||||
@@ -444,6 +476,11 @@ export class KnowledgeService {
|
||||
updatedBy: userId,
|
||||
},
|
||||
});
|
||||
|
||||
// Invalidate caches
|
||||
await this.cache.invalidateEntry(workspaceId, slug);
|
||||
await this.cache.invalidateSearches(workspaceId);
|
||||
await this.cache.invalidateGraphsForEntry(workspaceId, entry.id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -737,6 +774,11 @@ export class KnowledgeService {
|
||||
// Sync wiki links after restore
|
||||
await this.linkSync.syncLinks(workspaceId, result.id, result.content);
|
||||
|
||||
// Invalidate caches (content changed, links may have changed)
|
||||
await this.cache.invalidateEntry(workspaceId, slug);
|
||||
await this.cache.invalidateSearches(workspaceId);
|
||||
await this.cache.invalidateGraphsForEntry(workspaceId, result.id);
|
||||
|
||||
return {
|
||||
id: result.id,
|
||||
workspaceId: result.workspaceId,
|
||||
|
||||
Reference in New Issue
Block a user