dotnet / orleans

Cloud Native application framework for .NET
https://docs.microsoft.com/dotnet/orleans
MIT License
10.04k stars 2.02k forks source link

Management of internal and application dependencies #200

Closed sergeybykov closed 9 years ago

sergeybykov commented 9 years ago

This is meant to be an umbrella issue to discuss how we should approach and manage dependencies on external libraries that Orleans has internally and that applications use. One example is Azure SDK, which is a painful dependency to upgrade to a new version (https://github.com/dotnet/orleans/issues/68).

The baseline we starting from is that Orleans itself should depend on Azure SDK current-1 version, in order to give users time to migrate their code when a new version comes out. https://github.com/dotnet/orleans/pull/197 will bring us to that point. It is still not 100% clear if application will be able to use current version of Azure SDK, which is the intent. Looks like https://github.com/dotnet/orleans/issues/174 is currently blocking that.

AssemblyLoader not respecting assembly binding redirects is the most immediate problem (https://github.com/dotnet/orleans/issues/174).

Another, less immediate, layer of the problem is that in CoreCLR some of the Reflection APIs that AssemblyLoader is using are going away, and we need to think of how the whole process of discovering and loading of application assemblies should evolve, including dependency resolution.

We need to capture the versioning rules and approach in the documentation.

veikkoeeva commented 9 years ago

This is a tricky question.

Disclaimer: I may have glossed over something on how Orleans operates currently.

yevhen commented 9 years ago

I'd suspect it could improve loading times too if one would just list the assemblies that one wants be to loaded.

Exactly what we do in Orleankka. I hate magic :)

veikkoeeva commented 9 years ago

@yevhen I had to check this. Hmm, an interesting project! Who is we? Where does the name come from? What does it mean? It's just that ankka is 'duck' (bird) in Finnish. :-P

yevhen commented 9 years ago

It means Orleans with Akka-like message passing API.

sergeybykov commented 9 years ago

Continuing (merging) the discussion from https://github.com/dotnet/orleans/pull/197 here.

@ca-ta Don't we want to support application code that has dependencies on different versions of the same assemblies that the runtime depends on, e.g. Azure Storage 4.3 vs. 4.2? You mentioned workarounds, but it's not clear to me why you consider deploying grain assemblies with their dependencies to a subfolder a workaround. Isn't that the cleanest possible separation of concerns?

A configuration option to support restricting scanning to a fixed set of assemblies should be a relatively easy change. But I think the top-level question is still the one about runtime vs. app dependencies. My opinion is it's important to support different versions of dependencies, and subfolders is the only means I'm aware of (besides dynamic assemblies) that allows for that. What's the argument for not supporting different versions?

veikkoeeva commented 9 years ago

@sergeybykov Hmm, if you allow, I'll clarify a bit of what I've written here from the sideway with regard to versions and branches. Just to make sure I have been explicit or clear enough. I have assumed we'll follow semantic versioning (see at Really brief introduction to SemVer) as most the Nuget packages and other Microsoft libraries. If so, in that case, it's not clear why the runtime would fix a dependency on version 4.2 of WindowsAzure.Storage when there is version 4.3 available and it's backwards compatible. It looks like we consider this as a bug in the loader, but I'd rather be explicit as you mentioned as an example of versions 4.3 and 4.2 of Azure Storage.

An example scenario, from top of my head, with regard to Orleans would be to define, taking Storage as an example, that anything in the 4 series higher than the minimum set by Orleans should work. There could be quite a large assortment of Nuget packages in a given project and some could have bugs fixed in their dependencies that in turn fixes even serious bugs in the actual used packages. Using storage as an example, package XYZ could depend on Azure Storage and version 4.3 would have something in it that fixes a serious problem. If one’s grains would use this library, updating it would clash with the version Orleans uses. It may also feel quite laissez-faire, but a lot of projects are worked so that dependencies are added from Nuget and then the teams run Update-Package to update them all (as with Nuget, this is a bit imprecise if one really gets the latest libraries, but anyhow).

I don't know what would be the right model to handle this with regard to Orleans or who should discuss and decide it. I would think a workable mode would be to create a branch for every major release and tag the point releases along that branch until a new major release is worked on. When there are two major releases, one could decide how to support them. For instance, fixing bugs in the latest and backporting those that don't break the previous ones to their respective branches. If only the latest major release is officially supported, those with the time, skills and concern could be backporting if necessary. I have a feeling something like this is needed if/when Orleans gains traction.

sergeybykov commented 9 years ago

Thank @veikkoeeva. It is more clear to me now. Don't we have two related but distinct cases here though?

  1. Orleans runtime should be able to run with upgraded dependencies, so long as there aren't breaking changes, e.g. with Azure Storage >4.2. Absolutely.
  2. Application code wants to use an incompatible version of an assembly. For example, let's imagine there Azure Storage 5.0 that is incompatible with 4.2, and your grain code wants to use some of the new 5.0 functionality without requiring a major update to the Orleans code to make it compatible with 5.0.

In my opinion, we want both. Don't we?

I found a related bug in the AssemblyLoader in reflection-only inspection. Assembly.GetTypes() throws if dependencies aren't already loaded. I suspect it is blocking some of these scenarios, and in a non-deterministic way because it depends on the order of loading. I'll have a PR with a fix for it.

I am still confused with assembly binding redirects. As I mentioned in https://github.com/dotnet/orleans/pull/197, I see redirects working if they are in OrleansHost.exe.config in the local case. What's the gap here?

veikkoeeva commented 9 years ago

@sergeybykov I think we want both and you are correct in writing we have these two distinct cases. Number two is the tricky one, I believe. Maybe one way forwards would be to be on top of the game and release backwards incompatible versions somewhat quickly or then, say, internalize assemblies. A different discussion, though.

I'll get the #174 one in that thread.

cata commented 9 years ago

@sergeybykov I was referring to deploying to a subfolder as a workaround to 1) not working. Yes, I agree deploying to a subfolder is the way to go should one need to use incompatible assemblies (case 2. above).

That being said, your observation about assembly redirects prompted me to retry the scenario using the latest version of Orleans. So I got, built and installed the latest (as of 95375c8), it and retried setting redirects into my worker role's configuration - and it works (yay!, I guess... as I don't know why this didn't work for me less than two weeks ago and I haven't had the chance to look at what changed). More details in #174.

If this works consistently for others as well, I think we can consider 1) as working as intended.

@veikkoeeva: give paket a try - its nuget package versioning strategy makes a lot of sense.

sergeybykov commented 9 years ago

@ca-ta I just submitted https://github.com/dotnet/orleans/pull/236 that applies binding redirect policies and fixes reflection-only dependency resolution. In my manual testing with LocalSilo both 1 and 2 seemed to work. I'm not at all sure this covers everything. I just hope this is a step in the right direction.

sergeybykov commented 9 years ago

I added a doc page describing deployment options and dependency versioning - http://dotnet.github.io/orleans/Deployment-and-Versioning-of-Dependencies.

sergeybykov commented 9 years ago

I think we can now close this one.