115 lines
3.4 KiB
TypeScript
115 lines
3.4 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest';
|
|
import type { BackupConfig, MinioSyncAutomationConfig } from '../config/schema.js';
|
|
import type { MemoryStore } from '../memory/store.js';
|
|
import { MinioSyncScheduler } from './minioSync.js';
|
|
|
|
function makeBackupConfig(): BackupConfig {
|
|
return {
|
|
enabled: true,
|
|
schedule: undefined,
|
|
interval: '24h',
|
|
run_on_start: false,
|
|
notify: undefined,
|
|
failure_threshold: 1,
|
|
notify_recovery: true,
|
|
local_dir: '~/.local/share/flynn/backups',
|
|
include_vectors: true,
|
|
minio: {
|
|
enabled: true,
|
|
endpoint: 'localhost:9000',
|
|
access_key: 'minio-admin',
|
|
secret_key: 'minio-secret',
|
|
bucket: 'flynn-knowledge',
|
|
prefix: 'flynn',
|
|
secure: false,
|
|
},
|
|
};
|
|
}
|
|
|
|
function makeAutomationConfig(overrides?: Partial<MinioSyncAutomationConfig>): MinioSyncAutomationConfig {
|
|
return {
|
|
enabled: true,
|
|
interval: '6h',
|
|
run_on_start: false,
|
|
tasks: [{
|
|
prefix: 'knowledge/',
|
|
bucket: undefined,
|
|
namespace_base: 'global/knowledge/minio',
|
|
mode: 'append',
|
|
max_objects: 20,
|
|
max_chars_per_object: 8000,
|
|
force: false,
|
|
}],
|
|
notify: undefined,
|
|
notify_on_success: false,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe('MinioSyncScheduler', () => {
|
|
it('skips when memory store is unavailable', async () => {
|
|
const scheduler = new MinioSyncScheduler({
|
|
config: makeAutomationConfig(),
|
|
backupConfig: makeBackupConfig(),
|
|
memoryStore: undefined,
|
|
channelLookup: { get: () => undefined },
|
|
});
|
|
|
|
const result = await scheduler.runOnce();
|
|
expect(result).toEqual({ succeeded: 0, failed: 0, details: [] });
|
|
});
|
|
|
|
it('runs configured sync tasks and records success/failure counts', async () => {
|
|
const memoryStore = { write: vi.fn() } as unknown as MemoryStore;
|
|
const send = vi.fn(async () => undefined);
|
|
const scheduler = new MinioSyncScheduler({
|
|
config: makeAutomationConfig({
|
|
tasks: [
|
|
{
|
|
prefix: 'knowledge/good/',
|
|
bucket: undefined,
|
|
namespace_base: 'global/knowledge/minio',
|
|
mode: 'append',
|
|
max_objects: 20,
|
|
max_chars_per_object: 8000,
|
|
force: false,
|
|
},
|
|
{
|
|
prefix: 'knowledge/fail/',
|
|
bucket: undefined,
|
|
namespace_base: 'global/knowledge/minio',
|
|
mode: 'append',
|
|
max_objects: 20,
|
|
max_chars_per_object: 8000,
|
|
force: false,
|
|
},
|
|
],
|
|
notify: { channel: 'telegram', peer: '123' },
|
|
}),
|
|
backupConfig: makeBackupConfig(),
|
|
memoryStore,
|
|
channelLookup: { get: () => ({ send }) },
|
|
createSyncTool: () => ({
|
|
name: 'minio.sync',
|
|
description: '',
|
|
inputSchema: { type: 'object', properties: {} },
|
|
execute: async (rawArgs: unknown) => {
|
|
const prefix = (rawArgs as { prefix: string }).prefix;
|
|
if (prefix === 'knowledge/fail/') {
|
|
return { success: false, output: '', error: 'boom' };
|
|
}
|
|
return { success: true, output: 'ok' };
|
|
},
|
|
}),
|
|
});
|
|
|
|
const result = await scheduler.runOnce();
|
|
expect(result.succeeded).toBe(1);
|
|
expect(result.failed).toBe(1);
|
|
expect(result.details).toContain('OK knowledge/good/');
|
|
expect(result.details).toContain('FAIL knowledge/fail/: boom');
|
|
expect(send).toHaveBeenCalledTimes(1);
|
|
scheduler.stop();
|
|
});
|
|
});
|