Creating a seperate conatiner per queue - spring

I have a use case where we have a strict need that all of the queues have a dedicated thread and consumer, which means each thread will only serve one queue.
I have read this accepted answer and the comment by Gary Russell. He mentioned creating a child application context for having all the features of #RabbitListener for achieving what I am trying. Still I didn't get how to do this when the queues are dynamically added during runtime.
If possible please point me to the relevant article for solving this in both the application context way(also how can I create the child contexts) and the MessageListenerAdapter way as advised.

Here is some solution based on Spring Boot and child application context declaration.
I have #RabbitListener in the component which will be declared in the child context:
#EnableRabbit
public class DynamicRabbitListener {
#Bean
public AmqpAdmin amqpAdmin(ConnectionFactory connectionFactory) {
return new RabbitAdmin(connectionFactory);
}
#RabbitListener(queuesToDeclare = #Queue(name = "${dynamic.queue}", autoDelete = "true"))
public void listen(String payload, #Header(AmqpHeaders.CONSUMER_QUEUE) String queueName) {
System.out.printf("Received %s from queue %s%n", payload, queueName);
}
}
We need #EnableRabbit to register respective annotation processor to the child application context and be able to trigger the proper lifecycle.
W need AmqpAdmin in this context to be able to declare dynamic queues.
Both of those aspects give us some isolation in the processing and logic.
Now this is how I declare those contexts:
#Bean
ApplicationRunner applicationRunner(ConfigurableApplicationContext parent, RabbitTemplate rabbitTemplate) {
return args -> {
for (int i = 0; i < 10; i++) {
String dynamicQueue = "dynamicQueue#" + i;
AnnotationConfigApplicationContext childApplicationContext =
new AnnotationConfigApplicationContext();
childApplicationContext.setParent(parent);
childApplicationContext.register(DynamicRabbitListener.class);
ConfigurableEnvironment environment = parent.getEnvironment();
MapPropertySource propertySource =
new MapPropertySource("dynamic.queues", Map.of("dynamic.queue", dynamicQueue));
environment.getPropertySources().addLast(propertySource);
childApplicationContext.setEnvironment(environment);
childApplicationContext.refresh();
rabbitTemplate.convertAndSend(dynamicQueue, "test data #" + i);
}
};
}
Pay attention to the propertySource to achieve a dynamic requirements for every child application context with its specific #RabbitListener.
The output of my program is like this:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.7.0)
Received test data #0 from queue dynamicQueue#0
Received test data #1 from queue dynamicQueue#1
Received test data #2 from queue dynamicQueue#2
Received test data #3 from queue dynamicQueue#3
Received test data #4 from queue dynamicQueue#4
Received test data #5 from queue dynamicQueue#5
Received test data #6 from queue dynamicQueue#6
Received test data #7 from queue dynamicQueue#7
Received test data #8 from queue dynamicQueue#8
Received test data #9 from queue dynamicQueue#9

Related

Event Sourcing: How to combine divergent states?

