Releases: hudl/Mjolnir
3.2.1
v3.2.0
This adds the ability to put Bulkheads into a metrics only mode, through configuration at a per bulkhead, with MjolnirConfiguration.BulkheadConfigurations[<bulkhead-key>].MetricsOnly = true
, or at global level using MjolnirConfiguration.BulkheadMetricsOnly = true
Bulkhead concurrency is set at 10 by default in Mjolnir, but this really is an arbitrary number and if bulkhead concurrency isn't properly tuned in a production scenario then it's possible to get a lot of BulkheadRejectionExceptions
that actually would have been safe to execute without the need to throttle.
The changes in v3.2.0 add the ability to quickly turn off bulkhead rejections during a production scenario like this.
We felt like it was still important to get metrics for rejections during a time when they're effectively not rejecting, as this may help with tuning the concurrency levels in the future - hence "MetricsOnly".
This version also adds a new IMetricEvent
implementation, with the GaugeLogMetrics
class to help with some of the diagnostic actions mentioned above.
v3.1.1
v3.1.0 was released to nuget.org without the proper metadata on the NuGet package. Since nuget.org will no longer let you modify metadata after a package is published and also won't let you delete the package, I'm creating a patched version to fix NuGet metadata.
v3.1.0
Description
This version makes it easier to consume the Mjolnir library on more platforms. From this version will be possible to use it by everything that targets netstandard1.2 or greater.
We've also made properties of the MjolnirConfiguration
class virtual and the class is no longer sealed. This will allow easier adaptation of the configuration of Mjolnir.
Changes
Enhancements
- Add virtual modifiers to
MjolnirConfiguration
class and remove thesealed
keyword from the class. - Lower target framework to
netstandard1.2
- Add a new protected constructor to AsyncCommand and SyncCommand to allow for extensions of the classes to override the command name.
Bug fixes
- Fix bug with not being able to serialize exception due to GroupKey not being serializable
Other
- Remove global.json content (specific SDK requirement)
- Include File and assembly version in csproj.
v3.0.0
This release contains breaking changes.
Summary
Major themes:
- Remove obsolete/deprecated functionality.
- Focus on
CommandInvoker
as the library entry point - Remove external library dependencies (logging, config, thread pools, common)
- Make all functionality injectable through
ICommandInvoker
instead of static assignments - .NET Core support
CommandInvoker
becomes the sole entry point for the library. See its constructor overloads for DI options. CommandInvoker
was introduced in 2.6.0, which is documented here.
Major changes
- 0e36dd6 Removed old
Command
.SyncCommand
andAsyncCommand
, introduced in 2.6.0, are the preferred replacement. - 0e36dd6 Removed thread pools and SmartThreadPool dependency. The thread pool behavior (which was used to limit concurrency) uses semaphore-backed bulkheads introduced in 2.6.0. The removal of SmartThreadPool makes converting to .NET Core more manageable (see #16).
- f83b511 Removed
IStats
and implementations. The preferred replacement isIMetricEvents
. - 13320cc Made configuration injectable and removed dependency on Hudl.Config. There is currently no internal replacement for the actual config implementation. Would recommend using ASP.NET Core's Configuration API. See further details on configuration below and in the wiki.
- 0edaaf2 871ab1c Removed dependency on
Hudl.Common
. Copied over the few classes (e.g.IClock
,UtcSystemClock
) that Mjolnir needs. - 5dd8295 Make logging injectable and remove dependency on
log4net
. There is currently no internal replacement for the actual logging implementation. - Removed
CommandInvoker.Instance
, it's an anti-pattern. Prefer to use DI to create and manage a singletonICommandInvoker
throughout your application. - e787e52 Moved the circuit breaker "ignored exceptions" (originally set statically on
CommandContext
) functionality toIBreakerExceptionHandler
, which can be injected intoCommandInvoker
's constructor. - Removed ability to configure gauge intervals for metric events. Gauges now fire at a fixed 1000 ms interval; if a client is implementing
IMetricEvents
and handling gauge calls, the client should handle debouncing or otherwise aggregating the gauges at a less frequent resolution if desired. - 88642e9 Internally,
CommandContext
has been replaced with factory classes; there's no longer a static, central repository for state. Instead, the assumption is that the caller will only create a singleCommandInvoker
instance (via DI) and reuse it. Callers who need static access should consider creating a static singleton wrapper around a single instance ofCommandInvoker
. Docs will be updated to make it clear that only a singleCommandInvoker
should be used throughout an application. - 3fb1215 db6ae03 Removed
Hudl.Mjolnir.Attributes
and the reflective proxying helper classes. Clients can re-implement these if desired, but this 1) removes a dependency on Castle.Core, and 2) though convenient, fosters a pattern (using attributes) that makes code hard to unit test. We may bring this back in the future if it's needed, but if we do it'll be as a separate library instead of built into Mjolnir proper. - Convert project format to VS2017 csproj, and reorganize source into
src/
andtest/unit
directories. - Mjolnir configuration re-write. It is based on strongly-typed classes now. IMjolnirConfig has been removed.
To provide configuration into Mjolnir, it is required to instantiate MjolnirConfiguration class and pass it into Mjolnir objects. You should create one instance of this class only. Dependency injection pattern may be used in order to achieve this.
If reading config from a file is required, an example implementation for JSON file has been provided in test project. See https://github.com/hudl/Mjolnir/pull/63/files#diff-1db9d5dd67e3c39c783fd9759d414387
In order to update configuration, it is required to call NotifyAfterConfigUpdate on MjolnirConfiguration after any change to MjolnirConfiguration - IMjolnirLog interface modification, making it a generic type and adding the Debug(string) method. The IMjolnirLogFactory interface is updated too, making the CreateLog() method typed. The main reason being that it's easier to inject generic types with a DI system and since we we're always creating loggers with typeof(....), it made more sense to make the type generic and reduce the overhead of creating a Type object. See more details below on how to implement these interfaces below.
- In Mjolnir 3.0.0 we're removing the hard dependency on log4net, and instead using logging interfaces, giving users of the library the chance to wire up the logging to their preferred implementation. The default implementation in the Mjolnir library is a no-op logger (see DefaultMjolnirLog and DefaultMjolnirLogFactory). Since the primary entry point to the Mjolnir library will be the CommandInvoker, you can pass in your own implementation of the IMjolnirLogFactory here.
- Wiki documentation updated (right now it lives in Version3 branch in wiki project).
Removed / changed public APIs
Removed
Hudl.Mjolnir.Attributes
CommandAttribute
Hudl.Mjolnir.Attributes
CommandTimeoutAttribute
Hudl.Mjolnir.Attributes
FireAndForgetAttribute
Hudl.Mjolnir.Command.Attribute
CommandAttribute
Hudl.Mjolnir.Command.Attribute
CommandTimeoutAttribute
Hudl.Mjolnir.Command.Attribute
FireAndForgetAttribute
Hudl.Mjolnir.Command.Attribute
CommandInterceptor
Hudl.Mjolnir
ICommand
Hudl.Mjolnir
Command<TResult>
Hudl.Mjolnir.Command
Command
Hudl.Mjolnir.Command
CommandCancelledException
Hudl.Mjolnir.Command
CommandFailedException
Hudl.Mjolnir.Command
CommandRejectedException
Hudl.Mjolnir.Command
CommandTimeoutException
Hudl.Mjolnir.Command
CommandContext
Hudl.Mjolnir.Command
FallbackStatus
Hudl.Mjolnir.Command
VoidResult
Hudl.Mjolnir.External
IStats
Changed
Hudl.Mjolnir.Key
GroupKey
no longer has[Serializable]
attributeHudl.Mjolnir.External
IMetricEvents.BulkheadConfigGauge()
is nowBulkheadGauge()
and has new parameters for the state of the bulkhead alongside the config values.Hudl.Mjolnir.External
IMetricEvents.BreakerConfigGauge()
is nowBreakerGauge()
and has new parameters for the state of the breaker alongside the config values.- Breaker and Bulkhead names can no longer be named
default
- an exception will be thrown if they are. This is to avoid ambiguity with the default config properties.
Removed library dependencies
- Hudl.Config
- Hudl.Common
- SmartThreadPool
- log4net
Added public APIs
Hudl.Mjolnir.External
IBreakerExceptionHandler
Hudl.Mjolnir.External
IMjolnirLogFactory
Hudl.Mjolnir.External
IMjolnirLog
Hudl.Mjolnir.Breaker
IgnoredExceptionHandler
Hudl.Mjolnir.Config.MjolnirConfiguration
MjolnirConfiguration
- main class for Mjolnir configuration. Replaces IMjolnirConfig. Holds all configuration values.Hudl.Mjolnir.Config.BreakerConfiguation
BreakerConfiguation
- configuration values for circuit breakers.Hudl.Mjolnir.Config.BulkheadConfiguration
BulkheadConfiguration
- configuration values for bulkheads.Hudl.Mjolnir.Config.CommandConfiguration
CommandConfiguration
- configuration values for commands.
v2.6.0
Pull Requests
- #45 Upgrade xUnit to 2.0.0
- #46 Rework API to better work with async and sync calls
- #50 Upgrade tests to use xUnit 2.0.0
ThrowsAsync
assertions
Issues
- #19 Use counting semaphores instead of thread pools for limiting concurrency
- #30 Move most README contents to wiki page(s)
- #42 Configuration prefixes are inconsistent
- #49 Stack trace information gets lost in fallback re-throw
Notes
All documentation has been moved to the wiki. More detail on the larger changes in this release can be found on #46.
This is a large release, but backwards compatible. SyncCommand
and AsyncCommand
have been introduced as base classes to replace Command
. The original Command
still exists, but has been deprecated and will likely be removed in a future major release.
Highlights of the new SyncCommand
/AsyncCommand
API
- CommandInvoker with Throw/Return variants - To help force the question of "what should happen on failure", invocation happens via an
InvokeThrow
orInvokeReturn
call, with the latter wrapping any exceptions and letting the caller act more decisively in the face of failure. - Improved testability - Testing
Command
behavior with the originalCommand
API was difficult; the newly-introducedICommandInvoker
can be injected for unit testing. - Use semaphore bulkheads (without queues) by default - Thread pools have been replaced by semaphores for lower overhead, dependency reduction, and better
async
support. There are no longer queues in front of the Bulkhead; re-adding them will be assessed for a future release. - Better interface for hooking into metrics -
IMetricEvents
replacesIStats
for a clearer way of hooking into metrics.
Notable differences between new and old Commands
With the two new SyncCommand
and AsyncCommand
base classes, there are some notable differences in behavior to the original Command
base class:
- The
Invoke
INFO log isInvoke
for both sync and async calls (Invoke Command={0} Breaker={1} Pool={2} Timeout={3}
). In the old Command, it'sInvokeAsync
for the async call. - Exceptions aren't wrapped in a
CommandFailedException
. Instead, the root cause exception is simply rethrown with some Command-specific data attached to it. - "Pool" is now "Bulkhead" in a handful of configs, logs, and properties. If porting old Commands over to the new base classes, be sure to duplicate any configured pool values with the appropriate "bulkhead" configuration key.
- New Commands (sync/async) have a timeout configuration key that starts with
mjolnir.command.
The old Commands were inconsistent with the rest of the library and just started withcommand.
. Examples:- Old:
command.my-group.MyCommand.Timeout=1000
- New:
mjolnir.command.my-group.MyCommand.Timeout=1000
- Old:
- New commands default to a 2000ms timeout instead of 15000ms.
v2.5.0
#43 - Understand the cause of Mjolnir command failures
Notes:
Prior to this release a CommandFailedException
would be thrown with a status of "Canceled", regardless of whether it was an explicit cancellation by a custom CancellationToken
or if it was due to Mjolnir's built in timeout CancellationToken
. This release changes that status to more accurately reflect the true cause of the cancellation.
This is not considered as a breaking change but may have impact downstream assumptions about the CommandFailedException
status codes.
v2.4.0
v2.3.0
v2.2.0
-
#35 Change command loggers to use the command name instead of the generic class name.
[Hudl.Mjolnir.Command.Command
1]becomes
[Hudl.Mjolnir.Command.group-name.CommandName]`. -
#34 Allow global default configuration via chained
ConfigurableValues
. Example:mjolnir.breaker.<breaker-name>.thresholdPercentage
mjolnir.breaker.default.thresholdPercentage
- Literal default from
CommandContext
(50
).
Soft breaking change: Any breakers or pools that had previously been named
default
will and received specific configuration values will cause those values to get used over the defaults in the code.