Best design questions in January 2012

How does an application launcher update itself?

16 votes

Launchers are most common in games. Think of League of Legends, Starcraft II, or almost any MMO out there. Before starting the actual game, you have a small launcher app that takes care of updates and patching.

I want to move this direction with a particular non-game application I am developing. The concept of the launcher makes perfect sense: it checks for updates, replaces the appropriate binaries/libraries, maybe runs an integrity check, and launches the application. However, how do launchers update themselves? This tends to be a rare event, but how is it done? Does the launcher literally just write over the very binary it is currently running from? Or is there some kind of swap step after the download? I need to be able to push out (rare) updates to the launcher (especially if I discover some bug in my launcher).

My particular project will be in C#, but I am interested in conceptually similar C++ and/or Java solutions as well for future reference.

I've never tried, but this is what I would guess (assuming you can't overwrite a file being executed. If you can, this is all simpler)

Updater A checks if its the newest version
If launcher isnt the newest version
    Download the differences (to save bandwidth) to file B
    Apply the delta to own code into file C
    Launch file C.
    Close
If file C exists (update happened recently)
    Try to delete C  (update was previous launch, delete temporary file)
    If delete fails  (We are C, means A is out of date)
        Copy C over A  (update launcher)
If game isnt newest version
    Download the differences (to save bandwidth) to file B
    Apply the delta to game into file D
    Rename game->E (no-fail-swap-trick)
    Rename D->game
    delete file E
Run game

André Caron has shown me that the swap trick is done better with transactional file IO.

eCommerce application design: how to manage shopping carts on a used goods website?

6 votes

I'm making an eCommerce marketplace for used goods using Ruby on Rails with the PayPal API for completing purchases. So essentially the deal is that people can buy and sell their stuff - like eBay or Half.com. All items are used. Here's my question: used goods means that every item is unique - at least in the sense that sellers typically only carry 1 of the used good they are selling. That brings me my question, for any developers who have run into this kind of problem before: how should I handle the situation in which:

  • Seller lists his sweatshirt
  • Person #1 adds the sweatshirt to his cart
  • Person #2 adds the same sweatshirt to his cart
  • Person #1 checks out via PayPal

Now, what do I do with Person #2? Clearly, he can't check out the same sweatshirt, because the seller only has 1 sweatshirt. What I want to know is how I should handle this situation. So far, I've come up with two possible solutions, but neither seems satisfactory to me. (By the way, it might be relevant to add that a user's current cart is a session variable)

Option #1: When Person #1 adds the sweatshirt to his cart, you flag the sweatshirt with a boolean field such as available = false. The downside to this is that a user can add an item to his cart, and then go idle. Thus, no one can purchase the item until Person #1's cart expires.

Option #2: The sweatshirt is only flagged as unavailable when I get the IPN from PayPal. The downside to this is that you could theoretically have Person #1 and #2 checking out from PayPal at once, and thus they would both buy the sweatshirt, and it wouldn't be until after I get the IPN that I realize I've sold the product twice.

What does StackOverflow think? Is there anyone with experience in this field who can offer some insight?

Here is the deal -

  • Seller lists his sweatshirt
  • Person #1 adds the sweatshirt to his cart
  • Person #2 adds the same sweatshirt to his cart
  • Person #1 checks out via PayPal
  • Prevent both of them from end up buying same Item which has 1 quantity in your inventory.

One way to handle this scenario in my opinion is(Which is a kind of upgraded version of your option #1)-

When Person 1 adds an item in their cart you will(if not then you should) be changing the order status i.e. in cart, address, payment, complete etc.

So when Person 1 adds Item A in their cart(status: in cart) block it for 10 minutes for others(Person 2) to add them into their cart. Now you need to have a rake script or Delayed Job using crone job running on your server which checks for every products, in this case Item A in orders table with in cart status for 10 or more than 10 minutes and flush/ remove those products from that row. Which will enable others(Person 2) to add that Item into their cart. And have others(Person 2) and Person 1 updated about your process of this 10 minutes flushing thing with some sort of notice. For example: Item 1 Will be available in Time Counter running to Person 2 and Item 1 will go in Time Counter running to Person 1. Here this process will make a sense of urgency in users mind and you'll have a control over your inventory from not getting an item sold more than its count on hand/ quantity. You can check this website for a live and running implementation - http://www.thepeacockparade.com/

Hope it gives you a fair idea to handle this situation. And yes if, you get any better way to do the same thing please, do keep me updated about it because, I'm also looking for an upgrade.

Thanks

Update on performance

After implementing this process you may end up with some performance issues on your website. One way I figured out a way to keep your application running and, serving your customers and, the background process synced at the same time is, If you use amazon rds or any other cloud database service you can have two different application server altogether. One for your customers to serve and one for performing background processes such as, cleaning temporary data, files, rake tasks, uploading data etc. And since you have your application database totally outside of you application servers, it can be updated from both applications. So, it will keep your main application serving even better to its users instead of starving for memory used by background processes.

Update on database settings

Rails is awesome when it comes to database, tables and associations. If you are new to amazon cloud database service then, checkout their plans here: http://aws.amazon.com/rds/pricing. Best part about having your database on amazon rds are -

  • You are free to select the near endpoint/ server location to serve your database for your application, which will reduce latency of your db queries and your server load in processing them.
  • You can use multiple applications to access it. Apparently for different purposes, i.e. One for uploading data, second for running analytics etc.
  • You have to pay only for what you use.
  • If anything(sometimes for some reasons I prefer being a pessimist) goes wrong and server crashes for any weird reason. You are not screwed!! Your DATABASE is safe. Just set up a new application and voila!! You are back in no time.
  • You have freedom to automate database backup without messing your head into BASH SCRIPTS.
  • You can expand it as your Business grow.

To set up an amazon rds database go to your amazon rds console: https://console.aws.amazon.com/rds/home. Select your preferred region from Navigation pane on left side of the page. Click on "Launch DB Instance" button, select you preferred Database and follow rest of the flow, i.e. selecting instance type etc.

Now if you have your rds instance running, you are able to see an endpoint something like this: database-name.random-string.region-endpoint.rds.amazonaws.com. In your rails application edit and update your config/database.yml to this:

production:
  adapter: mysql2
  host: database-name.random-string.region-endpoint.rds.amazonaws.com
  encoding: utf8
  reconnect: false
  database: databse-name
  username: master-username
  password: password

Looked surprised?? Yes, that's it!! You are all set to you use your application with your new amazon rds DB instance. Now rake db:create to test connection and rake db:migrate to create your tables.

Here I'd like to add one more thing. If you care to make your life better then, you should use amazon s3(simple storage service) too. It's damn cheap and reliable, Check it out here: http://aws.amazon.com/s3/

Enjoy!!