I haven’t had much time to work on it lately, and I’ve been a bit under the weather the last few days. I’ve hardly done anything.
There have been a few minor setbacks, mostly of my own doing. One was not, though.
To make a long story short, something changed in Visual Studio 2013 Update 4 that results in files being locked even though they are no longer in use and their app domain has been unloaded. When the app server synchronizes, it downloads new applications and deletes the ones it no longer needs. The delete is failing because visual studio is locking those files. It works fine without the debugger, but it’s a pain when working on install/synchronization issues. It took a while for me to determine the problem was the debugger. I installed Visual Studio 2015 Ultimate Preview, and it has the same issue.
In other news, I’ve been working on the installer quite a bit, just trying to make it better and cleaner. most of the code in this thing is what I call a “shallow pass”, which is just enough to get it working without being complete junk. The installer is now pretty clean. I want to refactor it one more time because there’s too much in the single class… there are 4 or 5 steps in the install, and they should be separate classes. But, for what it is, it’s pretty solid. But every time I installed to remote machine, it was taking forever to start, and was using as much CPU as it could. It turns out that was because of the RabbitMQ code that I quickly wrote was written to quickly.
The RabbitMQ api allows you to DEQUEUE (with or without a timeout), or DEQUEUEWITHNOWAIT, which returns immediately if there aren’t any messages. Despite it being a shallow pass, there is a throttler to limit the number of channels per application. The throttler iterates the channels on x threads looking for messages. So, maybe there are 10 subscribers, but they are all handled by 2 threads. It uses DEQUEUEWITHNOWAIT to get the message if there is one, and if not it moves on to the next subscriber. The problem is that loop was too tight. I changed it to use DEQUEUE with a 500millisecond wait. That solved it.
Lastly, there is a bus problem which I have fixed, but it needs to be addressed. The app server defaults to the built in SignalR bus. If you call UseRabbitMQBus, it swaps it out with the RabbitMQBus version. The problem is that the the signalr bus was already instantiated and is running. It can’t connect to the server, because there isn’t work, but it’s trying. The quick fix was to add a Start method to the bus so that it doesn’t start working until started. Then, there’s a SignalR bus, instantiated but dormant, which is replaced with the RabbitMQ one, instantiated but dormant. When the server starts, it starts the bus. This isn’t very clean. I believe the cleaner approach will be for the setup code to register a bus factory rather than a bus, and then the server can use the factory to get the instance (then register it directly). I haven’t looked into it yet, but that’s my first impression.
I already mentioned that I did a lot of work on the installer. One new piece of functionality is that it publishes it’s status as it goes. Now the installer page in the admin portal receives a stream of events related to the install. Then, when it’s complete, it gives you the option to jump right to that server’s admin page. (Previously, it redirected automatically. Now that there’s feedback, you can peruse it before moving on.)
I’m not sure. I think I’m going to work on the Application Host Feature. I made a mistake in how the synchronization works… when the feature starts, it synchronizes all applications. This is efficient because shared files are only downloaded once. But, really, it should synchronize the applications as they start incase it has changed since the last time it started. I see this issue when I make configuration changes to the server. Restarting the app doesn’t recognize the changes. The server has to be restarted, and that’s sub par.
Also, I would like to add the option to have process isolation rather than app domain isolation. I have been laying the ground work for this from the beginning. I’m must not sure what technology to use to have the processes talk to each other. My first instinct is named pipes via WCF, but WCF feels like a dirty word these days. SignalR is an option, but I’d be using it for P2P, which isn’t what it’s for. There’s always HTTP, but then that’s public. Name pipes seems like the answer, but I’ll have to look into it before deciding.
The setback have been dealt with in some fashion. Everything is back to working as it should.
And, as always, PLEASE HELP ME!!!