Messages Patterns - RabbitMQ/NestJS - rabbitmq

I'm trying to integrate to a project done using NestJS, a simple api where you can publish messages with a name (or pattern) and send it to that system that has implemented a handler that matches the name.
The system I'm building is really small, it wouldn't make much of a sense using NestJS for that.
The problem I'm having is the following:
I'm creating a simple api that triggers the publish of the message onto a queue.
The consumer is on a system using NestJS.
I can't figure out how to give that messages a pattern that is recognized by that system.
For example:
Let's say I want to publish a message that has a name of "CreateRecord" with a payload to be processed from the other system that has a handler with the same name with an implementation.
Using amqplib how do I give messages a name or pattern?

You can provide a pattern in the content object when you are publishing a message.
publish(
'my_exchange',
'routing_key',
{ pattern: 'CreateRecord', data: 'Record' },
);

Related

How to access SAP OData messages in Kapsel offline app?

We are developing an SAP Fiori App to be used on the Launchpad and as an offline-enabled hybrid app as well using the SAP SDK and its Kapsel Plug Ins. One issue we are facing at the moment is the ODATA message handling.
On the Gateway, we are using the Message Manager to add additional information to the response
" ABAP snippet, random Gateway entity method
[...]
DATA(lo_message_container) = me->mo_context->get_message_container( ).
lo_message_container->add_message(
iv_msg_type = /iwbep/cl_cos_logger=>warning
iv_msg_number = '123'
iv_msg_id = 'ZFOO'
).
" optional, only used for 'true' errors
RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception
EXPORTING
message_container = lo_message_container.
In the Fiori app, we can directly access those data from the message manager. The data can be applied to a MessageView control.
// Fiori part (Desktop, online)
var aMessageData = sap.ui.getCore().getMessageManager().getMessageModel().getData();
However, our offline app always has an empty message model. After a sync or flush, the message model is always empty - even after triggering message generating methods in the backend.
The only way to get some kind of messages is to raise a /iwbep/cx_mgw_busi_exception and pass the message container. The messages can be found, in an unparsed state, in the /ErrorArchive entity and be read for further use.
// Hybrid App part, offline, after sync and flush
this.getModel().read("/ErrorArchive", { success: .... })
This approach limits us to negative, "exception worthy", messages only. We also have to code some parts of our app twice (Desktop vs. Offlne App).
So: Is there a "proper" to access those messages after an offline sync and flush?
For analyzing the issue, you might use the tool ILOData as seen in this blog:
Step by Step with the SAP Cloud Platform SDK for Android — Part 6c — Using ILOData
Note, ILOData is part of the Kapsel SDK, so while the blog above was part of a series on the SAP Cloud Platform SDK for Android, it also applies to Kapsel apps.
ILOData is a command line based tool that lets you execute OData requests and queries against an offline store.
It functions as an offline OData client, without the need for an application.
Therefore, it’s a good tool to use to test data from the backend system, as well as verify app behavior.
If a client has a problem with some entries on their device, the offline store from the device can be retrieved using the sendStore method and then ILOData can be used to query the database.
This blog about Kapsel Offline OData plugin might also be helpful.

How can I make publish and subscribe in one file?

