How to register an AsyncEventingBasicConsumer in F# - f#

I'm trying to create an asyncEventBasicConsumer in F#.
In order to do that I need to use add_Received that has the follow signature
member add_Received:
value: AsyncEventHandler<BasicDeliverEventArgs>
-> unit
But I don't have idea how to create an AsyncEventHandler from
async {}
This is the concrete function
let subscribe : Subscribe =
fun factory queueName handleMessage ->
let connection = factory.CreateConnection()
let model = connection.CreateModel()
let consumer = AsyncEventingBasicConsumer(model)
consumer.add_Received //?? how create a AsyncEventHandler
model.BasicConsume(queueName, false, consumer) |> ignore
(fun () ->
model.Close()
connection.Close())
And here the c# code
static void Main(string[] args)
{
var factory = new ConnectionFactory() { DispatchConsumersAsync = true };
const string queueName = "myqueue";
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queueName, true, false, false, null);
// consumer
var consumer = new AsyncEventingBasicConsumer(channel);
consumer.Received += Consumer_Received;
channel.BasicConsume(queueName, true, consumer);
// publisher
var props = channel.CreateBasicProperties();
int i = 0;
while (true)
{
var messageBody = Encoding.UTF8.GetBytes($"Message {++i}");
channel.BasicPublish("", queueName, props, messageBody);
Thread.Sleep(50);
}
}
}
private static async Task Consumer_Received(object sender, BasicDeliverEventArgs #event)
{
var message = Encoding.UTF8.GetString(#event.Body);
Console.WriteLine($"Begin processing {message}");
await Task.Delay(250);
Console.WriteLine($"End processing {message}");
}

This should do the trick
consumer.add_Received(fun sender event -> Consumer_Received sender event |> Async.StartAsTask :> Task)
Notable points are casting async to Task and upcasting Task<'a> to Task.

Related

Streaming seq in Giraffe F#

I was wondering what is the easiest way to stream F# seq in Giraffe. Not much, but here's what I have:
module HttpHandler =
let handlerGuids : HttpHandler =
handleContext(
fun ctx ->
task {
let collection =
seq {
let mutable i = 0
while (not ctx.RequestAborted.IsCancellationRequested) && i <10 do
i <- i + 1
Async.Sleep(2000) |> Async.RunSynchronously
yield Guid.NewGuid()
}
return! ctx.WriteJsonChunkedAsync collection
})
let router: HttpFunc -> HttpContext -> HttpFuncResult =
choose [ route "/" >=> handlerGuids ]
I laso have this test in C#
[Fact]
public async void Test1()
{
using var httpClient = new HttpClient();
httpClient.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
var requestUri = "http://localhost:8080/";
var stream = await httpClient.GetStreamAsync(requestUri);
using var reader = new StreamReader(stream);
while (!reader.EndOfStream) {
var currentLine = reader.ReadLine();
}
}
But it waits until all guids are generated on the server. Can someone give me some hints? Giraffe documentation says sth about streaming but it is related to files.

mvc pass Model object as variable to reduntant function

Have a MVC5 c# Entity Framework Project.
Have a MVC project and trying to reduce my functions and have several that are basically the same. The functions are updating the same 3 fields: operator, date and function performed on the table. Each function references different table names and field names. Is there a way to pass the Model table and field names into the function so I don't have to have one for each table in the Model?
These are my functions:
internal void TrackAggrTest(mts_aggrtest mts_aggrtest, string struser, string action)
{
// Tract User Action AggrSpec
mts_aggrtest.F_OPRID = struser.ToString().Substring(struser.LastIndexOf("\\") + 1).ToUpper();
mts_aggrtest.F_DATENT = DateTime.Today;
mts_aggrtest.F_FUNCT = action.ToString();
return;
}
internal void TrackBoltTest(mts_bolttest mts_bolttest, string struser, string action)
{
// Tract User Action mts_meshtest
mts_bolttest.T_OPRID = struser.ToString().Substring(struser.LastIndexOf("\\") + 1).ToUpper();
mts_bolttest.T_DATENT = DateTime.Today;
mts_bolttest.T_FUNCT = action.ToString();
return;
}
internal void TrackBoltSpec(mts_boltspec mts_boltspec, string struser, string action)
{
// Tract User Action mts_meshtest
mts_boltspec.TS_OPRID = struser.ToString().Substring(struser.LastIndexOf("\\") + 1).ToUpper();
mts_boltspec.TS_DATENT = DateTime.Today;
mts_boltspec.TS_FUNCT = action.ToString();
return;
}
These functions are called in the Controllers in the Edit/Create Actions.
In the MTS_aggrspecController in the Create action I have:
var struser = (Session["myUser"]).ToString();
b.TrackAggrSpec(mts_aggrspec, struser, "A");
In the EDIT action:
var struser = (Session["myUser"]).ToString();
b.TrackAggrSpec(mts_aggrspec, struser, "U");
In the MTS_aggrtestController the function is called :
var struser = (Session["myUser"]).ToString();
b.TrackAggrTest(mts_aggrtest, struser, "U");
This just seems so redundant and know there MUST be a better way I just don't know how.
Have looked at other post but can't find one that seems to suit this problem. Any help is appreciated or if can point me in right direction.
First of all, you don't need to call ToString() for strings.
mts_boltspec.TS_OPRID = struser
.ToString()
.Substring(struser.LastIndexOf("\\") + 1)
.ToUpper();
mts_boltspec.TS_FUNCT = Action.ToString();
Should just be
mts_boltspec.TS_OPRID = struser
.Substring(struser.LastIndexOf("\\") + 1)
.ToUpper();
mts_boltspec.TS_FUNCT = Action;
Secondly, Microsoft guidelines suggest lowercase parameters
internal void TrackAggrTest(mts_aggrtest mts_aggrtest, string struser, string Action)
should be
internal void TrackAggrTest(mts_aggrtest mts_aggrtest, string struser, string action)
Lastly, you don't need an empty return statement.
internal void TrackAggrTest(mts_aggrtest mts_aggrtest, string struser, string action)
{
mts_boltspec.TS_OPRID = struser
.Substring(struser.LastIndexOf("\\") + 1)
.ToUpper();
mts_boltspec.TS_DATENT = DateTime.Today;
mts_boltspec.TS_FUNCT;
}
With the basics out of the way, you can combine all these methods into one using generics and Action (delegate). To make readable, I would also create an extension method.
internal static class TrackAggrTestExtensions
{
public static void TrackAggrTest<TBoltSpec>(this TBoltSpec instance,
string struser,
string funct,
Action<TBoltSpec, string> assignOprId,
Action<TBoltSpec, DateTime> assignDateNT,
Action<TBoltSpec, string> assignFunct)
{
var oprid = struser
.Substring(struser.LastIndexOf("\\") + 1)
.ToUpper();
var datent = DateTime.Today;
assignOprId(instance, oprid);
assignDateNT(instance, datent);
assignFunct(instance, funct);
}
}
Now your calls looks like:
myAggrTest.TrackAggrTest(struser,
action,
(i, id) => i.F_OPRID = id,
(i, dt) => i.F_DATENT = dt,
(i, f) => i.F_FUNCT = f);
myBoltTest.TrackAggrTest(struser,
action,
(i, id) => i.T_OPRID = id,
(i, dt) => i.T_DATENT = dt,
(i, f) => i.T_FUNCT = f);
myBoltSpec.TrackAggrTest(struser,
action,
(i, id) => i.TS_OPRID = id,
(i, dt) => i.TS_DATENT = dt,
(i, f) => i.TS_FUNCT = f);
Not really sure that's any better however.

Flume Custom Interceptor is not Working

I want to change IP address in data by its mask IP. This is done in the "backup" part of my Flume agent (see below).
In this configuration there are 2 channels: the first channel dumps data to HBase, while the second one is used for backup:
a1.sources = r1 r2
a1.channels = channel1 Backup_channel
a1.sinks = FSink
a1.sources.r1.handler = com.flume.handler.JSONHandler
a1.sources.r1.type = avro
a1.sources.r1.bind = x.x.x.x
a1.sources.r1.port = 10008
a1.sources.r2.handler = com.flume.handler.JSONHandler
a1.sources.r2.type = avro
a1.sources.r2.bind = x.x.x.x
a1.sources.r2.port = 10009
a1.sources.r2.interceptors = i1
a1.sources.r2.interceptors.i1.type = com.flume.interceptor.DcInterceptor
a1.channels.channel1.type = file
a1.channels.channel1.checkpointDir = /root/flume/channels/Livechannel/checkpoint
a1.channels.channel1.dataDirs = /root/flume/channels/Livechannel/data
a1.sinks.FSink.type = hbase
a1.sinks.FSink.table = Temp_Test
a1.sinks.FSink.batchSize = 300
a1.sinks.FSink.columnFamily = T
a1.sinks.FSink.serializer = com.flume.sink.TestTP
a1.sources.r1.channels = channel1
a1.sources.r2.channels = Backup_channel
a1.channels.Backup_channel.type = file
a1.channels.Backup_channel.checkpointDir = /data/disk/flume/backup/checkpoint
a1.channels.Backup_channel.dataDirs = /data/disk/flume/backup/data
a1.sinks.FSink.channel = channel1
Following is my custom Java Interceptor Code. It implements the interception method, which get an IP address from the body, calculates its IP mask and then adds it to the body. But somehow it's not working:
public class DcInterceptor implements Interceptor {
private byte[] jsonTestBeans;
private final Type listType = new TypeToken < List < TestBeans >> () {}.getType();
#Override
public void close() {
// TODO Auto-generated method stub
}
#Override
public void initialize() {
// TODO Auto-generated method stub
new Logger();
}
#Override
public Event intercept(Event event) {
// TODO Auto-generated method stub
List < Row > actions = new ArrayList < Row > ();
this.jsonTestBeans = event.getBody();
Logger.logger.debug("In Interceptor");
System.out.println("In Interceptor");
Gson _Gson = new Gson();
String jsonstr = "";
try {
jsonstr = new String(jsonTestBeans, "UTF-8");
} catch (Exception e) {
// TODO: handle exception
Logger.logger.error(e.getMessage() + "In Interceptor");
jsonstr = new String(jsonTestBeans);
}
List < TestBeans > TestBeanss = _Gson.fromJson(jsonstr, listType);
System.out.println("Json String :" + jsonstr);
List < String > gTouch = new ArrayList < String > ();
for (TestBeans TestBeans: TestBeanss) {
String str = TestBeans.getIp();
Logger.logger.debug("IP : " + str);
String st = (str.substring(0, str.lastIndexOf(".") + 1) + "x");
Logger.logger.debug("Mask IP : " + st);
TestBeans.setRemoteIp(st);
}
event.setBody(_Gson.toJson(TestBeanss).getBytes());
Logger.logger.debug("Interceptor Ends");
return event;
}
#Override
public List < Event > intercept(List < Event > events) {
// TODO Auto-generated method stub
System.out.println("In List Interceptor");
Logger.logger.debug("In List Interceptor");
for (Event event: events) {
intercept(event);
}
return events;
}
public static class CounterInterceptorBuilder implements Interceptor.Builder {
private Context ctx;
#Override
public Interceptor build() {
Logger.logger.debug("In Interceptor Build");
System.out.println("In Build Interceptor");
return new DcInterceptor();
}
#Override
public void configure(Context context) {
this.ctx = context;
}
}
At least, I can see:
The configuration lines regarding your interceptor refer to an agent called ECircleTp_Test, while the rest of the configuration refer to a1.
You have configured com.flume.interceptor.DcInterceptor2, but the interceptor class you have developed is called DcInterceptor (without the final 2).
You have configured com.flume.interceptor.DcInterceptor2 as the fully qualified class name of your custom interceptor. Nevertheless, the code of the interceptor does not declare any package for the DcInterceptor(2) class.

Getting an error compiling webkit/webview app - Vala/GTK

I am trying to build my first webkit based app using Vala and GTK. I'm very new to these to languages and the process of compiling them so any help would be great.
This is the error I receive:
/home/elementary/GTKProjects/Fookbase/src/fookbase_main.vala:2.7-2.12: error: The namespace name `WebKit' could not be found using WebKit;
/home/elementary/GTKProjects/Fookbase/src/fookbase_main.vala:13.13-13.19: error: The type name `WebView' could not be found private WebView web_view;
This is my code:
using Gtk;
using WebKit;
public class Fookbase : Window {
private const string TITLE = "Fookbase";
private const string HOME_URL = "http://fookbase.com";
private const string DEFAULT_PROTOCOL = "http";
private Regex protocol_regex;
private Entry url_bar;
private WebView web_view;
private Label status_bar;
private ToolButton back_button;
private ToolButton forward_button;
private ToolButton reload_button;
public Fookbase () {
this.title = Fookbase.TITLE;
set_default_size (500, 800);
try {
this.protocol_regex = new Regex (".*://.*");
} catch (RegexError e) {
critical ("%s", e.message);
}
create_widgets ();
connect_signals ();
this.url_bar.grab_focus ();
}
private void create_widgets () {
var toolbar = new Toolbar ();
this.back_button = new ToolButton.from_stock (Stock.GO_BACK);
this.forward_button = new ToolButton.from_stock (Stock.GO_FORWARD);
this.reload_button = new ToolButton.from_stock (Stock.REFRESH);
toolbar.add (this.back_button);
toolbar.add (this.forward_button);
toolbar.add (this.reload_button);
this.web_view = new WebView ();
var scrolled_window = new ScrolledWindow (null, null);
scrolled_window.set_policy (PolicyType.AUTOMATIC, PolicyType.AUTOMATIC);
scrolled_window.add (this.web_view);
this.status_bar.xalign = 0;
var vbox = new VBox (false, 0);
vbox.pack_start (toolbar, false, true, 0);
vbox.pack_start (this.url_bar, false, true, 0);
vbox.add (scrolled_window);
vbox.pack_start (this.status_bar, false, true, 0);
add (vbox);
}
private void connect_signals () {
this.destroy.connect (Gtk.main_quit);
this.url_bar.activate.connect (on_activate);
this.web_view.title_changed.connect ((source, frame, title) => {
this.title = "%s - %s".printf (title, Fookbase.TITLE);
});
this.web_view.load_committed.connect ((source, frame) => {
this.url_bar.text = frame.get_uri ();
update_buttons ();
});
this.back_button.clicked.connect (this.web_view.go_back);
this.forward_button.clicked.connect (this.web_view.go_forward);
this.reload_button.clicked.connect (this.web_view.reload);
}
private void update_buttons () {
this.back_button.sensitive = this.web_view.can_go_back ();
this.forward_button.sensitive = this.web_view.can_go_forward ();
}
private void on_activate () {
var url = this.url_bar.text;
if (!this.protocol_regex.match (url)) {
url = "%s://%s".printf (Fookbase.DEFAULT_PROTOCOL, url);
}
this.web_view.open (url);
}
public void start () {
show_all ();
this.web_view.open (Fookbase.HOME_URL);
}
public static int main (string[] args) {
Gtk.init (ref args);
var browser = new Fookbase ();
browser.start ();
Gtk.main ();
return 0;
}
}
In order to use a library in Vala, you need to tell the compiler about it. Just saying "using WebKit" in the code isn't enough. You do this by passing the --pkg flag (with the desired value) to valac.
The name of the package for almost all bindings matches the pkg-config name so the Vala compiler can automatically determine the correct flags to pass to the C compiler and the linker. To see which packages are available from Vala, you can look in the /usr/share/vala/vapi and /usr/share/vala-x.yz/vapi directories (the latter being specific to the version of valac you're using). Valadoc.org also has the names for a lot of packages. I'm not sure what your reference was when you wrote your code, but generally they will tell you what package you're looking at.
For WebKit, if you're writing new software you probably want to use either webkit2gtk-4.0 or webkit2gtk-web-extension-4.0, which are the packages which link against gtk+-3.0.
So, something like
valac --pkg webkit2gtk-4.0 ... your-file.vala

What can i do with a stored type?

Dart allows variables of types: Type type = SomeType; But for what purpose?
For example, foo bar baz are misapplications:
class A {
Type type = List;
foo() => new type();
type bar() {
return new List();
}
type baz = new List();
}
void main() {
Type type = String;
var str = "Hello Dart";
print(type == str.runtimeType);//true
print(str is String);//true
print(str is type); //type error.
}
I think this one is pretty neat:
void main() {
foo(Type t) {
switch (t){
case int: return 5;
case List: return [1,2,3]; // This one gets me every time :(
case String: return "Hello Dart!";
default: return "default";
}}
print(foo(10.runtimeType)); //5
print(foo([2,4,6].runtimeType)); //default
print(foo("lalala".runtimeType)); //Hello Dart!
print(foo(foo.runtimeType)); //default
}
Is its sole purpose to be the return type for methods like runtimeType and type matching ?
I don't think you can use it for generics. There you need type literals. But you can use it for reflection.
Just one simple example:
import 'dart:mirrors' as mirr;
class A {
String s;
A(this.s);
#override
String toString() => s;
}
void main() {
Type type = A;
var str = "Hello Dart";
mirr.ClassMirror cm = mirr.reflectType(type);
var s = cm.newInstance(new Symbol(''), [str]).reflectee;
print(s);
}
You could also create a Map with registered factories for different types to avoid the need for reflection.
(not tested)
class A {
String s;
int a = 0;
int b = 0;
int c = 0;
A(this.s);
A.extended(this.s, this.a, this.b, this.c);
#override
String toString() => '${super.toString()}: $s, $a, $b, $c';
}
void main(args) {
Type t = A;
registerType(t, (List args) => new A.extended(args[0], args[1], args[2], args[3]));
...
var a = getInstance(t, ['hallo', 1, 2, 3]);
}
Map<Type,Function> _factories = {};
void registerType(Type t, Function factory) {
_factories[t] = factory;
}
void getNewInstance(Type t, List args) {
return _factories[t](args);
}

Resources