I'm new to web programming. I'm more experienced and comfortable with client-side code. Recently, I've been dabbling in web programming through Python's Google App Engine. I ran into some difficulty while trying to write some simple apps for the purposes of learning, mainly involving how to maintain some kind of consistent universally-accessible state for the application.

I tried to write a simple queueing management system, the kind you would expect to be used in a small clinic, or at a cafeteria. Typically, this is done with hardware. You take a number from a ticketing machine, and when your number is displayed or called you approach the counter for service. Alternatively, you could be given a small pager, which will beep or vibrate when it is your turn to receive service. The former is somewhat better in that you have an idea of how many people are still ahead of you in the queue.

In this situation, the global state is the last number in queue, which needs to be updated whenever a request is made to the server. I'm not sure how to best to store and maintain this value in a GAE context.

The solution I thought of was to keep the value in the Datastore, attempt to query it during a ticket request, update the value, and then re-store it with put. My problem is that I haven't figured out how to lock the resource so that other requests do not check the value while it is in the middle of being updated. I am concerned that I may end up ticket requests that have the same queue number. Also, the whole solution feels awkward to me. I was wondering if there was a more natural way to accomplish this without having to go through the Datastore.

Can anyone with more experience in this domain provide some advice on how to approach the design of the above application?

  • 2
    Good job recognizing the dangers of multithreading spot on. You need a lock, every multithreading language has a way of doing this. I don't know pythons but a lock is usually placed around a block of code and that block only allows one thread at a time. other terms for locks are mutex (mutually exclusive) and semaphore. some languages don't have blocks for this and require you to manually make a shared resource grab or wait for availability then release at the end of of your mutex so the next waiting thread can accomplish it's grab. Commented Dec 5, 2012 at 18:48
  • To add to Jimmy Hoffa, in Python, locks are provided in the standard library in either the multiprocessing or multithreading libraries, depending on whether you want to use multiple processes or multiple threads. For technical reasons too long to go into here (read about Python's global interpreter lock), multiprocessing is recommended for CPU-intensive tasks. If your program is mostly just waiting for IO, both will work - just make sure to wrap your tasks as threads or as processes Commented May 18, 2016 at 1:03
  • Incidentally, it sounds you're really just trying to write a concurrent scheduler. Locks are the way to go. :) Commented May 18, 2016 at 1:06

1 Answer 1

  • Each ticket request is logged in a ticket database table that stores the unique ID of the request and the time on which the request was made.
  • Whenever it is time to service a new request, fetch the first row from the ticket database table, ordered by request time.
  • Delete the row from the database.

If the last two steps are run as a single transaction, you'll be able to have multiple agents servicing requests simultaneously without treading on each others' toes.

I'm not sure how Google AppEngine's data store works, but any decent database should give you:

  • Automatic IDs that are guaranteed to be unique;
  • Transactional queries that can lock rows required by that transaction.
  • His problem is around multiple updaters, and your solution just offloads atomicity to the db, which is valid but not what's being asked for. Commented Dec 5, 2012 at 18:55
  • 1
    True, but the question was "how to approach the design of the above application" rather than "I've finalised my design but now need to handle mutexes in Python". I think this design eliminates the mutex problem and is more powerful (it can answer questions such as "how many requests are in the queue?", "how long is the average wait to be served?", etc). A useful variation would be to add a "served by" column to the DB, rather than deleting rows, which would allow tracking of the most efficient/least efficient servers.
    – Ant
    Commented Dec 5, 2012 at 19:05
  • I agree queueing through the DB and offloading threading troubles to it is a completely valid and oft used approach. Though if you know Python it would be nice to hear a simple explanation of the pythonic approach to mutexes since that's what he asked about, in addition to the overarching concept of using the DB's multi-threading management so you don't have to manage it yourself. Commented Dec 5, 2012 at 19:11
  • 2
    Its more than valid, its the only solution that would scale to multiple instances, or, multiple servers. Commented Jan 15, 2013 at 9:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.