Skip to content

Commit

Permalink
πŸ› fix: remove orphan chunks if there is no related file (lobehub#3578)
Browse files Browse the repository at this point in the history
* βœ… test: add more tests

* πŸ› fix: add `DISABLE_REMOVE_GLOBAL_FILE` in dbENV

* πŸ› fix: remove orphan chunks if there is related file

* βœ… test: fix test

* πŸ‘· fix: throw error when not set `APP_URL` at server side

* βœ… test: fix test
  • Loading branch information
arvinxx authored and akvsdk committed Aug 26, 2024
1 parent 8a511c9 commit 9431e31
Show file tree
Hide file tree
Showing 11 changed files with 479 additions and 81 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
ports:
- 5432:5432

steps:
- uses: actions/checkout@v4

Expand All @@ -40,7 +40,8 @@ jobs:
DATABASE_DRIVER: node
NEXT_PUBLIC_SERVICE_MODE: server
KEY_VAULTS_SECRET: LA7n9k3JdEcbSgml2sxfw+4TV1AzaaFU5+R176aQz4s=
NEXT_PUBLIC_S3_DOMAIN: https://example.com
S3_PUBLIC_DOMAIN: https://example.com
APP_URL: https://home.com

- name: Test App Coverage
run: bun run test-app:coverage
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ jobs:
DATABASE_DRIVER: node
NEXT_PUBLIC_SERVICE_MODE: server
KEY_VAULTS_SECRET: LA7n9k3JdEcbSgml2sxfw+4TV1AzaaFU5+R176aQz4s=
NEXT_PUBLIC_S3_DOMAIN: https://example.com
S3_PUBLIC_DOMAIN: https://example.com
APP_URL: https://home.com

- name: Upload Server coverage to Codecov
uses: codecov/codecov-action@v4
Expand Down
17 changes: 12 additions & 5 deletions src/config/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import { createEnv } from '@t3-oss/env-nextjs';
import { z } from 'zod';

import { isServerMode } from '@/const/version';

declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace NodeJS {
Expand All @@ -10,14 +12,19 @@ declare global {
}
}
}
const isInVercel = process.env.VERCEL === '1';

export const getAppConfig = () => {
const ACCESS_CODES = process.env.ACCESS_CODE?.split(',').filter(Boolean) || [];
const isInVercel = process.env.VERCEL === '1';
const vercelUrl = `https://${process.env.VERCEL_URL}`;

const vercelUrl = `https://${process.env.VERCEL_URL}`;
const APP_URL = process.env.APP_URL ? process.env.APP_URL : isInVercel ? vercelUrl : undefined;

const APP_URL = process.env.APP_URL ? process.env.APP_URL : isInVercel ? vercelUrl : undefined;
// only throw error in server mode and server side
if (typeof window === 'undefined' && isServerMode && !APP_URL) {
throw new Error('`APP_URL` is required in server mode');
}

export const getAppConfig = () => {
const ACCESS_CODES = process.env.ACCESS_CODE?.split(',').filter(Boolean) || [];

return createEnv({
client: {
Expand Down
4 changes: 4 additions & 0 deletions src/config/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export const getServerDBConfig = () => {
DATABASE_TEST_URL: process.env.DATABASE_TEST_URL,
DATABASE_URL: process.env.DATABASE_URL,

DISABLE_REMOVE_GLOBAL_FILE: process.env.DISABLE_REMOVE_GLOBAL_FILE === '1',

KEY_VAULTS_SECRET: process.env.KEY_VAULTS_SECRET,

NEXT_PUBLIC_ENABLED_SERVER_SERVICE: process.env.NEXT_PUBLIC_SERVICE_MODE === 'server',
Expand All @@ -20,6 +22,8 @@ export const getServerDBConfig = () => {
DATABASE_TEST_URL: z.string().optional(),
DATABASE_URL: z.string().optional(),

DISABLE_REMOVE_GLOBAL_FILE: z.boolean().optional(),

KEY_VAULTS_SECRET: z.string().optional(),
},
});
Expand Down
61 changes: 60 additions & 1 deletion src/database/server/models/__tests__/chunk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,66 @@ describe('ChunkModel', () => {
});
});

// Add more test cases for other methods...
describe('deleteOrphanChunks', () => {
it('should delete orphaned chunks', async () => {
// Create orphaned chunks
await serverDB
.insert(chunks)
.values([
{ text: 'Orphan Chunk 1', userId },
{ text: 'Orphan Chunk 2', userId },
])
.returning();

// Create a non-orphaned chunk
const [nonOrphanChunk] = await serverDB
.insert(chunks)
.values([{ text: 'Non-Orphan Chunk', userId }])
.returning();

await serverDB.insert(fileChunks).values([{ fileId: '1', chunkId: nonOrphanChunk.id }]);

// Execute the method
await chunkModel.deleteOrphanChunks();

// Check if orphaned chunks are deleted
const remainingChunks = await serverDB.query.chunks.findMany();
expect(remainingChunks).toHaveLength(1);
expect(remainingChunks[0].id).toBe(nonOrphanChunk.id);
});

it('should not delete any chunks when there are no orphans', async () => {
// Create non-orphaned chunks
const [chunk1, chunk2] = await serverDB
.insert(chunks)
.values([
{ text: 'Chunk 1', userId },
{ text: 'Chunk 2', userId },
])
.returning();

await serverDB.insert(fileChunks).values([
{ fileId: '1', chunkId: chunk1.id },
{ fileId: '2', chunkId: chunk2.id },
]);

// Execute the method
await chunkModel.deleteOrphanChunks();

// Check if all chunks are still present
const remainingChunks = await serverDB.query.chunks.findMany();
expect(remainingChunks).toHaveLength(2);
});

it('should not throw an error when the database is empty', async () => {
// Ensure the database is empty
await serverDB.delete(chunks);
await serverDB.delete(fileChunks);

// Execute the method and expect it not to throw
await expect(chunkModel.deleteOrphanChunks()).resolves.not.toThrow();
});
});

describe('semanticSearch', () => {
it('should perform semantic search and return results', async () => {
Expand Down
Loading

0 comments on commit 9431e31

Please sign in to comment.