3
3
// See the LICENSE file in the project root for more information
4
4
5
5
using System . IO . Abstractions ;
6
+ using Elastic . Channels ;
6
7
using Elastic . Documentation . Configuration ;
7
8
using Elastic . Documentation . Diagnostics ;
8
9
using Elastic . Documentation . Search ;
18
19
namespace Elastic . Documentation . Tooling . Exporters ;
19
20
20
21
public 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 )
21
58
: IMarkdownExporter , IDisposable
59
+ where TChannelOptions : CatalogIndexChannelOptionsBase < DocumentationDocument >
60
+ where TChannel : CatalogIndexChannel < DocumentationDocument , TChannelOptions >
22
61
{
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
+ """ ;
25
98
26
99
public async ValueTask StartAsync ( Cancel ctx = default )
27
100
{
@@ -41,36 +114,18 @@ public async ValueTask StartAsync(Cancel ctx = default)
41
114
var transport = new DistributedTransport ( configuration ) ;
42
115
//The max num threads per allocated node, from testing its best to limit our max concurrency
43
116
//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
46
119
{
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
72
123
} ;
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 ) ;
74
129
_logger . LogInformation ( $ "Bootstrapping { nameof ( SemanticIndexChannel < DocumentationDocument > ) } Elasticsearch target for indexing") ;
75
130
_ = await _channel . BootstrapElasticsearchAsync ( BootstrapMethod . Failure , null , ctx ) ;
76
131
}
@@ -103,6 +158,7 @@ public void Dispose()
103
158
_channel . Complete ( ) ;
104
159
_channel . Dispose ( ) ;
105
160
}
161
+
106
162
GC . SuppressFinalize ( this ) ;
107
163
}
108
164
@@ -134,6 +190,9 @@ public async ValueTask<bool> ExportAsync(MarkdownExportFileContext fileContext,
134
190
Url = url ,
135
191
Body = body ,
136
192
Description = fileContext . SourceFile . YamlFrontMatter ? . Description ,
193
+ Abstract = ! string . IsNullOrEmpty ( body )
194
+ ? body [ ..Math . Min ( body . Length , 400 ) ]
195
+ : string . Empty ,
137
196
Applies = fileContext . SourceFile . YamlFrontMatter ? . AppliesTo ,
138
197
} ;
139
198
return await TryWrite ( doc , ctx ) ;
0 commit comments