Orleans Extension not installed - c#

I'm starting to dive into the Orleans Streams and I'm running into an issue using ImplicitStreamSubscription. I'm building upon the QuickStart example by adding a new project that implements both the interfaces and the grains. Here is the all of the code I have so far in my grains.
[ImplicitStreamSubscription("RANDOMDATA")]
public class VSMDiscovery : Grain, IVSMDiscovery
{
public override Task OnActivateAsync()
{
Console.WriteLine("Started" + this.GetPrimaryKey());
return base.OnActivateAsync();
}
}
public interface IVSMDiscovery : IGrainWithIntegerKey
{
}
In the DevTest main, I simply send an event using
var guid = Guid.NewGuid();
//Get one of the providers which we defined in config
var streamProvider = Orleans.GrainClient.GetStreamProvider("SMSProvider");
//Get the reference to a stream
var stream = streamProvider.GetStream<int>(guid, "RANDOMDATA");
stream.OnNextAsync(1);
Everything seems to execute fine, a new grain is instantiated and OnActivateAsync is called which writes the message to the console, however I get this error.
VSM Started206d105b-d21b-496c-997a-9dac3cf370b3
Extension not installed on grain Draco.VSMConnection.VSMDiscovery attempting to invoke type Orleans.Streams.OrleansCodeGenStreamConsumerExtensionMethodInvoker from invokable Orleans.Runtime.ActivationData
Exception = Orleans.Runtime.GrainExtensionNotInstalledException: Extension not installed on grain Draco.VSMConnection.VSMDiscovery attempting to invoke type Orleans.Streams.OrleansCodeGenStreamConsumerExtensionMethodInvoker from invokable Orleans.Runtime.ActivationData
[2016-03-09 05:53:41.007 GMT 14 WARNING 103405 InsideRuntimeClient 127.0.0.1:11111] Extension not installed on grain Draco.VSMConnection.VSMDiscovery attempting to invoke type Orleans.Streams.OrleansCodeGenStreamConsumerExtensionMethodInvoker from invokable Orleans.Runtime.ActivationData for message NewPlacement Request S127.0.0.1:11111:195198808*cli/5853f180#9c59fabf->S127.0.0.1:11111:195198808*grn/EB2C0203/ac9d7a99#0e33939b #5: global::Orleans.Streams.IStreamConsumerExtension:DeliverItem()
As I mentioned, everything appears to be running ok, but having this error is very concerning. Any help would be greatly appreciated.

For me, this was caused by having a grain which had an implicit subscription attribute, but which FORGOT to subscribe to the stream in the OnActiveAsync method (which is required and is outlined in the quick start mentioned above).... not clear from the error message at all. Hope this saves someone else some pain.

You need to make sure that the "SMSProvider" stream provider is correctly specified in the config file, for both client and silo, like here: https://github.com/dotnet/orleans/blob/master/test/Tester/OrleansConfigurationForStreamingUnitTests.xml#L9

Related

IndividualAssemblyLoadContext XmlSerializers.dll memory leak

