Skip to content

Commit

Permalink
ISorted and SortBySortIndex
Browse files Browse the repository at this point in the history
  • Loading branch information
BEagle1984 committed Dec 26, 2019
1 parent 30698c7 commit d942ec2
Show file tree
Hide file tree
Showing 13 changed files with 101 additions and 30 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<Description>Silverback is a simple framework to build reactive, event-driven, microservices.</Description>
<License>MIT</License>
<Copyright>Copyright (c) 2019 Sergio Aquilini</Copyright>
<VersionSuffix>-rc2</VersionSuffix>
<VersionSuffix>-rc3</VersionSuffix>
<BaseVersion>1.1.0$(VersionSuffix)</BaseVersion>
<ProjectUrl>https://beagle1984.github.io/silverback/</ProjectUrl>
<RepositoryUrl>https://github.com/BEagle1984/silverback/</RepositoryUrl>
Expand Down
6 changes: 5 additions & 1 deletion docs/_docs/0-introduction/003-releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ permalink: /docs/releases
toc: true
---

## [1.1.0-rc2](https://github.com/BEagle1984/silverback/releases/tag/1.1.0-rc2)
## [1.1.0-rc3](https://github.com/BEagle1984/silverback/releases/tag/1.1.0-rc3)

### What's new
* Added `IEndpointsConfigurator` interface to allow splitting the endpoints configuration across multiple types (see [Connecting to a Message Broker]({{ site.baseurl }}/docs/quickstart/message-broker#using-iendpointsconfigurator))
* Added support for distributed tracing (based on standard [System.Diagnostics.DiagnosticSource](https://www.nuget.org/packages/System.Diagnostics.DiagnosticSource/))
* Added `IProducerBehavior` and `IConsumerBehavior` to create an extension point closer to the actual message broker logic (see [Behaviors]({{ site.baseurl }}/docs/quickstart/behaviors))

### Breaking Changes
* `ISortedBehavior` was removed and replaced by a generic `ISorted` interface

## [1.0.5](https://github.com/BEagle1984/silverback/releases/tag/1.0.5)

Expand Down
14 changes: 10 additions & 4 deletions docs/_docs/1-quickstart/107-behaviors.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ permalink: /docs/quickstart/behaviors
toc: false
---

Behaviors can be used to build a custom pipeline (similar to the asp.net pipeline), easily adding your cross-cutting functionalities such as logging, validation, etc.
The behaviors can be used to build a custom pipeline (similar to the asp.net pipeline), easily adding your cross-cutting functionalities such as logging, validation, etc.

## IBehavior

A behavior must implement the `IBehavior` interface and be registered for dependency injection.

```c#
using Silverback.Messaging.Subscribers;
using Silverback.Messaging.Publishing;

public class ValidationBehavior : IBehavior
{
Expand Down Expand Up @@ -43,7 +45,7 @@ public void ConfigureServices(IServiceCollection services)

At every call to `IPublisher.Publish` the `Handle` method of each registered behavior is called, passing in the array of messages and the delegate to the next step in the pipeline. This gives you the flexibility to execute any sort of code before and after the messages have been actually published (before or after calling the `next()` step). You can for example modify the messages before publishing them, validate them (like in the above example), add some logging / tracing, etc.

## Message headers
### Example: Message headers

The behaviors can be quite useful to get and set the message headers for inbound/outbound messages.

Expand Down Expand Up @@ -99,4 +101,8 @@ public class LogHeadersBehavior : IBehavior
```

**Note:** `IInboundMessage` and `IOutboundMessage` are internally used by Silverback to wrap the messages being sent to or received from the message broker.
{: .notice--info}
{: .notice--info}

## IProducerBehavior and IConsumerBehavior

The `IProducerBehavior` and `IConsumerBehavior` are similar to the `IBehavior` but work at a lower level, much closer to the message broker. You should be able to accomplish most tasks with the normal `IBehavior`.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright (c) 2019 Sergio Aquilini
// This code is licensed under MIT license (see LICENSE file for details)

namespace Silverback.Messaging.Publishing
namespace Silverback
{
public interface ISortedBehavior : IBehavior
public interface ISorted
{
int SortIndex { get; }
}
Expand Down
19 changes: 2 additions & 17 deletions src/Silverback.Core/Messaging/Publishing/Publisher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,23 +102,8 @@ private Task<IEnumerable<object>> InvokeNonExclusiveMethods(IEnumerable<object>
.ParallelSelectManyAsync(method =>
GetMethodInvoker().Invoke(method, messages, executeAsync));

private IEnumerable<IBehavior> GetBehaviors()
{
if (_behaviors == null)
{
var behaviors = _serviceProvider.GetServices<IBehavior>();
var sortedBehaviors = behaviors.OfType<ISortedBehavior>().OrderBy(b => b.SortIndex).ToList();
behaviors = behaviors.Where(b => !(b is ISortedBehavior)).ToList();

_behaviors =
sortedBehaviors.Where(b => b.SortIndex <= 0)
.Union(behaviors)
.Union(sortedBehaviors.Where(b => b.SortIndex > 0))
.ToList();
}

return _behaviors;
}
private IEnumerable<IBehavior> GetBehaviors() =>
_behaviors ??= _serviceProvider.GetServices<IBehavior>().SortBySortIndex();

private SubscribedMethodInvoker GetMethodInvoker() =>
_methodInvoker ??= _serviceProvider.GetRequiredService<SubscribedMethodInvoker>();
Expand Down
23 changes: 23 additions & 0 deletions src/Silverback.Core/Util/EnumerableSortExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2019 Sergio Aquilini
// This code is licensed under MIT license (see LICENSE file for details)

using System.Collections.Generic;
using System.Linq;

namespace Silverback.Util
{
internal static class EnumerableSortExtensions
{
public static IEnumerable<T> SortBySortIndex<T>(this IEnumerable<T> items)
{
var sorted = items.OfType<ISorted>().OrderBy(b => b.SortIndex).ToList();
var unsortable = items.Where(b => !(b is ISorted)).ToList();

return sorted
.Where(b => b.SortIndex <= 0).Cast<T>()
.Union(unsortable)
.Union(sorted.Where(b => b.SortIndex > 0).Cast<T>())
.ToList();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

namespace Silverback.Messaging.Behaviors
{
public class KafkaPartitioningKeyBehavior : ISortedBehavior
public class KafkaPartitioningKeyBehavior : IBehavior, ISorted
{
public int SortIndex { get; } = 200;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

namespace Silverback.Messaging.Connectors.Behaviors
{
public class OutboundProducingBehavior : ISortedBehavior
public class OutboundProducingBehavior : IBehavior, ISorted
{
private readonly IEnumerable<IOutboundConnector> _outboundConnectors;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

namespace Silverback.Messaging.Connectors.Behaviors
{
public class OutboundRoutingBehavior : ISortedBehavior
public class OutboundRoutingBehavior : IBehavior, ISorted
{
private readonly IServiceProvider _serviceProvider;
private readonly IOutboundRoutingConfiguration _routing;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Silverback.Tests.Core.TestTypes.Behaviors
{
public class TestSortedBehavior : ISortedBehavior
public class TestSortedBehavior : IBehavior, ISorted
{
private readonly List<string> _calls;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace Silverback.Tests.Core.Util
{
public class EnumerableForEachExtensions
public class EnumerableForEachExtensionsTests
{
[Fact]
public void ForEachTest()
Expand Down
53 changes: 53 additions & 0 deletions tests/Silverback.Core.Tests/Util/EnumerableSortExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) 2019 Sergio Aquilini
// This code is licensed under MIT license (see LICENSE file for details)

using System.Collections.Generic;
using FluentAssertions;
using Silverback.Messaging.Publishing;
using Silverback.Tests.Core.TestTypes.Behaviors;
using Silverback.Tests.Core.TestTypes.Messages;
using Silverback.Util;
using Xunit;

namespace Silverback.Tests.Core.Util
{
public class EnumerableSortExtensionsTests
{
[Fact]
public void SortBySortIndex_SomeItems_SortedAsExpected()
{
var items = new[]
{
new SortedItem(100),
new SortedItem(-50),
new SortedItem(50),
new SortedItem(-100),
new Item("unsorted3"),
new Item("unsorted2")
};

var sorted = items.SortBySortIndex();

sorted.Should().BeEquivalentTo(
new SortedItem(-100),
new SortedItem(-50),
new Item("unsorted3"),
new Item("unsorted2"),
new SortedItem(50),
new SortedItem(100)
);
}

private class Item
{
public Item(string id) => Id = id;
public string Id { get; }
}

private class SortedItem : Item, ISorted
{
public SortedItem(int sortIndex) : base(sortIndex.ToString()) => SortIndex = sortIndex;
public int SortIndex { get;}
}
}
}

0 comments on commit d942ec2

Please sign in to comment.