rebus-org / Rebus

:bus: Simple and lean service bus implementation for .NET
https://mookid.dk/category/rebus
Other
2.31k stars 360 forks source link

Port to .NET core #358

Closed mookid8000 closed 7 years ago

mookid8000 commented 8 years ago

http://blog.marcgravell.com/2015/11/the-road-to-dnx-part-1.html

mookid8000 commented 8 years ago

http://blog.marcgravell.com/2015/11/the-road-to-dnx-part-2.html

mookid8000 commented 8 years ago

http://blog.marcgravell.com/2015/11/the-road-to-dnxpart-3.html

gertjvr commented 8 years ago

I was able to run rebus + rabbitmq with mono inside docker container :)

mookid8000 commented 8 years ago

Cool! and that just worked?

gertjvr commented 8 years ago

Yip serilog was broken but got around it with the beta packages On 12 Feb 2016 6:50 PM, "Mogens Heller Grabe" notifications@github.com wrote:

Cool! and that just worked?

— Reply to this email directly or view it on GitHub https://github.com/rebus-org/Rebus/issues/358#issuecomment-183235168.

runes83 commented 8 years ago

Is this something you are working on? Could open up many new possiblities :-)

mookid8000 commented 8 years ago

I'm currently watching the .NET Core progress, waiting for things to settle down just a bit before I do too much.

So I'm not actively working on it, but I am definitely planning on doing it :)

imperugo commented 8 years ago

Hi, dunno if you already notice it (otherwise ignore my comment), but .NET Core is RTM now.

mookid8000 commented 8 years ago

Thanks for reminding me 😄 and yes, I did notice that - in fact I've installed it both on my Mac and in my Windows VM. My plan is to play around with releasing some of my smaller things on .NET Core first, e.g. Tababular and Injectionist

NKnusperer commented 8 years ago

Any updates on this?

mookid8000 commented 8 years ago

Not really – is it something you would find interesting?

NKnusperer commented 8 years ago

No, currently not. But would be cool to see Rebus services running on Linux ^^

gertjvr commented 8 years ago

Looking pretty close to having all dependencies there to port to .net core https://icanhasdot.net/result?github=rebus-org~2Frebus

bertvansteen commented 8 years ago

As a DevOps enthousiast I think the release of NET Core is awesome, I'm playing with .NET Core, Docker and NGINX in a pet project and absolutely love it.

Don't underestimate the effort that will go into supporting .NET Core: I hacked together a PoC version of Rebus that supports .NET Standard 1.5 with RabbitMQ and StructureMap, it's nothing near finished and didn't even run the unit tests:

https://github.com/bertvansteen/Rebus/tree/netcore-rabbitmq-structuremap-poc

Some notes:

I hope this helps in better understanding the effort required for supporting .NET Core.

mookid8000 commented 8 years ago

@bertvansteen thank you so much for reporting your experiences 👍

I don't understand fully how these things work yet.... I know .NETStandard 1.1 corresponds to .NET 4.5... are the .NETStandard targets backwards compatible, such that it would be possible to target .NETStandard 1.1 and thus support all newer platforms?

bertvansteen commented 8 years ago

This is an experiment for me too.

It appears that most of the compiler errors disappear when targetting .NET Standard 1.5 (supported in .NET 4.6.2 and .NET core) which is a superset of 1.4 which in turn is a superset... We have to target multiple frameworks and use compiler directives to support .NET 4.5, I've updated my PoC branch, I also fixed the unit testing discovery issue for .NET 4.5. (but autodata doesn't work yet)

You might want to consider removing the MSMQ transport and SQL Server persistance from the core project and move it to a separate assembly like RabbitMQ or Redis because commenting out a large chunk of code with compiler directives is not the way to go. Both versions of Rebus should more or less contain the same features and it might take a while before Microsoft releases a .NET Standard compatible version of the MSMQ connector since it's a Windows only product.

Some more notes:

mookid8000 commented 8 years ago

I have been messing around a little bit with these things. Rebus has not been split into separate repositories, which was a prerequisite in order to be able to commence porting the code to .NET Core.

As far as I can tell, it will be valid to use the following approach:

I have tried to port the code to the project.json/xproj format, but I stalled at the fact that ReSharper could not run my tests. I will probably have another go at it soon, maybe just running the tests from the command line. Or maybe experimenting with keeping the csproj around as well – as far as I can tell, project.json and xproj can be created and need not be modified unless packages are installed/uninstalled etc.

