2

Lots of words below, sorry - but I wanted to explain this situation well:

I'm in the process of creating a system that allows any logged in user to edit a single document, but I don't want more than one user to be able to edit that document at the same time.

(Just for reference, I plan to have an indefinite number of these documents on my website, and users can create new documents. Essentially, imagine Google Docs, but with only one user being able to edit a document at a time).

I currently have a JavaScript/AJAX/PHP solution that involves, for each document, a database-stored variable that holds the user id of the user who is currently editing that document. No other users can edit the document until that user is done, and the document

When a user is "done" editing (which means that they either closed the editing window or saved their changes), the document becomes available to any other user once again...or at least should in theory. For the app I'm developing, it's important that the document becomes available as soon as possible. That's not a problem if an editing user saves his or her changes, but is a problem if a user closes the editing window and doesn't save any changes.

My current setup, to account for the non-save case, is to do a periodic AJAX call, to a php page that essentially says, "I'm still editing. Give me two more minutes of editing time." So then, if the user closes the page, the document will become available to everyone within two minutes. That's too long for what I need though. I'd really like to make this as close to real time as possible (though a < 10 second delay wouldn't be awful).

These documents are publicly visible, and their statuses are displayed in list form. When a user loads the "view available documents" page, I need to do a query to check the state of all recent documents that should be shown, making documents with expired editing times available, and displaying them with the currently available ones.

Why this method is bad: When a ton of users use this web app simultaneously, it involves WAY too many db queries, and checks, and AJAX updates.

Is there a better way to do this? (I hope so!)

Other info: -I tried using window.unload (to send an AJAX call to an "I'm done editing" page), but there isn't enough time for the ajax call to execute. -I don't think that my hosting provider would allow the use of persistent PHP scripts (and I also don't have any experience with persistent php scripts). -Even if I could use a persistent PHP script, I'd be concerned about the processing involved if I had to run a ton of these scripts simultaneously. (100? 1000? More? I don't know how much processing power that could use.) -I'm not able to run cron jobs. -If I have my editing clients' "I'm still editing" AJAX script run every 10 seconds instead of every minute or so, that's going to be A LOT of AJAX calls per second if I have a lot of users, which would lead to a lot of db access, which wouldn't be great.

I realize that the needs I've presented here probably rule out a bunch of otherwise good potential solutions, but I'm curious whether anyone can think of any other possible methods of doing this.

Thanks!

Edit: (Adding a relevant response to a comment)

Unfortunately, these aren't actual files. They're sort of virtual compound files that are made up of individual contributions from users. Imagine a single page that, instead of being one single set of text was a set of serially-submitted (from top to bottom) segments of text that combine to make up the full document. Each user-submitted segment is short, and is stored individually in a database. --- Weird, I know, but helpful and necessary for this project.

hithere
  • 520
  • 4
  • 17
  • 1
    Are you sure that it is an issue to do a ajax call every minute and give an extra 2 minutes of editing time? 1000 concurrent editors would only mean 17 requests per second, which could be handled flawlessly by any capable web platform and database. Besides, you could store the "lock" information in memcached rather than in the database if needed. – gahooa Dec 10 '10 at 05:18
  • Hmm...I guess you're right about the server load. My current setup might not be as bad as I thought. Memcached would be a great option in this case, but my host doesn't offer it as part of the current PHP build. Are there any other ways to set/get data in memory? – hithere Dec 10 '10 at 05:27

1 Answers1

0

If these are actual files, you can use the technique outlined in this question.

Then keep doing what you're doing, close the file on them if no change is made in 2 minutes, or whatever time you want to set.

Edit: Could you store the currently used documents in memory and access them from there? This would remove the need for numerous database calls and would be pretty quick. Every 30 seconds you could query the site to reset the document timer (in memory). The next person that has access to the file could do a check on this document timer and if it's > your predetermined amount of elapsed time you could give them access.

Very interesting problem!

Community
  • 1
  • 1
Chuck Callebs
  • 16,293
  • 8
  • 56
  • 71
  • Thanks for the suggestion. Unfortunately, these aren't actual files. They're sort of *virtual compound files* that are made up of individual contributions from users. Imagine a single page that, instead of being one single set of text was a set of serially-submitted (from top to bottom) segments of text that combine to make up the full document. Each user-submitted segment is short, and is stored individually in a database. (Actually, I'm going to re-post this comment above to help clarify things for other people too.) – hithere Dec 10 '10 at 04:59
  • @Chuck's Edit - Now that's an interesting idea! Storing the current use data in memory...hmm. I'm not sure it my hosting allows that, but I'll have to check. I haven't ever tried anything like that before, but it sounds like something to look into. I know that I can create MEMORY type MySQL tables, but storing it in the actual memory would be more efficient than doing a bunch of db queries. Best of all, sets of "user x is editing document y" data wouldn't take up much memory per user-document combo. Any idea about how to do this? Unfortunately, I don't have the Memcache extension. – hithere Dec 10 '10 at 05:23
  • Memcache is the only way I know of to implement it unfortunately. I'll keep it in mind over the next few days and if anything comes to me I'll let you know. :-/ – Chuck Callebs Dec 10 '10 at 05:37
  • Although I can't use memcache myself, I'm still going to mark this as answered (since it may help other people who do have memcache). – hithere Dec 11 '10 at 06:01