Publishing an NServiceBus 4 event from a windows forms application - c#

I'm trying to write a test harness to send NServiceBus commands and events. I've managed to get it to send commands, and it happily calls publish, but it doesn't handle subscription requests when the app starts up so the publish call doesn't actually send any messages.
How do I tell NServiceBus to process the subscription requests when I initialise the Bus?
Here's the initialisation code so far:
Bus = Configure.With(LoadAssemblies())
.DefaultBuilder()
.UnicastBus()
.ImpersonateSender(true)
.DefiningCommandsAs(AllValidCommands)
.DefiningMessagesAs(AllValidMessages)
.DefiningEventsAs(AllValidEvents)
.RavenSubscriptionStorage()
.CreateBus();

In case of Pub/sub mode, you need to make sure, you run Publisher first & then subscribe .... check these link http://dennis.bloggingabout.net/2015/10/28/nservicebus-publish-subscribe-tutorial/

Related

Mass Transit connection management on class library

I am trying to use mass transit for request response handling. Most examples for mass transit are for console application or web application and I don't know how to start or stop bus on producer when I use it in class library.
Because in examples for web application bus started on application start but for class library there are no such a thing like startup.cs.
My question is where to start bus or stop when I use class library for connecting to bus?
My producer code looks like
IBusControl busControl = CreateBus();
TaskUtil.Await(() => busControl.StartAsync());
IRequestClient<IAccountingRequest, IAccountingResponse> client = CreateRequestClient(busControl);
IAccountingResponse response = null;
AccountingRequest accountingRequest = MapToAccountingRequest(accountingIntegration);
Task.Run(async () =>
{
response = await client.Request(accountingRequest);
}).Wait();
busControl.Stop();
But I think starting and stopping bus for every request is not good.
You should provide methods in your class library to Start/Stop the bus. You can abstract them however you want, but allow the developer the ability to startup and shutdown the bus. Many other libraries to this, typically via a method to Stop, Shutdown, Close, etc.
The fact that you're also hiding the Task in the above example and blocking/waiting makes me thing you're stuck within something super legacy that you can't get avoid. In this case, well, I had to say this, but manage the reference to the bus in some static singleton (yuck), and Start it the first time it's used (double yuck), then, try to find a hook on application exit to stop it clean (good luck).
The best solution is to give the developers a call into your library to shut it down so they can free the connection and resources.

Trigger WebJob at a particular time after record added to a database

I want to trigger an Azure Webjob 24Hours after I have added a record to a database using .NET . Obviously there will be multiple tasks for the Webjob to handle, all at their designated time. Is there a way ( in the Azure Library for .NET) in which i can schedule this tasks ?
I am free to use Message Queues , but I want to try and avoid the unnecessary polling of the WebJob for new messages.
If you want to trigger the execution of a WebJob 24 hours after a record insertion in a SQL database I would definitely use Azure Queues for this. So after you insert the record, just add a message to the queue.
In order to do this you can easily leverage the initialVisibilityDelay property that can be passed to the CloudQueue.AddMessage() method. This will make the message invisible for 24 hours in your case, and then it will appear to be processed by your Webjob. You don't have to schedule anything, just have a Continuous WebJob listening to a queue running.
Here's some sample code:
public void AddMessage(T message, TimeSpan visibilityDelay)
{
var serializedMessage = JsonConvert.SerializeObject(message);
var queue = GetQueueReference(message);
queue.AddMessage(new CloudQueueMessage(serializedMessage), null, visibilityDelay);
}
private static CloudQueue GetQueueReference(T message)
{
var storageAccount = CloudStorageAccount.Parse("Insert connection string");
var queueClient = storageAccount.CreateCloudQueueClient();
var queueReference = queueClient.GetQueueReference("Insert Queue Name");
queueReference.CreateIfNotExists();
return queueReference;
}
Hope this helps
Since the event of adding a record to the database is the trigger here, You can use Azure Management Libraries to create a Azure Scheduler Job to execute after 24hrs from the time the db record is inserted. Azure Scheduler Jobs can do only 3 things : make HTTP/HTTPS requests or Put Message in Queue. Since you do not want to poll queues, here are two options
Deploy the existing Web Job as Wep API where each task is reachable by unique URLs, so that the scheduler task can execute the right HTTP/HTTPS request
Create a new WebAPI/Wep API which takes accepts request (like a man in the middle) and pro-grammatically run the existing web job on demand, again using Azure management libraries.
Please let me know if any of these strategies help.
To invoke a WebJob from your Website,is not good idea rather than you can add the WebJob code inside your Website and simply call that code. you can still easily use the WebJob SDK from inside your Website.
https://github.com/Azure/azure-webjobs-sdk-samples
we wouldn't recommend to invoke the WebJob from your Website is that the invocation contains a secret you rather not store on your Website (deployment credentials).
Recommendation:
To separate WebJob and Website code, the best thing to do is to communicate using a queue, the WebJob listens on the queue and the Website pushes the request to the queue.

