public async Task Put() { using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context)) { var input = await context.ReadForMemoryAsync(RequestBodyStream(), "Analyzers"); if (input.TryGet("Analyzers", out BlittableJsonReaderArray analyzers) == false) { ThrowRequiredPropertyNameInRequest("Analyzers"); } var commands = new List <PutServerWideAnalyzerCommand>(); foreach (var analyzerToAdd in analyzers) { var analyzerDefinition = JsonDeserializationServer.AnalyzerDefinition((BlittableJsonReaderObject)analyzerToAdd); analyzerDefinition.Name = analyzerDefinition.Name?.Trim(); if (LoggingSource.AuditLog.IsInfoEnabled) { var clientCert = GetCurrentCertificate(); var auditLog = LoggingSource.AuditLog.GetLogger("Server", "Audit"); auditLog.Info($"Analyzer {analyzerDefinition.Name} PUT by {clientCert?.Subject} {clientCert?.Thumbprint} with definition: {analyzerToAdd}"); } analyzerDefinition.Validate(); // check if analyzer is compilable AnalyzerCompiler.Compile(analyzerDefinition.Name, analyzerDefinition.Code); var command = new PutServerWideAnalyzerCommand(analyzerDefinition, GetRaftRequestIdFromQuery()); commands.Add(command); } var index = 0L; foreach (var command in commands) { index = (await ServerStore.SendToLeaderAsync(command)).Index; } await ServerStore.WaitForCommitIndexChange(RachisConsensus.CommitIndexModification.GreaterOrEqual, index); NoContentStatus(HttpStatusCode.Created); } }
public void CanUseCustomAnalyzer_Restart_Faulty() { var serverPath = NewDataPath(); var databasePath = NewDataPath(); IOExtensions.DeleteDirectory(serverPath); IOExtensions.DeleteDirectory(databasePath); var analyzerName = GetDatabaseName(); using (var server = GetNewServer(new ServerCreationOptions { DataDirectory = serverPath, RunInMemory = false })) using (var store = GetDocumentStore(new Options { ModifyDatabaseName = _ => analyzerName, Path = databasePath, RunInMemory = false, Server = server, DeleteDatabaseOnDispose = false })) { var e = Assert.Throws <IndexCompilationException>(() => store.ExecuteIndex(new MyIndex(analyzerName))); Assert.Contains($"Cannot find analyzer type '{analyzerName}' for field: Name", e.Message); var analyzerCode = GetAnalyzer("RavenDB_14939.MyAnalyzer.cs", "MyAnalyzer", analyzerName); store.Maintenance.Server.Send(new PutServerWideAnalyzersOperation(new AnalyzerDefinition { Name = analyzerName, Code = analyzerCode })); store.ExecuteIndex(new MyIndex(analyzerName)); Fill(store); Indexes.WaitForIndexing(store); AssertCount <MyIndex>(store); server.ServerStore.DatabasesLandlord.UnloadDirectly(store.Database); // skipping compilation on purpose using (server.ServerStore.Engine.ContextPool.AllocateOperationContext(out ClusterOperationContext context)) using (var tx = context.OpenWriteTransaction()) { var command = new PutServerWideAnalyzerCommand( new AnalyzerDefinition { Name = analyzerName, Code = analyzerCode.Replace(analyzerName, "MyAnalyzer") }, RaftIdGenerator.NewId()); using (var json = context.ReadObject(command.ValueToJson(), command.Name)) { ClusterStateMachine.PutValueDirectly(context, command.Name, json, 1); } tx.Commit(); } } AnalyzerCompilationCache.Instance.RemoveServerWideItem(analyzerName); using (var server = GetNewServer(new ServerCreationOptions { DataDirectory = serverPath, RunInMemory = false, DeletePrevious = false })) using (var store = GetDocumentStore(new Options { ModifyDatabaseName = _ => analyzerName, Path = databasePath, RunInMemory = false, Server = server, CreateDatabase = false })) { store.Maintenance.Send(new ResetIndexOperation(new MyIndex(analyzerName).IndexName)); AssertErrors(store); // can override with database analyzer store.Maintenance.Send(new PutAnalyzersOperation(new AnalyzerDefinition { Name = analyzerName, Code = GetAnalyzer("RavenDB_14939.MyAnalyzer.cs", "MyAnalyzer", analyzerName) })); store.Maintenance.Send(new ResetIndexOperation(new MyIndex(analyzerName).IndexName)); Indexes.WaitForIndexing(store); AssertCount <MyIndex>(store); // can go back to server analyzer store.Maintenance.Send(new DeleteAnalyzerOperation(analyzerName)); store.Maintenance.Send(new ResetIndexOperation(new MyIndex(analyzerName).IndexName)); AssertErrors(store); // can fix server analyzer store.Maintenance.Server.Send(new PutServerWideAnalyzersOperation(new AnalyzerDefinition { Name = analyzerName, Code = GetAnalyzer("RavenDB_14939.MyAnalyzer.cs", "MyAnalyzer", analyzerName) })); store.Maintenance.Send(new ResetIndexOperation(new MyIndex(analyzerName).IndexName)); Indexes.WaitForIndexing(store); AssertCount <MyIndex>(store); } void AssertErrors(IDocumentStore store) { var errors = Indexes.WaitForIndexingErrors(store); Assert.Equal(1, errors.Length); Assert.Equal(1, errors[0].Errors.Length); Assert.Contains("is an implementation of a faulty analyzer", errors[0].Errors[0].Error); Assert.Contains("Could not find type", errors[0].Errors[0].Error); } }