skip to Main Content

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?

2

Answers


  1. 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!!

    Login or Signup to reply.
  2. Rather than having a locked flag and having a background process that finds locked items and expires those locks, you could instead have locked_by and locked_until flags.

    When a person adds something to their cart, set locked_by to them and locked_until to 10 minutes in the future. You might want to consider bumping locked_until if they take certain actions (e.g. give them another few minutes once they actually start the checkout process).

    When you want to test is something is available or not, simply check whether locked_until is in the past or not. This way you don’t need to reset the locking columns once the grace period has passed.

    If there are multiple instances of the same product (i.e. there is stock of 5 of this sweatshirt), you could still use this approach by having a second model that represents the actual physical objects, i.e. you might have

    class Product < AR:Base
      has_many :physical_objects
    end
    

    and instance of PhysicalObject represent the actual item (rather than the idealised object). Since you have 5 sweatshirts, the sweatshirt product has 5 physical objects. PhysicalObject could also track stuff that might vary on a per item basis (for example which warehouse it is in).

    The locking columns then sit on the physical object: when someone adds a product to their cart you lock one of the physical objects for that product, when an order is confirmed in you can make the physical object as permanently gone (or even delete it). If you use the same locking strategy as before then you don’t need to do any sweeping type tasks to clear locks.

    Whatever you do, you should probably look into optimistic locking, to prevent race conditions if two customers try to add the same product to their cart at the same time

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search