How to test akka.net persistent actors - c#

I'am using [Akka.Net 1.3.1] a mix of ReceiveActors and ReceivePersistentActors and now I want to write tests for my actorsystem.
MyPersistentActor inherits from ReceivePersistentActor and MyActor inherits from ReceiveActor.
I also installed Akka.TestKit using version 1.3.1 .
But it seems that only ReceiveActors can be tested by Akka.TestKit.
IActorRef myActorRef = this.Sys.ActorOf<MyActor>(); // is fine
IActorRef myPersistentActorRef = this.Sys.ActorOf<MyPersistentActor>(); // is a problem
I also found the nuget package Akka.Persistence.TestKit version 1.2.3.43-beta . The beta wasn't changed since three month and only support akka 1.2.2 . Is it still in development or is it dead. I can not find any kind of information regarding that.
How do you test your persistent actors?
Thanks for your help!
Richi

Akka.Persistence.TestKit has been renamed to Akka.Persistence.TCK and it is used only for testing custom event journal and snapshot store implementations for compatibility with Akka.Persistence protocol. It doesn't bring any utilities for testing user actors.
There are no built-in methods to cooperate with journals/snapshot stores for testing purposes beside having implementations of them working in-memory. With that being said, you can actually work with journal/snapshot store just like with any other actor. If you look into implementations of persistence TCK specs like JournalSpec, you may get some insights into how that protocol works.
For example, if you want to initialize your journal with some events before firing the test case, you can do it like following:
void InitWithEvents(string persistenceId, params object[] events)
{
var probe = CreateTestProbe();
var writerGuid = Guid.NewGuid().ToString();
var writes = new AtomicWrite[events.Length];
for (int i = 0; i < events.Length; i++)
{
var e = events[i];
writes[i] = new AtomicWrite(new Persistent(e, i+1, persistenceId, "", false, ActorRefs.NoSender, writerGuid));
}
var journal = Persistence.Instance.Apply(Sys).JournalFor(null);
journal.Tell(new WriteMessages(writes, probe.Ref, 1));
probe.ExpectMsg<WriteMessagesSuccessful>();
for (int i = 0; i < events.Length; i++)
probe.ExpectMsg<WriteMessageSuccess>();
}
PS: There is clearly a missing part in the persistence TestKit API, any contributions on that field are more than welcome.

I know this is an ols answer, but I couldn't find any better resource. In my tests I am actually only interested if the correct event(s) is (are) persisted after I give my command. Multiple events could be raised by starting a saga. Most of the time I am only interested in the last persisted event.
If somebody is hitting the same issue as me, this is how I fixed getting the last message, based on Bartosz initWithEvents.
private void InitWithEvents(string persistenceId, IList<object> events)
{
var probe = CreateTestProbe();
var writerGuid = Guid.NewGuid().ToString();
var writes = new AtomicWrite[events.Count];
for (int i = 0; i < events.Count; i++)
{
var e = events[i];
writes[i] = new AtomicWrite(new Persistent(e, i+1, persistenceId, "", false, ActorRefs.NoSender, writerGuid));
}
journal = Persistence.Instance.Apply(Sys).JournalFor(null);
journal.Tell(new WriteMessages(writes, probe.Ref, 1));
probe.ExpectMsg<WriteMessagesSuccessful>();
for (int i = 0; i < events.Count; i++)
probe.ExpectMsg<WriteMessageSuccess>();
}
private object GetLastPersistedMessageFromJournal(string persistenceId)
{
var repointable = journal as RepointableActorRef;
var underlying = repointable.Underlying as ActorCell;
PropertyInfo prop = typeof(ActorCell).GetProperty("Actor", BindingFlags.NonPublic | BindingFlags.Instance);
MethodInfo getter = prop.GetGetMethod(nonPublic: true);
MemoryJournal jrnl = getter.Invoke(underlying, null) as MemoryJournal;
var read = jrnl?.Read(persistenceId, 0, Int64.MaxValue, Int64.MaxValue);
return read?.Last().Payload;
}

Related

gRPC StarLink Router .Net