Suppose:
The events are A perceived, B perceived or Ping perceived.
A possible sequence of events could be A,A,A,B,Ping.
The states are InA, InB, PingMissing.
The rules are
No Ping in all events -> PingMissing.
A -> InA
B -> InB
(Only Ping events -> InA)
I would like to have one recommended action/ state.
I see three possibilities for the transition function f(s,e)->s:
Create a pseudo event likePingMissing perceived. Hence everything is in one function.
Two separate transition functions and combining the result.
One transition function with two states as a tuple and combining the result.
Any thoughts? Best practices?
Implementation of 2. in F# (language doesn't really matter):
type Event =
| A
| B
| Ping
type State1 =
| InA
| InB
type State2 =
| PingReceived
| PingMissing
type StateCombined =
| InA'
| InB'
| PingMissing'
let f1 s e :State1 =
match s,e with
| _, A -> InA
| _, B -> InB
| _, _ -> s
let f2 s e :State2 =
match s,e with
| _, Ping -> PingReceived
| _, _ -> s
let fCombined events =
let finalState1 = events |> Seq.fold f1 InA
let finalState2 = events |> Seq.fold f2 PingMissing
match finalState1, finalState2 with
| _, PingMissing -> PingMissing'
| InA, _ -> InA'
| InB, _ -> InB'
fCombined [A;A;A;B]
// PingMissing'
fCombined [A;A;A;B;Ping]
// InB'
I would tend to model the unified state as a tuple of the two substates (broadly in this case: "has a ping been received" and "if a ping has been received, was the last perception an A or a B"). A convenience function can then distill that into a recommendation.
This has the advantage of not reusing the sequence of events, so is a bit more compatible with a view of the events as a stream: at the very least this results in not having to refetch the events from an event store or keep the entire sequence of events in memory.
For example, in Scala (and explicitly modeling the situation where no A nor B has been perceived yet):
sealed trait Event
case object A extends Event
case object B extends Event
case object Ping extends Event
sealed trait PingState
case object PingReceived extends Event // Don't strictly need...
case object PingMissing extends Event
sealed trait LastPerceivedState
case object InA extends Event
case object InB extends Event
// ... could just as well be (Option[PingMissing], Option[LastPerceivedState])...
type State = (PingState, Option[LastPerceivedState])
// ... in which case, this is (Some(PingMissing), None)
val InitialState = PingMissing -> None
def distilledState(state: State): Either[PingMissing, Option[LastPerceivedState]] =
state match {
case (PingMissing, _) => Left(PingMissing)
case (_, lpsOpt) => Right(lpsOpt)
}
The transition function could then be written directly (taking advantage of the fact that the events can be partitioned into events which affect PingState or LastPerceivedState but never both):
val transitionF = { (state: State, evt: Event) =>
val (ps, lpsOpt) = state
evt match {
case A => ps -> Some(InA)
case B => ps -> Some(InB)
case Ping => PingReceived -> lpsOpt
}
}
In the event that there are events which affect both, then decomposing into subhandlers might simplify the code (at the expense of some possibly redundant invocations):
val pingStateTransition = { (ps: PingState, evt: Event) =>
if (ps == PingReceived) PingReceived
else if (evt == Ping) PingReceived
else ps
}
val lastPerceivedStateTransition = { (lpsOpt: Option[LastPerceivedState], evt: Event) =>
evt match {
case A => Some(InA)
case B => Some(InB)
case _ => lpsOpt
}
}
val transitionF = { (state: State, evt: Evt) =>
pingStateTransition(state._1, evt) -> lastPerceivedStateTransition(state._2, evt)
}