mvandevy commented 7 years ago

Been playing with the conversion of Rebus to .net core as well on my fork ([https://github.com/mvandevy/Rebus]) and been able to get it working as expected. All unit tests run green after some initial bug hunting. Probably made some suboptimal choices along the way, but wanted to get it running & testable. I've used the suggestions made by @bertvansteen to have an initial PoC running. What are there any plans to start the making the libraries .net core compatible?

mookid8000 commented 7 years ago

well.... I'm not sure I have thought it through yet – but I was thinking of making it .NET Core compatible and then call it "Rebus 3"....

but I guess that is not even necessary – it should be possible to compile a Rebus 2.2.0 even (the 2.1.6 version is the most recent on NuGet.org), simply adding a "lib/DNXORWHATEVERITISCALLEDTHESEDAYS" folder in addition to the existing "lib/NET45" folder in the NuGet package, right?

mookid8000 commented 7 years ago

Probably made some suboptimal choices along the way, but wanted to get it running & testable

That's a huge step btw., so that is just awesome!

mookid8000 commented 7 years ago

From the project.json it does not seem like you are targeting .NET 4.5 too – is there something I am missing?

mvandevy commented 7 years ago

You are right, I'm not yet targeting .NET 4.5. Thats the next step, just wanted to make sure that it worked on .net core first. Maybe you've already tried converting it and keeping it compatible with .NET 4.5. If that's the case, then I've missed that change/issue where you did something similar and mentioned it.

Anyway, by your response it seems I have some more work ahead before you'll accept a pull request ;-)

mookid8000 commented 7 years ago

Anyway, by your response it seems I have some more work ahead before you'll accept a pull request ;-)

well..... I would love a PR, but I don't want to obstruct the current line of development with Rebus.... I will accept your PR anytime, but I would like to keep it on a separate branch for now.

Just let me know when you feel like contributing it – then I will set up the branch 😄

mvandevy commented 7 years ago

I'll let you know when I have something decent to put into a branch. Hopefully rather sooner than later.

One of the most prominent breaking changes on .net core is the disappearance of the 'ApplicationException' base class. That caused me a headache at first while running the tests, especially in the 'TestRetryExceptionCustomization' test as I used the 'Exception' class as a replacement for the 'ApplicationException' class.

I've also the tests to Xunit, because didn't have the time yet to play around with NUnit on .net core. One thing to mention about this, is that the test suite doesn't really like to be executed in a parallel mode ;-)

mookid8000 commented 7 years ago

I'll let you know when I have something decent to put into a branch. Hopefully rather sooner than later.

🤘

One of the most prominent breaking changes on .net core is the disappearance of the 'ApplicationException' base class. That caused me a headache at first while running the tests, especially in the 'TestRetryExceptionCustomization' test as I used the 'Exception' class as a replacement for the 'ApplicationException' class.

I actually thought I had replaced all usage of ApplicationException with RebusApplicationException... 😳

I've also the tests to Xunit, because didn't have the time yet to play around with NUnit on .net core. One thing to mention about this, is that the test suite doesn't really like to be executed in a parallel mode ;-)

ah, bummer – but aren't almost all of the tests running on the in-mem transport?

do you know if there is a way to create "mutual exclusion groups" of tests, or somehow affect what gets to run in parallel and what needs to be serialized?

mvandevy commented 7 years ago

Come to think of it, if you are able to already set up the branch, then I'll start on this tonight. A slot opened up. 😃

ah, bummer – but aren't almost all of the tests running on the in-mem transport?

Yep, but the issue is related to the timeouts. Default timeouts are 5s and sometimes the test succeeds within these 5s, sometimes it doesn't. The tests that fail are completely random. At least on my Mac. Only got it working by disabling parallel execution.

do you know if there is a way to create "mutual exclusion groups" of tests, or somehow affect what gets to run in parallel and what needs to be serialized?

You've got the concept of test collections. Tests that are within the same test collection are not executed in parallel. So this would work.

BTW I'm guessing you probably want to keep the tests on NUnit?

mookid8000 commented 7 years ago

Come to think of it, if you are able to already set up the branch, then I'll start on this tonight. A slot opened up. 😃

I love it when that happens 😁 I just pushed this: feature/mvandevy

BTW I'm guessing you probably want to keep the tests on NUnit?

Well...... actually I am indifferent as to which attributes I have to put on things to have them executed.... I don't know anything about XUnit, but I use very few special features (e.g. [TestCase(..)] and stuff), so I guess converting to XUnit or Fixie or maybe even MS Test(*)(**) can easily be done.


(*) To my surprise, a recent project for a client containing MSTest tests actually revealed that running those tests from the R# runner was insanely fast!

When MS first introduced the test framework, it was horribly slow – but apparently, that has changed 😄

(**) Although I must say that [TestClass] and [TestMethod] are lame-ass names. [Test] is the best, [Fact] is also OK, and you cannot deny that a class with tests can be considered a [TestFixture] – although a class containing tests ought to be considered a test fixture just from the fact that it contains tests and is not abstract, like XUnit does it.

"TestClass"....... pfui!

mookid8000 commented 7 years ago

Btw. I'm not sure you can even make a PR against a specific branch.... just make the PR when you are ready, and then I will merge it the right place 😄

ajensenwaud commented 7 years ago

Does anyone have Rebus running in any shape or form on .NET Core 1.1 yet? Greetings from 7620 :)

mvandevy commented 7 years ago

Yep, I have a temporary fork at https://github.com/mvandevy/Rebus, but was planning to finish up a branch here tomorrow.

JonnyBooker commented 7 years ago

Is there any update on this? Looking forward to seeing this in .NET Core

mookid8000 commented 7 years ago

This is how to do it in VS2017, targeting .NET 4.5 and .NET Core at the same time:

skaermbillede 2017-01-19 kl 12 27 49

(original 🐦 : https://twitter.com/davkean/status/822040785658839040 )

mookid8000 commented 7 years ago

IOW it seems to be a matter of

mvandevy commented 7 years ago

@mookid8000

Hi, after countless tries and struggling with the RC versions of VS2017. I kinda gave on making rebus compatible with both net45 and netstandard. Last week I found the courage again to try again. After an update to the latest RC I couldn't believe it. (Partial) success! I've been able to get it building successfully for both net45 and netstandard1.6. One of the issues I still need to deal with though is GoCommando. This lib isn't compatible with netstandard yet. So would you be able to make a branch on GoCommando for me, just like the branch on Rebus? I'll then be able to trigger a pull request for GoCommando and get it in nuget (through you). After that I'll be able to (hopefully) complete the port.

mookid8000 commented 7 years ago

Last week I found the courage again to try again.

💪

After an update to the latest RC I couldn't believe it. (Partial) success! I've been able to get it building successfully for both net45 and netstandard1.6.

🤘

One of the issues I still need to deal with though is GoCommando. This lib isn't compatible with netstandard yet. So would you be able to make a branch on GoCommando for me, just like the branch on Rebus? I'll then be able to trigger a pull request for GoCommando and get it in nuget (through you). After that I'll be able to (hopefully) complete the port.

What do you say we ignore the Forklift for now? I had not though about this, but it is clear that it cannot readily be compiled for netstandard.

It would be an awesome achievement to get Rebus to simply have its core package available for netstandard!

jinhong- commented 7 years ago

Anyone still attempting this?

mookid8000 commented 7 years ago

Anyone still attempting this?

Yes 😄 @mvandevy ported Rebus core to the new project structure, and it looks like it compiles fine to .NET 4.5 and netstandard 1.6.

I am currently checking that things still work, and then I will try to figure out how it can be built.

Stay tuned 😁

mvandevy commented 7 years ago

Just noticed that you mistakingly removed the pull request and notified me a couple of hours ago. If you want to, I can make you another one. Free of charge 😁

mookid8000 commented 7 years ago

I don't think it is necessary – I have pulled your changes into the netcore_master branch and thus merged it with what will become Rebus 4.

I have a few things I need to solve though before I can get it into master:

  1. Figure out how to merge Newtonsoft.Json into Rebus.dll
  2. Figure out how to build a package that includes lib/NET45 and lib/netstandard16 folders

But I am on it! I have the entire day today available 😄

mvandevy commented 7 years ago

About the second item, if I'm not mistaken, then the current packing already packs it with both a lib/NET45 and a lib/netstandard16 folder. But maybe I'm reading the issue you're having wrong.

mookid8000 commented 7 years ago

I think you're right – when I

dotnet pack -c Release

it builds for all target frameworks, which is pretty cool!

Now I think I just need to hook the ILMergeing of Newtonsoft.JSON into the .csproj as a build task, and then all is well and good for the old .NET 4.5 dll....

mookid8000 commented 7 years ago

oh and then I need to figure out how to exclude Newtonsoft.Json from the list of dependencies in the .NET 4.5 section of this:

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
  <metadata>
    <id>Rebus</id>
    <version>3.2.0</version>
    <authors>mookid8000</authors>
    <owners>mookid8000</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <licenseUrl>https://raw.githubusercontent.com/rebus-org/Rebus/master/LICENSE.md</licenseUrl>
    <projectUrl>http://mookid.dk/oncode/rebus</projectUrl>
    <iconUrl>https://github.com/mookid8000/Rebus/raw/master/artwork/little_rebusbus2_copy-200x200.png</iconUrl>
    <description>Package Description</description>
    <copyright>Copyright 2012-2016</copyright>
    <tags>rebus queue messaging service bus</tags>
    <repository type="git" url="https://github.com/rebus-org/Rebus" />
    <dependencies>
      <group targetFramework=".NETStandard1.6">
        <dependency id="System.Diagnostics.TraceSource" version="4.3.0" exclude="Build,Analyzers" />
        <dependency id="System.Threading.Thread" version="4.3.0" exclude="Build,Analyzers" />
        <dependency id="NETStandard.Library" version="1.6.1" exclude="Build,Analyzers" />
        <dependency id="System.Threading" version="4.3.0" exclude="Build,Analyzers" />
        <dependency id="Newtonsoft.Json" version="9.0.1" exclude="Build,Analyzers" />
      </group>
      <group targetFramework=".NETFramework4.5">
        <dependency id="Newtonsoft.Json" version="9.0.1" exclude="Build,Analyzers" />
      </group>
    </dependencies>
  </metadata>
</package>

(it's the auto-generated nuspec found in the .nupkg)

mvandevy commented 7 years ago

Is it something like the developmentdependency you can use/misuse? https://docs.microsoft.com/en-us/nuget/tools/nuget-exe-cli-reference#excluding-development-dependencies-when-creating-packages

mookid8000 commented 7 years ago

Status report after having worked with this today: Excellent work, @mvandevy ! You got it a long way 😄

There's some stuff missing though before it can be merged to master (and thus become part of Rebus 4).

The most troublesome part is the fact that I used to tout Rebus' independence, which from the beginning has been possible because I have simply merged Newtonsoft JSON.NET into Rebus.dll.

I tried and mess around with ILMerge a bit, but it didn't seem to work with netstandard1.6 assemblies. I have no idea how ILMerge actually works, so I Googled some, but I couldn't find any information about it and .NET Core together.

So I figured I would keep the merge for the .NET 4.5 build only, and then only reference JSON.NET as a NuGet dependency for the netstandard 1.6 build.

Figuring out how to do this so I could simply

dotnet build -c Release

in order to build everything, and

dotnet pack -c Release

to generate packages is not super-easy, and it's not quite there yet. In fact, it's hard for me at this point to determine whether it is stupid to try and do that, and whether it would be better to

That was the current status .... if anyone has ideas or input of any kind, I would love to hear it.

atrauzzi commented 7 years ago

Ideally you shouldn't be bundling other peoples' packages. Not so much for proprietary reasons, but because the moment you do, you become a distributor of that package. That means if they post a minor update and you don't, your library becomes an unintended vector.

Because of this and probably a few other fairly rational reasons, I would specifically avoid any package that bundles its dependencies. It's just not common or the intended practice.

mookid8000 commented 7 years ago

Ideally you shouldn't be bundling other peoples' packages. Not so much for proprietary reasons, but because the moment you do, you become a distributor of that package.

Definitely a valid opinion. I would also say that I would not distribute any library that way, but I am willing to do it with JSON.NET because it makes including Rebus in any project trivial.

It looks like I may be forced to reconsider this approach though 😄

mvandevy commented 7 years ago

As JSON.NET is even referenced from asp.net core itself marks the library as a de facto standard. Including it as an explicit nuget dependency wouldn't make me change my mind about rebus and the quality of the library.

Adding it as an explicit reference would also make life a little easier it seems. No need for setting up a mechanism to include up-to-date code in Rebus.

mookid8000 commented 7 years ago

yeah.... I think I am getting more and more convinced that I need to let go my "Absolutely Zero Dependencies" principle 😁

atrauzzi commented 7 years ago

I'd say being easy to include won't be impacted by whether you declare a dependency or not. Granted it's late to the party, but it's not just the .net ecosystem that believes this. If anyone has a problem with that, they need to revisit their vendoring strategy on a whole.

And hey, the upshot is that it's obviously going to save you a tonne of work during packaging! 😉