Ctrl K
ComunidadGuías…

api/db/indexSync.tenant.spec.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
const mockIndex = {
  uid: 'test',
  getSettings: jest.fn().mockResolvedValue({ filterableAttributes: ['user'] }),
  search: jest.fn().mockResolvedValue({ hits: [] }),
  getDocuments: jest.fn().mockResolvedValue({ results: [] }),
  addDocumentsInBatches: jest.fn().mockResolvedValue([{ taskUid: 1 }]),
  deleteDocuments: jest.fn().mockResolvedValue({ taskUid: 1 }),
};

jest.mock('meilisearch', () => ({
  MeiliSearch: jest.fn(() => ({
    health: jest.fn().mockResolvedValue({ status: 'available' }),
    index: jest.fn(() => mockIndex),
    waitForTask: jest.fn().mockResolvedValue({ status: 'succeeded' }),
  })),
}));
jest.mock('~/cache', () => ({ getLogStores: () => undefined }));

// Both plugins and indexSync read their configuration at module load.
process.env.SEARCH = 'true';
process.env.MEILI_HOST = 'http://localhost:7700';
process.env.MEILI_MASTER_KEY = 'test-only';
process.env.TENANT_ISOLATION_STRICT = 'true';

const mongoose = require('mongoose');
const { MongoMemoryServer } = require('mongodb-memory-server');
const {
  createModels,
  runAsSystem,
  tenantStorage,
  getTenantId,
} = require('@librechat/data-schemas');
const indexSync = require('./indexSync');

let mongo;

beforeAll(async () => {
  mongo = await MongoMemoryServer.create({ instance: { args: ['--nounixsocket'] } });
  await mongoose.connect(mongo.getUri());
  createModels(mongoose);
});

beforeEach(async () => {
  await runAsSystem(async () => {
    await mongoose.models.Message.deleteMany({});
    await mongoose.models.Conversation.deleteMany({});
  });
  // Raw inserts model documents left unindexed by an older deployment.
  for (const tenantId of ['tenant-a', 'tenant-b']) {
    await mongoose.models.Message.collection.insertOne({
      messageId: `message-${tenantId}`,
      conversationId: `conversation-${tenantId}`,
      user: `user-${tenantId}`,
      text: 'Legacy message',
      tenantId,
    });
    await mongoose.models.Conversation.collection.insertOne({
      conversationId: `conversation-${tenantId}`,
      user: `user-${tenantId}`,
      title: 'Legacy conversation',
      tenantId,
    });
  }
  mockIndex.addDocumentsInBatches.mockClear();
});

afterAll(async () => {
  await mongoose.disconnect();
  await mongo?.stop();
});

it.each([undefined, 'tenant-a'])(
  'reconciles every tenant with no caller-owned system context (caller: %s)',
  async (tenantId) => {
    const result = await tenantStorage.run({ tenantId }, async () => {
      const synced = await indexSync();
      expect(getTenantId()).toBe(tenantId);
      return synced;
    });
    expect(result).toEqual({ messagesSync: true, convosSync: true });
    const indexed = await runAsSystem(async () =>
      Promise.all([
        mongoose.models.Message.find({ _meiliIndex: true }).lean(),
        mongoose.models.Conversation.find({ _meiliIndex: true }).lean(),
      ]),
    );
    for (const documents of indexed) {
      expect(documents.map((doc) => doc.tenantId).sort()).toEqual(['tenant-a', 'tenant-b']);
    }
    expect(mockIndex.addDocumentsInBatches).toHaveBeenCalledTimes(2);
  },
);