Push Notifications with PushSharp - the basics

I need to push notifications to tens of thousands of iOS devices that my app installed. I'm trying to do it with PushSharp, but I'm missing some fundamental concepts here. At first I tried to actually run this in a Windows service, but couldn't get it work - getting null reference errors coming from _push.QueueNotification() call. Then I did exactly what the documented sample code did and it worked:
PushService _push = new PushService();
_push.Events.OnNotificationSendFailure += new ChannelEvents.NotificationSendFailureDelegate(Events_OnNotificationSendFailure);
_push.Events.OnNotificationSent += new ChannelEvents.NotificationSentDelegate(Events_OnNotificationSent);
var cert = File.ReadAllBytes(HttpContext.Current.Server.MapPath("..pathtokeyfile.p12"));
_push.StartApplePushService(new ApplePushChannelSettings(false, cert, "certpwd"));
AppleNotification notification = NotificationFactory.Apple()
.ForDeviceToken(deviceToken)
.WithAlert(message)
.WithSound("default")
.WithBadge(badge);
_push.QueueNotification(notification);
_push.StopAllServices(true);
Issue #1:
This works perfectly and I see the notification pop up on the iPhone. However, since it's called a Push Service, I assumed it would behave like a service - meaning, I instantiate it and call _push.StartApplePushService() within a Windows service perhaps. And I thought to actually queue up my notifications, I could do this on the front-end (admin app, let's say):
PushService push = new PushService();
AppleNotification notification = NotificationFactory.Apple()
.ForDeviceToken(deviceToken)
.WithAlert(message)
.WithSound("default")
.WithBadge(badge);
push.QueueNotification(notification);
Obviously (and like I already said), it didn't work - the last line kept throwing a null reference exception.
I'm having trouble finding any other kind of documentation that would show how to set this up in a service/client manner (and not just call everything at once). Is it possible or am I missing the point of how PushSharp should be utilized?
Issue #2:
Also, I can't seem to find a way to target many device tokens at once, without looping through them and queuing up notifications one at a time. Is that the only way or am I missing something here as well?
Thanks in advance.
#baramuse explained it all, if you wish to see a service "processor" you can browse through my solution on https://github.com/vmandic/DevUG-PushSharp where I've implemented the workflow you seek for, i.e. a win service, win processor or even a web api ad hoc processor using the same core processor.
From what I've read and how I'm using it, the 'Service' keyword may have mislead you...
It is a service in a way that you configure it once and start it.
From this point, it will wait for you to push new notifications inside its queue system and it will raise events as soon as something happens (delivery report, delivery error...). It is asynchronous and you can push (=queue) 10000 notifications and wait for the results to come back later using the event handlers.
But still it's a regular object instance you will have to create and access as a regular one. It doesn't expose any "outside listener" (http/tcp/ipc connection for example), you will have to build that.
In my project I created a small selfhosted webservice (relying on ServiceStack) that takes care about the configuration and instance lifetime while only exposing the SendNotification function.
And about the Issue #2, there indeed isn't any "batch queue" but as the queue function returns straight away (enqueue and push later) it's just a matter of a looping into your device tokens list...
public void QueueNotification(Notification notification)
{
if (this.cancelTokenSource.IsCancellationRequested)
{
Events.RaiseChannelException(new ObjectDisposedException("Service", "Service has already been signaled to stop"), this.Platform, notification);
return;
}
notification.EnqueuedTimestamp = DateTime.UtcNow;
queuedNotifications.Enqueue(notification);
}

How to create a publisher within a console application

