ASP.Net web service synchronize call to process database queue - c#

I have an asp.net web service which is like a reservation system and cannot reserve the same seat by multiple persons and the eligibility for the reservation is based on some other table values in SQL server. I plan to use SQL server queue processing as mentioned here. My customer wants to do this in a synchronized call, means we want the result in the same web service method call. My question is how efficient it to allow a synchronized method call to process a queue and wait until the queue return values (by means of a loop within a time span or so). Please advise the best possible approaches to achieve this.

You are stepping in the XY problem trap. Your primary goal is to make sure no seat can be reserved twice. You should rethink your approach of using a queue is the appropriate solution to this problem. A queue is great to efficiently use your processing resources on a background task. For real-time processing (like yours) it will create more problems that it solves.
It seems like you want to avoid the race condition that occurs when multiple users try to access the same seat twice. The queue doesn't solve the problem, you just move it to the enqueing phase. The one who enters the queue first wins. At the end you have added an unnecessary complication that doesn't bring you any benefit.
A much simpler solution to your problem is to create a unique key on your DB that makes sure that no seat can be reserved twice. Once you try to reserve a seat that has been taken just a moment ago, you will get an SQLException with the error number 2627. You can then prompt the user that the seat is taken.

Related

keep track of current context of user action using SignalR for push notification

If you look at StackOverflow (SO) site, while you are looking at a specific thread and there is some update to that thread, SO pushes the notification to you. That means SO is aware of user context/user action (which thread you are currently seeing). I am trying to build something similar in my ASP.NET web API application using SignalR.
In order to implement this similar behavior, I am performing following steps.
Every time user views a thread, I make a get call to an endpoint to return thread information along with that, I am maintaining a dictionary which I update every time, this endpoint is called. In this dictionary I store the context.connectionId as key and threadId as value (keeping threadId as value since multiple users can view the same thread at the same time).
Anytime a change is made to any thread, I ask the dictionary to return me all the connectionId (keys) where value == threadId.
Then I push notification to all the coonectionId's returned in step2.
Questions:
I feel this is overkill and there might be an easier way to do all this. What is the best approach to handle this scenario?
Do you think this approach will scale well and application performance will not be impacted.
Tomorrow if I move to server farm, would this approach will still work ?
There's nothing wrong with this approach. This seems like a fairly straightforward pubsub approach. A user subscribes to a particular thread upon viewing. The server then publishes updates to that thread to the users who have subbed to it. What you outlined for a context dictionary is really the minimum amount of data needed to send targeted updates to users.
Scaling is fine, although I would argue that you should reverse your dictionary for better performance. You should key off the threadId, and keep a list of connectionIds that have subbed to that thread. In doing so, you'd be able to simply add a connectionId to a an existing list when a new user is viewing a thread. You minimize the amount of data you need to keep in memory. As it stands now, you have to loop over every connectionId to figure out what they're looking at and aggregate that into a single list, so you might as well just reverse it and store the list itself.
It would work so long as each server in the farm handles their own list of connectionId/threadId maps. If each server can respond to a change in the thread independently, then a farm setup should be fine.

Avoiding concurrent access of data in MSSQL

We are developing a C# application that used to work as a single instance application. Now we need to change it to be a multi-user application, meaning the GUI front-end will be run on multiple workstations while accessing a single MS SQL Server 2008 R2 data store.
Part of the work this application manages is queue based, meaning there's a pool of workitems (the list of workitems is in a single SQL table) from which each user can "take" the next available workitem. What I want to accomplish are the following:
once a workitem is "taken" by a user, no other user should have access to it in any way (including reading) until the first user finished working,
handle timeouts (user goes home for the weekend while workitem is taken) and frozen clients (reset button is pressed on the station while workitem is taken).
I know this is a rather general question (much rather a research), so I'm not expecting a detailed solution, but useful links, best practices and/or some literature to read on the subject. Any help is really appreciated since I'm completely lost where to start.
I've seen this done with a transactional resource lock table or column. For example, you assign the record to someone (be it by setting a user ID or some other mechanism) and you simultaneously set a timestamped record as to when that resource was locked. When accessing the data, be it querying it or trying to update it, you first check this lock table/column to make sure it's available. If not, you don't take the changes.
This also supports timeouts then. If the timestamp is too old, the lock is released. You can automatically assumed release if the timestamp is too old, or you can write a scheduled service that will check for expired locks and unlock them. I'd prefer the second way, as it is less costly to check if a lock is there (boolean logic for row exists or if field value exists [i.e. is not null]). But I've seen it done both ways.

Scalability and availability