I want to make easy application with sending messages (rabbitmq). When run program I want to write messages and receive it (in same console). So how can I write a method "subcribe" which will be running all the time(after starting program) and waiting to receive message? and at same time of course i should be able to write a message
Create a supervised app (mix new my_app --sup ).
You implement two GenServer, one for receiving (MyApp.Reader) and the other one for sending (MyApp.Writer). You add both GenServer as worker in your supervisor spec.
I guess your RabbitMQ adapter (never used it with elixir so you'll have to double check) will also be supervised. Name it, and pass its name to both GenServer init method (via the args you pass when declaring your workers for example)
You can also implement your API for the writer directly in MyApp. Something like:
def send(message) do
GenServer.cast(:name_of_writer, $message)
end
You'll then be able to do: MyApp.send("some message")
Your receiver worker, would on its side, receive all messages, and print them to the CLi, either using inspect or the Logger module
Have a look at the GenServer docs, there is some code example that will help you.

Use variable in a Parse Push message

I really like the Parse push service and integrated it with our CMS. I would like to make the notifications personal by adding the users name in the push message. How can i use a variable (Named 'voornaam' in the screenshot) which is stored in the Installation class in a push message?
If you are looking for something like a message template like
Hello ${username}, what's up
sadly its not there. One way you can make the kind of message you want to is by doing it in your server side code before you send the request for PUSH using the REST or other APIs

Is it possible to write a plugin for Glimpse's existing SQL tab?

Is it possible to write a plugin for Glimpse's existing SQL tab?
I'm trying to log my SQL queries and the currently available extensions don't support our in-house SQL libary. I have written a custom plugin which logs what I want, but it has limited functionality and it doesn't integrate with the existing SQL tab.
Currently, I'm logging to my custom plugin using a single helper method inside my DAL's base class. This function looks takes the SqlCommand and Duration in order to show data on my custom tab:
// simplified example:
Stopwatch sw = Stopwatch.StartNew();
sqlCommand.Connection = sqlConnection;
sqlConnection.Open();
object result = sqlCommand.ExecuteScalar();
sqlConnection.Close();
sw.Stop();
long duration = sw.ElapsedMilliseconds;
LogSqlActivity(sqlCommand, null, duration);
This works well on my 'custom' tab but unfortunately means I don't get metrics shown on Glimpse's HUD:
Is there a way I can provide Glimpse directly with the info it needs (in terms of method names, and parameters) so it displays natively on the SQL tab?
The following advise is based on the fact that you can't use DbProviderFactory and you can't use a proxied SqlCommand, etc.
The data that appears in the "out-of-the-box" SQL tab is based on messages of given types been published through our internal Message Broker (see below on information on this). Because of the above limitations in your case, to get things lighting up correctly (i.e. your data showing up in HUD and the SQL tab), you will need to simulate the work that we do under the covers when we publish these messages. This shouldn't be that difficult and once done, should just work moving forward.
If you have a look at the various proxies we have here you will be above to see what messages we publish in what circumstances. Here are some highlights:
DbCommand
Log command start - here
Log command error - here
Log command end - here
DbConnection:
Log connection open - here
Log connection closed - here
DbTransaction
Log Started - here
Log committed - here
Log rollback - here
Other
Command row count here - Glimpses calculates this at the DbDataReader level but you could do it elsewhere as well
Now that you have an idea of what messages we are expecting and how we generate them, as long as you pass in the right data when you publish those messages, everything should just light up - if you are interested here is the code that looks for the messages that you will be publishing.
Message Broker: If you at the GlimpseConfiguration here you will see how to access the Broker. This can be done statically if needed (as we do here). From here you can publish the messages you need.
Helpers: For generating some of the above messages, you can use the helpers inside the Support class here. I would have shifted all the code for publishing the actual messages to this class, but I didn't think there would be too many people doing what you are doing.
Update 1
Starting point: With the above approach you shouldn't need to write your own plugin. You should just be able to access the broker GlimpseConfiguration.GetConfiguredMessageBroker() (make sure you check if its null, which it is if Glimpse is turned off, etc) and publish your messages.
I would imagine that you would put the inspection that leverages the broker and published the messages, where ever you have knowledge of the information that needs to be collected (i.e. inside your custom lib). Normally this would require references inside your lib to glimpse (which you may not want), so to protect against this, from your lib, you would call a proxy (which could be another VS proj) that has the glimpse dependency. Hence your ado lib only has references to your own code.
To get your toes wet, try just publishing a couple of fake connection and command messages. Assuming the broker you get from GlimpseConfiguration.GetConfiguredMessageBroker() isn't null, these should just show up. Then you can work towards getting real data into it from your lib.
Update 2
Obsolete Broker Access
Its marked as obsolete because its going to change in v2. You will still be able to do what you need to do, but the way of accessing the broker has changed. For what you currently need to do this is ok.
Sometimes null
As you have found this is really dependent on where in the page lifecycle you are currently at. To get around this, I would probably change my original recommendation a little.
In the code where you are currently creating messages and pushing them to the message bus, try putting them into HttpContext.Current.Items. If you haven't used it before, this is a store which asp.net provides out of the box which lasts the lifetime of a given request. You could have a list that you put in there, still create the message objects that you are doing, but put them into that list instead of pushing them through the broker.
Then, create a HttpModule (its really simple to do) which taps into the PostLogRequest event. Within this handler, you would pull the list out of the context, iterate through it and push the message into the message broker (accessing the same way you have been).

Apache Camel : "direct:start" endpoint - what does it mean?

I'm new to Apache Camel. Can someone explain what "direct:start" means in Camel.
Please see
https://camel.apache.org/components/latest/http-component.html
from("direct:start")
.to("http://myhost/mypath");
Thanks.
The "direct:start" above is simply saying that the route starts with a Direct Component named "start".
The direct endpoint provides synchronous invocation of a route. If you want to send an Exchange to the direct:start endpoint you would create a ProducerTemplate and use the various send methods.
ProducerTemplate template = context.createProducerTemplate();
template.sendBody("direct:start", "This is a test message");
There is nothing special about the name start. It is simply the name you are going to use when referring to the endpoint and could have just as easily been direct:foo.
Assume like the direct route as a method with name start , so we need to call the start method /direct route to perform certain operation. The below example will help .
The first route will be triggered when an input file is available in XXXX location and when it reaches line , the actual flow will go to second route. Basically the direct route with from endpoint will be triggered by some producer endpoint.
<route id="fileRoute">
<from uri="file:XXXX">
..
<to uri="direct:start">
</route>
<route id="directStartRoute">
<from uri="direct:start">
<to uri="http://myhost/mypath">
</route>
Apache Camel direct is basically for sending Exchange from one route to another in SAME Camel context. So let’s say you are getting message from AMQ and you want to populate headers for every message you get and then send it to mail recipient list. So here you need to create new router which has following description
from(“direct:populateHeaders”)
.setHeader(“myHeader”, “myHeaderValue”)
.end()
And from any route you can send your Exchange object to this route by writing
...
.to(“direct:populateHeaders”)
...
Its important to keep in mind that this will not work out of your Camel Context.
direct:start provides synchronous ways to communicate between 2 endpoints and this is only been used if you want to communicate using camel messages and not generic file or xml messages.
Consider it like this :
There are two things whenever you are sending a message to camel route.
1. The URI scheme, which defines how your message is going to be delivered. And to which component type it is going to be delivered.
2. URI path, which defines the instance of that component.
Now, to your direct:start location.
'direct' tells that this message should send synchronously to the Direct Component.
'start' tells which instance of the Direct Component this message should be delivered.
Importance of different URI path:
Now consider if you are having to different routes. And wants to produce message from two different threads synchronously. Using 'direct:start' as start point for the routes will not work. Unless you are having some conditional processing component, forget this if you are beginner.
For, successfully deliver the messages to both the routes , you will have to add 2 entries i.e. 'direct:somename1' and 'direct:somename2'. 'start' is not a mandatory thing , you can give whatever name you like to.
I recommend you to read some chapters from Martin Fowler's EIP books. It is a wonderful resource to begin with. This will make you very easy to understand Camel.
It should be fairly easy to explain: exchange is always sent from a source to a destination. For that to happen, you need to create those 02 endpoints: one will consume (yes the start) and the other one will emit.
from("direct:start") means "directly consume the exchange from the "start" endpoint and process it anyhow.
to("direct:start") means "send" the exchange to the "start" endpoint "directly" within the same camel context.
What makes this really ambiguous is that the endpoint itself (i.e: "direct:start") is implicitly created on the fly so when writing your code, you are assuming that there is an endpoint called "direct:start" so you can retrieve exchange from it but you can also send an exchange to it.
Good luck!
forget about start. start is just a name of a halt point (direct).
Direct component can be take as a bridge between routes in same context.