F# Akkling Unable to send message through sharding proxy - f#

When I try to send a message to the akka.net region proxy with the following code,
open Akkling.Cluster.Sharding
open Akka.Actor
open Akka.Cluster
open Akka.Cluster.Sharding
open System
open Akkling
let configWithPort (port:int) =
let config = Configuration.parse ("""
akka {
actor {
provider = cluster
}
remote {
dot-netty.tcp {
public-hostname = "localhost"
hostname = "localhost"
port = """ + port.ToString() + """
}
}
cluster {
roles = ["Worker"]
sharding {
journal-plugin-id = "akka.persistence.journal.inmem"
snapshot-plugin-id = "akka.persistence.snapshot-store.inmem"
}
seed-nodes = [ "akka.tcp://cluster-system#localhost:5000" ]
}
}
""")
config
.WithFallback(Akka.Cluster.Tools.Singleton.ClusterSingletonManager.DefaultConfig())
.WithFallback(ClusterSharding.DefaultConfig())
let system1 = ActorSystem.Create("cluster-system", configWithPort 5000)
let system2 = ActorSystem.Create("cluster-system", configWithPort 5001)
/// Domain
type FileCommand = {
ProgramId : string
Duration : TimeSpan
FilePath : string
}
/// Actors
let aggregateRootActor (mailbox:Actor<_>) (msg:FileCommand) =
let nodeAddress = Cluster.Get(mailbox.System).SelfUniqueAddress
logInfof mailbox "Program: [%s] with path [%s] on [%A]" msg.ProgramId msg.FilePath nodeAddress
ignored ()
let extractorFunction (message:FileCommand) =
let entityId = message.ProgramId
let hash = entityId.GetHashCode()
let numberOfShards = 5
let shardId = sprintf "shard_%d" ((abs hash) % numberOfShards)
shardId, entityId, message
let region1 = spawnSharded extractorFunction system1 "fileRouter" (props (actorOf2 aggregateRootActor))
let region2 = spawnSharded extractorFunction system2 "fileRouter" (props (actorOf2 aggregateRootActor))
let shardRegionProxy =
spawnShardedProxy extractorFunction system1 "fileRouterProxy" None
And sending message to the proxy always failed.
shardRegionProxy <! { ProgramId = "a"; Duration = TimeSpan.FromMinutes 10.; FilePath = "\\a_1.mp4" } //this failed
The error message is
> [INFO][8/26/2020 5:13:15 PM][Thread 0027][akka://cluster-system/system/sharding/fileRouterProxyCoordinator/singleton/coordinator] Message [RegisterProxy] from akka://cluster-system/system/sharding/fileRouterProxyProxy to akka://cluster-system/system/sharding/fileRouterProxyCoordinator/singleton/coordinator was not delivered. [6] dead letters encountered. If this is not an expected behavior then akka://cluster-system/system/sharding/fileRouterProxyCoordinator/singleton/coordinator may have terminated unexpectedly. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
However these sends are successful.
region1 <! { ProgramId = "d"; Duration = TimeSpan.FromMinutes 8.; FilePath = "\\a_2.mp4" }
region2 <! { ProgramId = "a"; Duration = TimeSpan.FromMinutes 10.; FilePath = "\\a_1.mp4" }
Excuse me,
How do I correctly create the shardingcoordinator?
Or if it was incorrect, what's the problem using shardingcoordinator like this?

The name was wrong, change the code like this, and everything is FINE!
let shardRegionProxy = spawnShardedProxy extractorFunction system1 "fileRouter" (Some "Worker")

Related

How to invoke device method in ios using azure iot sdk

I am trying to call a method associated with the device using connection string.
I tried with the samples provided with other languages I am able to call the method in the device. eg: "setState" or "getState" of the lamp.
But I am not able to implement in iOS using swift.
I tried to match parameter parameter requirement by referring to the C sample. But I am getting
1. Func:sendHttpRequestDeviceMethod Line:337 Http Failure status code 400.
2. Func:IoTHubDeviceMethod_Invoke Line:492 Failure sending HTTP request for device method invoke
var status :Int32! = 0
var deviceId = "simulated_device_one";
var methodName = "GetState";
var uint8Pointer:UnsafeMutablePointer<UInt8>!
uint8Pointer = UnsafeMutablePointer<UInt8>.allocate(capacity:8)
var size = size_t(10000)
var bytes: [UInt8] = [39, 77, 111, 111, 102, 33, 39, 0]
uint8Pointer?.initialize(from: &bytes, count: 8)
var intValue : UnsafeMutablePointer<UInt8>?
intValue = UnsafeMutablePointer(uint8Pointer)
var char: UInt8 = UInt8(20)
var charPointer = UnsafeMutablePointer<UInt8>(&char)
var prediction = intValue
let serviceClientDeviceMethodHandle = IoTHubDeviceMethod_Create(service_client_handle)
let payLoad = "test"
var responsePayload = ""
let invoke = IoTHubDeviceMethod_Invoke(serviceClientDeviceMethodHandle, deviceId, methodName, payLoad , 100, &status, &prediction,&size )
I want to call a method in the device using IoTHubDeviceMethod_Invoke
You can download View controller file which I worked on from here
1.Create Connection in view did load
// declaring your connection string you can find it in azure iot dashboard
private let connectionString = "Enter your connection String";
// creating service handler
private var service_client_handle: IOTHUB_SERVICE_CLIENT_AUTH_HANDLE!;
// handler for the method invoke
private var iot_device_method_handle:IOTHUB_SERVICE_CLIENT_DEVICE_METHOD_HANDLE!;
// In view did load establish the connection
service_client_handle = IoTHubServiceClientAuth_CreateFromConnectionString(connectionString)
if (service_client_handle == nil) {
showError(message: "Failed to create IoT Service handle", sendState: false)
}
create method invoke function
I created it based on the demo provided for sending message
func openIothubMethodInvoke() -> Bool
{
print("In openIotHub method invoke")
let result: Bool;
iot_device_method_handle = IoTHubDeviceMethod_Create(service_client_handle);
let testValue : Any? = iot_device_method_handle;
if (testValue == nil) {
showError(message: "Failed to create IoT devicemethod", sendState: false);
result = false;
}
else
{
result = true;
}
return result;
}
call method invoke
** this is the main function for calling the method
func methodInvoke()
{
let testValue : Any? = iot_device_method_handle;
if (testValue == nil && !openIothubMethodInvoke() ) {
print("Failued to open IoThub messaging");
}
else {
let size = UnsafeMutablePointer<Int>.allocate(capacity: 1)
let responseStatus = UnsafeMutablePointer<Int32>.allocate(capacity: 1)
// Payload is the main change it is like specifying the format
var payload = UnsafeMutablePointer<UnsafeMutablePointer<UInt8>?>.allocate(capacity: 1)
// if payload is not expected please send empty json "{}"
let result = IoTHubDeviceMethod_Invoke(iot_device_method_handle, "nameOfTheDeviceYouWantToCallOn", "MethodName", "{payload you want to send}", 100, responseStatus, payload , size)
// extracting the data from response
let b = UnsafeMutableBufferPointer(start: payload.pointee, count: size.pointee)
let data = Data(buffer: b)
let str = String(bytes: data, encoding: .utf8)
print(str)
do{
let value = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
print(value)
}catch{
print(error)
}
}
}
As discussed above: the payload needs to be valid JSON. Even an empty json will do such as {}

Post trade Order Binance Signature error

I am trying to make trade using binance api from ios.
Always gives error ["code": -1022, "msg": Signature for this request is not valid.]
Code:
public override func requestFor(api: APIType) -> NSMutableURLRequest {
let mutableURLRequest = api.mutableRequest
if let key = key, let secret = secret, api.authenticated {
var postData = api.postData
//postData["symbol"] = "BNBBTC"
//postData["timestamp"] = "\(Int(Date().timeIntervalSince1970 * 1000))"
postData["symbol"] = "BNBBTC"
postData["side"] = "SELL"
postData["type"] = "MARKET"
postData["recvWindow"] = "5000"
postData["quantity"] = "0.1"
postData["timestamp"] = "\(Int(Date().timeIntervalSince1970 * 1000))"
if let hmac_sha = try? HMAC(key: secret, variant: .sha256).authenticate(Array(postData.queryString.utf8)) {
let signature = Data(bytes: hmac_sha).toHexString()
postData["signature"] = signature
}
var postDataString = ""
if let data = postData.data, let string = data.string, postData.count > 0 {
postDataString = string
if case .GET = api.httpMethod {
mutableURLRequest.httpBody = data
} else if case .POST = api.httpMethod {
var urlString = mutableURLRequest.url?.absoluteString
urlString?.append("?")
urlString?.append(postData.queryString)
let url = URL(string: urlString!)
mutableURLRequest.url = url
}
api.print("Request Data: \(postDataString)", content: .response)
}
mutableURLRequest.setValue(key, forHTTPHeaderField: "X-MBX-APIKEY")
}
return mutableURLRequest
}
Edit: While using account api i am not facing any issues with the signature. It gives response as expected
I had same ... problem and I found answer. When you generate signature, inputs for Test Order and Account Info are different.
Inputs for account info:
string input = "timestamp=1535623795177";
string apiSecret = "YOUR API SECRET"
Inputs for test limit order:
string input = "symbol=ETHBTC&side=BUY&recvWindow=6500&type=LIMIT&timeInForce=GTC&quantity=100&price=0.1&timestamp=1535623795177";
string apiSecret = "YOUR API SECRET"
and generate signature working example (C#):
private string GenerateSignature(string input, string apiSecret)
{
var encoding = new UTF8Encoding();
byte[] keyByte = encoding.GetBytes(apiSecret);
byte[] messageBytes = encoding.GetBytes(input);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashMessage = hmacsha256.ComputeHash(messageBytes);
return String.Concat(hashMessage.Select(b => b.ToString("x2")));
}
}

How do I resolve: Akka.Remote.EndpointDisassociatedException?

I have some code that involves remote deploying actors onto a separate process.
I am getting: Akka.Remote.EndpointDisassociatedException
[WARNING][3/24/2017 1:54:32 PM][Thread
0008][[akka://system1/system/endpointMana
ger/reliableEndpointWriter-akka.tcp%3A%2F%2Fsystem2%40localhost%3A8080-1#1408457
663]] Association with remote system akka.tcp://system2#localhost:8080
has faile d; address is now gated for 5000 ms. Reason is:
[Akka.Remote.EndpointDisassociat edException: Disassociated at
Akka.Remote.EndpointWriter.PublishAndThrow(Exception reason, LogLevel
leve l, Boolean needToThrow) at
Akka.Actor.ReceiveActor.ExecutePartialMessageHandler(Object message,
Parti alAction1 partialAction) at
Akka.Actor.ActorCell.<>c__DisplayClass114_0.<Akka.Actor.IUntypedActorConte
xt.Become>b__0(Object m) at
Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
at Akka.Actor.ActorCell.ReceiveMessage(Object message) at
Akka.Actor.ActorCell.AutoReceiveMessage(Envelope envelope) at
Akka.Actor.ActorCell.Invoke(Envelope envelope)] [ERROR][3/24/2017
1:54:32 PM][Thread 0008][akka://system1/system/endpointManager
/reliableEndpointWriter-akka.tcp%3A%2F%2Fsystem2%40localhost%3A8080-1/endpointWr
iter] Disassociated Cause: Akka.Remote.EndpointDisassociatedException:
Disassociated at
Akka.Remote.EndpointWriter.PublishAndThrow(Exception reason, LogLevel
leve l, Boolean needToThrow) at
Akka.Actor.ReceiveActor.ExecutePartialMessageHandler(Object message,
Parti alAction1 partialAction) at
Akka.Actor.ActorCell.<>c__DisplayClass114_0.b__0(Object m) at
Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
at Akka.Actor.ActorCell.ReceiveMessage(Object message) at
Akka.Actor.ActorCell.AutoReceiveMessage(Envelope envelope) at
Akka.Actor.ActorCell.Invoke(Envelope envelope)
Here's the code that I execute in a separate process that triggers that error:
use system = ActorSystem.Create("system1", config)
let reply = system.ActorOf<ReplyActor>("reply")
let props1 = Props.Create(typeof<SomeActor>, [||])
let props2 = Props.Create(typeof<SomeActor>, [||])
let props3 = Props.Create(typeof<SomeActor>, [||])
let remote1 = system.ActorOf(props1.WithRouter(FromConfig.Instance), "remoteactor1")
let remote2 = system.ActorOf(props2.WithRouter(FromConfig.Instance), "remoteactor2")
let remote3 = system.ActorOf(props3.WithRouter(FromConfig.Instance), "remoteactor3")
let hashGroup = system.ActorOf(Props.Empty.WithRouter(ConsistentHashingGroup(config)))
Task.Delay(500).Wait();
let routee1 = Routee.FromActorRef(remote1);
hashGroup.Tell(new AddRoutee(routee1));
let routee2 = Routee.FromActorRef(remote2);
hashGroup.Tell(new AddRoutee(routee2));
let routee3 = Routee.FromActorRef(remote3);
hashGroup.Tell(new AddRoutee(routee3));
Task.Delay(500).Wait();
for i = 0 to 5 do
for j = 0 to 7 do
let message = new HashMessage(j, sprintf "remote message: %i" j);
hashGroup.Tell(message, reply);
Console.ReadLine() |> ignore
Here's the configuration that my remote deploy code relies on:
open Akka.Configuration
let config = ConfigurationFactory.ParseString(#"
akka {
log-config-on-start = on
stdout-loglevel = DEBUG
loglevel = DEBUG
actor {
provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
debug {
receive = on
autoreceive = on
lifecycle = on
event-stream = on
unhandled = on
}
deployment {
/localactor {
router = consistent-hashing-pool
nr-of-instances = 5
virtual-nodes-factor = 10
}
/remoteactor1 {
router = consistent-hashing-pool
nr-of-instances = 5
remote = ""akka.tcp://system2#localhost:8080""
}
/remoteactor2 {
router = consistent-hashing-pool
nr-of-instances = 5
remote = ""akka.tcp://system2#localhost:8080""
}
/remoteactor3 {
router = consistent-hashing-pool
nr-of-instances = 5
remote = ""akka.tcp://system2#localhost:8080""
}
}
}
remote {
helios.tcp {
port = 8090
hostname = localhost
}
}
}
")
Here's the C# code that actually works that my F# implementation is based off:
var config = ConfigurationFactory.ParseString(#"
akka {
log-config-on-start = on
stdout-loglevel = DEBUG
loglevel = DEBUG
actor {
provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
debug {
receive = on
autoreceive = on
lifecycle = on
event-stream = on
unhandled = on
}
deployment {
/localactor {
router = consistent-hashing-pool
nr-of-instances = 5
virtual-nodes-factor = 10
}
/remoteactor1 {
router = consistent-hashing-pool
nr-of-instances = 5
remote = ""akka.tcp://system2#localhost:8080""
}
/remoteactor2 {
router = consistent-hashing-pool
nr-of-instances = 5
remote = ""akka.tcp://system2#localhost:8080""
}
/remoteactor3 {
router = consistent-hashing-pool
nr-of-instances = 5
remote = ""akka.tcp://system2#localhost:8080""
}
}
}
remote {
dot-netty.tcp {
port = 8090
hostname = localhost
}
}
}
");
using (var system = ActorSystem.Create("system1", config))
{
var reply = system.ActorOf<ReplyActor>("reply");
//create a remote deployed actor
var remote1 = system.ActorOf(Props.Create(() => new SomeActor(null, 123)).WithRouter(FromConfig.Instance), "remoteactor1");
var remote2 = system.ActorOf(Props.Create(() => new SomeActor(null, 456)).WithRouter(FromConfig.Instance), "remoteactor2");
var remote3 = system.ActorOf(Props.Create(() => new SomeActor(null, 789)).WithRouter(FromConfig.Instance), "remoteactor3");
var hashGroup = system.ActorOf(Props.Empty.WithRouter(new ConsistentHashingGroup(config)));
Task.Delay(500).Wait();
var routee1 = Routee.FromActorRef(remote1);
hashGroup.Tell(new AddRoutee(routee1));
var routee2 = Routee.FromActorRef(remote2);
hashGroup.Tell(new AddRoutee(routee2));
var routee3 = Routee.FromActorRef(remote3);
hashGroup.Tell(new AddRoutee(routee3));
Task.Delay(500).Wait();
for (var i = 0; i < 5; i++)
{
for (var j = 0; j < 7; j++)
{
var message = new SomeMessage(j, $"remote message: {j}");
hashGroup.Tell(message, reply);
}
}
Console.ReadLine();
}
}
}
}
Can anyone provide guidance on why I'm getting this exception and how I can resolve it?
Hence, the F# implementation closely mirrors the working C# implementation.
The F# code can be found on GitHub.
When you're starting your application, you may read an exact exception that causes node disassociation: Could not load file or assembly 'System1....
What you've defined in your routers configuration is remote deployment. This means, that from one system you're trying to create actors on another node and communicate with them as if they were available locally. While this is possible, there is one requirement: a destination actor system must know how to build an actor. Since your actors are defined in System1 and created in System2, which doesn't know anything about SomeActor it fails and causes actor system to disassociate.
You need to pass SomeActor class to shared assembly, available for both systems, in order for your scenario to work.

