ramblingcookiemonster / psrabbitmq Goto Github PK
View Code? Open in Web Editor NEWPowerShell module to send and receive messages from a RabbitMq server
Home Page: http://ramblingcookiemonster.github.io/RabbitMQ-Intro/
License: MIT License
PowerShell module to send and receive messages from a RabbitMq server
Home Page: http://ramblingcookiemonster.github.io/RabbitMQ-Intro/
License: MIT License
I have an exchange that is only accessible via a custom vhost. When I try to use the Send-RabbitMqMessage module to publish a message I get an error that the specified endpoint was not available.
The RabbitMQ logs shows the following error:
{amqp_error,access_refused, "access to vhost '/' refused for user 'mytest'", 'connection.open'}}
Is there any way to tell the Send-RabbitMQMessage module to connect to an alternate vhost?
Passing -Exchange an empty string should resort to the "default" exchange in RabbitMQ.
Taken from: https://www.rabbitmq.com/tutorials/tutorial-three-java.html
Nameless exchange
In previous parts of the tutorial we knew nothing about exchanges, but still were able to send messages to queues. That was possible because we were using a default exchange, which we identify by the empty string ("").
Recall how we published a message before:
channel.basicPublish("", "hello", null, message.getBytes());
The first parameter is the the name of the exchange. The empty string denotes the default or nameless exchange: messages are routed to the queue with the name specified by routingKey, if it exists.
I'm implementing RPC via direct reply-to messages. The PHP part that sends a request works, I get the request in PowerShell, but I find nothing on how to send back an acknowledgement.
working variant 1:
while ($true) {
Try {
$data = Wait-RabbitMqMessage -Exchange $ExchangeName -Key $QueueName -QueueName $QueueName -Timeout 120 @Params -ErrorAction SilentlyContinue
$data = $data |ConvertFrom-Json
$data
} Catch {
# do nothing
$_.Exception
}
}
working variant 2:
Start-RabbitMqListener -ComputerName 'localhost' -Exchange $ExchangeName -QueueName $QueueName -Key $QueueName -Credential $credentials |% { $_ }
Both variants print out the message. But all I get is a string ... how do I send a response?
When Connecting a channel using Connect-RabbitMQChannel, the Key parameter is a unique [string] value, and the queue binding is done only once:
Connect-RabbitMqChannel.ps1 line 113
$Channel.QueueBind($QueueName, $Exchange, $Key)
When using Topic exchange, a great feature is to have a queue with multiple bindings based on different key, to have multiple routing: http://www.rabbitmq.com/tutorials/tutorial-five-dotnet.html
Although the extra bindings could be done later, I believe it would be nice to accept an array of keys, and bind for each routing key.
[edit]Was being dumb. Changing to [string[]] should be enough, will test tomorrow and create a new PR [/edit]
If I have a queue with 3 items in it, should this drain the queue and display each item?
$maxLoops = 5
For ($i=0; $i -le $maxLoops; $i++)
{
$Incoming = Wait-RabbitMqMessage -Exchange $Exchange -Key $QueueName -QueueName $QueueName -Timeout 20 -vhost base @Params
Write-Host $Incoming
}
It pauses 20 seconds, then the Write-Host statement displays only the first item in the queue
From the RabbitMQ web interface, I see the queue empty after running this.
Thanks,
Neal
I find out that there was a breaking change in a recent commit here:
PSRabbitMq/PSRabbitMq/Register-RabbitMqEvent.ps1
Lines 140 to 152 in cbc0196
When Credential is not used as parameter, $ArgList
is not set.
When using the pipeline the body is not re-calculated for each inputObject, $Body is tested to be re-created and has a value. I changed to:
process
{
**$Body = $null**
switch ($SerializeAs) {
Hi,
I haven't tested this yet, but it looks like the While loop is only decreasing a counter [int], without pausing in that loop.
Also the $Timeout
variable has a default value of 1, so $SecondsRemaining = [Double]::PositiveInfinity
is never reached/used.
I would prefer a loop with a timespan like this: https://mjolinor.wordpress.com/2012/01/14/making-a-timed-loop-in-powershell/
But ensuring backward compatibility with an [int] as param requires a bit extra work and I don't have time atm.
So just filing for later.
It is not possible to specify other ports other than the default ones when using the following functions Register-RabbitMqEvent
and Send-RabbitMqMessage
.
Proposed changes on the following pull request:
Pull request
#33
Thank you
I have been using this module with great success on PS 5.1 so thank you for your hard work. I did however run into issues when trying to use on Linux in PS 7.0. I can go into detail on why but to suit my purposes (and as a learning experience) I have created a new module to complement PSRabbitMQ, focusing on Consuming.
It is yet very simple and a work in progress but I thought it might be worth sharing via the PSGallery. So far I have named it PSRabbitMq.Consumer
as it is intended to be used with your module.
Would you be happy for me to publish such a module? As far as i know you haven't copyrighted the name but I felt that I would like to have your approval out of courtesy.
You can find my module here. All feedback and questions welcome.
There are about 3 functions that dont support specifying the -vhost flag. Adding them...
One thing I've been working on lately is DRY'ing out my PowerShell code, especially when it comes to defining parameters. Coming from Ruby, I can't stand how a PowerShell function isn't able to inherit parameter declarations from another base function. This feeling was unpleasant so I attempted to work around it. I noticed the code here has quite a few repeat parameters. This will allow you to define some common parameters and load them into a function:
https://gist.github.com/derekmwright/91504970eb876ca4ff9c6c5714ada2ef
It's still a little bit of a work in progress, but I figure more eyes is a good thing and maybe it can benefit. Esp w/ the chatter of a possible version bump.
Without the details of the security and servername, I'm sending a message like this:
$Exchange = "D.Data.Integrations.Topic"
$RoutingKey = "D.Data.Echo.BSSR.Legacy204Outbound"
$message = get-content "d:\Tests\EDI204_from_WCFSQLPollingEDIStaging_CTII_Original.xml"
Write-Host "Message = $message"
Send-RabbitMQMessage -Exchange $Exchange -Key $RoutingKey -InputObject $message -vhost base -Persistent @Params
Write-Host "Sent Message to $RoutingKey "
When I read it using PSRabbitMQ it looks okay. But when doing a Get Message from RabbitMQ web interface (or BizTalk Server) the message has been wrapped with a lot of XML.
Example XML:
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<Obj RefId="0">
<TN RefId="0">
<T>System.Object[]</T>
<T>System.Array</T>
<T>System.Object</T>
</TN>
<LST>
<Obj RefId="1">
<S><EGL_204Out_Sql xmlns="http://EGL.BizTalk.Common.Schemas.EGL_204Out_SQL"> </S>
<MS>
<S N="PSPath">D:\GitLTLShipmentOut_Dev\Echo.BSSR.Gateway.LTLShipmentOut\Echo.BSSR.Gateway.LTLShipmentOut.Transforms\Tests\EDI204_from_WCFSQLPollingEDIStaging_CTII_Original.xml</S>
<S N="PSParentPath">D:\GitLTLShipmentOut_Dev\Echo.BSSR.Gateway.LTLShipmentOut\Echo.BSSR.Gateway.LTLShipmentOut.Transforms\Tests</S>
<S N="PSChildName">EDI204_from_WCFSQLPollingEDIStaging_CTII_Original.xml</S>
<Obj N="PSDrive" RefId="2">
<TN RefId="1">
<T>System.Management.Automation.PSDriveInfo</T>
<T>System.Object</T>
</TN>
<ToString>D</ToString>
<Props>
<S N="CurrentLocation"></S>
<S N="Name">D</S>
<Obj N="Provider" RefId="3">
<TN RefId="2">
<T>System.Management.Automation.ProviderInfo</T>
<T>System.Object</T>
</TN>
<ToString>Microsoft.PowerShell.Core\FileSystem</ToString>
<Props>
I find my data in there, for example I have a city name of Ontario.
In my XML:
<N401>ONTARIO</N401>
In the above XML:
<Obj RefId="102">
<S>_x0009__x0009__x0009__x0009__x0009_<N401>ONTARIO RDC</N401></S>
<MS>
<S N="PSPath">D:\GitLTLShipmentOut_Dev\Echo.BSSR.Gateway.LTLShipmentOut\Echo.BSSR.Gateway.LTLShipmentOut.Transforms\Tests\EDI204_from_WCFSQLPollingEDIStaging_CTII_Original.xml</S>
<S N="PSParentPath">D:\GitLTLShipmentOut_Dev\Echo.BSSR.Gateway.LTLShipmentOut\Echo.BSSR.Gateway.LTLShipmentOut.Transforms\Tests</S>
<S N="PSChildName">EDI204_from_WCFSQLPollingEDIStaging_CTII_Original.xml</S>
<Ref N="PSDrive" RefId="2" />
<Ref N="PSProvider" RefId="3" />
<I64 N="ReadCount">98</I64>
</MS>
</Obj>
How do I get the message to be stored in my simple original XML without all that Powershell XML wrapper "stuff" around it?
Thanks,
Neal Walters
Hello,
I'm using the module and when I run Wait-RabbitMqMessage it removes all messages but only returns 1 output. Trying to understand if this is the expected behavior as I expected it to be more like the Get-RabbitMQMessage where it would return 1 object per run as Wait-RabbitMqMessage doesn't have the count parameter.
Get-NetIPAddress | Select-Object -ExpandProperty IPAddress | Send-RabbitMQMessage -Exchange TestFanExc -Key 'TestQueue'-Persistent @Params -SerializeAs "text/plain"
$Incoming = Wait-RabbitMQMessage -Exchange TestFanExc -Key 'TestQueue' -QueueName TestQueue2 -Timeout 120 @Params
$Incoming
# ::1
Thank you,
Kensel
Attempting to leverage the library and connect to a internal testing instance of RabbitMQ and noticed via TCPDump that the client was not making the connection. It appears in the connection factory the port is being overridden to use the SSL port, even if SSL is not being specified:
$TcpPortProp = [RabbitMQ.Client.ConnectionFactory].GetField("Port")
$TcpPortProp.SetValue($Factory, 5671)
Perhaps it should be something like:
$TcpPortProp = [RabbitMQ.Client.ConnectionFactory].GetField("Port")
if( $Ssl ) {
$TcpPortProp.SetValue($Factory, 5671)
} else {
$TcpPortProp.SetValue($Factory, 5672)
}
I'll try to get something working and submit a PR but I'm not familiar with the .Net client DLL thats being leveraged here. I'm also unsure how to handle this bigger picture, ie: -Port flag for user overriding?
Hi,
I'm looking at addin an Active Declaration of basic exchanges (that is, non-autodelete, non-durable, and without any other fancy option) and would like your input.
The goal is to not need to create specific exchanges when consuming messages from a queue, so that we don't need to orchestrate the creation of the exchanges prior connecting a channel (No need to use RabbitMQTools before waiting for message for instance).
Looking at the simplest signature:
channel.ExchangeDeclare(exchangeName, ExchangeType.Direct);
I suggest that we:
Connect-RabbitMqChannel.ps1
#in param()
[parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
[ValidateSet('Direct','Fanout','Topic','Headers')]
[string]$ExchangeType = $null,
# [...]
#Actively declare the Exchange (as non-autodelete, non-durable)
if($ExchangeType -and [string]::Empty -ne $Exchange) {
$ExchangeResult = $Channel.ExchangeDeclare($Exchange,$ExchangeType)
}
Here's the link to my branch for a potential PR.
Is possible pass a parameter to Start-RabbitMqListener with the port to use?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.