Simple Throttle control in Go [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 1 year ago.
Improve this question
How to create a simple throttle control to stop your API receiving to many requests. or effectively getting DDOSed? Since sometimes you might have a forward facing API passing all connections to your service. There is as mentioned some other solutions that build throttle into the actual connection, but do over complicate what is effectively a simple solution, looking at the recommended solutions, they pretty much do what is suggested below by adding id to a map. For those still learning, this is not a bad option, but as go is so great, you can attempt simple, and then refine to a better solution as you begin to understand the mechanisms better.
Though this was flagged as promoting some Book or something, it is simply my attempt to help others. if that's bad, then Ill stay bad. :D
Here is some simple throttle control code, use this as an IF call with the unique identifier of said service, in this case an IP, and the time you want to wait. as you can see by the code, you can change seconds to minutes or milliseconds. and you would be better to use a service like cloudflare, but as a last stand option, placing this in your API and putting an IF statement around the handler code, you can throttle control the connections. this is to keep it simple, I am sure there are other elegant solutions out their, and my dumb attempt might be ridiculed, but I am sure someone will learn from this, and suggestions for improvement will also be included if they make sense.
/******************************************************************************
* _ _ _ _ _ _ _
* | | | | | | | | | | /\ | | |
* | |_| |__ _ __ ___ | |_| |_| | ___ / \ | | | _____ __
* | __| '_ \| '__/ _ \| __| __| |/ _ \ / /\ \ | | |/ _ \ \ /\ / /
* | |_| | | | | | (_) | |_| |_| | __// ____ \| | | (_) \ V V /
* \__|_| |_|_| \___/ \__|\__|_|\___/_/ \_\_|_|\___/ \_/\_/
* ----------------------------------------------------------------------------
* This function will temp store the value in a map and then remove it, it will
* return true or false if the item is in the map, Now sets delay on second response
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
var throttle = make(map[string]bool)
func throttleAllow(ip string, timeout int) (retVal bool) {
if throttle[ip] == true {
fmt.Println("WARM","-=Throttle=-To frequent calls from:",ip)
time.Sleep(time.Duration(timeout)*time.Second) //Random next cycle.
retVal = true // false will result is receiging to frequent message
} else {
throttle[ip] = true
go func(){
time.Sleep(time.Duration(timeout)*time.Second) //Random next cycle.
delete(throttle, ip)
}()
retVal = true
}
return
}

F# Fabulous Xamarin: external event subscription

I'm new to Fabulous and MUV model, and I'm trying to implement application that works with BLE. I'm also a bit new to F#, mostly worked with erlang and C# in the past, so a bit lost with external events processing. CrossBluetoothLE.Current.Adapter has DeviceDiscovered event handler (IEvent). What's the most correct way of linking this event handler to the Fabulous update function?
E.g. after I will call CrossBluetoothLE.Current.Adapter.StartScanningForDevicesAsync(), I want that this event handler supply newly discovered devices to the update function.
And if I will do something like this (this is not working):
type MyApp () as app =
inherit Application ()
let deviceDiscovered dispatch =
CrossBluetoothLE.Current.Adapter.DeviceDiscovered.Subscribe (fun x -> dispatch (App.Msg.Discovered x.Device) )
let runner =
App.program
|> Program.withConsoleTrace
|> Program.withSubscription (fun _ -> Cmd.ofSub deviceDiscovered)
|> XamarinFormsProgram.run app
if it works, it will be ok for device discovery because CrossBluetoothLE.Current.Adapter is static. However after device will be discovered, I will need to work with (e.g. receive notifications or replies from it), and it will not be possible to include dynamic device handler into Program.withSubscription.
Not sure whether the Fabulous is applicable here.
Ok, I was able to find some solution and it works now, but the overall architecture looks a bit weird. So generic approach is to create an external mailbox, that will dispatch messages to the MUV loop.
Describe all messages of the MUV in the external module, e.g.:
type Msg =
| Scan
| Discovered of IDevice
| Connect of IDevice
| ClockMsg of System.DateTime
| TextMsg of string
Create type that encapsulates mailbox:
type DispatchFunc = Msgs.Msg -> unit
type State =
| Initialized of DispatchFunc
| NotInitialized
type Mail =
| Dispatch of DispatchFunc
| Msg of Msgs.Msg
| None
let rand = System.Random()
let id = rand.NextDouble()
let postbox = MailboxProcessor.Start(fun inbox ->
let rec messageLoop (state:State) = async{
let! mail = inbox.Receive()
let new_state =
match mail with
| None ->
state
| Msg msg ->
match state with
| NotInitialized -> NotInitialized
| Initialized df ->
df msg
state
| Dispatch df ->
Initialized df
return! messageLoop (new_state)
}
messageLoop (NotInitialized))
let post(o) =
postbox.Post o
Here, mailbox starts with NotInitialized state and wait while application will start. When everything is done, mailbox received dispatch function, that will be used in further dispatching of the external messages to the MUV main loop.
Pass dispatch handler to the mailbox:
type MyApp () as app =
inherit Application ()
// generate initial events + start threads + pass dispatch reference to the mailbox
let initThreads dispatch =
// init & start external (e.g. bluetooth receiver) threads here
// or start them asynchronously from MUV loop
Postbox.post (Postbox.Dispatch dispatch)
()
let runner =
App.program
|> Program.withConsoleTrace
|> Program.withSubscription (fun _ -> Cmd.ofSub initThreads)
|> XamarinFormsProgram.run app
So now, if you want to send event to the MUV from external thread, just start it inside initThreads (or, e.g. from within MUV loop) and use something like: Postbox.post (Postbox.Msg (Msgs.TextMsg "It works!")).
E.g. for my purposes (BLE discovery) it will look like this:
let update msg model =
match msg with
| Msgs.Scan ->
CrossBluetoothLE.Current.Adapter.StopScanningForDevicesAsync() |> Async.AwaitTask |> ignore
CrossBluetoothLE.Current.Adapter.DeviceDiscovered.Subscribe (
fun (a) ->
Postbox.post (Postbox.Msg (Msgs.Discovered a.Device))
()
) |> ignore
CrossBluetoothLE.Current.Adapter.StartScanningForDevicesAsync() |> Async.AwaitTask |> ignore
model, Cmd.none
| Msgs.ClockMsg msg ->
{ model with label = msg.ToString() }, Cmd.none
| Msgs.TextMsg msg ->
{ model with label = msg }, Cmd.none
| Msgs.Discovered d ->
{ model with gattDevices = d::model.gattDevices; label = "Discovered " + d.ToString() }, Cmd.none
| Msgs.Connect d -> { model with connectedDevice = d }, Cmd.none
This is for sure a very ugly solution, but I wasn't able to imagine something more beautiful :(.

io_service object working mechanism

I am confused about io_services object working mechanism. My understanding is that there is a queue associates with io_service object, if any async invocation will add one item in the queue, when io_service.run_once is called ,one async invocation will run and dequeue from the queue. if the queue is empty the io_service.run_one will do nothing until new invocation is added. I organized some code form the boost example but It seems that my understanding is wrong.
#include <boost/asio/connect.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/system/system_error.hpp>
#include <boost/asio/write.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
using boost::asio::deadline_timer;
using boost::asio::ip::tcp;
class client
{
public:
client()
: socket_(io_service_)
{
}
void connect_handler(const boost::system::error_code& error,boost::system::error_code *er)
{
std::cerr<<"connect handler"<<std::endl;
*er = error;
std::cerr<<error<<std::endl;
}
void connect(const std::string& host, const std::string& service)
{
tcp::resolver::query query(host, service);
tcp::resolver::iterator iter = tcp::resolver(io_service_).resolve(query);
std::cerr<<"connect start"<<std::endl;
boost::system::error_code ec = boost::asio::error::would_block;
boost::asio::async_connect(socket_, iter, bind(&client::connect_handler,this,_1,&ec));
do
{io_service_.run_one();
}while (ec == boost::asio::error::would_block);
//io_service_.reset(); // The write async will be stuck without this reset call.
std::cerr<<"connect done"<<std::endl;
if (ec || !socket_.is_open())
throw boost::system::system_error(
ec ? ec : boost::asio::error::operation_aborted);
}
void write_handler(const boost::system::error_code& error, std::size_t size,boost::system::error_code* er )
{
std::cerr<<"write handler "<<std::endl;
*er=error;
std::cerr<<error<<std::endl;
}
void write_line(const std::string& line)
{
std::cerr<<"write start"<<std::endl;
std::string data = line + "\n";
boost::system::error_code ec = boost::asio::error::would_block;
boost::asio::async_write(socket_, boost::asio::buffer(data), bind(&client::write_handler,this,_1,_2,&ec));
do
{
io_service_.run_one();
}while (ec == boost::asio::error::would_block);
std::cerr<<"write done";
if (ec)
throw boost::system::system_error(ec);
}
private:
boost::asio::io_service io_service_;
tcp::socket socket_;
};
int main()
{
try
{
client c,d;
c.connect("172.217.6.36", "80");// google IP.
c.write_line("example");
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
My understand is that:
Start
|
async_connect ----> add one item in io_service queue
|
|
io_serivce.run_one() ------> dequeue the async_connect call back from io_serivce queue
|
|
connect_handler --------> connect_handler called change the ec value
|
|
async_write ----------> add one item in io_service queue.
|
|
io_service.run_one()------------>dequeue the async_write call back from io_serivce queue
|
|
write_handler()----------------->write handler called and change the ec value
|
Done
but the reality is
Start
|
async_connect ----> add one item in io_service queue
|
|
io_serivce.run_one() ------> dequeue the async_connect call back from io_serivce queue
|
|
connect_handler --------> connect_handler called change the ec value
|
|
async_write ----------> add one item in io_service queue.
|
|
io_service.run_one()------------>stuck here in the while loop forever, the async_write handler is never be called the ec is never be changed.
Sehe told me that the io_service.reset needed to be called in another post, what I don't understand why io_service.reset needs to be called? the original example doesn't use this call and it works fine. With the reset call works:
Start
|
async_connect ----> add one item in io_service queue
|
|
io_serivce.run_one() ------> dequeue the async_connect call back from io_serivce queue
|
|
connect_handler --------> connect_handler called change the ec value
|
|
io_service.reset() --------> reset the io service.
|
|
async_write ----------> add one item in io_service queue.
|
|
io_service.run_one()------------>dequeue the async_write call back from io_serivce queue
|
|
write_handler()----------------->write handler called and change the ec value
|
Done
The original sample uses the deadline-timer which is in a continuous chain of async_waits. This means that the io_service will never run out of work.
That's it. The whole difference. If you let the service run out of work, run_* will return and you will need to call reset() before you can use the io_service again.
See also Why must io_service::reset() be called?
For context the earlier answer boost socket example stuck in while loop where I give several better approaches to making this work either using synchronous calls or using asynchronous calls.

Boost: Example needed: for timeout

I am already working long on this without success.
Imagine you have your main function some sort like this:
bool running = true;
int i = 0;
//waitHandler();
while(running)
i++;
Now I would like to add and call a timer, which sets running to false,
when it expires.
void waitHandler(){
boost::asio::io_service timerService;
//create and bind the timer
boost::asio::deadline_timer timer(timerService,
boost::posix_time::milliseconds(2000));
timer.wait();
running = true;
cout<<"WaitHandler triggered"<<endl;
}
Of course this does not work (when u uncomment the comment above),
since the timer will block the main thread.
What to do, if I would want to have this functionality without blocking the main function.
EDIT:
//transfer some error message
void set_result(boost::system::error_code* a, boost::system::error_code b,deadline_timer &timer)
{
a->assign(b.value(),b.category());
}
template<class SOCKET>
void read_with_timeout(SOCKET & sock, unsigned int delay,
const asio::mutable_buffers_1& buffers)
{
//create error messages
boost::system::error_code timer_result;
boost::system::error_code read_result;
//initialize timer
deadline_timer timer(sock.get_io_service());
timer.expires_from_now(boost::posix_time::milliseconds(delay));
timer.async_wait(boost::bind(set_result, &timer_result, _1,boost::ref(timer)));
//initialize receive mechanism
sock.async_receive(buffers, boost::bind(set_result, &read_result, _1,boost::ref(timer)));
sock.get_io_service().reset();
//should run for one handler
while (sock.get_io_service().run_one())
{
if (read_result.value()==0){ //zero stands for, that the message was received properly.
timer.cancel();
//cout<<"Message received: => Timer cancelled => RETURN!"<<endl;
return;
}
if(timer.expires_from_now().total_milliseconds() <=0){
sock.cancel();
//cout<<"Timeout => Socket cancelled => RETURN!"<<endl;
return;
}
}
}
As said this almost shows the wished behavior, but there are some questions to it:
Why by even using run_one, both the handler for the timer and the one for the receive can be fired
Why does receive also fire, when 0 bytes are received. For me that sounds like nothing is received and the function is supposed to wait?
Is this the right way to do it - as I said I want to receive or timeout. (like pinging)
Actually the pakets are received in wrong order as they appeared in Wireshark - I guess it has something to do with async_receive, which does not really wait for a incoming message, but just takes what is in the buffer before the function call.
What to do?
You are making this much more complex than it needs to be. There are piles of questions on this site dealing with timeouts, and a fantastic example on the Boost.Asio website. The comment from the async_tcp_client example has an excellent ASCII diagram explaining this scenario
// This class manages socket timeouts by applying the concept of a deadline.
// Some asynchronous operations are given deadlines by which they must complete.
// Deadlines are enforced by an "actor" that persists for the lifetime of the
// client object:
//
// +----------------+
// | |
// | check_deadline |<---+
// | | |
// +----------------+ | async_wait()
// | |
// +---------+
//
// If the deadline actor determines that the deadline has expired, the socket
// is closed and any outstanding operations are consequently cancelled.
//
// Connection establishment involves trying each endpoint in turn until a
// connection is successful, or the available endpoints are exhausted. If the
// deadline actor closes the socket, the connect actor is woken up and moves to
// the next endpoint.
//
// +---------------+
// | |
// | start_connect |<---+
// | | |
// +---------------+ |
// | |
// async_- | +----------------+
// connect() | | |
// +--->| handle_connect |
// | |
// +----------------+
// :
// Once a connection is :
// made, the connect :
// actor forks in two - :
// :
// an actor for reading : and an actor for
// inbound messages: : sending heartbeats:
// :
// +------------+ : +-------------+
// | |<- - - - -+- - - - ->| |
// | start_read | | start_write |<---+
// | |<---+ | | |
// +------------+ | +-------------+ | async_wait()
// | | | |
// async_- | +-------------+ async_- | +--------------+
// read_- | | | write() | | |
// until() +--->| handle_read | +--->| handle_write |
// | | | |
// +-------------+ +--------------+
//
// The input actor reads messages from the socket, where messages are delimited
// by the newline character. The deadline for a complete message is 30 seconds.
//
// The heartbeat actor sends a heartbeat (a message that consists of a single
// newline character) every 10 seconds. In this example, no deadline is applied
// message sending.
//
You should strive to achieve a similar design in your application. There is no need to bumble around by writing a read_with_timeout() function like you have posted in your question. Using async_read(), async_write(), and async_wait() will be enough to give you the desired functionality.
I think part of your confusion arises over threading. Don't think about it, understand the basic concepts first. You will want to use a single thread (the one invoking main()) and a single io_service to start. After that, you can explore more advanced concepts. If you're trying to integrate this code into a larger application, that is a different question entirely.
Studying the proactor design pattern may be helpful to you as well.
You can either execute io_service::run in a separate thread (and somehow synchronize the access to running) or pump the io_service loop manually within your while loop, using run_one()/poll()/poll_one() - whatever is appropriate in your case.
I have found out some sort of solution. I am ok with it even though there are things I do not understand.
//transfer some error message
void set_result(boost::system::error_code* a, boost::system::error_code b,deadline_timer &timer)
{
a->assign(b.value(),b.category());
}
template<class SOCKET>
void read_with_timeout(SOCKET & sock, unsigned int delay,
const asio::mutable_buffers_1& buffers)
{
//create error messages
boost::system::error_code timer_result;
boost::system::error_code read_result;
//initialize timer
deadline_timer timer(sock.get_io_service());
timer.expires_from_now(boost::posix_time::milliseconds(delay));
timer.async_wait(boost::bind(set_result, &timer_result, _1,boost::ref(timer)));
//initialize receive mechanism
sock.async_receive(buffers, boost::bind(set_result, &read_result, _1,boost::ref(timer)));
sock.get_io_service().reset();
//should run for one handler
while (sock.get_io_service().run_one())
{
if (read_result.value()==0){ //zero stands for, that the message was received properly.
timer.cancel();
//cout<<"Message received: => Timer cancelled => RETURN!"<<endl;
return;
}
if(timer.expires_from_now().total_milliseconds() <=0){
sock.cancel();
//cout<<"Timeout => Socket cancelled => RETURN!"<<endl;
return;
}
}
}
This actually works for my case and was taken from http://lists.boost.org/Archives/boost/2007/04/120339.php
referenced by this thread: How to set a timeout on blocking sockets in boost asio?
I just adapted it to Boost 1.51.
A few things are still obscured to me like e.g.
io_service.run_one actually still fires more event handlers even though it is supposed to only fire one.
Also there are events from the timer which do not at all interest me. I just want to catch the timeout and not other stuff. (I don know why there is other stuff)
In any case my problem was solved so far.
You have to spawn the timer on its own thread and then make sure that you protect the running variable from concurrent access.

Resources