New Info:
I thought I would paste this in full as I can not seem to find any samples on the web of a c# solution for StarLink so hopefully anyone else looking for something may find this helpful and may contribute.
My New Proto File - (partial) - I took the advise of Yuri below. Thanks for the direction here. I was able to I have been using this tool and it has brought a lot of insight but I am still stuck on the c# side of the solution. I am an old VB.Net developer though I have done a bunch in c# I am by no means savvy in it and am probably missing something so simple. Again, any insight would be awesome. I can not post the full proto here as stack has char limit on posts. this is the first bit with messages etc. I can post more if it helps but trying to keep it to the important part.
syntax = "proto3";
option csharp_namespace = "SpaceX.API.Device";
package SpaceX.API.Device;
service Device {
//rpc Handle (.SpaceX.API.Device.Request) returns (.SpaceX.API.Device.Response) {}
//rpc Stream (stream .SpaceX.API.Device.ToDevice) returns (stream .SpaceX.API.Device.FromDevice) {}
rpc Handle (Request) returns (Response);
rpc Stream (Request) returns (Response);
}
message ToDevice {
string message = 1;
}
message Request {
uint64 id = 1;
string target_id = 13;
uint64 epoch_id = 14;
oneof request {
SignedData signed_request = 15;
RebootRequest reboot = 1001;
SpeedTestRequest speed_test = 1003;
GetStatusRequest get_status = 1004;
AuthenticateRequest authenticate = 1005;
GetNextIdRequest get_next_id = 1006;
GetHistoryRequest get_history = 1007;
GetDeviceInfoRequest get_device_info = 1008;
GetPingRequest get_ping = 1009;
SetTrustedKeysRequest set_trusted_keys = 1010;
FactoryResetRequest factory_reset = 1011;
GetLogRequest get_log = 1012;
SetSkuRequest set_sku = 1013;
UpdateRequest update = 1014;
GetNetworkInterfacesRequest get_network_interfaces = 1015;
PingHostRequest ping_host = 1016;
GetLocationRequest get_location = 1017;
EnableFlowRequest enable_flow = 1018;
GetHeapDumpRequest get_heap_dump = 1019;
RestartControlRequest restart_control = 1020;
FuseRequest fuse = 1021;
GetPersistentStatsRequest get_persistent_stats = 1022;
GetConnectionsRequest get_connections = 1023;
FlushTelemRequest flush_telem = 1026;
StartSpeedtestRequest start_speedtest = 1027;
GetSpeedtestStatusRequest get_speedtest_status = 1028;
ReportClientSpeedtestRequest report_client_speedtest = 1029;
InitiateRemoteSshRequest initiate_remote_ssh = 1030;
SelfTestRequest self_test = 1031;
SetTestModeRequest set_test_mode = 1032;
DishStowRequest dish_stow = 2002;
DishGetContextRequest dish_get_context = 2003;
DishSetEmcRequest dish_set_emc = 2007;
DishGetObstructionMapRequest dish_get_obstruction_map = 2008;
DishGetEmcRequest dish_get_emc = 2009;
DishSetConfigRequest dish_set_config = 2010;
DishGetConfigRequest dish_get_config = 2011;
StartDishSelfTestRequest start_dish_self_test = 2012;
WifiSetConfigRequest wifi_set_config = 3001;
WifiGetClientsRequest wifi_get_clients = 3002;
WifiSetupRequest wifi_setup = 3003;
WifiGetPingMetricsRequest wifi_get_ping_metrics = 3007;
WifiGetDiagnosticsRequest wifi_get_diagnostics = 3008;
WifiGetConfigRequest wifi_get_config = 3009;
WifiSetMeshDeviceTrustRequest wifi_set_mesh_device_trust = 3012;
WifiSetMeshConfigRequest wifi_set_mesh_config = 3013;
WifiGetClientHistoryRequest wifi_get_client_history = 3015;
TransceiverIFLoopbackTestRequest transceiver_if_loopback_test = 4001;
TransceiverGetStatusRequest transceiver_get_status = 4003;
TransceiverGetTelemetryRequest transceiver_get_telemetry = 4004;
}
reserved 1025, 3011, 3014;
}
message SignedData {
bytes data = 1;
bytes signature = 2;
}
My New .cs
I have tried many things from Microsoft's examples to thing I can gather from other samples. I simply can not get it to work and am lost. Again, any insight would be amazing and hopefully helpful to others looking for a solution in c#. You will see my commented code of this I have been playing with. Basically I am attempting to achieve three things and have made some movement in one of them.
Goals:
1 - Use Server Reflection to discover services.
I think I got this one resolved with dot-net grpc.
2 - Simply want to check available methods under a service and potentially either check or generate a new .proto file in case things change. StaLink does not publish its proto schema so I assume it could change anytime without warning.
3 - Just run any one of the available methods. I have tried the GetDeviceInfoRequest but can not seem to construct the request message properly. I have not been able to get this accomplishe in the gRPCurl tool either. I can do it on the basic service shown by Microsoft of course but these methods seem to be more complex and I simply get all kinds of errors.
Again, any insight or assistance would be amazing. Thanks to any and all in advance.
New .cs File
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Net.Client;
using Grpc.Reflection.V1Alpha;
using ServerReflectionClient = Grpc.Reflection.V1Alpha.ServerReflection.ServerReflectionClient;
using SpaceX.API.Device;
public class Program
{
static async Task Main(string[] args)
{
//SETUP CHANNEL AND CLIENT
using var channel = GrpcChannel.ForAddress("http://192.168.100.1:9200");
var client = new ServerReflectionClient(channel);
var StarLinkClient = new Device.DeviceClient(channel);
//using var call = StarLinkClient.StreamAsync(new ToDevice { Request = GetDeviceInfoRequest });
//await foreach (var response in call.ResponseStream.ReadAllAsync())
//var request = Device.GetDeviceInfoRequest;
//var reply = await StarLinkClient.HandleAsync(
// new Request {'"getDeviceInfo" : {} '});
//Console.WriteLine(reply.Message);
//=============================================SERVER REFLECTION=============================================================
Console.WriteLine("Calling reflection service:");
var response = await SingleRequestAsync(client, new ServerReflectionRequest
{
ListServices = "" // Get all services
});
Console.WriteLine("Services:");
foreach (var item in response.ListServicesResponse.Service)
{
Console.WriteLine("- " + item.Name);
Console.WriteLine();
var StarLink = item.Name;
//Console.WriteLine(StarLink.getStatus());
}
//=============================================SERVER REFLECTION=============================================================
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
void setupchannel()
{
}
private static Task SingleRequestAsync(ServerReflectionClient client, Metadata metadata)
{
throw new NotImplementedException();
}
private static async Task<ServerReflectionResponse> SingleRequestAsync(ServerReflectionClient client, ServerReflectionRequest request)
{
using var call = client.ServerReflectionInfo();
await call.RequestStream.WriteAsync(request);
Debug.Assert(await call.ResponseStream.MoveNext());
var response = call.ResponseStream.Current;
await call.RequestStream.CompleteAsync();
return response;
}
}
Again, thanks in advance to anyone willing to assist here. Hopefully this helps others as well.

Apache Ignite .Net GetDataStreamer WithExpiryPolicy

var cache = client.GetOrCreateCache<int, int>("test").WithExpiryPolicy(new ExpiryPolicy(TimeSpan.FromSeconds(5), null, null));
using (var ldr = client.GetDataStreamer<int, int>("test"))
{
for (int i = 0; i < 20; i++)
ldr.AddData(i, i);
ldr.Flush();
}
I set the WithExpiryPolicy, but the data added by GetDataStreamer does not expire. Please tell me how to set the data to expire.
WithExpiryPolicy does not modify the underlying cache itself. Instead, it returns a new instance with the specified policies. This allows you to configure different policies on the same cache depending on some business logic.
At the same time, the DataStreamer is looking for a cache as it was created and doesn't care about WithExpiryPolicy. I'd suggest you configure the cache explicitly and re-run your example with the following configuration:
var cacheConfiguration = new CacheConfiguration
{
Name = name,
ExpiryPolicyFactory = new ExpiryPolicyFactory(
new ExpiryPolicy(TimeSpan.FromSeconds(1), null, null))
};

Could not load type 'SAS.LanguageServiceCarriageControl' from assembly

In addition to using the integration components of SAS Enterprise Edition, I am using parts of the following project I found on Github to connect with a SAS server. The goal here is to command the server to run programs on a schedule. However, the programs need to be modified each time, which is why I am attempting to trigger them to run in this manner. However, it keeps throwing an error at lang.FlushLogLines.
https://github.com/cjdinger/SasHarness
SAS.Workspace ws = server.Workspace;
List<string> results = new List<string>();
Array CCs;
Array lineTypes;
Array logLines;
int maxLines = 100;
SAS.LanguageService lang = (SAS.LanguageService)ws.LanguageService;
Array linesVar = (Array)new string[] { PROGRAM_TEXT };
lang.SubmitLines(ref linesVar);
//THROWS AN ERROR HERE
lang.FlushLogLines(maxLines, out CCs, out lineTypes, out logLines);
for (int i = 0; i < logLines.Length; i++)
{
results.Add((string)logLines.GetValue(i));
}
After a bit of research I found the following thread where it is recommended to make sure that all the required dlls are referenced in my project. The mystery here is that I do have them referenced, but the error still occurs.
http://blogs.sas.com/content/sasdummy/2013/06/09/sas-client-with-microsoft-dot-net/
Moreover, starting after the very first line, the code is no longer using SASHarness, but is using native SAS integration libraries only. The code above is also based on examples listed in the following documentation from SAS.
https://support.sas.com/documentation/cdl/en/itechwcdg/61500/PDF/default/itechwcdg.pdf (page 27-28)
Has anybody encountered an error similar to this, and if so, how did you correct it?
Strangely, fixing this error required declaring an instance for each of the assemblies that could not be loaded. I have no idea why this fixes the problem, but it works now.
SAS.Workspace ws = server.Workspace;
string wsId = ws.UniqueIdentifier;
List<string> results = new List<string>();
Array CCs;
Array lineTypes;
Array logLines;
int maxLines = 100;
SAS.LanguageService lang = (SAS.LanguageService) server.Workspace.LanguageService;
Array linesVar = (Array) new string[] { PROGRAM_TEXT };
lang.SubmitLines(ref linesVar);
//For some reason, these two declarations need to be here
SAS.LanguageServiceCarriageControl CarriageControl = new SAS.LanguageServiceCarriageControl();
SAS.LanguageServiceLineType LineType = new SAS.LanguageServiceLineType();
lang.FlushLogLines(maxLines, out CCs, out lineTypes, out logLines);
for (int i = 0; i < logLines.Length; i++)
{
results.Add((string) logLines.GetValue(i));
}

Using C#, how do I determine if an uploaded file has any accessible metadata/document properties?

Suppose I have a program which allows a user to upload any kind of file. Along with getting generic information such as file type and file size, I would like to attempt to grab any extra information (such as document properties like author, last revised, etc) that may be transported along with the document.
Since I don't have any knowledge about the incoming document/file ahead of time, I can't simply use classes that are specific to, say Microsoft Office docs. I need to do this generically and then construct a dynamic object or dictionary to hold any found key/value results.
Is this possible? If so, how? Any help is appreciated!
I found a few answers on StackOverflow for this, but none gave me a nice, clean dictionary of document properties. Here is what I finally came up with and it seems to be working nicely (you will need to reference "Microsoft Shell Controls and Automation" from the COM folder and add using Shell32; to your code:
public static Dictionary<string,string> GetDocumentMetadata(string fileName)
{
var properties = new Dictionary<string,string>();
var arrHeaders = new List<string>();
var shell = new Shell();
var objFolder = shell.NameSpace(HttpContext.Current.Server.MapPath("~/RawFiles"));
var file = objFolder.ParseName(fileName);
for (var i = 0; i < short.MaxValue; i++)
{
var header = objFolder.GetDetailsOf(null, i);
if (String.IsNullOrEmpty(header))
break;
arrHeaders.Add(header);
}
for (var i = 0; i < arrHeaders.Count; i++)
{
var value = objFolder.GetDetailsOf(file, i);
if (!String.IsNullOrEmpty(value))
{
properties.Add(arrHeaders[i], value);
}
}
return properties;
}

Is There a Settings Viewer/Manager for Windows 8 apps?

For testing my roaming and/or local settings, I'd like to be able to clear all the settings.
I could do it like so, I guess:
App.roamingSettings.Value["SomeVal"] = string.Empty;
App.roamingSettings.Value["SomeOtherVal"] = string.Empty;
App.roamingSettings.Value["YetAnotherVal"] = string.Empty;
...
etc.
...but I'd rather have some quicker, cleaner (no pun intended) way. Is there one?
Also, relatedly, it would be nice to have a "Settings Manager" utility for quickly verifying they are what you think they are, too. Does anybody know of one?
UPDATE
This is my attempt to "roll my own" based on the answer; so far, no go:
string roamingSettingPairs = string.Empty;
for (int i = 0; i < App.roamingSettings.Values.Count; i++)
{
// Print out whatever you want to verify that everything is as it should be
//string roamingSettingName = App.roamingSettings.Name[i].ToString();
//string roamingSettingValue = App.roamingSettings.Values[i].ToString();
Dictionary<string, object> roamingSettingVals = App.roamingSettings.Values;
string roamingSettingName = roamingSettingVals.Keys[i];
object roamingSettingObj = roamingSettingVals.Values[i];
//roamingSettingPairs = string.Format("{0}{1}={2}{3}", roamingSettingPairs, roamingSettingName,
// roamingSettingValue, Environment.NewLine);
}
You can delete all of your roaming settings using this code:
ApplicationData.Current.RoamingSettings.Values.Clear();
For a Settings Manager, I would probably just use a for loop like so:
for (int i = 0; i < ApplicationData.Current.RoamingSettings.Values.Count; i++)
{
// Print out whatever you want to verify that everything is as it should be
}

Categories