33// See the LICENSE file in the project root for more information
44
55using System . IO . Abstractions ;
6+ using Elastic . Channels ;
67using Elastic . Documentation . Configuration ;
78using Elastic . Documentation . Diagnostics ;
89using Elastic . Documentation . Search ;
1819namespace Elastic . Documentation . Tooling . Exporters ;
1920
2021public class ElasticsearchMarkdownExporter ( ILoggerFactory logFactory , IDiagnosticsCollector collector , DocumentationEndpoints endpoints )
22+ : ElasticsearchMarkdownExporterBase < CatalogIndexChannelOptions < DocumentationDocument > , CatalogIndexChannel < DocumentationDocument > >
23+ ( logFactory , collector , endpoints )
24+ {
25+ /// <inheritdoc />
26+ protected override CatalogIndexChannelOptions < DocumentationDocument > NewOptions ( DistributedTransport transport ) => new ( transport )
27+ {
28+ GetMapping = ( ) => CreateMapping ( null ) ,
29+ IndexFormat = "documentation{0:yyyy.MM.dd.HHmmss}" ,
30+ ActiveSearchAlias = "documentation"
31+ } ;
32+
33+ /// <inheritdoc />
34+ protected override CatalogIndexChannel < DocumentationDocument > NewChannel ( CatalogIndexChannelOptions < DocumentationDocument > options ) => new ( options ) ;
35+ }
36+ public class ElasticsearchMarkdownSemanticExporter ( ILoggerFactory logFactory , IDiagnosticsCollector collector , DocumentationEndpoints endpoints )
37+ : ElasticsearchMarkdownExporterBase < SemanticIndexChannelOptions < DocumentationDocument > , SemanticIndexChannel < DocumentationDocument > >
38+ ( logFactory , collector , endpoints )
39+ {
40+ /// <inheritdoc />
41+ protected override SemanticIndexChannelOptions < DocumentationDocument > NewOptions ( DistributedTransport transport ) => new ( transport )
42+ {
43+ GetMapping = ( inferenceId , _ ) => CreateMapping ( inferenceId ) ,
44+ IndexFormat = "semantic-documentation-{0:yyyy.MM.dd.HHmmss}" ,
45+ ActiveSearchAlias = "semantic-documentation" ,
46+ IndexNumThreads = IndexNumThreads ,
47+ InferenceCreateTimeout = TimeSpan . FromMinutes ( 4 ) ,
48+ } ;
49+
50+ /// <inheritdoc />
51+ protected override SemanticIndexChannel < DocumentationDocument > NewChannel ( SemanticIndexChannelOptions < DocumentationDocument > options ) => new ( options ) ;
52+ }
53+
54+ public abstract class ElasticsearchMarkdownExporterBase < TChannelOptions , TChannel > (
55+ ILoggerFactory logFactory ,
56+ IDiagnosticsCollector collector ,
57+ DocumentationEndpoints endpoints )
2158 : IMarkdownExporter , IDisposable
59+ where TChannelOptions : CatalogIndexChannelOptionsBase < DocumentationDocument >
60+ where TChannel : CatalogIndexChannel < DocumentationDocument , TChannelOptions >
2261{
23- private CatalogIndexChannel < DocumentationDocument > ? _channel ;
24- private readonly ILogger < ElasticsearchMarkdownExporter > _logger = logFactory . CreateLogger < ElasticsearchMarkdownExporter > ( ) ;
62+ private TChannel ? _channel ;
63+ private readonly ILogger < IMarkdownExporter > _logger = logFactory . CreateLogger < IMarkdownExporter > ( ) ;
64+
65+ protected abstract TChannelOptions NewOptions ( DistributedTransport transport ) ;
66+ protected abstract TChannel NewChannel ( TChannelOptions options ) ;
67+
68+ protected int IndexNumThreads => 8 ;
69+
70+ protected static string CreateMapping ( string ? inferenceId ) =>
71+ // langugage=json
72+ $$ """
73+ {
74+ "properties": {
75+ "title": { "type": "text" },
76+ "body": { "type": "text" }
77+ {{ ( ! string . IsNullOrWhiteSpace ( inferenceId ) ? AbstractInferenceMapping ( inferenceId ) : AbstractMapping ( ) ) }}
78+ }
79+ }
80+ """ ;
81+
82+ private static string AbstractMapping ( ) =>
83+ // langugage=json
84+ """
85+ , "abstract": {
86+ "type": "text",
87+ }
88+ """ ;
89+
90+ private static string AbstractInferenceMapping ( string inferenceId ) =>
91+ // langugage=json
92+ $$ """
93+ , "abstract": {
94+ "type": "semantic_text",
95+ "inference_id": "{{ inferenceId }} "
96+ }
97+ """ ;
2598
2699 public async ValueTask StartAsync ( Cancel ctx = default )
27100 {
@@ -41,36 +114,18 @@ public async ValueTask StartAsync(Cancel ctx = default)
41114 var transport = new DistributedTransport ( configuration ) ;
42115 //The max num threads per allocated node, from testing its best to limit our max concurrency
43116 //producing to this number as well
44- var indexNumThreads = 8 ;
45- var options = new CatalogIndexChannelOptions < DocumentationDocument > ( transport )
117+ var options = NewOptions ( transport ) ;
118+ options . BufferOptions = new BufferOptions
46119 {
47- BufferOptions =
48- {
49- OutboundBufferMaxSize = 100 ,
50- ExportMaxConcurrency = indexNumThreads ,
51- ExportMaxRetries = 3
52- } ,
53- SerializerContext = SourceGenerationContext . Default ,
54- // IndexNumThreads = indexNumThreads,
55- IndexFormat = "documentation-{0:yyyy.MM.dd.HHmmss}" ,
56- ActiveSearchAlias = "documentation" ,
57- ExportBufferCallback = ( ) => _logger . LogInformation ( "Exported buffer to Elasticsearch" ) ,
58- ExportExceptionCallback = e => _logger . LogError ( e , "Failed to export document" ) ,
59- ServerRejectionCallback = items => _logger . LogInformation ( "Server rejection: {Rejection}" , items . First ( ) . Item2 ) ,
60- //GetMapping = (inferenceId, _) => // language=json
61- GetMapping = ( ) => // language=json
62- $$ """
63- {
64- "properties": {
65- "title": { "type": "text" },
66- "body": {
67- "type": "text"
68- }
69- }
70- }
71- """
120+ OutboundBufferMaxSize = 100 ,
121+ ExportMaxConcurrency = IndexNumThreads ,
122+ ExportMaxRetries = 3
72123 } ;
73- _channel = new CatalogIndexChannel < DocumentationDocument > ( options ) ;
124+ options . SerializerContext = SourceGenerationContext . Default ;
125+ options . ExportBufferCallback = ( ) => _logger . LogInformation ( "Exported buffer to Elasticsearch" ) ;
126+ options . ExportExceptionCallback = e => _logger . LogError ( e , "Failed to export document" ) ;
127+ options . ServerRejectionCallback = items => _logger . LogInformation ( "Server rejection: {Rejection}" , items . First ( ) . Item2 ) ;
128+ _channel = NewChannel ( options ) ;
74129 _logger . LogInformation ( $ "Bootstrapping { nameof ( SemanticIndexChannel < DocumentationDocument > ) } Elasticsearch target for indexing") ;
75130 _ = await _channel . BootstrapElasticsearchAsync ( BootstrapMethod . Failure , null , ctx ) ;
76131 }
@@ -103,6 +158,7 @@ public void Dispose()
103158 _channel . Complete ( ) ;
104159 _channel . Dispose ( ) ;
105160 }
161+
106162 GC . SuppressFinalize ( this ) ;
107163 }
108164
@@ -134,6 +190,9 @@ public async ValueTask<bool> ExportAsync(MarkdownExportFileContext fileContext,
134190 Url = url ,
135191 Body = body ,
136192 Description = fileContext . SourceFile . YamlFrontMatter ? . Description ,
193+ Abstract = ! string . IsNullOrEmpty ( body )
194+ ? body [ ..Math . Min ( body . Length , 400 ) ]
195+ : string . Empty ,
137196 Applies = fileContext . SourceFile . YamlFrontMatter ? . AppliesTo ,
138197 } ;
139198 return await TryWrite ( doc , ctx ) ;
0 commit comments