Translating C# code for ZMQ socket polling to F#

My question concerns translating to F# the answer for this stackoverflow question. I am using the ZeroMQ C# CLR package.
Here is part of the C# (from the answer to the linked post):
ZSocket[] sockets = { receiver1, receiver2 };
ZPollItem[] pollItems = { ZPollItem.CreateReceiver(), ZPollItem.CreateReceiver() };
ZError error;
ZMessage[] msg;
while (true)
{
if (sockets.PollIn(pollItems, out msg, out error, timeout))
{
if (msg[0] != null)
{
// The first message gotten from receiver1
}
if (msg[1] != null)
{
// The second message gotten from receiver2
}
}
}
Here is my attempt at the translation:
let ctx = new ZeroMQ.ZContext()
let sub1 = new ZeroMQ.ZSocket(ctx, ZeroMQ.ZSocketType.SUB)
sub1.SubscribeAll()
sub1.Connect("tcp://localhost:3001")
let sub2 = new ZeroMQ.ZSocket(ctx, ZeroMQ.ZSocketType.SUB)
sub2.SubscribeAll()
sub2.Connect("tcp://localhost:3002")
let timeout = System.TimeSpan.FromMilliseconds(10.)
let sockets = [|sub1; sub2|]
let pollItems = [|ZeroMQ.ZPollItem.CreateReceiver(); ZeroMQ.ZPollItem.CreateReceiver()|]
let mutable error = ZeroMQ.ZError
let mutable msg = Array.init<ZeroMQ.ZMessage> 2 // ??? C#: ZMessage[] msg;
while true do
if ZeroMQ.ZPollItems.PollIn(pollItems, &msg, &error, timeout) then // no overloads match
if msg.[0] <> null then
() // work
if msg.[1] <> null then
() // work
()
Maybe the no overload error on the PollIn method line resolves if the ZMessage[] msg is properly defined in F#. I think the library itself is besides the point but happy to provide further details if needed. My main problem is I don't understand C# and barely understand F#.
As the compiler wrote - there is no such overload. Just look at what the function expects to receive:
You forgot to specify the socket as the first parameter.
Timeout must be of type Nullable:
So...
open ZeroMQ
open System
let ctx = new ZContext()
let sub1 = new ZSocket(ctx, ZSocketType.SUB)
sub1.SubscribeAll()
sub1.Connect("tcp://localhost:3001")
let sub2 = new ZSocket(ctx, ZSocketType.SUB)
sub2.SubscribeAll()
sub2.Connect("tcp://localhost:3002")
let timeout = TimeSpan.FromMilliseconds(10.) |> Nullable
let sockets = [|sub1; sub2|]
let pollItems = [|ZPollItem.CreateReceiver(); ZPollItem.CreateReceiver()|]
let mutable error = null
let mutable msg = null
while true do
if ZPollItems.PollIn(sockets, pollItems, &msg, &error, timeout) then
if msg.[0] <> null then
() // work
if msg.[1] <> null then
() // work
()

