feat(server): add cloud indexer with Elasticsearch and Manticoresearch providers (#11835)

close CLOUD-137

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced advanced workspace-scoped search and aggregation capabilities with support for complex queries, highlights, and pagination.
  - Added pluggable search providers: Elasticsearch and Manticoresearch.
  - New GraphQL queries, schema types, and resolver support for search and aggregation.
  - Enhanced configuration options for search providers in self-hosted and cloud deployments.
  - Added Docker Compose services and environment variables for Elasticsearch and Manticoresearch.
  - Integrated indexer service into deployment and CI workflows.

- **Bug Fixes**
  - Improved error handling with new user-friendly error messages for search provider and indexer issues.

- **Documentation**
  - Updated configuration examples and environment variable references for indexer and search providers.

- **Tests**
  - Added extensive end-to-end and provider-specific tests covering indexing, searching, aggregation, deletion, and error cases.
  - Included snapshot tests and test fixtures for search providers.

- **Chores**
  - Updated deployment scripts, Helm charts, and Kubernetes manifests to include indexer-related environment variables and secrets.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
fengmk2
2025-05-14 14:52:40 +00:00
parent 7c22b3931f
commit a1bcf77447
66 changed files with 10139 additions and 10 deletions
@@ -0,0 +1,61 @@
import { z } from 'zod';
import { defineModuleConfig } from '../../base';
export enum SearchProviderType {
Manticoresearch = 'manticoresearch',
Elasticsearch = 'elasticsearch',
}
const SearchProviderTypeSchema = z.nativeEnum(SearchProviderType);
declare global {
interface AppConfigSchema {
indexer: {
enabled: boolean;
provider: {
type: SearchProviderType;
endpoint: string;
username: string;
password: string;
};
};
}
}
defineModuleConfig('indexer', {
enabled: {
desc: 'Enable indexer plugin',
default: true,
},
'provider.type': {
desc: 'Indexer search service provider name',
default: SearchProviderType.Manticoresearch,
shape: SearchProviderTypeSchema,
env: ['AFFINE_INDEXER_SEARCH_PROVIDER', 'string'],
},
'provider.endpoint': {
desc: 'Indexer search service endpoint',
default: 'http://localhost:9308',
env: ['AFFINE_INDEXER_SEARCH_ENDPOINT', 'string'],
validate: val => {
// allow to be nullable and empty string
if (!val) {
return { success: true, data: val };
}
return z.string().url().safeParse(val);
},
},
'provider.username': {
desc: 'Indexer search service auth username, if not set, basic auth will be disabled. Optional for elasticsearch',
link: 'https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html',
default: '',
env: ['AFFINE_INDEXER_SEARCH_USERNAME', 'string'],
},
'provider.password': {
desc: 'Indexer search service auth password, if not set, basic auth will be disabled. Optional for elasticsearch',
default: '',
env: ['AFFINE_INDEXER_SEARCH_PASSWORD', 'string'],
},
});