I have a problem with a memory leak in .NET Core 3.1 API. The application is hosted in azure app service.
It is clearly visible on a graph that under constant load the memory is very slowly growing. it will only go down after app restart.
I created two memory dumps. One with high memory and one after restart and it's clearly visible that the reason is the app trying to load XmlSerialization.dll multiple times.
Now we have multiple other APIs that are using almost identical code when it comes to serialization and I'm not exactly sure why the problem occurs only in this one. Potentially because maybe this one has a much higher traffic when using the APIs.
I've read some articles about XmlSerializer class having memory issues but those were listed for some of the constructors we are not using. The only instance of using XmlSerializer directly in code was using an XmlSerializer(Type) constructor.
private static async Task<T> ParseResponseContentAsync<T>(HttpResponseMessage response, Accept accept)
{
try
{
using (Stream contentStream = await response.Content.ReadAsStreamAsync())
{
using (StreamReader reader = new StreamReader(contentStream, Encoding.UTF8))
{
switch (accept)
{
case Accept.Xml:
XmlSerializer serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(reader);
case Accept.Json:
string stringContent = await reader.ReadToEndAsync();
return JsonConvert.DeserializeObject<T>(stringContent);
default:
throw new CustomHttpResponseException(HttpStatusCode.NotImplemented, $"Unsupported Accept type '{accept}'");
}
}
}
}
catch (Exception ex)
{
throw new InvalidOperationException($"Response content could not be deserialized as {accept} to {typeof(T)}", ex);
}
}
But I'm pretty sure this method is not used in this API anyway .
So another potential problematic place could be somewhere in the Controller serialization of responses.
Startup.cs registration:
services
.AddControllers(options =>
{
options.OutputFormatters.Add(new XmlSerializerOutputFormatter(
new XmlWriterSettings
{
OmitXmlDeclaration = false
}));
options.Filters.Add<CustomHttpResponseExceptionFilter>();
})
.AddNewtonsoftJson(options => options.SerializerSettings.Converters.Add(
new StringEnumConverter(typeof(CamelCaseNamingStrategy))))
.AddXmlSerializerFormatters();
Example of an endpoint:
[Produces(MimeType.ApplicationXml, MimeType.TextXml, MimeType.ApplicationJson, MimeType.TextJson)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[HttpGet("EndpointName")]
[Authorize]
public async Task<ActionResult<ResponseDto>> Get([FromModel] InputModel inputModel)
{
//some code
return responseDto;
}
Dto returned from the API:
[XmlRoot(ElementName = "SomeName")]
public class ResponseDto
{
[XmlElement(ElementName = "Result")]
public Result Result { get; set; }
[XmlAttribute(AttributeName = "Status")]
public string Status { get; set; }
[XmlAttribute(AttributeName = "DoneSoFar")]
public int DoneSoFar { get; set; }
[XmlAttribute(AttributeName = "OfTotal")]
public int OfTotal { get; set; }
}
Now I haven't been able to find any documented cases of .AddXmlSerialization causing these kinds of issues and I'm not sure what the solution or a workaround should be. Any help would be greatly appreciated.
EDIT:
I've run some additional tests as #dbc suggested.
Now it seems that we are not even hitting this line new XmlSerializer(typeof(T) in our scenarios since nothing was logged after logger code was added. We do however use default xml serialization for some of our API endpoints. Now one thing I noticed that might be causing this behavior is that the paths in memory dumps logs don't match the files that actually exist in the root folder.
The paths which are visible in memory dumps are *.Progress.Lib.XmlSerializers.dll or *.Domain.Lib.XmlSerializers.dll
Now I wonder if this isn't the issue documented here - link since I can't see those files in wwwroot directory.
If it is I'm not sure if the solution would be to somehow reference the .dlls directly ?
Edit2:
Adding a screen of how memory looks like after deploying cached serializer suggested by #dbc. There is no constant growth but it seems after few hours memory rises and doesn't go down. It is possible that the main problem is resolved but since it takes a lot of time to notice big differences we will monitor this for now. There is nothing showing in large object heap or any big number of memory is not allocated in managed memory. This API however when first deployed runs around 250 mB and after one day now at 850 mB. When we turn off the load test tool the memory didn't really go down too much.
Edit3:
So we looked closer at some historical data and it seems that the last screen is a normal behavior. It never grows beyond a certain point. Not sure why that happens but this is acceptable.
The assemblies that the new XmlSerializer(typeof(T)) constructor are trying to load are Microsoft XML Serializer Generator assemblies a.k.a Sgen.exe assemblies that might have or might not been created at the time the app was built.
But what are Sgen assemblies? In brief, XmlSerializer works by generating code to serialize and deserialize the type passed into the constructor, then compiling that generated code into a DLL and loading it into the application domain to do the actual serialization. This run-time DLL generation can be time-consuming, but as long as you use the XmlSerializer(Type) or XmlSerializer(Type, String) constructors it will only be done once per type T, with the resulting assembly being cached internally in a static dictionary by XmlSerializer.
As you might imagine this can cause the first call to new XmlSerializer(typeof(T)) to be slow, so (in .NET 2 I believe, this is all very old code) Microsoft introduced a tool to generate those run-time serialization DLLs at application build time: SGen.exe. This tool doesn't work for all types (e.g. generics) and was, if I recall correctly, finicky to use, but when it did work it did speed up serializer construction. Once loaded successfully the Sgen assembly is cached in the same cache used for generated assemblies.
And it seems like you have stumbled across a bug in .NET Core 3.1, 5, and 6 related to this:
The base class method OutputFormatter.CanWriteResult(OutputFormatterCanWriteContext context) of XmlSerializerOutputFormatter tests whether a type can be serialized by calling XmlSerializerOutputFormatter.CanWriteType(Type type). This in turn tests to see whether a type is serializable by XmlSerializer by attempting to construct a serializer for the type and returning false if construction failed because any exception was thrown. The serializer is cached if construction was successful, but nothing is cached if construction failed.
the new XmlSerializer(Type) constructor tries to load an Sgen assembly unless an assembly has already been cached for the type by a previous successful call to the constructor.
But if a type is not serializable by XmlSerializer, the constructor will throw an exception and nothing will be cached. Thus successive attempts to construct a serializer for the same non-serializable type will result in multiple calls to load Sgen assemblies.
As you yourself found, .NET Core itself permanently leaks a small amount of IndividualAssemblyLoadContext memory every time assembly load fails: Failed Assembly.Load and Assembly.LoadFile leaks memory #58093.
Putting all this together, enabling XML serialization when some of your DTOs are not serializable (because e.g. they don't have parameterless constructors) can result in ever-growing IndividualAssemblyLoadContext memory use.
So, what are your options for a workaround?
Firstly, issue #58093 was apparently fixed in .NET 7 with pull #68502 so if you upgrade to this version the problem may resolve itself.
Secondly, you could subclass XmlSerializerOutputFormatter to cache returned XmlSerializer instances even when null. This will prevent multiple attempts to create serializers for non-seializable types.
First, subclass XmlSerializerOutputFormatter and override XmlSerializerOutputFormatter.CreateSerializer(Type) as follows:
public class CachedXmlSerializerOutputFormatter : XmlSerializerOutputFormatter
{
// Cache and reuse the serializers returned by base.CreateSerializer(t). When null is returned for a non-serializable type,
// a null serializer will be cached and returned.
static readonly ConcurrentDictionary<Type, XmlSerializer> Serializers = new ConcurrentDictionary<Type, XmlSerializer>();
public CachedXmlSerializerOutputFormatter() : base() { }
public CachedXmlSerializerOutputFormatter(ILoggerFactory loggerFactory) : base(loggerFactory) { }
public CachedXmlSerializerOutputFormatter(XmlWriterSettings writerSettings) : base(writerSettings) { }
public CachedXmlSerializerOutputFormatter(XmlWriterSettings writerSettings, ILoggerFactory loggerFactory) : base(writerSettings, loggerFactory) { }
protected override XmlSerializer CreateSerializer(Type type) { return Serializers.GetOrAdd(type, (t) => base.CreateSerializer(t)); }
}
Then replace use of XmlSerializerOutputFormatter with your subclassed version as follows:
services
.AddControllers(options =>
{
options.OutputFormatters.Add(new CachedXmlSerializerOutputFormatter (
new XmlWriterSettings
{
OmitXmlDeclaration = false
}));
options.Filters.Add<CustomHttpResponseExceptionFilter>();
})
.AddNewtonsoftJson(options => options.SerializerSettings.Converters.Add(
new StringEnumConverter(typeof(CamelCaseNamingStrategy))))
.AddXmlSerializerFormatters();
This should in theory eliminate the repeated failing calls to load Sgen assemblies.
Notes:
If you have enabled XML model binding and some of your input types are not XML-serializable, you may need to similarly subclass XmlSerializerInputFormatter. Its CreateSerializer(Type type)) also fails to cache failed attempts to construct a serializer.
Demo fiddles:
Demo fiddle showing that that multiple calls to XmlSerializerOutputFormatter.CanWriteType() for a non-serializable DTO result in multiple assembly load failures here: demo #1.
Demo fiddle showing that CachedXmlSerializerOutputFormatter fixes this problem here: demo #2.
Demo that multiple calls to XmlSerializerOutputFormatter.CanWriteType() for a serializable DTO do not result in multiple assembly load failures, and hence don't cause growing IndividualAssemblyLoadContext memory use, here: demo #3.
This might not be feasible, but could you offload the XML generation onto Azure API Management?
https://learn.microsoft.com/en-us/azure/api-management/api-management-transformation-policies#ConvertJSONtoXML

Runtime casting of COM objects in C#

I am working on a application which needs to communicate via COM interface with multiple CAD applications (not in the same time). I want to have nice and reusable code, but I came across problems with type casting of COM objects when I made generic application handle getter method.
What I tried so far:
This is the attempt I would like the most if it worked.
public static TCadAppType CadApp<TCadAppType>()
{
dynamic cadApp = default(TCadAppType);
//Here under Dynamic View/Message there is already an error
// Message = "Element not found. (Exception from HRESULT: 0x8002802B (TYPE_E_ELEMENTNOTFOUND))"
// cadVersion.Value evaluates to "SldWorks.Application"
cadApp = (TCadAppType)Marshal.GetActiveObject(cadVersion.Value);
//Following 2 lines of code are for testing purposes only, i am testing with Solidworks API
AssemblyDoc Assembly;
//The exception is thrown when I try to access some method from the Solidworks API
Assembly = (AssemblyDoc)cadApp.OpenDoc6("some parametras...");
}
Attempt using Convert class
// Another attempt using Convert class
public static TCadAppType CadApp<TCadAppType>()
{
dynamic cadApp = default(TCadAppType);
// cadVersion.Value evaluates to "SldWorks.Application"
cadApp = Marshal.GetActiveObject(cadVersion.Value);
cadApp = Convert.ChangeType(cadApp, typeof(SldWorks.SldWorks));
// Exception is thrown with the following message:
// Message = "Object must implement IConvertible."
}
I really thought that I am on the right track, since there is an article on Microsoft Docs website explaining how dynamic can help you with com interopt: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/using-type-dynamic#com-interop
Any ideas how I can do this runtime casting a keep my code as reusable as possible?
My software setup:
Win 10
Project is targeted for .NET 4.7.2
First Tests are with Solidworks 2019
Turns out that the my coding attempt 1 was valid c# code indeed.
I tried it using with Autodesk Inventor, and it works.
So the only thing left for me is to conclude that this is some bug from Solidworks and their COM interfacing.
Thank you Optional Option for your interest in the topic.

Table has no (public) columns only on real device

I have the simplest of apps that I thought I would try on my device before I got too engrossed. However, I am getting the strangest error message when I run it on my iPhone (as apposed to the the emulator on my macbook).
Table has no (public) columns .
I am using the SQLite.Net PCL and I have built it from git hub as I had some problems with it not having the platform dlls for IOS otherwise.
Relevant code.
In my models I have this:
public class Setting
{
[PrimaryKey, AutoIncrement]
public long Id { get; set; }
[Indexed]
public string Key { get; set; }
public string Value { get; set; }
}
The code that throws this error message is the simple:
using (SQLiteConnection db = GetCon ()) {
db.CreateTable<Setting> ();
}
but in my opinion the strangest thing is that this code works fine on the emulator but crashes the application on the iphone itself.
If anyone has some ideas that would be great.
EDIT:
This error is thrown on the SQLite.Net-PCL library on this file line 380 but only on the device and not on the emulator.
For others to whom this may concern, I found the answer to my problem. The issue was with the Type not having any properties (the type in question the simple model class). Knowing that to be rubbish I found the following links that gave more information which I will relate in this post in case the links go dead:
Type.GetProperties returning nothing
NOTE: Be careful with assembly linker
If you're building with linker enabled you may need to use the class
somewhere, so it will not be ripped off at compile time. Sometimes,
only instantiating the class in your code is not enough, the linker
may detect that the instance is never used and will remove it anyway.
http://developer.xamarin.com/guides/ios/advanced_topics/linker/
The linking process can be customized via the linker behavior
drop-down in Project Options. To access this double-click on the iOS
project and browse to iOS Build > Linker Options, as illustrated below
(see link for details)
I have for now left it to be unlinked, however, I will try before release to get the linker to ignore these classes. Thanks for all your help.
I found my problem was just a (not that subtle) programming error. I was working with the TypeInfo class and wanted to use the Sqlite Connection method:
CreateTable (Type type);
What I had in my hand was a TypeInfo instance which I needed to convert back to the System.Type. I accidentally without thinking used the GetType() method instead of AsType() method which is obvious when you think about it. The clue I got was in the exception message along with the OP message was does System.Runtime have public properties?
var type = table.TypeInfo.AsType();
// var type = table.TypeInfo.GetType(); *WRONG*
connection.CreateTable(type);

Is it possible to use Gephi compiled with IKVM in a website?

I'm currently trying to load and use the Gephi Toolkit from within a .Net 4 C# website.
I have a version of the toolkit jar file compiled against the IKVM virtual machine, which works as expected from a command line application using the following code:
var controller = (ProjectController)Lookup.getDefault().lookup(typeof(ProjectController));
controller.closeCurrentProject();
controller.newProject();
var project = controller.getCurrentProject();
var workspace = controller.getCurrentWorkspace();
The three instances are correctly instantiated in a form similar to org.gephi.project.impl.ProjectControllerImpl#8ddb93.
If however I run the exact same code, with the exact same using statements & references, the very first line loading the ProjectController instance returns null.
I have tried a couple of solutions
Firstly, I have tried ignoring the Lookup.getDefault().lookup(type) call, instead trying to create my own instances:
var controller = new ProjectControllerImpl();
controller.closeCurrentProject();
controller.newProject();
var project = controller.getCurrentProject();
var workspace = controller.getCurrentWorkspace();
This fails at the line controller.newProject();, I think because internally (using reflector) the same Lookup.getDefault().lookup(type) is used in a constructor, returns null and then throws an exception.
Secondly, from here: Lookup in Jython (and Gephi) I have tried to set the %CLASSPATH% to the location of both the toolkit JAR and DLL files.
Is there a reason why the Lookup.getDefault().lookup(type) would not work in a web environment? I'm not a Java developer, so I am a bit out of my depth with the Java side of this.
I would have thought it possible to create all of the instances myself, but haven't been able to find a way to do so.
I also cannot find a way of seeing why the ProjectController load returned null. No exception is thrown, and unless I'm being very dumb, there doesn't appear to be a method to see the result of the attempted load.
Update - Answer
Based on the answer from Jeroen Frijters, I resolved the issue like this:
public class Global : System.Web.HttpApplication
{
public Global()
{
var assembly = Assembly.LoadFrom(Path.Combine(root, "gephi-toolkit.dll"));
var acl = new AssemblyClassLoader(assembly);
java.lang.Thread.currentThread().setContextClassLoader(new MySystemClassLoader(acl));
}
}
internal class MySystemClassLoader : ClassLoader
{
public MySystemClassLoader(ClassLoader parent)
: base(new AppDomainAssemblyClassLoader(typeof(MySystemClassLoader).Assembly))
{ }
}
The code ikvm.runtime.Startup.addBootClassPathAssemby() didn't seem to work for me, but from the provided link, I was able to find a solution that seems to work in all instances.
This is a Java class loader issue. In a command line app your main executable functions as the system class loader and knows how to load assembly dependencies, but in a web process there is no main executable so that system class loader doesn't know how to load anything useful.
One of the solutions is to call ikvm.runtime.Startup.addBootClassPathAssemby() to add the relevant assemblies to the boot class loader.
For more on IKVM class loading issues see http://sourceforge.net/apps/mediawiki/ikvm/index.php?title=ClassLoader

Build-time code validation and generation based upon code files across projects

I'm looking for a method that let's me validate code and generator code as part of the build process, using Visual Studio 2010 (not express) and MSBuild.
Background Validation:
I'm writing a RESTful web service using the WCF Web Api. Inside the service class that represents the web service I have to define an endpoint, declaring additionally parameters as plain test. When the parameter name inside the endpoint declaration differs from the parameter of the C# method I get a error - unfortunately at run time when accessing the web service, not at compile time. So I thought it would be nice to analyze the web service class as part of the compile step for flaws like this, returning an error when something is not right.
Example:
[WebGet(UriTemplate = "Endpoint/{param1}/{param2}")]
public string MyMethod(string param1, string parameter2) {
// Accessing the web service now will result in an error,
// as there's no fitting method-parameter named "param2".
}
Also I'd like to enforce some naming rules, such as GET-Methods must start with the "Get" word. I believe this will help the service to remain much more maintainable when working with several colleagues.
Background Generation:
I will be using this REST web service in a few other projects, there for I need to write a client to access this service. But I don't want to write a client for each of these, always adjusting whenever the service changes. I'd like the clients to be generated automatically, based upon the web service code files.
Previous approach:
So far I tried to use a T4 template using the DTE interface to parse the code file and validate it, or generate the client. This worked fine in Visual Studio when saving manually, but integrating this in the build process turned out to be not so working well, as the Visual Studio host is not available using MSBuild.
Any suggestion is welcome. :)
Instead of using DTE or some other means to parse the C# code you could use reflection (with Reflection-Only context) to examine the assembly after it's compiled. Using reflection is a more robust solution and probably faster also (especially if you use Mono.Cecil to do the reflecting).
For the MSBuild integration I would recommend writing a custom MSBuild task - it's fairly easy and more robust/elegant than writing a command line utility that's executed by MSBuild.
This may be a long shot but still qualifies as "any suggestion" :)
You could compile the code, then run a post-build command which would be a tool that you'd have to write which uses reflection to compare the parsed UriTemplate text with the method parameter names, catching errors and outputting them in a manner that MSBuild will pickup. Look at This Link for information on how to output so MSBuild will put the errors in the visual studio error list. The post-build tool could then delete the compiled assemblies if errors were found, thus "simulating" a failed build.
Here's the SO Link that lead me to the MSBuild Blog too, just for reference.
HTH
For the enforcement side of things, custom FxCop rules would probably be a very good fit.
For the client code generation, there are quite a few possibilities. If you like the T4 approach, there is probably a way to get it working with MSBuild (but you would definitely need to provide a bit more detail regarding what isn't working now). If you're want an alternative anyway, a reflection-based post-build tool is yet another way to go...
Here is a short, extremely ugly program that you can run over an assembly or group of assemblies (just pass the dlls as arguments) to perform the WebGet UriTemplate check. If you don't pass anything, it runs on itself (and fails, appropriately, as it is its own unit test).
The program will print out to stdout the name of the methods that are missing the parameters and the names of the missing parameters, and if any are found, will return a non-zero return code (standard for a program failing), making it suitable as a post-build event. I am not responsible if your eyes bleed:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.ServiceModel.Web;
namespace ConsoleApplication1
{
class Program
{
static int Main(string[] args)
{
var failList = new ConcurrentDictionary<MethodInfo, ISet<String>>();
var assembliesToRunOn = (args.Length == 0 ? new[] {Assembly.GetExecutingAssembly()} : args.Select(Assembly.LoadFrom)).ToList();
assembliesToRunOn.AsParallel().ForAll(
a => Array.ForEach(a.GetTypes(), t => Array.ForEach(t.GetMethods(BindingFlags.Public | BindingFlags.Instance),
mi =>
{
var miParams = mi.GetParameters();
var attribs = mi.GetCustomAttributes(typeof (WebGetAttribute), true);
if (attribs.Length <= 0) return;
var wga = (WebGetAttribute)attribs[0];
wga.UriTemplate
.Split('/')
.ToList()
.ForEach(tp =>
{
if (tp.StartsWith("{") && tp.EndsWith("}"))
{
var tpName = tp.Substring(1, tp.Length - 2);
if (!miParams.Any(pi => pi.Name == tpName))
{
failList.AddOrUpdate(mi, new HashSet<string> {tpName}, (miv, l) =>
{
l.Add(tpName);
return l;
});
}
}
});
})));
if (failList.Count == 0) return 0;
failList.ToList().ForEach(kvp => Console.Out.WriteLine("Method " + kvp.Key + " in type " + kvp.Key.DeclaringType + " is missing the following expected parameters: " + String.Join(", ", kvp.Value.ToArray())));
return failList.Count;
}
[WebGet(UriTemplate = "Endpoint/{param1}/{param2}")]
public void WillPass(String param1, String param2) { }
[WebGet(UriTemplate = "Endpoint/{param1}/{param2}")]
public void WillFail() { }
[WebGet(UriTemplate = "Endpoint/{param1}/{param2}")]
public void WillFail2(String param1) { }
}
}

Categories