Grails Issue Dealing With Tcp Client & Tcp Server

I created a Tcp Client & Tcp Server in Groovy awhile back and had no issues with it. I was only connecting to one machine at the time to gather data. This time I am attempting to connect to the script on multiple hosts and it is only saving one of the hosts information in my grails app.
My Grails application is simple, it has a domain class for Machines (basically the computers and the information on them that I seek) and it will use my TcpClient.groovy script to connect and gather information from the TcpServer.groovy on the other computers. For each host, it should save the information gathered, however, it seems to skip right over saving any host aside from the last one.
Tcp Client :
//TCP CLIENT
public void queryData(def hosts) {
for(int aHost = 0; aHost < hosts.size; aHost++) {
cristalClient(hosts[aHost]);
}
}
public void cristalClient(String host) {
commands = ["dateScan", "computerName", "ip", "quit"]
answers = [commands.size]
requestSocket = new Socket(host, 2000)
r = new BufferedReader(new InputStreamReader(requestSocket.getInputStream()));
w = new BufferedWriter(new OutputStreamWriter(requestSocket.getOutputStream()));
String message = "Connection was successful"
message = readAvailable(r)
println("Sever>" + message)
for(int n = 0; n < commands.size; n++) {
sendMessage(commands[n]);
answers[n] = readAvailable(r)
}
lastRead = answers[0]
machineName = answers[1]
ipAddress = answers[3]
w.flush()
w.close()
}
public String readAvailable(r) {
String out = ""
String dum = null
while((dum = r.readLine()) !=null) {
if(dum == ">>EOF<<") return out
if(out.length() > 0) out += "\r\n"
out += dum
}
return out
}
public void sendMessage(msg) {
w.write(msg+"\r\n");
w.flush();
println("Client>" + msg);
}
public void printData(abc) {
abc.eachWithIndex { it, index ->
println "Drive $index"
it.each { k, v ->
println "\t$k = $v"
}
}
}
Tcp Server :
//TCP Server
def server = new ServerSocket(2000)
println("Waiting for connection")
server.accept() { socket ->
socket.withStreams { input, output ->
w = new BufferedWriter(new OutputStreamWriter(output))
String message = "Connection was successful"
r = new BufferedReader(new InputStreamReader(input))
while(true) {
if(message != null) {
sendMessage(message)
message = null
}
String a = r.readLine()
if(a == "dateScan") {
message = new Date
} else if(a == "computerName") {
message = InetAddress.getLocalHost().hostName
} else if(a == "ip") {
message = InetAddress.getLocalHost().getHostAddress()
} else if(a == "quit") {
server.close()
return
} else {
message = "$a command unknown."
println message
}
}
}
}
def sendMessage(String msg) {
println( "sending: >" + msg + "<" )
w.writeLine(msg)
w.writeLine(">>EOF<<")
w.flush();
}
Grails Controller :
//Grails Controller
CollectMachines {
def w = new tcpClient()
def hosts = ["winXp", "Win7"]
w.queryData(hosts)
def abc = w.hardDrive
abc.each { println it }
int numberOfDrives = abc.size()
//add new machine
numberOfDrives.times {
def machineName = abc.computerName[it]
def machineInstance = Machine.findByMachineName(machineName)
if (!machineInstance) {
machineInstance = new Machine(machineName)
}
def lastScan = abc.lastScan[it]
def scanDate = new Date().parse("E MMM dd H:m:s z yyyy", lastScan)
def ipAddress = abc.ipAddress[it]
machineInstance.setIpAddress(ipAddress)
machineInstance.setDateScanned(scanDate)
machineInstance.save()
}
redirect(action: "list")
}
Do I need to put a pause in so that the server has time to send a response? My Tcp Client does send out all the commands but only gets responses for the last set of commands.
Also, sorry for the indentation issues with my code snippets, I'm not sure why they are messed up.
.
There are a few problems with your code. tcpClient never assigns to hardDrive, for example. Assuming this is an oversight, I think the real problem is that tcpClient is querying data for multiple hosts, and storing all the results in the same instance variables answers, and ultimately lastRead, machineName, and ipAddress.
You need to store the results for each host separately. One way would be to have answers be a map of lists. For example, answers[host][0] would be the first answer for a given host.
I don't think any kind of pause is necessary.

Resources