From 71032ce900500f45361065ec6164e6cc905f5cd1 Mon Sep 17 00:00:00 2001 From: Boris Yakhno Date: Thu, 24 Aug 2023 06:57:15 +0000 Subject: [PATCH] Added an option of creating a service message writer that doesn't set a top-level flowId attribute on messages --- .../ServiceMessageParserPerformanceTest.cs | 3 +- .../TeamCity.ServiceMessages.Tests.csproj | 19 +++---- .../FlowAwareServiceMessageWriterTest.cs | 49 +++++++++++++++++++ .../Specials/TeamCityFlowWriterBaseTest.cs | 7 +-- .../Write/Specials/TeamCityFlowWriterTest.cs | 25 +++++++++- .../Write/Specials/TeamCityTestsWriterTest.cs | 2 +- .../Write/Specials/TeamCityWriterBaseTest.cs | 2 +- .../TeamCity.ServiceMessages.csproj | 3 +- ...s => IFlowAwareServiceMessageProcessor.cs} | 6 +-- .../Write/Special/ITeamCityServiceMessages.cs | 14 ++---- ...er.cs => FlowAwareServiceMessageWriter.cs} | 35 ++++++++----- .../Write/Special/Impl/TeamCityWriterImpl.cs | 4 +- .../Impl/Updater/FlowMessageUpdater.cs | 18 ++----- .../Special/Impl/Writer/TeamCityFlowWriter.cs | 34 +++++++------ .../Impl/Writer/TeamCityTestSuiteBlock.cs | 4 +- .../Write/Special/TeamCityServiceMessages.cs | 18 ++++--- build.proj | 2 +- 17 files changed, 164 insertions(+), 81 deletions(-) create mode 100644 TeamCity.ServiceMessages.Tests/Write/Specials/FlowAwareServiceMessageWriterTest.cs rename TeamCity.ServiceMessages/Write/Special/{IFlowServiceMessageProcessor.cs => IFlowAwareServiceMessageProcessor.cs} (88%) rename TeamCity.ServiceMessages/Write/Special/Impl/{FlowServiceMessageWriter.cs => FlowAwareServiceMessageWriter.cs} (69%) diff --git a/TeamCity.ServiceMessages.Tests/Read/ServiceMessageParserPerformanceTest.cs b/TeamCity.ServiceMessages.Tests/Read/ServiceMessageParserPerformanceTest.cs index 81ffcad..f10bcdf 100644 --- a/TeamCity.ServiceMessages.Tests/Read/ServiceMessageParserPerformanceTest.cs +++ b/TeamCity.ServiceMessages.Tests/Read/ServiceMessageParserPerformanceTest.cs @@ -25,6 +25,7 @@ namespace JetBrains.TeamCity.ServiceMessages.Tests.Read using ServiceMessages.Read; [TestFixture] + [Explicit] public class ServiceMessageParserPerformanceTest { private static string GenerateTestData(int sz) @@ -77,4 +78,4 @@ public void Parse10000() Console.Out.WriteLine(trash); } } -} \ No newline at end of file +} diff --git a/TeamCity.ServiceMessages.Tests/TeamCity.ServiceMessages.Tests.csproj b/TeamCity.ServiceMessages.Tests/TeamCity.ServiceMessages.Tests.csproj index e522243..e27cb11 100644 --- a/TeamCity.ServiceMessages.Tests/TeamCity.ServiceMessages.Tests.csproj +++ b/TeamCity.ServiceMessages.Tests/TeamCity.ServiceMessages.Tests.csproj @@ -1,5 +1,5 @@ - - + + netstandard1.6;net45;netcoreapp1.0;netcoreapp2.0;netcoreapp3.0 TeamCity.ServiceMessages.Tests @@ -14,16 +14,17 @@ True TeamCity.ServiceMessages.snk False - - + + + 3.12.0 - - + + - - - + + + diff --git a/TeamCity.ServiceMessages.Tests/Write/Specials/FlowAwareServiceMessageWriterTest.cs b/TeamCity.ServiceMessages.Tests/Write/Specials/FlowAwareServiceMessageWriterTest.cs new file mode 100644 index 0000000..fa3a381 --- /dev/null +++ b/TeamCity.ServiceMessages.Tests/Write/Specials/FlowAwareServiceMessageWriterTest.cs @@ -0,0 +1,49 @@ +namespace JetBrains.TeamCity.ServiceMessages.Tests.Write.Specials +{ + using System.Collections.Generic; + using System.Linq; + using Moq; + using NUnit.Framework; + using ServiceMessages.Write; + using ServiceMessages.Write.Special; + using ServiceMessages.Write.Special.Impl; + + [TestFixture] + public class FlowAwareServiceMessageWriterTest + { + [Test] + public void ShouldNotAddFlowIdAttributeToServiceMessageWhenFlowIdIsNotSet() + { + var processorMock = new Mock(); + var flowAwareWriter = new FlowAwareServiceMessageWriter( + null, + processorMock.Object, + Mock.Of(), + new List()); + + var serviceMessage = new ServiceMessage("foo"); + flowAwareWriter.AddServiceMessage(serviceMessage); + + processorMock.Verify(x => x.AddServiceMessage( + It.Is(m => m.Keys.All(k => k != "flowId")))); + } + + [Test] + public void ShouldAddFlowIdAttributeToServiceMessageWhenFlowIdIsSet() + { + string flowId = "123"; + var processorMock = new Mock(); + var flowAwareWriter = new FlowAwareServiceMessageWriter( + flowId, + processorMock.Object, + Mock.Of(), + new List()); + + var serviceMessage = new ServiceMessage("foo"); + flowAwareWriter.AddServiceMessage(serviceMessage); + + processorMock.Verify(x => x.AddServiceMessage( + It.Is(m => m.GetValue("flowId") == flowId))); + } + } +} diff --git a/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityFlowWriterBaseTest.cs b/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityFlowWriterBaseTest.cs index a830d73..036bb38 100644 --- a/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityFlowWriterBaseTest.cs +++ b/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityFlowWriterBaseTest.cs @@ -24,11 +24,12 @@ namespace JetBrains.TeamCity.ServiceMessages.Tests.Write.Specials public abstract class TeamCityFlowWriterBaseTest : TeamCityWriterBaseTest { - protected abstract T Create(IFlowServiceMessageProcessor proc); + protected abstract T Create(IFlowAwareServiceMessageProcessor proc); protected sealed override T Create(IServiceMessageProcessor proc) { - return Create(new FlowServiceMessageWriter(proc, new DefaultFlowIdGenerator(), Enumerable.Empty())); + var flowIdGenerator = new DefaultFlowIdGenerator(); + return Create(new FlowAwareServiceMessageWriter(flowIdGenerator.NewFlowId(), proc, flowIdGenerator, Enumerable.Empty())); } protected override ToStringProcessor CreateProcessor() @@ -70,4 +71,4 @@ private string FlowToString(string flowId) } } } -} \ No newline at end of file +} diff --git a/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityFlowWriterTest.cs b/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityFlowWriterTest.cs index 8548a6e..ed8e4d8 100644 --- a/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityFlowWriterTest.cs +++ b/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityFlowWriterTest.cs @@ -17,6 +17,8 @@ namespace JetBrains.TeamCity.ServiceMessages.Tests.Write.Specials { using System; + using System.Linq; + using Moq; using NUnit.Framework; using ServiceMessages.Write.Special; using ServiceMessages.Write.Special.Impl; @@ -25,7 +27,7 @@ namespace JetBrains.TeamCity.ServiceMessages.Tests.Write.Specials [TestFixture] public class TeamCityFlowWriterTest : TeamCityFlowWriterBaseTest> { - protected override TeamCityFlowWriter Create(IFlowServiceMessageProcessor proc) + protected override TeamCityFlowWriter Create(IFlowAwareServiceMessageProcessor proc) { return new TeamCityFlowWriter(proc, (x, _) => x, DisposableDelegate.Empty); } @@ -43,5 +45,24 @@ public void TestOpenCloseBlock() "##teamcity[flowStarted parent='1' flowId='2']", "##teamcity[flowFinished flowId='2']"); } + + [Test] + public void ShouldNotAddParentFlowAttributeToMessageAfterOpeningNewFlowIfThereIsNoParentFlow() + { + var parentFlowAwareProcessorMock = new Mock(); + var childFlowAwareProcessorMock = new Mock(); + parentFlowAwareProcessorMock.SetupGet(x => x.FlowId).Returns((string)null); + parentFlowAwareProcessorMock.Setup(x => x.ForNewFlow()).Returns(childFlowAwareProcessorMock.Object); + var teamCityFlowWriter = new TeamCityFlowWriter( + parentFlowAwareProcessorMock.Object, + (handler, processor) => Mock.Of(), + Mock.Of()); + + teamCityFlowWriter.OpenFlow(); + + childFlowAwareProcessorMock.Verify( + x => x.AddServiceMessage( + It.Is(m => m.Keys.All(k => k != "parent")))); + } } -} \ No newline at end of file +} diff --git a/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityTestsWriterTest.cs b/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityTestsWriterTest.cs index 37b98f0..0fe76d7 100644 --- a/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityTestsWriterTest.cs +++ b/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityTestsWriterTest.cs @@ -26,7 +26,7 @@ namespace JetBrains.TeamCity.ServiceMessages.Tests.Write.Specials [TestFixture] public class TeamCityTestsWriterTest : TeamCityFlowWriterBaseTest { - protected override ITeamCityTestsWriter Create(IFlowServiceMessageProcessor proc) + protected override ITeamCityTestsWriter Create(IFlowAwareServiceMessageProcessor proc) { return new TeamCityTestSuiteBlock(proc, DisposableDelegate.Empty); } diff --git a/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityWriterBaseTest.cs b/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityWriterBaseTest.cs index d9f2d08..2bc68dd 100644 --- a/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityWriterBaseTest.cs +++ b/TeamCity.ServiceMessages.Tests/Write/Specials/TeamCityWriterBaseTest.cs @@ -86,7 +86,7 @@ public virtual void AddServiceMessage(IServiceMessage serviceMessage) public abstract class TeamCityWriterBaseTest : TeamCityFlowWriterBaseTest { - protected override ITeamCityWriter Create(IFlowServiceMessageProcessor proc) + protected override ITeamCityWriter Create(IFlowAwareServiceMessageProcessor proc) { return new TeamCityWriterImpl(proc, DisposableDelegate.Empty); } diff --git a/TeamCity.ServiceMessages/TeamCity.ServiceMessages.csproj b/TeamCity.ServiceMessages/TeamCity.ServiceMessages.csproj index 6b6e312..2dc16d9 100644 --- a/TeamCity.ServiceMessages/TeamCity.ServiceMessages.csproj +++ b/TeamCity.ServiceMessages/TeamCity.ServiceMessages.csproj @@ -21,10 +21,11 @@ False JetBrains TeamCity Service Messages read/write access - This library provides read/write access to TeamCity Service messages. Take a look at the description of service messages at http://confluence.jetbrains.net/display/TCDL/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ServiceMessages + This library provides read/write access to TeamCity Service messages. The documentation on service messages can be found at https://www.jetbrains.com/help/teamcity/service-messages.html https://github.com/JetBrains/TeamCity.ServiceMessages/raw/master/LICENSE.txt https://github.com/JetBrains/TeamCity.ServiceMessages https://github.com/JetBrains/TeamCity.ServiceMessages/raw/master/icon.png + Release descriptions are available at https://github.com/JetBrains/TeamCity.ServiceMessages/releases https://github.com/JetBrains/TeamCity.ServiceMessages.git git TeamCity ServiceMessage ServiceMessages diff --git a/TeamCity.ServiceMessages/Write/Special/IFlowServiceMessageProcessor.cs b/TeamCity.ServiceMessages/Write/Special/IFlowAwareServiceMessageProcessor.cs similarity index 88% rename from TeamCity.ServiceMessages/Write/Special/IFlowServiceMessageProcessor.cs rename to TeamCity.ServiceMessages/Write/Special/IFlowAwareServiceMessageProcessor.cs index e3f47e4..691c198 100644 --- a/TeamCity.ServiceMessages/Write/Special/IFlowServiceMessageProcessor.cs +++ b/TeamCity.ServiceMessages/Write/Special/IFlowAwareServiceMessageProcessor.cs @@ -19,7 +19,7 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special /// /// FlowId aware implementation of ServiceMessagesProcessor /// - public interface IFlowServiceMessageProcessor : IServiceMessageProcessor + public interface IFlowAwareServiceMessageProcessor : IServiceMessageProcessor { /// /// Current flow Id @@ -31,6 +31,6 @@ public interface IFlowServiceMessageProcessor : IServiceMessageProcessor /// /// [NotNull] - IFlowServiceMessageProcessor ForNewFlow(); + IFlowAwareServiceMessageProcessor ForNewFlow(); } -} \ No newline at end of file +} diff --git a/TeamCity.ServiceMessages/Write/Special/ITeamCityServiceMessages.cs b/TeamCity.ServiceMessages/Write/Special/ITeamCityServiceMessages.cs index e682dcc..9440bf0 100644 --- a/TeamCity.ServiceMessages/Write/Special/ITeamCityServiceMessages.cs +++ b/TeamCity.ServiceMessages/Write/Special/ITeamCityServiceMessages.cs @@ -25,24 +25,20 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special public interface ITeamCityServiceMessages { /// - /// Created writer that generates service messages to a Console.Out + /// Creates a writer that outputs service messages to Console.Out /// - /// - /// Implementation does not support multiple-threads. - /// If you need to log more me - /// /// [NotNull] ITeamCityWriter CreateWriter(); /// - /// Creates writer that translates service messages to the given - /// delegate. + /// Creates a writer that uses the provided delegate to output service messages /// /// generated service messages processor + /// specifies whether messages written without explicitly opening a flow should be marked with a common flow id /// [NotNull] - ITeamCityWriter CreateWriter(Action destination); + ITeamCityWriter CreateWriter(Action destination, bool addFlowIdsOnTopLevelMessages = true); /// /// Adds user-specific service message updater to the list of service message updaters. @@ -50,4 +46,4 @@ public interface ITeamCityServiceMessages /// updater instance void AddServiceMessageUpdater([NotNull] IServiceMessageUpdater updater); } -} \ No newline at end of file +} diff --git a/TeamCity.ServiceMessages/Write/Special/Impl/FlowServiceMessageWriter.cs b/TeamCity.ServiceMessages/Write/Special/Impl/FlowAwareServiceMessageWriter.cs similarity index 69% rename from TeamCity.ServiceMessages/Write/Special/Impl/FlowServiceMessageWriter.cs rename to TeamCity.ServiceMessages/Write/Special/Impl/FlowAwareServiceMessageWriter.cs index 242b78e..5d3fe36 100644 --- a/TeamCity.ServiceMessages/Write/Special/Impl/FlowServiceMessageWriter.cs +++ b/TeamCity.ServiceMessages/Write/Special/Impl/FlowAwareServiceMessageWriter.cs @@ -22,30 +22,35 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special.Impl using Updater; /// - /// Servivce message acceptor implementation with support of IServiceMessageUpdater chains + /// Service message acceptor implementation that is aware of service message flows and supports IServiceMessageUpdater chains /// - public class FlowServiceMessageWriter : IFlowServiceMessageProcessor + public class FlowAwareServiceMessageWriter : IFlowAwareServiceMessageProcessor { private readonly IFlowIdGenerator _generator; private readonly IServiceMessageProcessor _processor; private readonly List _updaters; /// - /// Creates generic processor that calls messages updaters and sends output to provided deledate. + /// Creates generic processor that calls messages updaters and sends output to provided delegate. /// + /// id of the flow assigned to messages written through this processor, can be null /// writer of service messages objects /// flow id generator that is called to create next flowId /// service message updaters, i.e. timestamp updater - public FlowServiceMessageWriter([NotNull] IServiceMessageProcessor processor, + public FlowAwareServiceMessageWriter( + string serviceMessageFlowId, + [NotNull] IServiceMessageProcessor processor, [NotNull] IFlowIdGenerator generator, [NotNull] IEnumerable updaters) { if (processor == null) throw new ArgumentNullException(nameof(processor)); if (generator == null) throw new ArgumentNullException(nameof(generator)); if (updaters == null) throw new ArgumentNullException(nameof(updaters)); + + FlowId = serviceMessageFlowId; _processor = processor; _generator = generator; - _updaters = IncludeFlowId(updaters); + _updaters = AddFlowIdUpdater(updaters.ToList()); } public void AddServiceMessage(IServiceMessage serviceMessage) @@ -54,26 +59,32 @@ public void AddServiceMessage(IServiceMessage serviceMessage) _processor.AddServiceMessage(_updaters.Aggregate(serviceMessage, (current, updater) => updater.UpdateServiceMessage(current))); } - public string FlowId => _updaters.OfType().First().FlowId; + public string FlowId { get; } /// /// Creates new ServiceMessage updater that uses specified FlowId /// - public IFlowServiceMessageProcessor ForNewFlow() + public IFlowAwareServiceMessageProcessor ForNewFlow() { - return new FlowServiceMessageWriter( + return new FlowAwareServiceMessageWriter( + _generator.NewFlowId(), _processor, _generator, - IncludeFlowId(_updaters) + _updaters ); } [NotNull] - private List IncludeFlowId([NotNull] IEnumerable updaters) + private List AddFlowIdUpdater([NotNull] List updaters) { + if (FlowId == null) + { + return updaters; + } + return updaters.Where(x => !(x is FlowMessageUpdater)) - .Union(new[] {new FlowMessageUpdater(_generator)}) + .Union(new[] {new FlowMessageUpdater(FlowId)}) .ToList(); } } -} \ No newline at end of file +} diff --git a/TeamCity.ServiceMessages/Write/Special/Impl/TeamCityWriterImpl.cs b/TeamCity.ServiceMessages/Write/Special/Impl/TeamCityWriterImpl.cs index f43af2a..b5eafc8 100644 --- a/TeamCity.ServiceMessages/Write/Special/Impl/TeamCityWriterImpl.cs +++ b/TeamCity.ServiceMessages/Write/Special/Impl/TeamCityWriterImpl.cs @@ -25,7 +25,7 @@ public class TeamCityWriterImpl : TeamCityWriterFacade, ISubWriter private readonly IEnumerable _writeCheck; public TeamCityWriterImpl( - [NotNull] IFlowServiceMessageProcessor processor, + [NotNull] IFlowAwareServiceMessageProcessor processor, [NotNull] IDisposable dispose) : this(processor, new TeamCityFlowWriter(processor, (handler, writer) => new TeamCityWriterImpl(writer, handler), DisposableDelegate.Empty), @@ -89,4 +89,4 @@ protected override void CheckConsistency() AssertNoChildOpened(); } } -} \ No newline at end of file +} diff --git a/TeamCity.ServiceMessages/Write/Special/Impl/Updater/FlowMessageUpdater.cs b/TeamCity.ServiceMessages/Write/Special/Impl/Updater/FlowMessageUpdater.cs index 66f2428..77b528d 100644 --- a/TeamCity.ServiceMessages/Write/Special/Impl/Updater/FlowMessageUpdater.cs +++ b/TeamCity.ServiceMessages/Write/Special/Impl/Updater/FlowMessageUpdater.cs @@ -24,28 +24,20 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special.Impl.Updater /// public class FlowMessageUpdater : IServiceMessageUpdater { + [NotNull] private readonly string _flowId; + /// /// Constructs updater /// /// flowId set to all messages public FlowMessageUpdater([NotNull] string flowId) { - FlowId = flowId ?? throw new ArgumentNullException(nameof(flowId)); + _flowId = flowId ?? throw new ArgumentNullException(nameof(flowId)); } - /// - /// Creates flow id from given generator instance - /// - /// - public FlowMessageUpdater([NotNull] IFlowIdGenerator flowId) : this(flowId.NewFlowId()) - { - } - - public string FlowId { [NotNull] get; } - public IServiceMessage UpdateServiceMessage(IServiceMessage message) { - return message.DefaultValue != null || message.GetValue("flowId") != null ? message : new PatchedServiceMessage(message) { { "flowId", FlowId } }; + return message.DefaultValue != null || message.GetValue("flowId") != null ? message : new PatchedServiceMessage(message) { { "flowId", _flowId } }; } } -} \ No newline at end of file +} diff --git a/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityFlowWriter.cs b/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityFlowWriter.cs index 216f68b..f5d6240 100644 --- a/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityFlowWriter.cs +++ b/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityFlowWriter.cs @@ -19,20 +19,20 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special.Impl.Writer using System; using System.Threading; - public class TeamCityFlowWriter : BaseDisposableWriter, ITeamCityFlowWriter, ISubWriter + public class TeamCityFlowWriter : BaseDisposableWriter, ITeamCityFlowWriter, ISubWriter where TCloseBlock : IDisposable { - public delegate TCloseBlock CreateWriter([NotNull] IDisposable disposeHandler, [NotNull] IFlowServiceMessageProcessor writer); + public delegate TCloseBlock CreateWriter([NotNull] IDisposable disposeHandler, [NotNull] IFlowAwareServiceMessageProcessor writer); private readonly CreateWriter _closeBlock; - private int _isChildFlowOpenned; + private int _isChildFlowOpened; - public TeamCityFlowWriter([NotNull] IFlowServiceMessageProcessor target, [NotNull] CreateWriter closeBlock, [NotNull] IDisposable disposableHander) - : base(target, disposableHander) + public TeamCityFlowWriter([NotNull] IFlowAwareServiceMessageProcessor target, [NotNull] CreateWriter closeBlock, [NotNull] IDisposable disposableHandler) + : base(target, disposableHandler) { if (target == null) throw new ArgumentNullException(nameof(target)); if (closeBlock == null) throw new ArgumentNullException(nameof(closeBlock)); - if (disposableHander == null) throw new ArgumentNullException(nameof(disposableHander)); + if (disposableHandler == null) throw new ArgumentNullException(nameof(disposableHandler)); _closeBlock = closeBlock; } @@ -52,23 +52,29 @@ public TCloseBlock OpenFlow() ); //##teamcity[flowStarted flowId='%lt;new flow id>' parent='current flow id'] - processor.AddServiceMessage(new ServiceMessage("flowStarted") {{"parent", myTarget.FlowId}}); - Interlocked.Increment(ref _isChildFlowOpenned); + var flowStartedMessage = new ServiceMessage("flowStarted"); + if (myTarget.FlowId != null) + { + flowStartedMessage.Add("parent", myTarget.FlowId); + } + processor.AddServiceMessage(flowStartedMessage); + + Interlocked.Increment(ref _isChildFlowOpened); return block; } protected override void DisposeImpl() { - if (_isChildFlowOpenned != 0) + if (_isChildFlowOpened != 0) throw new InvalidOperationException("Some of child block writers were not disposed"); } - private void CloseBlock([NotNull] IFlowServiceMessageProcessor flowId) + private void CloseBlock([NotNull] IFlowAwareServiceMessageProcessor flowAwareServiceMessageProcessor) { - if (flowId == null) throw new ArgumentNullException(nameof(flowId)); - Interlocked.Decrement(ref _isChildFlowOpenned); + if (flowAwareServiceMessageProcessor == null) throw new ArgumentNullException(nameof(flowAwareServiceMessageProcessor)); + Interlocked.Decrement(ref _isChildFlowOpened); //##teamcity[flowFinished flowId='%lt;new flow id>'] - flowId.AddServiceMessage(new ServiceMessage("flowFinished")); + flowAwareServiceMessageProcessor.AddServiceMessage(new ServiceMessage("flowFinished")); } } -} \ No newline at end of file +} diff --git a/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityTestSuiteBlock.cs b/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityTestSuiteBlock.cs index 1ad8501..3b9b487 100644 --- a/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityTestSuiteBlock.cs +++ b/TeamCity.ServiceMessages/Write/Special/Impl/Writer/TeamCityTestSuiteBlock.cs @@ -18,13 +18,13 @@ namespace JetBrains.TeamCity.ServiceMessages.Write.Special.Impl.Writer { using System; - public class TeamCityTestSuiteBlock : BaseDisposableWriter, ITeamCityTestsSubWriter, ISubWriter + public class TeamCityTestSuiteBlock : BaseDisposableWriter, ITeamCityTestsSubWriter, ISubWriter { private readonly TeamCityFlowWriter _flows; private int _isChildSuiteOpened; private int _isChildTestOpened; - public TeamCityTestSuiteBlock([NotNull] IFlowServiceMessageProcessor target, [NotNull] IDisposable disposableHandler) + public TeamCityTestSuiteBlock([NotNull] IFlowAwareServiceMessageProcessor target, [NotNull] IDisposable disposableHandler) : base(target, disposableHandler) { if (target == null) throw new ArgumentNullException(nameof(target)); diff --git a/TeamCity.ServiceMessages/Write/Special/TeamCityServiceMessages.cs b/TeamCity.ServiceMessages/Write/Special/TeamCityServiceMessages.cs index bbc8464..29defbf 100644 --- a/TeamCity.ServiceMessages/Write/Special/TeamCityServiceMessages.cs +++ b/TeamCity.ServiceMessages/Write/Special/TeamCityServiceMessages.cs @@ -65,19 +65,23 @@ public void AddServiceMessageUpdater(IServiceMessageUpdater updater) Updaters = Updaters.Union(new[] {updater}).ToArray(); } - public ITeamCityWriter CreateWriter() - { - return CreateWriter(Console.WriteLine); - } + public ITeamCityWriter CreateWriter() => CreateWriter(Console.WriteLine, true); - public ITeamCityWriter CreateWriter(Action destination) + public ITeamCityWriter CreateWriter(Action destination, bool addFlowIdsOnTopLevelMessages = true) { if (destination == null) throw new ArgumentNullException(nameof(destination)); - var processor = new FlowServiceMessageWriter(new ServiceMessagesWriter(Formatter, destination), FlowIdGenerator, Updaters.ToList()); + + var rootServiceMessageFlowId = addFlowIdsOnTopLevelMessages ? FlowIdGenerator.NewFlowId() : null; + var processor = new FlowAwareServiceMessageWriter( + rootServiceMessageFlowId, + new ServiceMessagesWriter(Formatter, destination), + FlowIdGenerator, + Updaters.ToList()); + return new TeamCityWriterImpl( processor, DisposableDelegate.Empty ); } } -} \ No newline at end of file +} diff --git a/build.proj b/build.proj index 09a0962..3792c93 100644 --- a/build.proj +++ b/build.proj @@ -1,7 +1,7 @@ - 3.0.0-dev + 4.0.0-dev Release packages