I'm just starting out with NServiceBus and have updated the PubSub sample to work with .NET 4.0 Framework. That's working perfectly ok. This runs one publisher and two subscribers within the "NServiceBus.Host.exe" environment - so it is that which takes responsibility for setting up an instance of the Bus and doing any relevant subscriptions. That's all working fine (as you'd expect) but I'm now trying to move the publisher out of being run within "NServiceBus.Host.exe" into it's own console application (eventually I would like to publish messages from a website so this seems a good small step in that direction).
If I start the 3 projects (my console app, Sub1 and Sub2) it creates 5 msmq on my local machine, but instead of the endpoint.config...subscriptions Q, it creates a generic "nservicebus_subscriptions" Q. If I enable journals, I see that the MyPublisherInputQueue has three (processed) completion messages with an errorcode 0, whilst the subscriber1inputqueue and subscriber2inputqueue each have one. This all seems good, but if I then publish messages, the publisher doesn't appear to throw any errors, but no messages make it as far as the subscribers (they just sit waiting for a message). Also no messages appear in either the new message or journal for any of the MQs.
I'm obviously missing some step(s) - Is the console application not opening itself up for subscriptions? If so, what steps are needed to do that? What steps am I missing that run when you host the publisher in the nservicebus.host.exe?
To create the console application I've done the following:
Within the pubsub solution, created a console application.
Added references in the console application to mymessages, nservicebus.dll and nservicebus.core.dll
From the existing pub code and example on the NServiceBus website, added following code to "Main()"
Code:
IBus Bus = Configure.With()
.Log4Net()
.DefaultBuilder()
.MsmqSubscriptionStorage()
.XmlSerializer()
.MsmqTransport()
.UnicastBus()
.LoadMessageHandlers()
.CreateBus()
.Start();
bool publishIEvent = true;
do
{
Console.ReadLine();
var eventMessage = publishIEvent ? Bus.CreateInstance<IEvent>() : new EventMessage();
eventMessage.EventId = Guid.NewGuid();
eventMessage.Time = DateTime.Now.Second > 30 ? (DateTime?)DateTime.Now : null;
eventMessage.Duration = TimeSpan.FromSeconds(99999D);
Bus.Send(eventMessage);
Console.WriteLine("Published event with Id {0}.", eventMessage.EventId);
} while (true);
Created an app.config for the new console application using the contents of the existing "publisher" app.config.
Added "NServiceBus.Integration" to command line arguments for console application project.
If you look at your logs, it is likely that NServiceBus is telling you that you need to have your publisher be configured to be transactional. The way to do that is to include .IsTransactional(true) after .MsmqTransport().

How do I wait until a console application is idle?

I have a console application that starts up, hosts a bunch of services (long-running startup), and then waits for clients to call into it. I have integration tests that start this console application and make "client" calls. How do I wait for the console application to complete its startup before making the client calls?
I want to avoid doing Thread.Sleep(int) because that's dependent on the startup time (which may change) and I waste time if the startup is faster.
Process.WaitForInputIdle works only on applications with a UI (and I confirmed that it does throw an exception in this case).
I'm open to awkward solutions like, have the console application write a temp file when it's ready.
One option would be to create a named EventWaitHandle. This creates a synchronization object that you can use across processes. Then you have your 'client' applications wait until the event is signalled before proceeding. Once the main console application has completed the startup it can signal the event.
http://msdn.microsoft.com/en-us/library/41acw8ct(VS.80).aspx
As an example, your "Server" console application might have the following. This is not compiled so it is just a starting point :)
using System.Threading;
static EventWaitHandle _startedEvent;
static void main()
{
_startedEvent = new EventWaitHandle(false, EventResetMode.ManualReset, #"Global\ConServerStarted");
DoLongRunnningInitialization();
// Signal the event so that all the waiting clients can proceed
_startedEvent.Set();
}
The clients would then be doing something like this
using System.Threading;
static void main()
{
EventWaitHandle startedEvent = new EventWaitHandle(false, EventResetMode.ManualReset, #"Global\ConServerStarted");
// Wait for the event to be signaled, if it is already signalled then this will fall throught immediately.
startedEvent.WaitOne();
// ... continue communicating with the server console app now ...
}
What about setting a mutex, and removing it once start up is done. Have the client app wait until it can grab the mutex before it starts doing things.
Include an is ready check in the app's client interface, or have it return a not ready error if called before it's ready.
Create a WCF service that you can use for querying the status of the server process. Only start this service if a particular command is passed on the command line. The following traits will ensure a very fast startup of this service:
Host this service as the first operation of the client application
Use the net.tcp or net.pipe binding because they start very quickly
Keep this service as simple as possible to ensure that as long as the console application doesn't terminate, it will remain available
The test runner can attempt to connect to this service. Retry the attempt if it fails until the console application terminates or a reasonably short timeout period expires. As long as the console application doesn't terminate unexpectedly you can rely on this service to provide any additional information before starting your tests in a reasonably short period of time.
Since the two(the console application, and integration test app that makes client calls - as I understand) are separate application, so there should be a mechanism - a bridge - that would tell play as a mediator(socket, external file, registry, etc).
Another possibility could be that you come up with an average time the console takes to load the services and use that time in your test app; well, just thinking out loud!

Categories