I am quite confused on which approach to take and what is best practice.
Lets say i have a C# application which does the following:
sends emails from a queue. Emails to send and all the content is stored in the DB.
Now, I know how to make my C# application almost scalable but I need to go somewhat further.
I want some form of responsibility of being able to distribute the tasks across say X servers. So it is not just 1 server doing all the processing but to share it amoungst the servers.
If one server goes down, then the load is shared between the other servers. I know NLB does this but im not looking for an NLB here.
Sure, you could add a column of some kind in the DB table to indicate which server should be assigned to process that record, and each of the applications on the servers would have an ID of some kind that matches the value in the DB and they would only pull their own records - but this I consider to be cheap, bad practice and unrealistic.
Having a DB table row lock as well, is not something I would do due to potential deadlocks and other possible issues.
I am also NOT indicating using threading "to the extreme" here but yes, there will be threading per item to process or batching them up per thread for x amount of threads.
How should I approach and what do you recommend on making a C# application which is scalable and has high availability? The aim is to have X servers, each with the same application and for each to be able to get records and process them but have the level of processing/items to process shared amoungst the servers so incase if one server or service fails, the other can take on that load until another server is put back.
Sorry for my lack of understanding or knowledge but have been thinking about this quite alot and had lack of sleep trying to think of a good robust solution.
I would be thinking of batching up the work, so each app only pulled back x number of records at a time, marking those retrieved records as taken with a bool field in the table. I'd amend the the SELECT statement to pull only records not marked as taken/done. Table locks would be ok in this instance for very short periods to ensure there is no overlap of apps processing the same records.
EDIT: It's not very elegant, but you could have a datestamp and a status for each entry (instead of a bool field as above). Then you could run a periodic Agent job which runs a sproc to reset the status of any records which have a status of In Progress but which have gone beyond a time threshold without being set to complete. They would be ready for reprocessing by another app later on.
This may not be enterprise-y enough for your tastes, but I'd bet my hide that there are plenty of apps out there in the enterprise which are just as un-sophisticated and work just fine. The best things work with the least complexity.

Windows service threading with looping and WCF

First off, I will be talking about some legacy code and we are trying to avoid changing it as much as possible. Also, my experience with windows services and WCF is a bit limited so some of the questions may be a bit newbie. Just to give a bit of context before the question.
We have an existing service that loops. It checks via a database call to see if it has records to process. If it does not find any records, it sleeps for 30 seconds and then wakes back up to try again.
I would like to add an entry point to this service that would allow me to pass a record to this service in addition to it processing the records from the database. So the basic flow would be.
Loop
* Read record from database
* If no record from DB, process any records that were passed in via the entry point.
* No records at all, sleep for 30 seconds.
My concern is this. Is it possible to implement this in one service such that I have the looping process but I also allow for calls to come in at any time and add additional items to a queue that can be processed within the loop. My concern is with concurrency and keeping the loop and the listener from stepping on each other.
I know this question may not be worded quite right but I am on the new side with working with this. Any help would be appreciated.
My concern is with concurrency and keeping the loop and the listener from stepping on each other.
This shouldn't be an issue, provided you synchronize access correctly.
The simplest option might be to use a thread safe collection, such as a ConcurrentQueue<T>, to hold your items to process. The WCF service can just add items to the collection without worry, and your next processing step would handle it. The synchronization in this case is really minimal, as the queue would already be fully thread safe.
In addition to Reed's excellent answer, you might want to persist the records in a MSMQ queue to prevent your service from losing records on shutdown, restart, or crash of your service.

How should I complete this type of notification?

I am basically creating a site for recruiters. One of the functionality in my application requires posting to Facebook periodically. The posting frequency can be from 0(Never) to 4(High)
For Eg. If a recruiter has 4 open jobs and he has posting frequency set to 4, each job should be posted as per it's turn: 1st job on 1st day, 2nd job on 2nd, 3rd job on 3rd etc, on 5th day again 1st job (round robin fashion).
Had he set the posting frequency to 2, two jobs would be posted daily (thus each job would be posted every 2 days)
My only question is what type of threading should I create for this since this is all dynamic!! Also, any guidelines on what type of information should I store in database?
I need just a general strategy to solve this problem. No code..
I think you need to seperate it from your website, I mean its better to run the logic for posting jobs in a service hosted on IIS ( I am not sure such a thing exists or not, but I guess there is).
Also you need to have table for job queue to remember which jobs need to be posted, then your service would pick them up and post them one by one.
To decide if this is the time for posting a job you can define a timer with a configurable interval to check if there is any job to post or not.
Make sure that you keep the verbose log details if posting fails. It is important because it is possible that Facebook changes its API or your API key becomes invalid or anything else then you need to know what happened.
Also I strongly suggest to have a webpage for reporting the status of jobs-to-post queue, if they failed what was the causes of problem.
If you program runs non-stop, you can just use one of the Timer classes available in .NET framework, without the need to go for full-blown concurrency (e.g. via Task Parallel Library).
I suspect, though, that you'll need more than that - some kind of mechanism to detect which jobs were successfully posted and which were "missed" due program not running (or network problems etc.), so they can be posted the next time the program is started (or network becomes available). A small local database (such as SQLite or MS SQL Server Compact) should serve this purpose nicely.
If the requirements are as simple as you described, then I wouldn't use threading at all. It wouldn't even need to be a long-running app. I'd create a simple app that would just try to post a job and then exit immediately. However, I would scheduled it to run once every given period (via Windows Task Scheduler).
This app would check first if it hasn't posted any job yet for the given posting frequency. Maybe put a "Last-Successful-Post-Time" setting in your datastore. If it's allowed to post, the app would just query the highest priority job and then post it to Facebook. Once it successfully posts to Facebook, that job would then be downgraded to the lowest priority.
The job priority could just be a simple integer column in your data store. Lower values mean higher priorities.
Edit:
I guess what I'm suggesting is if you have clear boundaries in your requirements, I would suggest breaking your project into multiple applications. This way there is a separation of concerns. You wouldn't then need to worry how to spawn your Facebook notification process inside your web site code.

Categories