fix(core): Resolve TypeScript strict mode and ES client API compatibility issues for v3.0.0

- Fix ES client v8+ API: use document/doc instead of body for index/update operations
- Add type assertions (as any) for ES client ILM, template, and search APIs
- Fix strict null checks with proper undefined handling (nullish coalescing)
- Fix MetricsCollector interface to match required method signatures
- Fix Logger.error signature compatibility in plugins
- Resolve TermsQuery type index signature conflict
- Remove sourceMap from tsconfig (handled by tsbuild with inlineSourceMap)
This commit is contained in:
2025-11-29 21:19:28 +00:00
parent ec8dfbcfe6
commit 820f84ee61
30 changed files with 344 additions and 220 deletions

View File

@@ -7,12 +7,11 @@ import type {
BulkIndexerStats,
BulkProgress,
BackpressureState,
BatchingStrategy,
} from './types.js';
import { ElasticsearchConnectionManager } from '../../core/connection/connection-manager.js';
import { defaultLogger } from '../../core/observability/logger.js';
import { defaultMetrics } from '../../core/observability/metrics.js';
import { defaultTracing } from '../../core/observability/tracing.js';
import { defaultMetricsCollector } from '../../core/observability/metrics.js';
import { defaultTracer } from '../../core/observability/tracing.js';
/**
* Enterprise-grade bulk indexer with adaptive batching and parallel workers
@@ -297,7 +296,7 @@ export class BulkIndexer {
// ============================================================================
private async executeBatch(operations: BulkOperation[]): Promise<BulkBatchResult> {
const span = defaultTracing.createSpan('bulkIndexer.executeBatch', {
const span = defaultTracer.startSpan('bulkIndexer.executeBatch', {
'batch.size': operations.length,
});
@@ -369,11 +368,11 @@ export class BulkIndexer {
success,
type: op?.type as BulkOperationType,
index: actionResult._index,
id: actionResult._id,
id: actionResult._id ?? undefined,
status: actionResult.status,
error: actionResult.error ? {
type: actionResult.error.type,
reason: actionResult.error.reason,
reason: actionResult.error.reason ?? 'Unknown error',
causedBy: actionResult.error.caused_by ? JSON.stringify(actionResult.error.caused_by) : undefined,
} : undefined,
seqNo: actionResult._seq_no,
@@ -408,8 +407,8 @@ export class BulkIndexer {
}
// Record metrics
defaultMetrics.requestsTotal.inc({ operation: 'bulk', result: 'success' });
defaultMetrics.requestDuration.observe({ operation: 'bulk' }, durationMs);
defaultMetricsCollector.requestsTotal.inc({ operation: 'bulk', index: 'bulk' });
defaultMetricsCollector.requestDuration.observe(durationMs / 1000, { operation: 'bulk', index: 'bulk' });
const result: BulkBatchResult = {
successful,
@@ -443,9 +442,9 @@ export class BulkIndexer {
this.stats.totalBatchesFailed++;
this.stats.activeWorkers--;
defaultMetrics.requestErrors.inc({ operation: 'bulk' });
defaultLogger.error('Bulk batch failed', {
error: error instanceof Error ? error.message : String(error),
defaultMetricsCollector.requestErrors.inc({ operation: 'bulk', index: 'bulk', error_code: 'bulk_error' });
const err = error instanceof Error ? error : new Error(String(error));
defaultLogger.error('Bulk batch failed', err, {
batchSize: operations.length,
});
@@ -518,16 +517,15 @@ export class BulkIndexer {
attempts,
});
} catch (dlqError) {
defaultLogger.error('Failed to send to dead-letter queue', {
error: dlqError instanceof Error ? dlqError.message : String(dlqError),
});
const err = dlqError instanceof Error ? dlqError : new Error(String(dlqError));
defaultLogger.error('Failed to send to dead-letter queue', err);
}
}
private resolveDeadLetterIndexName(): string {
const pattern = this.config.deadLetterIndex;
if (pattern.includes('{now/d}')) {
const date = new Date().toISOString().split('T')[0];
const date = new Date().toISOString().split('T')[0] ?? 'unknown';
return pattern.replace('{now/d}', date);
}
return pattern;
@@ -609,22 +607,34 @@ export class BulkIndexer {
* Worker for parallel batch processing
*/
class Worker {
private indexer: BulkIndexer;
private id: number;
private running = false;
private _indexer: BulkIndexer;
private _id: number;
private _running = false;
constructor(indexer: BulkIndexer, id: number) {
this.indexer = indexer;
this.id = id;
this._indexer = indexer;
this._id = id;
}
get id(): number {
return this._id;
}
get indexer(): BulkIndexer {
return this._indexer;
}
get isRunning(): boolean {
return this._running;
}
start(): void {
this.running = true;
this._running = true;
// Workers are passive - they respond to triggers from the indexer
}
stop(): void {
this.running = false;
this._running = false;
}
}